From 7811e6aa3299d712722c08a2a9a6c3c365eb22ff Mon Sep 17 00:00:00 2001 From: Skull Merlin <86374920+skkuull@users.noreply.github.com> Date: Thu, 17 Mar 2022 02:35:10 +0200 Subject: [PATCH] stuff --- src/client/component/arxan.cpp | 164 ++++ src/client/component/auth.cpp | 25 +- src/client/component/binding.cpp | 138 ---- src/client/component/bots.cpp | 103 --- src/client/component/branding.cpp | 65 -- src/client/component/colors.cpp | 182 ----- src/client/component/command.cpp | 648 ---------------- src/client/component/command.hpp | 50 -- src/client/component/console.cpp | 299 -------- src/client/component/console.hpp | 35 - src/client/component/dedicated.cpp | 333 -------- src/client/component/dedicated_info.cpp | 65 -- src/client/component/demonware.cpp | 604 --------------- src/client/component/demonware.hpp | 6 - src/client/component/discord.cpp | 148 ---- src/client/component/dvars.cpp | 443 ----------- src/client/component/dvars.hpp | 28 - src/client/component/exception.cpp | 261 ------- src/client/component/fastfiles.cpp | 49 -- src/client/component/fastfiles.hpp | 8 - src/client/component/filesystem.cpp | 94 --- src/client/component/filesystem.hpp | 19 - src/client/component/fps.cpp | 174 ----- src/client/component/game_console.cpp | 793 -------------------- src/client/component/game_console.hpp | 7 - src/client/component/game_module.cpp | 3 +- src/client/component/localized_strings.cpp | 52 -- src/client/component/localized_strings.hpp | 6 - src/client/component/logfile.cpp | 317 -------- src/client/component/logfile.hpp | 13 - src/client/component/lui.cpp | 58 -- src/client/component/map_rotation.cpp | 180 ----- src/client/component/network.cpp | 11 +- src/client/component/party.cpp | 630 ---------------- src/client/component/party.hpp | 17 - src/client/component/patches.cpp | 293 -------- src/client/component/renderer.cpp | 77 -- src/client/component/scheduler.cpp | 8 +- src/client/component/scripting.cpp | 141 ---- src/client/component/scripting.hpp | 8 - src/client/component/server_list.cpp | 443 ----------- src/client/component/server_list.hpp | 12 - src/client/component/shaders.cpp | 50 -- src/client/component/slowmotion.cpp | 53 -- src/client/component/splash.cpp | 141 ---- src/client/component/system_check.cpp | 25 +- src/client/component/thread_names.cpp | 60 -- src/client/component/ui_scripting.cpp | 180 ----- src/client/component/ui_scripting.hpp | 12 - src/client/component/updater.cpp | 474 ------------ src/client/component/updater.hpp | 26 - src/client/component/videos.cpp | 55 -- src/client/component/virtuallobby.cpp | 63 -- src/client/loader/loader.cpp | 7 +- src/client/loader/loader.hpp | 2 +- src/client/resources/ui_scripts/common.lua | 164 ---- src/client/resources/ui_scripts/updater.lua | 164 ---- 57 files changed, 200 insertions(+), 8286 deletions(-) create mode 100644 src/client/component/arxan.cpp delete mode 100644 src/client/component/binding.cpp delete mode 100644 src/client/component/bots.cpp delete mode 100644 src/client/component/branding.cpp delete mode 100644 src/client/component/colors.cpp delete mode 100644 src/client/component/command.cpp delete mode 100644 src/client/component/command.hpp delete mode 100644 src/client/component/console.cpp delete mode 100644 src/client/component/console.hpp delete mode 100644 src/client/component/dedicated.cpp delete mode 100644 src/client/component/dedicated_info.cpp delete mode 100644 src/client/component/demonware.cpp delete mode 100644 src/client/component/demonware.hpp delete mode 100644 src/client/component/discord.cpp delete mode 100644 src/client/component/dvars.cpp delete mode 100644 src/client/component/dvars.hpp delete mode 100644 src/client/component/exception.cpp delete mode 100644 src/client/component/fastfiles.cpp delete mode 100644 src/client/component/fastfiles.hpp delete mode 100644 src/client/component/filesystem.cpp delete mode 100644 src/client/component/filesystem.hpp delete mode 100644 src/client/component/fps.cpp delete mode 100644 src/client/component/game_console.cpp delete mode 100644 src/client/component/game_console.hpp delete mode 100644 src/client/component/localized_strings.cpp delete mode 100644 src/client/component/localized_strings.hpp delete mode 100644 src/client/component/logfile.cpp delete mode 100644 src/client/component/logfile.hpp delete mode 100644 src/client/component/lui.cpp delete mode 100644 src/client/component/map_rotation.cpp delete mode 100644 src/client/component/party.cpp delete mode 100644 src/client/component/party.hpp delete mode 100644 src/client/component/patches.cpp delete mode 100644 src/client/component/renderer.cpp delete mode 100644 src/client/component/scripting.cpp delete mode 100644 src/client/component/scripting.hpp delete mode 100644 src/client/component/server_list.cpp delete mode 100644 src/client/component/server_list.hpp delete mode 100644 src/client/component/shaders.cpp delete mode 100644 src/client/component/slowmotion.cpp delete mode 100644 src/client/component/splash.cpp delete mode 100644 src/client/component/thread_names.cpp delete mode 100644 src/client/component/ui_scripting.cpp delete mode 100644 src/client/component/ui_scripting.hpp delete mode 100644 src/client/component/updater.cpp delete mode 100644 src/client/component/updater.hpp delete mode 100644 src/client/component/videos.cpp delete mode 100644 src/client/component/virtuallobby.cpp delete mode 100644 src/client/resources/ui_scripts/common.lua delete mode 100644 src/client/resources/ui_scripts/updater.lua diff --git a/src/client/component/arxan.cpp b/src/client/component/arxan.cpp new file mode 100644 index 00000000..adff7199 --- /dev/null +++ b/src/client/component/arxan.cpp @@ -0,0 +1,164 @@ +#include +#include "loader/component_loader.hpp" +#include "scheduler.hpp" +#include "game/game.hpp" + +#include + +namespace arxan +{ + namespace + { + utils::hook::detour nt_close_hook; + utils::hook::detour nt_query_information_process_hook; + + NTSTATUS WINAPI nt_query_information_process_stub(const HANDLE handle, const PROCESSINFOCLASS info_class, + const PVOID info, + const ULONG info_length, const PULONG ret_length) + { + auto* orig = static_cast(nt_query_information_process_hook. + get_original()); + const auto status = orig(handle, info_class, info, info_length, ret_length); + + if (NT_SUCCESS(status)) + { + if (info_class == ProcessBasicInformation) + { + static DWORD explorer_pid = 0; + if (!explorer_pid) + { + auto* const shell_window = GetShellWindow(); + GetWindowThreadProcessId(shell_window, &explorer_pid); + } + + static_cast(info)->Reserved3 = PVOID(DWORD64(explorer_pid)); + } + else if (info_class == 30) // ProcessDebugObjectHandle + { + *static_cast(info) = nullptr; + + return 0xC0000353; + } + else if (info_class == 7) // ProcessDebugPort + { + *static_cast(info) = nullptr; + } + else if (info_class == 31) + { + *static_cast(info) = 1; + } + } + + return status; + } + + NTSTATUS NTAPI nt_close_stub(const HANDLE handle) + { + char info[16]; + if (NtQueryObject(handle, OBJECT_INFORMATION_CLASS(4), &info, 2, nullptr) >= 0 && size_t(handle) != 0x12345) + { + auto* orig = static_cast(nt_close_hook.get_original()); + return orig(handle); + } + + return STATUS_INVALID_HANDLE; + } + + LONG WINAPI exception_filter(const LPEXCEPTION_POINTERS info) + { + if (info->ExceptionRecord->ExceptionCode == STATUS_INVALID_HANDLE) + { + return EXCEPTION_CONTINUE_EXECUTION; + } + + return EXCEPTION_CONTINUE_SEARCH; + } + + void hide_being_debugged() + { + auto* const peb = PPEB(__readgsqword(0x60)); + peb->BeingDebugged = false; + *reinterpret_cast(LPSTR(peb) + 0xBC) &= ~0x70; + } + + void remove_hardware_breakpoints() + { + CONTEXT context; + ZeroMemory(&context, sizeof(context)); + context.ContextFlags = CONTEXT_DEBUG_REGISTERS; + + auto* const thread = GetCurrentThread(); + GetThreadContext(thread, &context); + + context.Dr0 = 0; + context.Dr1 = 0; + context.Dr2 = 0; + context.Dr3 = 0; + context.Dr6 = 0; + context.Dr7 = 0; + + SetThreadContext(thread, &context); + } + + BOOL WINAPI set_thread_context_stub(const HANDLE thread, CONTEXT* context) + { + if (!game::environment::is_sp() + && game::dwGetLogOnStatus() == game::DW_LIVE_CONNECTED + && context->ContextFlags == CONTEXT_DEBUG_REGISTERS) + { + return TRUE; + } + + return SetThreadContext(thread, context); + } + } + + int just_return() + { + return 1; + } + + class component final : public component_interface + { + public: + void* load_import(const std::string& library, const std::string& function) override + { + if (function == "SetThreadContext") + { + //return set_thread_context_stub; + } + + if (function == "LoadStringA" || function == "LoadStringW") + { + return just_return; + } + + return nullptr; + } + + void post_load() override + { + hide_being_debugged(); + scheduler::loop(hide_being_debugged, scheduler::pipeline::async); + + const utils::nt::library ntdll("ntdll.dll"); + nt_close_hook.create(ntdll.get_proc("NtClose"), nt_close_stub); + nt_query_information_process_hook.create(ntdll.get_proc("NtQueryInformationProcess"), + nt_query_information_process_stub); + + AddVectoredExceptionHandler(1, exception_filter); + } + + void post_unpack() override + { + // cba to implement sp, not sure if it's even needed + if (game::environment::is_sp()) return; + + // some of arxan crashes + utils::hook::nop(0x14CDEFCAA, 6); + utils::hook::call(0x1405BCAD1, &just_return); + } + }; +} + +REGISTER_COMPONENT(arxan::component) \ No newline at end of file diff --git a/src/client/component/auth.cpp b/src/client/component/auth.cpp index 346c8d80..c5aa8240 100644 --- a/src/client/component/auth.cpp +++ b/src/client/component/auth.cpp @@ -42,7 +42,7 @@ namespace auth std::string get_protected_data() { - std::string input = "X-Labs-H1Mod-Auth"; + std::string input = "X-Labs-H1STEAM-Auth"; DATA_BLOB data_in{}, data_out{}; data_in.pbData = reinterpret_cast(input.data()); @@ -177,21 +177,20 @@ namespace auth game::SV_DirectConnect(from); } - // CAN'T FIND //void* get_direct_connect_stub() //{ // return utils::hook::assemble([](utils::hook::assembler& a) - // { - // a.lea(rcx, qword_ptr(rsp, 0x20)); - // a.movaps(xmmword_ptr(rsp, 0x20), xmm0); + // { + // a.lea(rcx, qword_ptr(rsp, 0x20)); + // a.movaps(xmmword_ptr(rsp, 0x20), xmm0); - // a.pushad64(); - // a.mov(rdx, rsi); - // a.call_aligned(direct_connect); - // a.popad64(); + // a.pushad64(); + // a.mov(rdx, rsi); + // a.call_aligned(direct_connect); + // a.popad64(); - // a.jmp(0x140488CE2); // H1MP64(1.4) - // }); + // a.jmp(0x140488CE2); // H1MP64(1.4) + // }); //} } @@ -225,8 +224,8 @@ namespace auth utils::hook::jump(0x1D7542_b, 0x1D7587_b); // STEAM MAYBE `1401D7553` ON FIRST utils::hook::jump(0x1D7A82_b, 0x1D7AC8_b); // STEAM - //utils::hook::jump(0x140488BC1, get_direct_connect_stub(), true); // H1(1.4) can't find - utils::hook::call(0x12D437_b, send_connect_data_stub); // H1(1.4) + //utils::hook::jump(0x1401CAE70, get_direct_connect_stub(), true); // STEAM + utils::hook::call(0x12D437_b, send_connect_data_stub); // STEAM // Skip checks for sending connect packet utils::hook::jump(0x1402508FC, 0x140250946); diff --git a/src/client/component/binding.cpp b/src/client/component/binding.cpp deleted file mode 100644 index e40b7f42..00000000 --- a/src/client/component/binding.cpp +++ /dev/null @@ -1,138 +0,0 @@ -#include -#include "loader/component_loader.hpp" -#include "game/game.hpp" - -#include -#include - -namespace binding -{ - namespace - { - std::vector custom_binds = {}; - - utils::hook::detour cl_execute_key_hook; - - int get_num_keys() - { - return SELECT_VALUE(102, 103); - } - - int key_write_bindings_to_buffer_stub(int /*localClientNum*/, char* buffer, const int buffer_size) - { - auto bytes_used = 0; - const auto buffer_size_align = static_cast(buffer_size) - 4; - - for (auto key_index = 0; key_index < 256; ++key_index) - { - const auto* const key_button = game::Key_KeynumToString(key_index, 0, 1); - auto value = game::playerKeys->keys[key_index].binding; - - if (value && value < get_num_keys()) - { - const auto len = sprintf_s(&buffer[bytes_used], (buffer_size_align - bytes_used), - "bind %s \"%s\"\n", key_button, game::command_whitelist[value]); - - if (len < 0) - { - return bytes_used; - } - - bytes_used += len; - } - else if (value >= get_num_keys()) - { - value -= get_num_keys(); - if (static_cast(value) < custom_binds.size() && !custom_binds[value].empty()) - { - const auto len = sprintf_s(&buffer[bytes_used], (buffer_size_align - bytes_used), - "bind %s \"%s\"\n", key_button, custom_binds[value].data()); - - if (len < 0) - { - return bytes_used; - } - - bytes_used += len; - } - } - } - - buffer[bytes_used] = 0; - return bytes_used; - } - - int get_binding_for_custom_command(const char* command) - { - auto index = 0; - for (auto& bind : custom_binds) - { - if (bind == command) - { - return index; - } - index++; - } - - custom_binds.emplace_back(command); - index = static_cast(custom_binds.size()) - 1; - - return index; - } - - int key_get_binding_for_cmd_stub(const char* command) - { - // original binds - for (auto i = 0; i <= get_num_keys(); i++) - { - if (game::command_whitelist[i] && !strcmp(command, game::command_whitelist[i])) - { - return i; - } - } - - // custom binds - return get_num_keys() + get_binding_for_custom_command(command); - } - - void cl_execute_key_stub(const int local_client_num, int key, const int down, const int time) - { - if (key >= get_num_keys()) - { - key -= get_num_keys(); - - if (static_cast(key) < custom_binds.size() && !custom_binds[key].empty()) - { - game::Cbuf_AddText(local_client_num, utils::string::va("%s\n", custom_binds[key].data())); - } - - return; - } - - cl_execute_key_hook.invoke(local_client_num, key, down, time); - } - } - - class component final : public component_interface - { - public: - void post_unpack() override - { - if (game::environment::is_dedi()) - { - return; - } - - // write all bindings to config file - utils::hook::call(SELECT_VALUE(0x1401881DB, 0x14025032F), key_write_bindings_to_buffer_stub); // H1(1.4) - - // links a custom command to an index - utils::hook::jump(SELECT_VALUE(0x140343C00, 0x1404041E0), key_get_binding_for_cmd_stub); // H1(1.4) - - // execute custom binds - cl_execute_key_hook.create(SELECT_VALUE(0x140183C70, 0x14024ACF0), &cl_execute_key_stub); // H1(1.4) - } - }; -} - -REGISTER_COMPONENT(binding::component) diff --git a/src/client/component/bots.cpp b/src/client/component/bots.cpp deleted file mode 100644 index 81f74628..00000000 --- a/src/client/component/bots.cpp +++ /dev/null @@ -1,103 +0,0 @@ -#include -#include "loader/component_loader.hpp" - -#include "command.hpp" -#include "scheduler.hpp" -#include "network.hpp" -#include "party.hpp" - -#include "game/game.hpp" -#include "game/scripting/execution.hpp" - -#include -#include -#include - -namespace bots -{ - namespace - { - bool can_add() - { - if (party::get_client_count() < *game::mp::svs_numclients) - { - return true; - } - return false; - } - - // TODO: when scripting comes, fix this to use better notifies - void bot_team_join(const int entity_num) - { - const game::scr_entref_t entref{static_cast(entity_num), 0}; - scheduler::once([entref]() - { - scripting::notify(entref, "luinotifyserver", {"team_select", 2}); - scheduler::once([entref]() - { - auto* _class = utils::string::va("class%d", utils::cryptography::random::get_integer() % 5); - scripting::notify(entref, "luinotifyserver", {"class_select", _class}); - }, scheduler::pipeline::server, 2s); - }, scheduler::pipeline::server, 2s); - } - - void spawn_bot(const int entity_num) - { - game::SV_SpawnTestClient(&game::mp::g_entities[entity_num]); - if (game::Com_GetCurrentCoDPlayMode() == game::CODPLAYMODE_CORE) - { - bot_team_join(entity_num); - } - } - - void add_bot() - { - if (!can_add()) - { - return; - } - - // SV_BotGetRandomName - const auto* const bot_name = game::SV_BotGetRandomName(); - auto* bot_ent = game::SV_AddBot(bot_name); - if (bot_ent) - { - spawn_bot(bot_ent->s.entityNum); - } - else if (can_add()) // workaround since first bot won't ever spawn - { - add_bot(); - } - } - } - - class component final : public component_interface - { - public: - void post_unpack() override - { - if (game::environment::is_sp()) - { - return; - } - - command::add("spawnBot", [](const command::params& params) - { - if (!game::SV_Loaded() || game::VirtualLobby_Loaded()) return; - - auto num_bots = 1; - if (params.size() == 2) - { - num_bots = atoi(params.get(1)); - } - - for (auto i = 0; i < (num_bots > *game::mp::svs_numclients ? *game::mp::svs_numclients : num_bots); i++) - { - scheduler::once(add_bot, scheduler::pipeline::server, 100ms * i); - } - }); - } - }; -} - -REGISTER_COMPONENT(bots::component) \ No newline at end of file diff --git a/src/client/component/branding.cpp b/src/client/component/branding.cpp deleted file mode 100644 index 2f74693b..00000000 --- a/src/client/component/branding.cpp +++ /dev/null @@ -1,65 +0,0 @@ -#include -#include "loader/component_loader.hpp" - -#include "localized_strings.hpp" -#include "scheduler.hpp" -#include "command.hpp" -#include "version.hpp" - -#include "game/game.hpp" -#include "dvars.hpp" - -#include -#include - -// fonts/default.otf, fonts/defaultBold.otf, fonts/fira_mono_regular.ttf, fonts/fira_mono_bold.ttf - -namespace branding -{ - namespace - { - utils::hook::detour ui_get_formatted_build_number_hook; - - float color[4] = {0.666f, 0.666f, 0.666f, 0.666f}; - - const char* ui_get_formatted_build_number_stub() - { - const auto* const build_num = ui_get_formatted_build_number_hook.invoke(); - return utils::string::va("%s (%s)", VERSION, build_num); - } - } - - class component final : public component_interface - { - public: - void post_unpack() override - { - - if (game::environment::is_dedi()) - { - return; - } - - if (game::environment::is_mp()) - { - localized_strings::override("LUA_MENU_MULTIPLAYER_CAPS", "H1-MOD: MULTIPLAYER\n"); - localized_strings::override("MENU_MULTIPLAYER_CAPS", "H1-MOD: MULTIPLAYER"); - } - - dvars::override::set_string("version", utils::string::va("H1-Mod %s", VERSION)); - - ui_get_formatted_build_number_hook.create( - SELECT_VALUE(0x1403B1C40, 0x1404E74C0), ui_get_formatted_build_number_stub); - - scheduler::loop([]() - { - const auto font = game::R_RegisterFont("fonts/fira_mono_bold.ttf", 20); - - game::R_AddCmdDrawText("H1-Mod: " VERSION, 0x7FFFFFFF, font, 10.f, - 5.f + static_cast(font->pixelHeight), 1.f, 1.f, 0.0f, color, 0); - }, scheduler::pipeline::renderer); - } - }; -} - -REGISTER_COMPONENT(branding::component) diff --git a/src/client/component/colors.cpp b/src/client/component/colors.cpp deleted file mode 100644 index 75eff23a..00000000 --- a/src/client/component/colors.cpp +++ /dev/null @@ -1,182 +0,0 @@ -#include -#include "loader/component_loader.hpp" - -#include "game/game.hpp" - -#include -#include - -namespace colors -{ - struct hsv_color - { - unsigned char h; - unsigned char s; - unsigned char v; - }; - - namespace - { - std::vector color_table; - - DWORD hsv_to_rgb(const hsv_color hsv) - { - DWORD rgb; - - if (hsv.s == 0) - { - return RGB(hsv.v, hsv.v, hsv.v); - } - - // converting to 16 bit to prevent overflow - const unsigned int h = hsv.h; - const unsigned int s = hsv.s; - const unsigned int v = hsv.v; - - const auto region = static_cast(h / 43); - const auto remainder = (h - (region * 43)) * 6; - - const auto p = static_cast((v * (255 - s)) >> 8); - const auto q = static_cast( - (v * (255 - ((s * remainder) >> 8))) >> 8); - const auto t = static_cast( - (v * (255 - ((s * (255 - remainder)) >> 8))) >> 8); - - switch (region) - { - case 0: - rgb = RGB(v, t, p); - break; - case 1: - rgb = RGB(q, v, p); - break; - case 2: - rgb = RGB(p, v, t); - break; - case 3: - rgb = RGB(p, q, v); - break; - case 4: - rgb = RGB(t, p, v); - break; - default: - rgb = RGB(v, p, q); - break; - } - - return rgb; - } - - int color_index(const char c) - { - const auto index = c - 48; - return index >= 0xC ? 7 : index; - } - - char add(const uint8_t r, const uint8_t g, const uint8_t b) - { - const char index = '0' + static_cast(color_table.size()); - color_table.push_back(RGB(r, g, b)); - return index; - } - - void com_clean_name_stub(const char* in, char* out, const int out_size) - { - strncpy_s(out, out_size, in, _TRUNCATE); - } - - char* i_clean_str_stub(char* string) - { - utils::string::strip(string, string, static_cast(strlen(string)) + 1); - - return string; - } - - size_t get_client_name_stub(const int local_client_num, const int index, char* buf, const int size, - const size_t unk, const size_t unk2) - { - // CL_GetClientName (CL_GetClientNameAndClantag?) - const auto result = utils::hook::invoke(0x14025BAA0, local_client_num, index, buf, size, unk, unk2); - - utils::string::strip(buf, buf, size); - - return result; - } - - void rb_lookup_color_stub(const char index, DWORD* color) - { - *color = RGB(255, 255, 255); - - if (index == '8') - { - *color = *reinterpret_cast(SELECT_VALUE(0x14F142FF8, 0x14FE70634)); // H1(1.4) - } - else if (index == '9') - { - *color = *reinterpret_cast(SELECT_VALUE(0x14F142FFC, 0x14FE70638)); // H1(1.4) - } - else if (index == ':') - { - *color = hsv_to_rgb({static_cast((game::Sys_Milliseconds() / 100) % 256), 255, 255}); - } - else if (index == ';') - { - *color = *reinterpret_cast(SELECT_VALUE(0x14F143004, 0x14FE70640)); // H1(1.4) - } - else if (index == '<') - { - *color = 0xFFFCFF80; - } - else - { - *color = color_table[color_index(index)]; - } - } - } - - class component final : public component_interface - { - public: - void post_unpack() override - { - if (game::environment::is_dedi()) - { - return; - } - - if (!game::environment::is_sp()) - { - // allows colored name in-game - utils::hook::jump(0x140503810, com_clean_name_stub); // H1(1.4) - - // don't apply colors to overhead names - utils::hook::call(0x1400AB416, get_client_name_stub); // H1(1.4) - - // patch I_CleanStr - utils::hook::jump(0x140503D00, i_clean_str_stub); // H1(1.4) - } - - // force new colors - utils::hook::jump(SELECT_VALUE(0x140524BD0, 0x1406206A0), rb_lookup_color_stub); // H1(1.4) - - // add colors - add(0, 0, 0); // 0 - Black - add(255, 49, 49); // 1 - Red - add(134, 192, 0); // 2 - Green - add(255, 173, 34); // 3 - Yellow - add(0, 135, 193); // 4 - Blue - add(32, 197, 255); // 5 - Light Blue - add(151, 80, 221); // 6 - Pink - add(255, 255, 255); // 7 - White - - add(0, 0, 0); // 8 - Team color (axis?) - add(0, 0, 0); // 9 - Team color (allies?) - - add(0, 0, 0); // 10 - Rainbow (:) - add(0, 0, 0); - // 11 - Server color (;) - using that color in infostrings (e.g. your name) fails, ';' is an illegal character! - } - }; -} - -REGISTER_COMPONENT(colors::component) diff --git a/src/client/component/command.cpp b/src/client/component/command.cpp deleted file mode 100644 index b5c1ad40..00000000 --- a/src/client/component/command.cpp +++ /dev/null @@ -1,648 +0,0 @@ -#include -#include "loader/component_loader.hpp" -#include "command.hpp" -#include "console.hpp" -#include "game_console.hpp" - -#include "game/game.hpp" - -#include -#include -#include -#include "utils/io.hpp" -#include - -namespace command -{ - namespace - { - utils::hook::detour client_command_hook; - - std::unordered_map> handlers; - std::unordered_map> handlers_sv; - - void main_handler() - { - params params = {}; - - const auto command = utils::string::to_lower(params[0]); - if (handlers.find(command) != handlers.end()) - { - handlers[command](params); - } - } - - void client_command(const int client_num, void* a2) - { - params_sv params = {}; - - const auto command = utils::string::to_lower(params[0]); - if (handlers_sv.find(command) != handlers_sv.end()) - { - handlers_sv[command](client_num, params); - } - - client_command_hook.invoke(client_num, a2); - } - - // Shamelessly stolen from Quake3 - // https://github.com/id-Software/Quake-III-Arena/blob/dbe4ddb10315479fc00086f08e25d968b4b43c49/code/qcommon/common.c#L364 - void parse_command_line() - { - static auto parsed = false; - if (parsed) - { - return; - } - - static std::string comand_line_buffer = GetCommandLineA(); - auto* command_line = comand_line_buffer.data(); - - auto& com_num_console_lines = *reinterpret_cast(0x142623FB4); //H1(1.4) - auto* com_console_lines = reinterpret_cast(0x142623FC0); //H1(1.4) - - auto inq = false; - com_console_lines[0] = command_line; - com_num_console_lines = 0; - - while (*command_line) - { - if (*command_line == '"') - { - inq = !inq; - } - // look for a + separating character - // if commandLine came from a file, we might have real line seperators - if ((*command_line == '+' && !inq) || *command_line == '\n' || *command_line == '\r') - { - if (com_num_console_lines == 0x20) // MAX_CONSOLE_LINES - { - break; - } - com_console_lines[com_num_console_lines] = command_line + 1; - com_num_console_lines++; - *command_line = '\0'; - } - command_line++; - } - parsed = true; - } - - void parse_commandline_stub() - { - parse_command_line(); - utils::hook::invoke(0x1400D8210); - } - - game::dvar_t* dvar_command_stub() - { - const params args; - - if (args.size() <= 0) - { - return 0; - } - - const auto dvar = game::Dvar_FindVar(args[0]); - - if (dvar) - { - if (args.size() == 1) - { - const auto current = game::Dvar_ValueToString(dvar, dvar->current); - const auto reset = game::Dvar_ValueToString(dvar, dvar->reset); - - console::info("\"%s\" is: \"%s\" default: \"%s\" hash: 0x%08lX", - args[0], current, reset, dvar->hash); - - console::info(" %s\n", dvars::dvar_get_domain(dvar->type, dvar->domain).data()); - } - else - { - char command[0x1000] = { 0 }; - game::Dvar_GetCombinedString(command, 1); - game::Dvar_SetCommand(dvar->hash, "", command); - } - - return dvar; - } - - return 0; - } - } - - void read_startup_variable(const std::string& dvar) - { - // parse the commandline if it's not parsed - parse_command_line(); - - auto& com_num_console_lines = *reinterpret_cast(0x142623FB4); //H1(1.4) - auto* com_console_lines = reinterpret_cast(0x142623FC0); //H1(1.4) - - for (int i = 0; i < com_num_console_lines; i++) - { - game::Cmd_TokenizeString(com_console_lines[i]); - - // only +set dvar value - if (game::Cmd_Argc() >= 3 && game::Cmd_Argv(0) == "set"s && game::Cmd_Argv(1) == dvar) - { - game::Dvar_SetCommand(game::generateHashValue(game::Cmd_Argv(1)), "", game::Cmd_Argv(2)); - } - - game::Cmd_EndTokenizeString(); - } - } - - params::params() - : nesting_(game::cmd_args->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 ""; - } - - 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)); - } - return result; - } - - params_sv::params_sv() - : nesting_(game::sv_cmd_args->nesting) - { - } - - int params_sv::size() const - { - return game::sv_cmd_args->argc[this->nesting_]; - } - - const char* params_sv::get(const int index) const - { - if (index >= this->size()) - { - return ""; - } - - return game::sv_cmd_args->argv[this->nesting_][index]; - } - - std::string params_sv::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)); - } - return result; - } - - void add_raw(const char* name, void (*callback)()) - { - game::Cmd_AddCommandInternal(name, callback, utils::memory::get_allocator()->allocate()); - } - - void add_test(const char* name, void (*callback)()) - { - static game::cmd_function_s cmd_test; - return game::Cmd_AddCommandInternal(name, callback, &cmd_test); - } - - void add(const char* name, const std::function& callback) - { - static game::cmd_function_s cmd_test; - - const auto command = utils::string::to_lower(name); - - if (handlers.find(command) == handlers.end()) - add_raw(name, main_handler); - - handlers[command] = callback; - } - - void add(const char* name, const std::function& callback) - { - add(name, [callback](const params&) - { - callback(); - }); - } - - void add_sv(const char* name, std::function callback) - { - // doing this so the sv command would show up in the console - add_raw(name, nullptr); - - const auto command = utils::string::to_lower(name); - - if (handlers_sv.find(command) == handlers_sv.end()) - handlers_sv[command] = std::move(callback); - } - - void execute(std::string command, const bool sync) - { - command += "\n"; - - if (sync) - { - game::Cmd_ExecuteSingleCommand(0, 0, command.data()); - } - else - { - game::Cbuf_AddText(0, command.data()); - } - } - - class component final : public component_interface - { - public: - void post_unpack() override - { - if (game::environment::is_sp()) - { - add_commands_sp(); - } - else - { - utils::hook::call(0x1400D728F, &parse_commandline_stub); // MWR TEST - utils::hook::jump(0x14041D750, dvar_command_stub); - - add_commands_mp(); - } - - add_commands_generic(); - } - - private: - static void add_commands_generic() - { - add("quit", game::Quit); - //add("quit_hard", utils::nt::raise_hard_exception); /* this command delivers you to a windows blue screen, its quit hard from windows xD */ - add("crash", []() - { - *reinterpret_cast(1) = 0; - }); - - /*add("consoleList", [](const params& params) - { - const std::string input = params.get(1); - - std::vector matches; - game_console::find_matches(input, matches, false); - - for (auto& match : matches) - { - auto* dvar = game::Dvar_FindVar(match.c_str()); - if (!dvar) - { - console::info("[CMD]\t %s\n", match.c_str()); - } - else - { - console::info("[DVAR]\t%s \"%s\"\n", match.c_str(), game::Dvar_ValueToString(dvar, dvar->current, 0)); - } - } - - console::info("Total %i matches\n", matches.size()); - });*/ - - add("commandDump", [](const params& argument) - { - console::info("================================ COMMAND DUMP =====================================\n"); - game::cmd_function_s* cmd = (*game::cmd_functions); - std::string filename; - if (argument.size() == 2) - { - filename = "h1-mod/"; - filename.append(argument[1]); - if (!filename.ends_with(".txt")) - { - filename.append(".txt"); - } - } - int i = 0; - while (cmd) - { - if (cmd->name) - { - if (!filename.empty()) - { - const auto line = std::format("{}\r\n", cmd->name); - utils::io::write_file(filename, line, i != 0); - } - console::info("%s\n", cmd->name); - i++; - } - cmd = cmd->next; - } - console::info("\n%i commands\n", i); - console::info("================================ END COMMAND DUMP =================================\n"); - }); - - /*add("listassetpool", [](const params& params) - { - if (params.size() < 2) - { - console::info("listassetpool [filter]: list all the assets in the specified pool\n"); - - for (auto i = 0; i < game::XAssetType::ASSET_TYPE_COUNT; i++) - { - console::info("%d %s\n", i, game::g_assetNames[i]); - } - } - else - { - const auto type = static_cast(atoi(params.get(1))); - - if (type < 0 || type >= game::XAssetType::ASSET_TYPE_COUNT) - { - console::error("Invalid pool passed must be between [%d, %d]\n", 0, game::XAssetType::ASSET_TYPE_COUNT - 1); - return; - } - - console::info("Listing assets in pool %s\n", game::g_assetNames[type]); - - const std::string filter = params.get(2); - enum_assets(type, [type, filter](const game::XAssetHeader header) - { - const auto asset = game::XAsset{type, header}; - const auto* const asset_name = game::DB_GetXAssetName(&asset); - //const auto entry = game::DB_FindXAssetEntry(type, asset_name); - //TODO: display which zone the asset is from - - if (!filter.empty() && !game_console::match_compare(filter, asset_name, false)) - { - return; - } - - console::info("%s\n", asset_name); - }, true); - } - }); - - add("vstr", [](const params& params) - { - if (params.size() < 2) - { - console::info("vstr : execute a variable command\n"); - return; - } - - const auto* dvarName = params.get(1); - const auto* dvar = game::Dvar_FindVar(dvarName); - - if (dvar == nullptr) - { - console::info("%s doesn't exist\n", dvarName); - return; - } - - if (dvar->type != game::dvar_type::string - && dvar->type != game::dvar_type::enumeration) - { - console::info("%s is not a string-based dvar\n", dvar->hash); - return; - } - - execute(dvar->current.string); - });*/ - } - - static void add_commands_sp() - { - add("god", []() - { - if (!game::SV_Loaded()) - { - return; - } - - game::sp::g_entities[0].flags ^= 1; - game::CG_GameMessage(0, utils::string::va("godmode %s", - game::sp::g_entities[0].flags & 1 - ? "^2on" - : "^1off")); - }); - - add("demigod", []() - { - if (!game::SV_Loaded()) - { - return; - } - - game::sp::g_entities[0].flags ^= 2; - game::CG_GameMessage(0, utils::string::va("demigod mode %s", - game::sp::g_entities[0].flags & 2 - ? "^2on" - : "^1off")); - }); - - add("notarget", []() - { - if (!game::SV_Loaded()) - { - return; - } - - game::sp::g_entities[0].flags ^= 4; - game::CG_GameMessage(0, utils::string::va("notarget %s", - game::sp::g_entities[0].flags & 4 - ? "^2on" - : "^1off")); - }); - - add("noclip", []() - { - if (!game::SV_Loaded()) - { - return; - } - - game::sp::g_entities[0].client->flags ^= 1; - game::CG_GameMessage(0, utils::string::va("noclip %s", - game::sp::g_entities[0].client->flags & 1 - ? "^2on" - : "^1off")); - }); - - add("ufo", []() - { - if (!game::SV_Loaded()) - { - return; - } - - game::sp::g_entities[0].client->flags ^= 2; - game::CG_GameMessage(0, utils::string::va("ufo %s", - game::sp::g_entities[0].client->flags & 2 - ? "^2on" - : "^1off")); - }); - } - - static void add_commands_mp() - { - //client_command_hook.create(0x1402E98F0, &client_command); - - /*add_sv("god", [](const int client_num, const params_sv&) - { - if (!game::Dvar_FindVar("sv_cheats")->current.enabled) - { - game::SV_GameSendServerCommand(client_num, game::SV_CMD_RELIABLE, - "f \"Cheats are not enabled on this server\""); - return; - } - - game::mp::g_entities[client_num].flags ^= 1; - game::SV_GameSendServerCommand(client_num, game::SV_CMD_RELIABLE, - utils::string::va("f \"godmode %s\"", - game::mp::g_entities[client_num].flags & 1 - ? "^2on" - : "^1off")); - }); - - add_sv("demigod", [](const int client_num, const params_sv&) - { - if (!game::Dvar_FindVar("sv_cheats")->current.enabled) - { - game::SV_GameSendServerCommand(client_num, game::SV_CMD_RELIABLE, - "f \"Cheats are not enabled on this server\""); - return; - } - - game::mp::g_entities[client_num].flags ^= 2; - game::SV_GameSendServerCommand(client_num, game::SV_CMD_RELIABLE, - utils::string::va("f \"demigod mode %s\"", - game::mp::g_entities[client_num].flags & 2 - ? "^2on" - : "^1off")); - }); - - add_sv("notarget", [](const int client_num, const params_sv&) - { - if (!game::Dvar_FindVar("sv_cheats")->current.enabled) - { - game::SV_GameSendServerCommand(client_num, game::SV_CMD_RELIABLE, - "f \"Cheats are not enabled on this server\""); - return; - } - - game::mp::g_entities[client_num].flags ^= 4; - game::SV_GameSendServerCommand(client_num, game::SV_CMD_RELIABLE, - utils::string::va("f \"notarget %s\"", - game::mp::g_entities[client_num].flags & 4 - ? "^2on" - : "^1off")); - }); - - add_sv("noclip", [](const int client_num, const params_sv&) - { - if (!game::Dvar_FindVar("sv_cheats")->current.enabled) - { - game::SV_GameSendServerCommand(client_num, game::SV_CMD_RELIABLE, - "f \"Cheats are not enabled on this server\""); - return; - } - - game::mp::g_entities[client_num].client->flags ^= 1; - game::SV_GameSendServerCommand(client_num, game::SV_CMD_RELIABLE, - utils::string::va("f \"noclip %s\"", - game::mp::g_entities[client_num].client->flags & 1 - ? "^2on" - : "^1off")); - }); - - add_sv("ufo", [](const int client_num, const params_sv&) - { - if (!game::Dvar_FindVar("sv_cheats")->current.enabled) - { - game::SV_GameSendServerCommand(client_num, game::SV_CMD_RELIABLE, - "f \"Cheats are not enabled on this server\""); - return; - } - - game::mp::g_entities[client_num].client->flags ^= 2; - game::SV_GameSendServerCommand(client_num, game::SV_CMD_RELIABLE, - utils::string::va("f \"ufo %s\"", - game::mp::g_entities[client_num].client->flags & 2 - ? "^2on" - : "^1off")); - }); - - add_sv("give", [](const int client_num, const params_sv& params) - { - if (!game::Dvar_FindVar("sv_cheats")->current.enabled) - { - game::SV_GameSendServerCommand(client_num, game::SV_CMD_RELIABLE, - "f \"Cheats are not enabled on this server\""); - return; - } - - if (params.size() < 2) - { - game::SV_GameSendServerCommand(client_num, game::SV_CMD_RELIABLE, - "f \"You did not specify a weapon name\""); - return; - } - - auto ps = game::SV_GetPlayerstateForClientNum(client_num); - const auto wp = game::G_GetWeaponForName(params.get(1)); - if (wp) - { - if (game::G_GivePlayerWeapon(ps, wp, 0, 0, 0, 0, 0, 0)) - { - game::G_InitializeAmmo(ps, wp, 0); - game::G_SelectWeapon(client_num, wp); - } - } - }); - - add_sv("take", [](const int client_num, const params_sv& params) - { - if (!game::Dvar_FindVar("sv_cheats")->current.enabled) - { - game::SV_GameSendServerCommand(client_num, game::SV_CMD_RELIABLE, - "f \"Cheats are not enabled on this server\""); - return; - } - - if (params.size() < 2) - { - game::SV_GameSendServerCommand(client_num, game::SV_CMD_RELIABLE, - "f \"You did not specify a weapon name\""); - return; - } - - auto ps = game::SV_GetPlayerstateForClientNum(client_num); - const auto wp = game::G_GetWeaponForName(params.get(1)); - if (wp) - { - game::G_TakePlayerWeapon(ps, wp); - } - });*/ - } - }; -} - -REGISTER_COMPONENT(command::component) diff --git a/src/client/component/command.hpp b/src/client/component/command.hpp deleted file mode 100644 index bd70d0c6..00000000 --- a/src/client/component/command.hpp +++ /dev/null @@ -1,50 +0,0 @@ -#pragma once - -namespace command -{ - class params - { - public: - params(); - - int size() const; - const char* get(int index) const; - std::string join(int index) const; - - const char* operator[](const int index) const - { - return this->get(index); // - } - - private: - int nesting_; - }; - - class params_sv - { - public: - params_sv(); - - int size() const; - const char* get(int index) const; - std::string join(int index) const; - - const char* operator[](const int index) const - { - return this->get(index); // - } - - private: - int nesting_; - }; - - void read_startup_variable(const std::string& dvar); - - void add_raw(const char* name, void (*callback)()); - void add(const char* name, const std::function& callback); - void add(const char* name, const std::function& callback); - - void add_sv(const char* name, std::function callback); - - void execute(std::string command, bool sync = false); -} \ No newline at end of file diff --git a/src/client/component/console.cpp b/src/client/component/console.cpp deleted file mode 100644 index 174beaf8..00000000 --- a/src/client/component/console.cpp +++ /dev/null @@ -1,299 +0,0 @@ -#include -#include "console.hpp" -#include "loader/component_loader.hpp" -#include "game/game.hpp" -#include "command.hpp" - -#include -#include -#include -#include - -namespace game_console -{ - void print(int type, const std::string& data); -} - -namespace console -{ - namespace - { - using message_queue = std::queue; - utils::concurrency::container messages; - - bool native_console() - { - static const auto flag = utils::flags::has_flag("nativeconsole"); - return flag; - } - - void hide_console() - { - auto* const con_window = GetConsoleWindow(); - - DWORD process; - GetWindowThreadProcessId(con_window, &process); - - if (!native_console() && (process == GetCurrentProcessId() || IsDebuggerPresent())) - { - ShowWindow(con_window, SW_HIDE); - } - } - - std::string format(va_list* ap, const char* message) - { - static thread_local char buffer[0x1000]; - - const auto count = _vsnprintf_s(buffer, sizeof(buffer), sizeof(buffer), message, *ap); - - if (count < 0) return {}; - return {buffer, static_cast(count)}; - } - - void dispatch_message(const int type, const std::string& message) - { - if (native_console()) - { - printf("%s\n", message.data()); - return; - } - - game_console::print(type, message); - messages.access([&message](message_queue& msgs) - { - msgs.emplace(message); - }); - } - - void append_text(const char* text) - { - dispatch_message(con_type_info, text); - } - } - - class component final : public component_interface - { - public: - component() - { - hide_console(); - - if (native_console()) - { - setvbuf(stdout, nullptr, _IONBF, 0); - setvbuf(stderr, nullptr, _IONBF, 0); - } - else - { - (void)_pipe(this->handles_, 1024, _O_TEXT); - (void)_dup2(this->handles_[1], 1); - (void)_dup2(this->handles_[1], 2); - } - } - - void post_start() override - { - this->terminate_runner_ = false; - - this->console_runner_ = utils::thread::create_named_thread("Console IO", [this] - { - if (native_console()) - { - this->native_input(); - } - else - { - this->runner(); - } - }); - } - - void pre_destroy() override - { - this->terminate_runner_ = true; - - printf("\r\n"); - _flushall(); - - if (this->console_runner_.joinable()) - { - this->console_runner_.join(); - } - - if (this->console_thread_.joinable()) - { - this->console_thread_.join(); - } - -#ifndef NATIVE_CONSOLE - _close(this->handles_[0]); - _close(this->handles_[1]); -#endif - - messages.access([&](message_queue& msgs) - { - msgs = {}; - }); - } - - void post_unpack() override - { - // Redirect input (]command) - utils::hook::jump(SELECT_VALUE(0x1403E34C0, 0x1405141E0), append_text); // H1(1.4) - - this->initialize(); - } - - private: - volatile bool console_initialized_ = false; - volatile bool terminate_runner_ = false; - - std::thread console_runner_; - std::thread console_thread_; - - int handles_[2]{}; - - void initialize() - { - this->console_thread_ = utils::thread::create_named_thread("Console", [this]() - { - if (!native_console() && (game::environment::is_dedi() || !utils::flags::has_flag("noconsole"))) - { - game::Sys_ShowConsole(); - } - - if (!game::environment::is_dedi()) - { - // Hide that shit - ShowWindow(console::get_window(), SW_MINIMIZE); - } - - { - messages.access([&](message_queue&) - { - this->console_initialized_ = true; - }); - } - - MSG msg; - while (!this->terminate_runner_) - { - if (PeekMessageA(&msg, nullptr, NULL, NULL, PM_REMOVE)) - { - if (msg.message == WM_QUIT) - { - command::execute("quit", false); - break; - } - - TranslateMessage(&msg); - DispatchMessage(&msg); - } - else - { - this->log_messages(); - std::this_thread::sleep_for(1ms); - } - } - }); - } - - void log_messages() - { - /*while*/ - if (this->console_initialized_ && !messages.get_raw().empty()) - { - std::queue message_queue_copy; - - { - messages.access([&](message_queue& msgs) - { - message_queue_copy = std::move(msgs); - msgs = {}; - }); - } - - while (!message_queue_copy.empty()) - { - log_message(message_queue_copy.front()); - message_queue_copy.pop(); - } - } - - fflush(stdout); - fflush(stderr); - } - - static void log_message(const std::string& message) - { - OutputDebugStringA(message.data()); - game::Conbuf_AppendText(message.data()); - } - - void runner() - { - char buffer[1024]; - - while (!this->terminate_runner_ && this->handles_[0]) - { - const auto len = _read(this->handles_[0], buffer, sizeof(buffer)); - if (len > 0) - { - dispatch_message(con_type_info, std::string(buffer, len)); - } - else - { - std::this_thread::sleep_for(1ms); - } - } - - std::this_thread::yield(); - } - - void native_input() - { - std::string cmd; - - while (!this->terminate_runner_) - { - std::getline(std::cin, cmd); - command::execute(cmd); - } - - std::this_thread::yield(); - } - }; - - HWND get_window() - { - return *reinterpret_cast((SELECT_VALUE(0x14CF56C00, 0x14DDFC2D0))); // H1(1.4) - } - - void set_title(std::string title) - { - SetWindowText(get_window(), title.data()); - } - - void set_size(const int width, const int height) - { - RECT rect; - GetWindowRect(get_window(), &rect); - - SetWindowPos(get_window(), nullptr, rect.left, rect.top, width, height, 0); - - auto* const logo_window = *reinterpret_cast(SELECT_VALUE(0x14CF56C10, 0x14DDFC2E0)); // H1(1.4) - SetWindowPos(logo_window, nullptr, 5, 5, width - 25, 60, 0); - } - - void print(const int type, const char* fmt, ...) - { - va_list ap; - va_start(ap, fmt); - const auto result = format(&ap, fmt); - va_end(ap); - - dispatch_message(type, result); - } -} - -REGISTER_COMPONENT(console::component) diff --git a/src/client/component/console.hpp b/src/client/component/console.hpp deleted file mode 100644 index 302951a8..00000000 --- a/src/client/component/console.hpp +++ /dev/null @@ -1,35 +0,0 @@ -#pragma once - -namespace console -{ - HWND get_window(); - void set_title(std::string title); - void set_size(int width, int height); - - enum console_type - { - con_type_error = 1, - con_type_warning = 3, - con_type_info = 7 - }; - - void print(int type, const char* fmt, ...); - - template - void error(const char* fmt, Args&&... args) - { - print(con_type_error, fmt, std::forward(args)...); - } - - template - void warn(const char* fmt, Args&&... args) - { - print(con_type_warning, fmt, std::forward(args)...); - } - - template - void info(const char* fmt, Args&&... args) - { - print(con_type_info, fmt, std::forward(args)...); - } -} \ No newline at end of file diff --git a/src/client/component/dedicated.cpp b/src/client/component/dedicated.cpp deleted file mode 100644 index 8de5e9ac..00000000 --- a/src/client/component/dedicated.cpp +++ /dev/null @@ -1,333 +0,0 @@ -#include -#include "loader/component_loader.hpp" -#include "scheduler.hpp" -#include "server_list.hpp" -#include "network.hpp" -#include "command.hpp" -#include "game/game.hpp" -#include "game/dvars.hpp" -#include "dvars.hpp" -#include "console.hpp" - -#include -#include - -namespace dedicated -{ - namespace - { - utils::hook::detour gscr_set_dynamic_dvar_hook; - utils::hook::detour com_quit_f_hook; - - void init_dedicated_server() - { - static bool initialized = false; - if (initialized) return; - initialized = true; - - // R_LoadGraphicsAssets - utils::hook::invoke(0x1405DF4B0); - } - - void send_heartbeat() - { - auto* const dvar = game::Dvar_FindVar("sv_lanOnly"); - if (dvar && dvar->current.enabled) - { - return; - } - - game::netadr_s target{}; - if (server_list::get_master_server(target)) - { - network::send(target, "heartbeat", "H1"); - } - } - - std::vector& get_startup_command_queue() - { - static std::vector startup_command_queue; - return startup_command_queue; - } - - void execute_startup_command(int client, int /*controllerIndex*/, const char* command) - { - if (game::Live_SyncOnlineDataFlags(0) == 0) - { - game::Cbuf_ExecuteBufferInternal(0, 0, command, game::Cmd_ExecuteSingleCommand); - } - else - { - get_startup_command_queue().emplace_back(command); - } - } - - void execute_startup_command_queue() - { - const auto queue = get_startup_command_queue(); - get_startup_command_queue().clear(); - - for (const auto& command : queue) - { - game::Cbuf_ExecuteBufferInternal(0, 0, command.data(), game::Cmd_ExecuteSingleCommand); - } - } - - std::vector& get_console_command_queue() - { - static std::vector console_command_queue; - return console_command_queue; - } - - void execute_console_command(const int client, const char* command) - { - if (game::Live_SyncOnlineDataFlags(0) == 0) - { - game::Cbuf_AddText(client, command); - game::Cbuf_AddText(client, "\n"); - } - else - { - get_console_command_queue().emplace_back(command); - } - } - - void execute_console_command_queue() - { - const auto queue = get_console_command_queue(); - get_console_command_queue().clear(); - - for (const auto& command : queue) - { - game::Cbuf_AddText(0, command.data()); - game::Cbuf_AddText(0, "\n"); - } - } - - void sync_gpu_stub() - { - std::this_thread::sleep_for(1ms); - } - - game::dvar_t* gscr_set_dynamic_dvar() - { - /* - auto s = game::Scr_GetString(0); - auto* dvar = game::Dvar_FindVar(s); - - if (dvar && !strncmp("scr_", dvar->name, 4)) - { - return dvar; - } - */ - - return gscr_set_dynamic_dvar_hook.invoke(); - } - - void kill_server() - { - for (auto i = 0; i < *game::mp::svs_numclients; ++i) - { - if (game::mp::svs_clients[i].header.state >= 3) - { - game::SV_GameSendServerCommand(i, game::SV_CMD_CAN_IGNORE, - utils::string::va("r \"%s\"", "EXE_ENDOFGAME")); - } - } - - com_quit_f_hook.invoke(); - } - - void sys_error_stub(const char* msg, ...) - { - char buffer[2048]; - - va_list ap; - va_start(ap, msg); - - vsnprintf_s(buffer, sizeof(buffer), _TRUNCATE, msg, ap); - - va_end(ap); - - scheduler::once([]() - { - command::execute("map_rotate"); - }, scheduler::main, 3s); - - game::Com_Error(game::ERR_DROP, "%s", buffer); - } - } - - void initialize() - { - command::execute("exec default_xboxlive.cfg", true); - command::execute("onlinegame 1", true); - command::execute("xblive_privatematch 1", true); - } - - class component final : public component_interface - { - public: - void* load_import(const std::string& library, const std::string& function) override - { - return nullptr; - } - - void post_unpack() override - { - if (!game::environment::is_dedi()) - { - return; - } - -#ifdef DEBUG - printf("Starting dedicated server\n"); -#endif - - // Register dedicated dvar - dvars::register_bool("dedicated", true, game::DVAR_FLAG_READ); - - // Add lanonly mode - dvars::register_bool("sv_lanOnly", false, game::DVAR_FLAG_NONE); - - // Disable VirtualLobby - dvars::override::register_bool("virtualLobbyEnabled", false, game::DVAR_FLAG_READ); - - // Disable r_preloadShaders - dvars::override::register_bool("r_preloadShaders", false, game::DVAR_FLAG_READ); - - // Stop crashing from sys_errors - utils::hook::jump(0x140511520, sys_error_stub); - - // Hook R_SyncGpu - utils::hook::jump(0x1405E12F0, sync_gpu_stub); - - utils::hook::jump(0x140254800, init_dedicated_server); - - // delay startup commands until the initialization is done - utils::hook::call(0x1400D72D6, execute_startup_command); - - // delay console commands until the initialization is done - utils::hook::call(0x1400D808C, execute_console_command); - utils::hook::nop(0x1400D80A4, 5); - - // patch GScr_SetDynamicDvar to behave better - gscr_set_dynamic_dvar_hook.create(0x14036B600, &gscr_set_dynamic_dvar); - - utils::hook::nop(0x1404ED90E, 5); // don't load config file - utils::hook::nop(0x140403D92, 5); // ^ - utils::hook::set(0x1400DC1D0, 0xC3); // don't save config file - utils::hook::set(0x140274710, 0xC3); // disable self-registration - utils::hook::set(0x140515890, 0xC3); // init sound system (1) - utils::hook::set(0x1406574F0, 0xC3); // init sound system (2) - utils::hook::set(0x140620D10, 0xC3); // render thread - utils::hook::set(0x14025B850, 0xC3); // called from Com_Frame, seems to do renderer stuff - utils::hook::set(0x1402507B0, 0xC3); // CL_CheckForResend, which tries to connect to the local server constantly - utils::hook::set(0x1405D5178, 0x00); // r_loadForRenderer default to 0 - utils::hook::set(0x14050C2D0, 0xC3); // recommended settings check - TODO: Check hook - utils::hook::set(0x140514C00, 0xC3); // some mixer-related function called on shutdown - utils::hook::set(0x140409830, 0xC3); // dont load ui gametype stuff - - utils::hook::nop(0x140481B06, 6); // unknown check in SV_ExecuteClientMessage - utils::hook::nop(0x140480FAC, 4); // allow first slot to be occupied - utils::hook::nop(0x14025619B, 2); // properly shut down dedicated servers - utils::hook::nop(0x14025615E, 2); // ^ - utils::hook::nop(0x1402561C0, 5); // don't shutdown renderer - - utils::hook::set(0x140091840, 0xC3); // something to do with blendShapeVertsView - utils::hook::nop(0x140659A0D, 8); // sound thing - - // (COULD NOT FIND IN H1) - // utils::hook::set(0x1404D6960, 0xC3); // cpu detection stuff? - utils::hook::set(0x1405E97F0, 0xC3); // gfx stuff during fastfile loading - utils::hook::set(0x1405E9700, 0xC3); // ^ - utils::hook::set(0x1405E9790, 0xC3); // ^ - utils::hook::set(0x1402C1180, 0xC3); // ^ - utils::hook::set(0x1405E9750, 0xC3); // ^ - utils::hook::set(0x1405AD5B0, 0xC3); // directx stuff - utils::hook::set(0x1405DB150, 0xC3); // ^ - utils::hook::set(0x140625220, 0xC3); // ^ - mutex - utils::hook::set(0x1405DB650, 0xC3); // ^ - - utils::hook::set(0x14008B5F0, 0xC3); // rendering stuff - utils::hook::set(0x1405DB8B0, 0xC3); // ^ - utils::hook::set(0x1405DB9C0, 0xC3); // ^ - utils::hook::set(0x1405DC050, 0xC3); // ^ - utils::hook::set(0x1405DCBA0, 0xC3); // ^ - utils::hook::set(0x1405DD240, 0xC3); // ^ - - // shaders - utils::hook::set(0x1400916A0, 0xC3); // ^ - utils::hook::set(0x140091610, 0xC3); // ^ - utils::hook::set(0x14061ACC0, 0xC3); // ^ - mutex - - utils::hook::set(0x140516080, 0xC3); // idk - utils::hook::set(0x1405AE5F0, 0xC3); // ^ - - utils::hook::set(0x1405E0B30, 0xC3); // R_Shutdown - utils::hook::set(0x1405AE400, 0xC3); // shutdown stuff - utils::hook::set(0x1405E0C00, 0xC3); // ^ - utils::hook::set(0x1405DFE50, 0xC3); // ^ - - // utils::hook::set(0x1404B67E0, 0xC3); // sound crashes (H1 - questionable, function looks way different) - - utils::hook::set(0x14048B660, 0xC3); // disable host migration - - utils::hook::set(0x14042B2E0, 0xC3); // render synchronization lock - utils::hook::set(0x14042B210, 0xC3); // render synchronization unlock - - utils::hook::set(0x140176D2D, 0xEB); // LUI: Unable to start the LUI system due to errors in main.lua - - utils::hook::nop(0x140506ECE, 5); // Disable sound pak file loading - utils::hook::nop(0x140506ED6, 2); // ^ - utils::hook::set(0x1402C5910, 0xC3); // Disable image pak file loading - - // Reduce min required memory - utils::hook::set(0x14050C717, 0x80000000); - - utils::hook::set(0x1402BF7F0, 0xC3); // some loop - utils::hook::set(0x14007E150, 0xC3); // related to shader caching / techsets / fastfiles - - // initialize the game after onlinedataflags is 32 (workaround) - scheduler::schedule([=]() - { - if (game::Live_SyncOnlineDataFlags(0) == 32 && game::Sys_IsDatabaseReady2()) - { - scheduler::once([]() - { - command::execute("xstartprivateparty", true); - command::execute("disconnect", true); // 32 -> 0 - }, scheduler::pipeline::main, 1s); - return scheduler::cond_end; - } - - return scheduler::cond_continue; - }, scheduler::pipeline::main, 1s); - - scheduler::on_game_initialized([]() - { - initialize(); - - console::info("==================================\n"); - console::info("Server started!\n"); - console::info("==================================\n"); - - // remove disconnect command - game::Cmd_RemoveCommand("disconnect"); - - execute_startup_command_queue(); - execute_console_command_queue(); - - // Send heartbeat to dpmaster - scheduler::once(send_heartbeat, scheduler::pipeline::server); - scheduler::loop(send_heartbeat, scheduler::pipeline::server, 10min); - command::add("heartbeat", send_heartbeat); - }, scheduler::pipeline::main, 1s); - - command::add("killserver", kill_server); - com_quit_f_hook.create(0x1400DA640, &kill_server); - } - }; -} - -REGISTER_COMPONENT(dedicated::component) \ No newline at end of file diff --git a/src/client/component/dedicated_info.cpp b/src/client/component/dedicated_info.cpp deleted file mode 100644 index 55973193..00000000 --- a/src/client/component/dedicated_info.cpp +++ /dev/null @@ -1,65 +0,0 @@ -#include -#include "console.hpp" -#include "loader/component_loader.hpp" -#include "game/game.hpp" -#include "scheduler.hpp" -#include - -namespace dedicated_info -{ - class component final : public component_interface - { - public: - void post_unpack() override - { - if (!game::environment::is_dedi()) - { - return; - } - - scheduler::loop([]() - { - auto* sv_running = game::Dvar_FindVar("sv_running"); - if (!sv_running || !sv_running->current.enabled) - { - console::set_title("H1-Mod Dedicated Server"); - return; - } - - auto* const sv_hostname = game::Dvar_FindVar("sv_hostname"); - auto* const sv_maxclients = game::Dvar_FindVar("sv_maxclients"); - auto* const mapname = game::Dvar_FindVar("mapname"); - - auto bot_count = 0; - auto client_count = 0; - - for (auto i = 0; i < sv_maxclients->current.integer; i++) - { - auto* client = &game::mp::svs_clients[i]; - auto* self = &game::mp::g_entities[i]; - - if (client->header.state >= 1 && self && self->client) - { - client_count++; - if (game::SV_BotIsBot(i)) - { - ++bot_count; - } - } - } - - std::string cleaned_hostname; - cleaned_hostname.resize(static_cast(strlen(sv_hostname->current.string) + 1)); - - utils::string::strip(sv_hostname->current.string, cleaned_hostname.data(), - static_cast(strlen(sv_hostname->current.string)) + 1); - - console::set_title(utils::string::va("%s on %s [%d/%d] (%d)", cleaned_hostname.data(), - mapname->current.string, client_count, - sv_maxclients->current.integer, bot_count)); - }, scheduler::pipeline::main, 1s); - } - }; -} - -REGISTER_COMPONENT(dedicated_info::component) \ No newline at end of file diff --git a/src/client/component/demonware.cpp b/src/client/component/demonware.cpp deleted file mode 100644 index 4cb3362c..00000000 --- a/src/client/component/demonware.cpp +++ /dev/null @@ -1,604 +0,0 @@ -#include -#include "loader/component_loader.hpp" - -#include -#include - -#include "game/game.hpp" -#include "game/demonware/servers/lobby_server.hpp" -#include "game/demonware/servers/auth3_server.hpp" -#include "game/demonware/servers/stun_server.hpp" -#include "game/demonware/servers/umbrella_server.hpp" -#include "game/demonware/server_registry.hpp" -#include - -#define TCP_BLOCKING true -#define UDP_BLOCKING false - -namespace demonware -{ - namespace - { - volatile bool exit_server; - std::thread server_thread; - utils::concurrency::container> blocking_sockets; - utils::concurrency::container> socket_map; - server_registry tcp_servers; - server_registry udp_servers; - - tcp_server* find_server(const SOCKET socket) - { - return socket_map.access([&](const std::unordered_map& map) -> tcp_server* - { - const auto entry = map.find(socket); - if (entry == map.end()) - { - return nullptr; - } - - return entry->second; - }); - } - - bool socket_link(const SOCKET socket, const uint32_t address) - { - auto* server = tcp_servers.find(address); - if (!server) - { - return false; - } - - socket_map.access([&](std::unordered_map& map) - { - map[socket] = server; - }); - - return true; - } - - void socket_unlink(const SOCKET socket) - { - socket_map.access([&](std::unordered_map& map) - { - const auto entry = map.find(socket); - if (entry != map.end()) - { - map.erase(entry); - } - }); - } - - bool is_socket_blocking(const SOCKET socket, const bool def) - { - return blocking_sockets.access([&](std::unordered_map& map) - { - const auto entry = map.find(socket); - if (entry == map.end()) - { - return def; - } - - return entry->second; - }); - } - - void remove_blocking_socket(const SOCKET socket) - { - blocking_sockets.access([&](std::unordered_map& map) - { - const auto entry = map.find(socket); - if (entry != map.end()) - { - map.erase(entry); - } - }); - } - - void add_blocking_socket(const SOCKET socket, const bool block) - { - blocking_sockets.access([&](std::unordered_map& map) - { - map[socket] = block; - }); - } - - void server_main() - { - exit_server = false; - - while (!exit_server) - { - tcp_servers.frame(); - udp_servers.frame(); - std::this_thread::sleep_for(50ms); - } - } - - namespace io - { - int getaddrinfo_stub(const char* name, const char* service, - const addrinfo* hints, addrinfo** res) - { -#ifdef DEBUG - printf("[ network ]: [getaddrinfo]: \"%s\" \"%s\"\n", name, service); -#endif - - base_server* server = tcp_servers.find(name); - if (!server) - { - server = udp_servers.find(name); - } - - if (!server) - { - return getaddrinfo(name, service, hints, res); - } - - const auto address = utils::memory::get_allocator()->allocate(); - const auto ai = utils::memory::get_allocator()->allocate(); - - auto in_addr = reinterpret_cast(address); - in_addr->sin_addr.s_addr = server->get_address(); - in_addr->sin_family = AF_INET; - - ai->ai_family = AF_INET; - ai->ai_socktype = SOCK_STREAM; - ai->ai_addr = address; - ai->ai_addrlen = sizeof(sockaddr); - ai->ai_next = nullptr; - ai->ai_flags = 0; - ai->ai_protocol = 0; - ai->ai_canonname = const_cast(name); - - *res = ai; - - return 0; - } - - void freeaddrinfo_stub(addrinfo* ai) - { - if (!utils::memory::get_allocator()->find(ai)) - { - return freeaddrinfo(ai); - } - - utils::memory::get_allocator()->free(ai->ai_addr); - utils::memory::get_allocator()->free(ai); - } - - int getpeername_stub(const SOCKET s, sockaddr* addr, socklen_t* addrlen) - { - auto* server = find_server(s); - - if (server) - { - auto in_addr = reinterpret_cast(addr); - in_addr->sin_addr.s_addr = server->get_address(); - in_addr->sin_family = AF_INET; - *addrlen = sizeof(sockaddr); - - return 0; - } - - return getpeername(s, addr, addrlen); - } - - int getsockname_stub(const SOCKET s, sockaddr* addr, socklen_t* addrlen) - { - auto* server = find_server(s); - - if (server) - { - auto in_addr = reinterpret_cast(addr); - in_addr->sin_addr.s_addr = server->get_address(); - in_addr->sin_family = AF_INET; - *addrlen = sizeof(sockaddr); - - return 0; - } - - return getsockname(s, addr, addrlen); - } - - hostent* gethostbyname_stub(const char* name) - { -#ifdef DEBUG - printf("[ network ]: [gethostbyname]: \"%s\"\n", name); -#endif - - base_server* server = tcp_servers.find(name); - if (!server) - { - server = udp_servers.find(name); - } - - if (!server) - { -#pragma warning(push) -#pragma warning(disable: 4996) - return gethostbyname(name); -#pragma warning(pop) - } - - static thread_local in_addr address{}; - address.s_addr = server->get_address(); - - static thread_local in_addr* addr_list[2]{}; - addr_list[0] = &address; - addr_list[1] = nullptr; - - static thread_local hostent host{}; - host.h_name = const_cast(name); - host.h_aliases = nullptr; - host.h_addrtype = AF_INET; - host.h_length = sizeof(in_addr); - host.h_addr_list = reinterpret_cast(addr_list); - - return &host; - } - - int connect_stub(const SOCKET s, const struct sockaddr* addr, const int len) - { - if (len == sizeof(sockaddr_in)) - { - const auto* in_addr = reinterpret_cast(addr); - if (socket_link(s, in_addr->sin_addr.s_addr)) return 0; - } - - return connect(s, addr, len); - } - - int closesocket_stub(const SOCKET s) - { - remove_blocking_socket(s); - socket_unlink(s); - - return closesocket(s); - } - - int send_stub(const SOCKET s, const char* buf, const int len, const int flags) - { - auto* server = find_server(s); - - if (server) - { - server->handle_input(buf, len); - return len; - } - - return send(s, buf, len, flags); - } - - int recv_stub(const SOCKET s, char* buf, const int len, const int flags) - { - auto* server = find_server(s); - - if (server) - { - if (server->pending_data()) - { - return static_cast(server->handle_output(buf, len)); - } - else - { - WSASetLastError(WSAEWOULDBLOCK); - return -1; - } - } - - return recv(s, buf, len, flags); - } - - int sendto_stub(const SOCKET s, const char* buf, const int len, const int flags, const sockaddr* to, - const int tolen) - { - const auto* in_addr = reinterpret_cast(to); - auto* server = udp_servers.find(in_addr->sin_addr.s_addr); - - if (server) - { - server->handle_input(buf, len, {s, to, tolen}); - return len; - } - - return sendto(s, buf, len, flags, to, tolen); - } - - int recvfrom_stub(const SOCKET s, char* buf, const int len, const int flags, struct sockaddr* from, - int* fromlen) - { - // Not supported yet - if (is_socket_blocking(s, UDP_BLOCKING)) - { - return recvfrom(s, buf, len, flags, from, fromlen); - } - - size_t result = 0; - udp_servers.for_each([&](udp_server& server) - { - if (server.pending_data(s)) - { - result = server.handle_output( - s, buf, static_cast(len), from, fromlen); - } - }); - - if (result) - { - return static_cast(result); - } - - return recvfrom(s, buf, len, flags, from, fromlen); - } - - int select_stub(const int nfds, fd_set* readfds, fd_set* writefds, fd_set* exceptfds, - struct timeval* timeout) - { - if (exit_server) - { - return select(nfds, readfds, writefds, exceptfds, timeout); - } - - auto result = 0; - std::vector read_sockets; - std::vector write_sockets; - - socket_map.access([&](std::unordered_map& sockets) - { - for (auto& s : sockets) - { - if (readfds) - { - if (FD_ISSET(s.first, readfds)) - { - if (s.second->pending_data()) - { - read_sockets.push_back(s.first); - FD_CLR(s.first, readfds); - } - } - } - - if (writefds) - { - if (FD_ISSET(s.first, writefds)) - { - write_sockets.push_back(s.first); - FD_CLR(s.first, writefds); - } - } - - if (exceptfds) - { - if (FD_ISSET(s.first, exceptfds)) - { - FD_CLR(s.first, exceptfds); - } - } - } - }); - - if ((!readfds || readfds->fd_count == 0) && (!writefds || writefds->fd_count == 0)) - { - timeout->tv_sec = 0; - timeout->tv_usec = 0; - } - - result = select(nfds, readfds, writefds, exceptfds, timeout); - if (result < 0) result = 0; - - for (const auto& socket : read_sockets) - { - if (readfds) - { - FD_SET(socket, readfds); - result++; - } - } - - for (const auto& socket : write_sockets) - { - if (writefds) - { - FD_SET(socket, writefds); - result++; - } - } - - return result; - } - - int ioctlsocket_stub(const SOCKET s, const long cmd, u_long* argp) - { - if (static_cast(cmd) == (FIONBIO)) - { - add_blocking_socket(s, *argp == 0); - } - - return ioctlsocket(s, cmd, argp); - } - - BOOL internet_get_connected_state_stub(LPDWORD, DWORD) - { - // Allow offline play - return TRUE; - } - } - - void bd_logger_stub(char* a1, void* a2, void* a3, void* a4, const char* function, ...) - { - - } - -#ifdef DEBUG - void a(unsigned int n) - { - printf("bdAuth: Auth task failed with HTTP code [%u]\n", n); - } - - void b(unsigned int n) - { - printf("bdAuth: Decoded client ticket of unexpected size [%u]\n", n); - } - - void c(unsigned int n) - { - printf("bdAuth: Decoded server ticket of unexpected size [%u]\n", n); - } - - void d() - { - printf("bdAuth: Auth ticket magic number mismatch\n"); - } - - void e() - { - printf("bdAuth: Cross Authentication completed\n"); - } - - void f() - { - printf("bdAuth: Auth task reply contains invalid data / format\n"); - } - - void g(unsigned int n) - { - printf("bdAuth: Auth task returned with error code [%u]\n", n); - } - - void h(unsigned int n) - { - printf("bdAuth: Invalid or No Task ID [%u] in Auth reply\n", n); - } - - void i() - { - printf("bdAuth: Received reply from DemonWare Auth server\n"); - } - - void l() - { - printf("bdAuth: Unknown error\n"); - } -#endif - } - - class component final : public component_interface - { - public: - component() - { - udp_servers.create("phoenix.stun.us.demonware.net"); - udp_servers.create("phoenix.stun.eu.demonware.net"); - udp_servers.create("phoenix.stun.jp.demonware.net"); - udp_servers.create("phoenix.stun.au.demonware.net"); - - udp_servers.create("stun.us.demonware.net"); - udp_servers.create("stun.eu.demonware.net"); - udp_servers.create("stun.jp.demonware.net"); - udp_servers.create("stun.au.demonware.net"); - - tcp_servers.create("mwr-pc-steam-auth3.prod.demonware.net"); - tcp_servers.create("mwr-pc-steam-lobby.prod.demonware.net"); - tcp_servers.create("prod.umbrella.demonware.net"); - } - - void post_load() override - { - server_thread = utils::thread::create_named_thread("Demonware", server_main); - } - - void* load_import(const std::string& library, const std::string& function) override - { - if (library == "WS2_32.dll") - { - if (function == "#3") return io::closesocket_stub; - if (function == "#4") return io::connect_stub; - if (function == "#5") return io::getpeername_stub; - if (function == "#6") return io::getsockname_stub; - if (function == "#10") return io::ioctlsocket_stub; - if (function == "#16") return io::recv_stub; - if (function == "#17") return io::recvfrom_stub; - if (function == "#18") return io::select_stub; - if (function == "#19") return io::send_stub; - if (function == "#20") return io::sendto_stub; - if (function == "#52") return io::gethostbyname_stub; - if (function == "getaddrinfo") return io::getaddrinfo_stub; - if (function == "freeaddrinfo") return io::freeaddrinfo_stub; - } - - if (function == "InternetGetConnectedState") - { - return io::internet_get_connected_state_stub; - } - - return nullptr; - } - - void post_unpack() override - { - /* - mwr has upgraded some networking methods and the gethostbyname import from winsock library is no longer used - gethostbyname has been replaced with getaddrinfo - btw, still you can't get online.. - */ - utils::hook::jump(SELECT_VALUE(0x140610320, 0x1407400B0), bd_logger_stub); // H1MP64(1.4) - - if (game::environment::is_sp()) - { - utils::hook::set(0x1405FCA00, 0xC3); // bdAuthSteam H1(1.4) - utils::hook::set(0x140333A00, 0xC3); // dwNet H1(1.4) - return; - } - - utils::hook::set(0x140715039, 0x0); // CURLOPT_SSL_VERIFYPEER H1MP64(1.4) - utils::hook::set(0x140715025, 0xAF); // CURLOPT_SSL_VERIFYHOST H1MP64(1.4) - utils::hook::set(0x14095433C, 0x0); // HTTPS -> HTTP [MWR OK][S1X: 0x14088D0E8] - - //HTTPS -> HTTP - utils::hook::inject(0x14006DDA9, "http://prod.umbrella.demonware.net/v1.0/"); // ---> [H1MP1.4 - S1X: 0x14003852E] - utils::hook::inject(0x14006E11C, "http://prod.umbrella.demonware.net/v1.0/"); // ---> [H1MP1.4 - S1X: 0x14003884F] - utils::hook::inject(0x14006E2FB, "http://prod.umbrella.demonware.net/v1.0/"); // ---> [H1MP1.4 - S1X: 0x140038A07] - utils::hook::inject(0x14006E9A9, "http://prod.uno.demonware.net/v1.0/"); - utils::hook::inject(0x14006ED49, "http://prod.uno.demonware.net/v1.0/"); - utils::hook::inject(0x140728170, "http://%s:%d/auth/"); - - utils::hook::set(0x14047F290, 0xC3); // SV_SendMatchData H1MP64(1.4) - utils::hook::set(0x140598990, 0xC3); // Live_CheckForFullDisconnect H1MP64(1.4) - -#ifdef DEBUG - // yes - utils::hook::call(0x140727BEB, l); - utils::hook::call(0x140727AFC, i); - utils::hook::call(0x140727E49, h); - utils::hook::call(0x140727E30, g); - utils::hook::call(0x140727E37, f); - utils::hook::call(0x140727DF2, e); - utils::hook::call(0x140727DF9, d); - utils::hook::call(0x140727CFC, c); - utils::hook::call(0x140727C82, b); - utils::hook::call(0x140727E6A, a); -#endif - // Checks X-Signature header or something - utils::hook::set(0x140728380, 0xC301B0); - // Checks extended_data and extra_data in json object - utils::hook::set(0x140728E90, 0xC301B0); - // Update check - utils::hook::set(0x1403A5390, 0xC301B0); - - // Remove some while loop in demonware that freezes the rendering for a few secs at launch - utils::hook::nop(0x14057DBC5, 5); - } - - void pre_destroy() override - { - exit_server = true; - if (server_thread.joinable()) - { - server_thread.join(); - } - } - }; -} - -REGISTER_COMPONENT(demonware::component) diff --git a/src/client/component/demonware.hpp b/src/client/component/demonware.hpp deleted file mode 100644 index d26d1ccd..00000000 --- a/src/client/component/demonware.hpp +++ /dev/null @@ -1,6 +0,0 @@ -#pragma once - -namespace demonware -{ - -} \ No newline at end of file diff --git a/src/client/component/discord.cpp b/src/client/component/discord.cpp deleted file mode 100644 index 5925a64a..00000000 --- a/src/client/component/discord.cpp +++ /dev/null @@ -1,148 +0,0 @@ -#include -#include "loader/component_loader.hpp" -#include "scheduler.hpp" -#include "game/game.hpp" - -#include "console.hpp" -#include "command.hpp" -#include "network.hpp" -#include "party.hpp" - -#include - -#include - -namespace discord -{ - namespace - { - DiscordRichPresence discord_presence; - - void update_discord() - { - Discord_RunCallbacks(); - - if (!game::CL_IsCgameInitialized() || game::VirtualLobby_Loaded()) - { - discord_presence.details = game::environment::is_sp() ? "Singleplayer" : "Multiplayer"; - discord_presence.state = "Main Menu"; - - auto firingRangeDvar = game::Dvar_FindVar("virtualLobbyInFiringRange"); - if (firingRangeDvar && firingRangeDvar->current.enabled == 1) - { - discord_presence.state = "Firing Range"; - } - - discord_presence.partySize = 0; - discord_presence.partyMax = 0; - discord_presence.startTimestamp = 0; - discord_presence.largeImageKey = game::environment::is_sp() ? "menu_singleplayer" : "menu_multiplayer"; - } - else - { - const auto map = game::Dvar_FindVar("mapname")->current.string; - const auto mapname = game::UI_SafeTranslateString(utils::string::va("PRESENCE_%s%s", (game::environment::is_sp() ? "SP_" : ""), map)); - - if (game::environment::is_mp()) - { - const auto gametype = game::UI_GetGameTypeDisplayName(game::Dvar_FindVar("g_gametype")->current.string); - - discord_presence.details = utils::string::va("%s on %s", gametype, mapname); - - char clean_hostname[0x100] = {0}; - utils::string::strip(game::Dvar_FindVar("sv_hostname")->current.string, - clean_hostname, sizeof(clean_hostname)); - auto max_clients = party::server_client_count(); - - // When true, we are in Private Match - if (game::SV_Loaded()) - { - strcpy_s(clean_hostname, "Private Match"); - max_clients = game::Dvar_FindVar("sv_maxclients")->current.integer; - } - - discord_presence.partySize = *reinterpret_cast(0x1429864C4); - discord_presence.partyMax = max_clients; - discord_presence.state = clean_hostname; - discord_presence.largeImageKey = map; - } - else if (game::environment::is_sp()) - { - discord_presence.state = ""; - discord_presence.largeImageKey = map; - discord_presence.details = mapname; - } - - if (!discord_presence.startTimestamp) - { - discord_presence.startTimestamp = std::chrono::duration_cast( - std::chrono::system_clock::now().time_since_epoch()).count(); - } - } - - Discord_UpdatePresence(&discord_presence); - } - } - - class component final : public component_interface - { - public: - void post_load() override - { - if (game::environment::is_dedi()) - { - return; - } - - DiscordEventHandlers handlers; - ZeroMemory(&handlers, sizeof(handlers)); - handlers.ready = ready; - handlers.errored = errored; - handlers.disconnected = errored; - handlers.joinGame = nullptr; - handlers.spectateGame = nullptr; - handlers.joinRequest = nullptr; - - Discord_Initialize("947125042930667530", &handlers, 1, nullptr); - - scheduler::once([]() - { - scheduler::once(update_discord, scheduler::pipeline::async); - scheduler::loop(update_discord, scheduler::pipeline::async, 5s); - }, scheduler::pipeline::main); - - initialized_ = true; - } - - void pre_destroy() override - { - if (!initialized_ || game::environment::is_dedi()) - { - return; - } - - Discord_Shutdown(); - } - - private: - bool initialized_ = false; - - static void ready(const DiscordUser* /*request*/) - { - ZeroMemory(&discord_presence, sizeof(discord_presence)); - - discord_presence.instance = 1; - - console::info("Discord: Ready\n"); - - Discord_UpdatePresence(&discord_presence); - } - - static void errored(const int error_code, const char* message) - { - console::error("Discord: Error (%i): %s\n", error_code, message); - } - }; -} - -REGISTER_COMPONENT(discord::component) \ No newline at end of file diff --git a/src/client/component/dvars.cpp b/src/client/component/dvars.cpp deleted file mode 100644 index d9c77fdf..00000000 --- a/src/client/component/dvars.cpp +++ /dev/null @@ -1,443 +0,0 @@ -#include -#include "loader/component_loader.hpp" -#include "dvars.hpp" - -#include "game/game.hpp" - -#include - -namespace dvars -{ - struct dvar_base - { - unsigned int flags{}; - }; - - struct dvar_bool : dvar_base - { - bool value{}; - }; - - struct dvar_float : dvar_base - { - float value{}; - float min{}; - float max{}; - }; - - struct dvar_vector2 : dvar_base - { - float x{}; - float y{}; - float min{}; - float max{}; - }; - - struct dvar_vector3 : dvar_base - { - - float x{}; - float y{}; - float z{}; - float min{}; - float max{}; - }; - - struct dvar_int : dvar_base - { - int value{}; - int min{}; - int max{}; - }; - - struct dvar_string : dvar_base - { - std::string value{}; - }; - - namespace - { - template - T* find_dvar(std::unordered_map& map, const std::string& name) - { - auto i = map.find(name); - if (i != map.end()) - { - return &i->second; - } - - return nullptr; - } - - template - T* find_dvar(std::unordered_map& map, const int hash) - { - for (auto i = map.begin(); i != map.end(); ++i) - { - if (game::generateHashValue(i->first.data()) == hash) - { - return &i->second; - } - } - - return nullptr; - } - - bool find_dvar(std::unordered_set& set, const std::string& name) - { - return set.find(name) != set.end(); - } - - - bool find_dvar(std::unordered_set& set, const int hash) - { - for (auto i = set.begin(); i != set.end(); ++i) - { - if (game::generateHashValue(i->data()) == hash) - { - return true; - } - } - - return false; - } - } - - namespace disable - { - static std::unordered_set set_bool_disables; - static std::unordered_set set_float_disables; - static std::unordered_set set_int_disables; - static std::unordered_set set_string_disables; - - void set_bool(const std::string& name) - { - set_bool_disables.emplace(name); - } - - void set_float(const std::string& name) - { - set_float_disables.emplace(name); - } - - void set_int(const std::string& name) - { - set_int_disables.emplace(name); - } - - void set_string(const std::string& name) - { - set_string_disables.emplace(name); - } - } - - namespace override - { - static std::unordered_map register_bool_overrides; - static std::unordered_map register_float_overrides; - static std::unordered_map register_int_overrides; - static std::unordered_map register_string_overrides; - static std::unordered_map register_vector2_overrides; - static std::unordered_map register_vector3_overrides; - - static std::unordered_map set_bool_overrides; - static std::unordered_map set_float_overrides; - static std::unordered_map set_int_overrides; - static std::unordered_map set_string_overrides; - static std::unordered_map set_from_string_overrides; - - void register_bool(const std::string& name, const bool value, const unsigned int flags) - { - dvar_bool values; - values.value = value; - values.flags = flags; - register_bool_overrides[name] = std::move(values); - } - - void register_float(const std::string& name, const float value, const float min, const float max, - const unsigned int flags) - { - dvar_float values; - values.value = value; - values.min = min; - values.max = max; - values.flags = flags; - register_float_overrides[name] = std::move(values); - } - - void register_int(const std::string& name, const int value, const int min, const int max, - const unsigned int flags) - { - dvar_int values; - values.value = value; - values.min = min; - values.max = max; - values.flags = flags; - register_int_overrides[name] = std::move(values); - } - - void register_string(const std::string& name, const std::string& value, - const unsigned int flags) - { - dvar_string values; - values.value = value; - values.flags = flags; - register_string_overrides[name] = std::move(values); - } - - void register_vec2(const std::string& name, float x, float y, float min, float max, - const unsigned int flags) - { - dvar_vector2 values; - values.x = x; - values.y = y; - values.min = min; - values.max = max; - values.flags = flags; - register_vector2_overrides[name] = std::move(values); - } - - void register_vec3(const std::string& name, float x, float y, float z, float min, - float max, const unsigned int flags) - { - dvar_vector3 values; - values.x = x; - values.y = y; - values.z = z; - values.min = min; - values.max = max; - values.flags = flags; - register_vector3_overrides[name] = std::move(values); - } - - void set_bool(const std::string& name, const bool value) - { - set_bool_overrides[name] = value; - } - - void set_float(const std::string& name, const float value) - { - set_float_overrides[name] = value; - } - - void set_int(const std::string& name, const int value) - { - set_int_overrides[name] = value; - } - - void set_string(const std::string& name, const std::string& value) - { - set_string_overrides[name] = value; - } - - void set_from_string(const std::string& name, const std::string& value) - { - set_from_string_overrides[name] = value; - } - } - - utils::hook::detour dvar_register_bool_hook; - utils::hook::detour dvar_register_float_hook; - utils::hook::detour dvar_register_int_hook; - utils::hook::detour dvar_register_string_hook; - utils::hook::detour dvar_register_vector2_hook; - utils::hook::detour dvar_register_vector3_hook; - - utils::hook::detour dvar_set_bool_hook; - utils::hook::detour dvar_set_float_hook; - utils::hook::detour dvar_set_int_hook; - utils::hook::detour dvar_set_string_hook; - utils::hook::detour dvar_set_from_string_hook; - - game::dvar_t* dvar_register_bool(const int hash, const char* name, bool value, unsigned int flags) - { - auto* var = find_dvar(override::register_bool_overrides, hash); - if (var) - { - value = var->value; - flags = var->flags; - } - - return dvar_register_bool_hook.invoke(hash, name, value, flags); - } - - game::dvar_t* dvar_register_float(const int hash, const char* name, float value, float min, float max, unsigned int flags) - { - auto* var = find_dvar(override::register_float_overrides, hash); - if (var) - { - value = var->value; - min = var->min; - max = var->max; - flags = var->flags; - } - - return dvar_register_float_hook.invoke(hash, name, value, min, max, flags); - } - - game::dvar_t* dvar_register_int(const int hash, const char* name, int value, int min, int max, unsigned int flags) - { - auto* var = find_dvar(override::register_int_overrides, hash); - if (var) - { - value = var->value; - min = var->min; - max = var->max; - flags = var->flags; - } - - return dvar_register_int_hook.invoke(hash, name, value, min, max, flags); - } - - game::dvar_t* dvar_register_string(const int hash, const char* name, const char* value, unsigned int flags) - { - auto* var = find_dvar(override::register_string_overrides, hash); - if (var) - { - value = var->value.data(); - flags = var->flags; - } - - return dvar_register_string_hook.invoke(hash, name, value, flags); - } - - game::dvar_t* dvar_register_vector2(const int hash, const char* name, float x, float y, float min, float max, - unsigned int flags) - { - auto* var = find_dvar(override::register_vector2_overrides, hash); - if (var) - { - x = var->x; - y = var->y; - min = var->min; - max = var->max; - flags = var->flags; - } - - return dvar_register_vector2_hook.invoke(hash, name, x, y, min, max, flags); - } - - game::dvar_t* dvar_register_vector3(const int hash, const char* name, float x, float y, float z, float min, - float max, unsigned int flags) - { - auto* var = find_dvar(override::register_vector3_overrides, hash); - if (var) - { - x = var->x; - y = var->y; - z = var->z; - min = var->min; - max = var->max; - flags = var->flags; - } - - return dvar_register_vector3_hook.invoke(hash, name, x, y, z, min, max, flags); - } - - void dvar_set_bool(game::dvar_t* dvar, bool boolean) - { - const auto disabled = find_dvar(disable::set_bool_disables, dvar->hash); - if (disabled) - { - return; - } - - auto* var = find_dvar(override::set_bool_overrides, dvar->hash); - if (var) - { - boolean = *var; - } - - return dvar_set_bool_hook.invoke(dvar, boolean); - } - - void dvar_set_float(game::dvar_t* dvar, float fl) - { - const auto disabled = find_dvar(disable::set_float_disables, dvar->hash); - if (disabled) - { - return; - } - - auto* var = find_dvar(override::set_float_overrides, dvar->hash); - if (var) - { - fl = *var; - } - - return dvar_set_float_hook.invoke(dvar, fl); - } - - void dvar_set_int(game::dvar_t* dvar, int integer) - { - const auto disabled = find_dvar(disable::set_int_disables, dvar->hash); - if (disabled) - { - return; - } - - auto* var = find_dvar(override::set_int_overrides, dvar->hash); - if (var) - { - integer = *var; - } - - return dvar_set_int_hook.invoke(dvar, integer); - } - - void dvar_set_string(game::dvar_t* dvar, const char* string) - { - const auto disabled = find_dvar(disable::set_string_disables, dvar->hash); - if (disabled) - { - return; - } - - auto* var = find_dvar(override::set_string_overrides, dvar->hash); - if (var) - { - string = var->data(); - } - - return dvar_set_string_hook.invoke(dvar, string); - } - - void dvar_set_from_string(game::dvar_t* dvar, const char* string, game::DvarSetSource source) - { - const auto disabled = find_dvar(disable::set_string_disables, dvar->hash); - if (disabled) - { - return; - } - - auto* var = find_dvar(override::set_from_string_overrides, dvar->hash); - if (var) - { - string = var->data(); - } - - return dvar_set_from_string_hook.invoke(dvar, string, source); - } - - class component final : public component_interface - { - public: - void post_unpack() override - { - dvar_register_bool_hook.create(SELECT_VALUE(0x1403C47E0, 0x1404FA540), &dvar_register_bool); - dvar_register_float_hook.create(SELECT_VALUE(0x1403C4BB0, 0x1404FA910), &dvar_register_float); - dvar_register_int_hook.create(SELECT_VALUE(0x1403C4CC0, 0x1404FAA20), &dvar_register_int); - dvar_register_string_hook.create(SELECT_VALUE(0x1403C4DA0, 0x1404FAB00), &dvar_register_string); - dvar_register_vector2_hook.create(SELECT_VALUE(0x1403C4E80, 0x1404FABE0), &dvar_register_vector2); - dvar_register_vector3_hook.create(SELECT_VALUE(0x1403C4FC0, 0x1404FACE0), &dvar_register_vector3); - - dvar_set_bool_hook.create(SELECT_VALUE(0x1403C7020, 0x1404FCDF0), &dvar_set_bool); - dvar_set_float_hook.create(SELECT_VALUE(0x1403C7420, 0x1404FD360), &dvar_set_float); - dvar_set_int_hook.create(SELECT_VALUE(0x1403C76C0, 0x1404FD5E0), &dvar_set_int); - dvar_set_string_hook.create(SELECT_VALUE(0x1403C7900, 0x1404FD8D0), &dvar_set_string); - dvar_set_from_string_hook.create(SELECT_VALUE(0x1403C7620, 0x1404FD520), &dvar_set_from_string); - } - }; -} - -REGISTER_COMPONENT(dvars::component) diff --git a/src/client/component/dvars.hpp b/src/client/component/dvars.hpp deleted file mode 100644 index 66d6912d..00000000 --- a/src/client/component/dvars.hpp +++ /dev/null @@ -1,28 +0,0 @@ -#pragma once - -namespace dvars -{ - namespace disable - { - void set_bool(const std::string& name); - void set_float(const std::string& name); - void set_int(const std::string& name); - void set_string(const std::string& name); - } - - namespace override - { - void register_bool(const std::string& name, bool value, const unsigned int flags); - void register_float(const std::string& name, float value, float min, float max, const unsigned int flags); - void register_int(const std::string& name, int value, int min, int max, const unsigned int flags); - void register_string(const std::string& name, const std::string& value, const unsigned int flags); - void register_vec2(const std::string& name, float x, float y, float min, float max, const unsigned int flags); - void register_vec3(const std::string& name, float x, float y, float z, float min, float max, const unsigned int flags); - - void set_bool(const std::string& name, bool boolean); - void set_float(const std::string& name, float fl); - void set_int(const std::string& name, int integer); - void set_string(const std::string& name, const std::string& string); - void set_from_string(const std::string& name, const std::string& value); - } -} diff --git a/src/client/component/exception.cpp b/src/client/component/exception.cpp deleted file mode 100644 index 028bb238..00000000 --- a/src/client/component/exception.cpp +++ /dev/null @@ -1,261 +0,0 @@ -#include -#include "loader/component_loader.hpp" -#include "system_check.hpp" -#include "scheduler.hpp" - -#include "game/game.hpp" - -#include -#include -#include -#include -#include - -#include - -#include - -#include "game/dvars.hpp" - -namespace exception -{ - namespace - { - thread_local struct - { - DWORD code = 0; - PVOID address = nullptr; - } exception_data; - - struct - { - std::chrono::time_point last_recovery{}; - std::atomic recovery_counts = {0}; - } recovery_data; - - bool is_game_thread() - { - static std::vector allowed_threads = - { - game::THREAD_CONTEXT_MAIN, - }; - - const auto self_id = GetCurrentThreadId(); - for (const auto& index : allowed_threads) - { - if (game::threadIds[index] == self_id) - { - return true; - } - } - - return false; - } - - bool is_exception_interval_too_short() - { - const auto delta = std::chrono::high_resolution_clock::now() - recovery_data.last_recovery; - return delta < 1min; - } - - bool too_many_exceptions_occured() - { - return recovery_data.recovery_counts >= 3; - } - - volatile bool& is_initialized() - { - static volatile bool initialized = false; - return initialized; - } - - bool is_recoverable() - { - return is_initialized() - && is_game_thread() - && !is_exception_interval_too_short() - && !too_many_exceptions_occured(); - } - - void show_mouse_cursor() - { - while (ShowCursor(TRUE) < 0); - } - - void display_error_dialog() - { - std::string error_str = utils::string::va("Fatal error (0x%08X) at 0x%p.\n" - "A minidump has been written.\n\n", - exception_data.code, exception_data.address); - - if (!system_check::is_valid()) - { - error_str += "Make sure to get supported game files to avoid such crashes!"; - } - else - { - error_str += "Make sure to update your graphics card drivers and install operating system updates!"; - } - - utils::thread::suspend_other_threads(); - show_mouse_cursor(); - - MessageBoxA(nullptr, error_str.data(), "H1-Mod ERROR", MB_ICONERROR); - TerminateProcess(GetCurrentProcess(), exception_data.code); - } - - void reset_state() - { - if (dvars::cg_legacyCrashHandling && dvars::cg_legacyCrashHandling->current.enabled) - { - display_error_dialog(); - } - - // TODO: Add a limit for dedi restarts - if (game::environment::is_dedi()) - { - utils::nt::relaunch_self(); - utils::nt::terminate(exception_data.code); - } - - if (is_recoverable()) - { - recovery_data.last_recovery = std::chrono::high_resolution_clock::now(); - ++recovery_data.recovery_counts; - - game::Com_Error(game::ERR_DROP, "Fatal error (0x%08X) at 0x%p.\nA minidump has been written.\n\n" - "H1-Mod has tried to recover your game, but it might not run stable anymore.\n\n" - "Make sure to update your graphics card drivers and install operating system updates!\n" - "Closing or restarting Steam might also help.", - exception_data.code, exception_data.address); - } - else - { - display_error_dialog(); - } - } - - size_t get_reset_state_stub() - { - static auto* stub = utils::hook::assemble([](utils::hook::assembler& a) - { - a.sub(rsp, 0x10); - a.or_(rsp, 0x8); - a.jmp(reset_state); - }); - - return reinterpret_cast(stub); - } - - std::string get_timestamp() - { - tm ltime{}; - char timestamp[MAX_PATH] = {0}; - const auto time = _time64(nullptr); - - _localtime64_s(<ime, &time); - strftime(timestamp, sizeof(timestamp) - 1, "%Y-%m-%d-%H-%M-%S", <ime); - - return timestamp; - } - - std::string generate_crash_info(const LPEXCEPTION_POINTERS exceptioninfo) - { - std::string info{}; - const auto line = [&info](const std::string& text) - { - info.append(text); - info.append("\r\n"); - }; - - line("H1-Mod Crash Dump"); - line(""); - line("Version: "s + VERSION); - line("Environment: "s + game::environment::get_string()); - line("Timestamp: "s + get_timestamp()); - line("Clean game: "s + (system_check::is_valid() ? "Yes" : "No")); - line(utils::string::va("Exception: 0x%08X", exceptioninfo->ExceptionRecord->ExceptionCode)); - line(utils::string::va("Address: 0x%llX", exceptioninfo->ExceptionRecord->ExceptionAddress)); - -#pragma warning(push) -#pragma warning(disable: 4996) - OSVERSIONINFOEXA version_info; - ZeroMemory(&version_info, sizeof(version_info)); - version_info.dwOSVersionInfoSize = sizeof(version_info); - GetVersionExA(reinterpret_cast(&version_info)); -#pragma warning(pop) - - line(utils::string::va("OS Version: %u.%u", version_info.dwMajorVersion, version_info.dwMinorVersion)); - - return info; - } - - void write_minidump(const LPEXCEPTION_POINTERS exceptioninfo) - { - const std::string crash_name = utils::string::va("minidumps/h1-mod-crash-%d-%s.zip", - game::environment::get_real_mode(), - get_timestamp().data()); - - utils::compression::zip::archive zip_file{}; - zip_file.add("crash.dmp", create_minidump(exceptioninfo)); - zip_file.add("info.txt", generate_crash_info(exceptioninfo)); - zip_file.write(crash_name, "H1-Mod Crash Dump"); - } - - bool is_harmless_error(const LPEXCEPTION_POINTERS exceptioninfo) - { - const auto code = exceptioninfo->ExceptionRecord->ExceptionCode; - return code == STATUS_INTEGER_OVERFLOW || code == STATUS_FLOAT_OVERFLOW || code == STATUS_SINGLE_STEP; - } - - LONG WINAPI exception_filter(const LPEXCEPTION_POINTERS exceptioninfo) - { - if (is_harmless_error(exceptioninfo)) - { - return EXCEPTION_CONTINUE_EXECUTION; - } - - write_minidump(exceptioninfo); - - exception_data.code = exceptioninfo->ExceptionRecord->ExceptionCode; - exception_data.address = exceptioninfo->ExceptionRecord->ExceptionAddress; - exceptioninfo->ContextRecord->Rip = get_reset_state_stub(); - - return EXCEPTION_CONTINUE_EXECUTION; - } - - LPTOP_LEVEL_EXCEPTION_FILTER WINAPI set_unhandled_exception_filter_stub(LPTOP_LEVEL_EXCEPTION_FILTER) - { - // Don't register anything here... - return &exception_filter; - } - } - - class component final : public component_interface - { - public: - component() - { - SetUnhandledExceptionFilter(exception_filter); - } - - void post_load() override - { - SetUnhandledExceptionFilter(exception_filter); - utils::hook::jump(SetUnhandledExceptionFilter, set_unhandled_exception_filter_stub, true); - - scheduler::on_game_initialized([]() - { - is_initialized() = true; - }); - } - - void post_unpack() override - { - dvars::cg_legacyCrashHandling = dvars::register_bool("cg_legacyCrashHandling", - false, game::DVAR_FLAG_SAVED, true); - } - }; -} - -REGISTER_COMPONENT(exception::component) diff --git a/src/client/component/fastfiles.cpp b/src/client/component/fastfiles.cpp deleted file mode 100644 index d4eda37f..00000000 --- a/src/client/component/fastfiles.cpp +++ /dev/null @@ -1,49 +0,0 @@ -#include -#include "loader/component_loader.hpp" -#include "fastfiles.hpp" - -#include "command.hpp" -#include "console.hpp" - -#include -#include - -namespace fastfiles -{ - static utils::concurrency::container current_fastfile; - - namespace - { - utils::hook::detour db_try_load_x_file_internal_hook; - - void db_try_load_x_file_internal(const char* zone_name, const int flags) - { - printf("Loading fastfile %s\n", zone_name); - current_fastfile.access([&](std::string& fastfile) - { - fastfile = zone_name; - }); - db_try_load_x_file_internal_hook.invoke(zone_name, flags); - } - } - - std::string get_current_fastfile() - { - return current_fastfile.access([&](std::string& fastfile) - { - return fastfile; - }); - } - - class component final : public component_interface - { - public: - void post_unpack() override - { - db_try_load_x_file_internal_hook.create( - SELECT_VALUE(0x1401CDDD0, 0x1402BFFE0), &db_try_load_x_file_internal); - } - }; -} - -REGISTER_COMPONENT(fastfiles::component) diff --git a/src/client/component/fastfiles.hpp b/src/client/component/fastfiles.hpp deleted file mode 100644 index ac26d2ec..00000000 --- a/src/client/component/fastfiles.hpp +++ /dev/null @@ -1,8 +0,0 @@ -#pragma once - -#include "game/game.hpp" - -namespace fastfiles -{ - std::string get_current_fastfile(); -} diff --git a/src/client/component/filesystem.cpp b/src/client/component/filesystem.cpp deleted file mode 100644 index da11d2e4..00000000 --- a/src/client/component/filesystem.cpp +++ /dev/null @@ -1,94 +0,0 @@ -#include -#include "loader/component_loader.hpp" -#include "filesystem.hpp" -#include "game_module.hpp" - -#include "game/game.hpp" -#include "dvars.hpp" - -#include -#include - -namespace filesystem -{ - namespace - { - bool custom_path_registered = false; - - std::string get_binary_directory() - { - const auto dir = game_module::get_host_module().get_folder(); - return utils::string::replace(dir, "/", "\\"); - } - - void register_custom_path_stub(const char* path, const char* dir) - { - if (!custom_path_registered) - { - custom_path_registered = true; - - const auto launcher_dir = get_binary_directory(); - game::FS_AddLocalizedGameDirectory(launcher_dir.data(), "data"); - } - - game::FS_AddLocalizedGameDirectory(path, dir); - } - - void fs_startup_stub(const char* gamename) - { - custom_path_registered = false; - game::FS_Startup(gamename); - } - } - - file::file(std::string name) - : name_(std::move(name)) - { - char* buffer{}; - const auto size = game::FS_ReadFile(this->name_.data(), &buffer); - - if (size >= 0 && buffer) - { - this->valid_ = true; - this->buffer_.append(buffer, size); - game::FS_FreeFile(buffer); - } - } - - bool file::exists() const - { - return this->valid_; - } - - const std::string& file::get_buffer() const - { - return this->buffer_; - } - - const std::string& file::get_name() const - { - return this->name_; - } - - class component final : public component_interface - { - public: - void post_unpack() override - { - // Set fs_basegame - dvars::override::register_string("fs_basegame", "h1-mod", game::DVAR_FLAG_WRITE); - - utils::hook::call(SELECT_VALUE(0x1403B76E2, 0x1404ED3E2), fs_startup_stub); - if (game::environment::is_mp()) - { - utils::hook::call(0x1404ED823, fs_startup_stub); - } - - utils::hook::call(SELECT_VALUE(0x1403B8D31, 0x1404EE3D0), register_custom_path_stub); - utils::hook::call(SELECT_VALUE(0x1403B8D51, 0x1404EE3F0), register_custom_path_stub); - utils::hook::call(SELECT_VALUE(0x1403B8D90, 0x1404EE42F), register_custom_path_stub); - } - }; -} - -REGISTER_COMPONENT(filesystem::component) \ No newline at end of file diff --git a/src/client/component/filesystem.hpp b/src/client/component/filesystem.hpp deleted file mode 100644 index 6cec8c87..00000000 --- a/src/client/component/filesystem.hpp +++ /dev/null @@ -1,19 +0,0 @@ -#pragma once - -namespace filesystem -{ - class file - { - public: - file(std::string name); - - bool exists() const; - const std::string& get_buffer() const; - const std::string& get_name() const; - - private: - bool valid_ = false; - std::string name_; - std::string buffer_; - }; -} \ No newline at end of file diff --git a/src/client/component/fps.cpp b/src/client/component/fps.cpp deleted file mode 100644 index db471119..00000000 --- a/src/client/component/fps.cpp +++ /dev/null @@ -1,174 +0,0 @@ -#include -#include "loader/component_loader.hpp" - -#include "game/game.hpp" -#include "game/dvars.hpp" - -#include -#include -#include - -namespace fps -{ - namespace - { - game::dvar_t* cg_drawfps; - game::dvar_t* cg_drawping; - - float fps_color_good[4] = {0.6f, 1.0f, 0.0f, 1.0f}; - float fps_color_ok[4] = {1.0f, 0.7f, 0.3f, 1.0f}; - float fps_color_bad[4] = {1.0f, 0.3f, 0.3f, 1.0f}; - float ping_color[4] = {1.0f, 1.0f, 1.0f, 0.65f}; - - struct cg_perf_data - { - std::chrono::time_point perf_start; - std::int32_t current_ms{}; - std::int32_t previous_ms{}; - std::int32_t frame_ms{}; - std::int32_t history[32]{}; - std::int32_t count{}; - std::int32_t index{}; - std::int32_t instant{}; - std::int32_t total{}; - float average{}; - float variance{}; - std::int32_t min{}; - std::int32_t max{}; - }; - - cg_perf_data cg_perf{}; - - void perf_calc_fps(cg_perf_data* data, const std::int32_t value) - { - data->history[data->index % 32] = value; - data->instant = value; - data->min = 0x7FFFFFFF; - data->max = 0; - data->average = 0.0f; - data->variance = 0.0f; - data->total = 0; - - for (auto i = 0; i < data->count; ++i) - { - const std::int32_t idx = (data->index - i) % 32; - - if (idx < 0) - { - break; - } - - data->total += data->history[idx]; - - if (data->min > data->history[idx]) - { - data->min = data->history[idx]; - } - - if (data->max < data->history[idx]) - { - data->max = data->history[idx]; - } - } - - data->average = static_cast(data->total) / static_cast(data->count); - ++data->index; - } - - void perf_update() - { - cg_perf.count = 32; - - cg_perf.current_ms = static_cast(std::chrono::duration_cast( - std::chrono::high_resolution_clock::now() - cg_perf.perf_start).count()); - cg_perf.frame_ms = cg_perf.current_ms - cg_perf.previous_ms; - cg_perf.previous_ms = cg_perf.current_ms; - - perf_calc_fps(&cg_perf, cg_perf.frame_ms); - - utils::hook::invoke(SELECT_VALUE(0x1405487A0, 0x1406575A0)); // H1(1.4) - } - - void cg_draw_fps() - { - if (cg_drawfps->current.integer > 0) - { - const auto fps = static_cast(static_cast(1000.0f / static_cast(cg_perf. - average)) - + 9.313225746154785e-10); - - const auto font = game::R_RegisterFont("fonts/fira_mono_regular.ttf", 25); - const auto fps_string = utils::string::va("%i", fps); - - const auto x = (game::ScrPlace_GetViewPlacement()->realViewportSize[0] - 15.0f) - game::R_TextWidth( - fps_string, 0x7FFFFFFF, font); - const auto y = font->pixelHeight + 10.f; - - const auto fps_color = fps >= 60 ? fps_color_good : (fps >= 30 ? fps_color_ok : fps_color_bad); - game::R_AddCmdDrawText(fps_string, 0x7FFFFFFF, font, x, y, 1.f, 1.f, 0.0f, fps_color, 6); - } - } - - void cg_draw_ping() - { - if (cg_drawping->current.integer > 0 && game::CL_IsCgameInitialized() && !game::VirtualLobby_Loaded()) - { - const auto ping = *reinterpret_cast(0x142D106F0); - - const auto font = game::R_RegisterFont("fonts/consolefont", 20); - const auto ping_string = utils::string::va("Ping: %i", ping); - - const auto x = (game::ScrPlace_GetViewPlacement()->realViewportSize[0] - 375.0f) - game::R_TextWidth( - ping_string, 0x7FFFFFFF, font); - - const auto y = font->pixelHeight + 15.f; - game::R_AddCmdDrawText(ping_string, 0x7FFFFFFF, font, x, y, 1.f, 1.f, 0.0f, ping_color, 6); - } - } - - game::dvar_t* cg_draw_fps_register_stub(const char* name, const char** _enum, const int value, unsigned int /*flags*/, - const char* desc) - { - cg_drawfps = dvars::register_int("cg_drawFps", 0, 0, 2, game::DVAR_FLAG_SAVED, false); - return cg_drawfps; - } - } - - class component final : public component_interface - { - public: - void post_unpack() override - { - if (game::environment::is_dedi()) - { - return; - } - - // fps setup - cg_perf.perf_start = std::chrono::high_resolution_clock::now(); - utils::hook::call(SELECT_VALUE(0x14018D261, 0x14025B747), &perf_update); - - // change cg_drawfps flags to saved - utils::hook::call(SELECT_VALUE(0x140139F48, 0x140222A46), &cg_draw_fps_register_stub); - - scheduler::loop(cg_draw_fps, scheduler::pipeline::renderer); - - if (game::environment::is_sp()) - { - cg_drawfps = dvars::register_int("cg_drawFps", 0, 0, 2, game::DVAR_FLAG_SAVED, false); - } - - if (game::environment::is_mp()) - { - // fix ping value - utils::hook::nop(0x14025AC41, 2); - - cg_drawping = dvars::register_int("cg_drawPing", 0, 0, 1, game::DVAR_FLAG_SAVED, true); - - scheduler::loop(cg_draw_ping, scheduler::pipeline::renderer); - } - } - }; -} - -REGISTER_COMPONENT(fps::component) diff --git a/src/client/component/game_console.cpp b/src/client/component/game_console.cpp deleted file mode 100644 index cf7c3056..00000000 --- a/src/client/component/game_console.cpp +++ /dev/null @@ -1,793 +0,0 @@ -#include -#include "loader/component_loader.hpp" -#include "game_console.hpp" -#include "command.hpp" -#include "console.hpp" -#include "scheduler.hpp" - -#include "game/game.hpp" -#include "game/dvars.hpp" - -#include -#include -#include - -#include "version.hpp" - -#define console_font game::R_RegisterFont("fonts/fira_mono_regular.ttf", 18) -#define material_white game::Material_RegisterHandle("white") - -namespace game_console -{ - namespace - { - struct console_globals - { - float x{}; - float y{}; - float left_x{}; - float font_height{}; - bool may_auto_complete{}; - char auto_complete_choice[64]{}; - int info_line_count{}; - }; - - using output_queue = std::deque; - - struct ingame_console - { - char buffer[256]{}; - int cursor{}; - int font_height{}; - int visible_line_count{}; - int visible_pixel_width{}; - float screen_min[2]{}; //left & top - float screen_max[2]{}; //right & bottom - console_globals globals{}; - bool output_visible{}; - int display_line_offset{}; - int line_count{}; - utils::concurrency::container output{}; - }; - - ingame_console con{}; - - std::int32_t history_index = -1; - std::deque history{}; - - std::string fixed_input{}; - std::vector matches{}; - - float color_white[4] = {1.0f, 1.0f, 1.0f, 1.0f}; - float color_title[4] = {0.25f, 0.62f, 0.3f, 1.0f}; - - void clear() - { - strncpy_s(con.buffer, "", sizeof(con.buffer)); - con.cursor = 0; - - fixed_input = ""; - matches.clear(); - } - - void print_internal(const std::string& data) - { - con.output.access([&](output_queue& output) - { - if (con.visible_line_count > 0 - && con.display_line_offset == (output.size() - con.visible_line_count)) - { - con.display_line_offset++; - } - output.push_back(data); - if (output.size() > 512) - { - output.pop_front(); - } - }); - } - - void toggle_console() - { - clear(); - - con.output_visible = false; - *game::keyCatchers ^= 1; - } - - void toggle_console_output() - { - con.output_visible = con.output_visible == 0; - } - - void check_resize() - { - con.screen_min[0] = 6.0f; - con.screen_min[1] = 6.0f; - con.screen_max[0] = game::ScrPlace_GetViewPlacement()->realViewportSize[0] - 6.0f; - con.screen_max[1] = game::ScrPlace_GetViewPlacement()->realViewportSize[1] - 6.0f; - - if (console_font) - { - con.font_height = console_font->pixelHeight; - con.visible_line_count = static_cast((con.screen_max[1] - con.screen_min[1] - (con.font_height * 2) - ) - - 24.0f) / con.font_height; - con.visible_pixel_width = static_cast(((con.screen_max[0] - con.screen_min[0]) - 10.0f) - 18.0f); - } - else - { - con.font_height = 0; - con.visible_line_count = 0; - con.visible_pixel_width = 0; - } - } - - void draw_box(const float x, const float y, const float w, const float h, float* color) - { - game::vec4_t dark_color; - - dark_color[0] = color[0] * 0.5f; - dark_color[1] = color[1] * 0.5f; - dark_color[2] = color[2] * 0.5f; - dark_color[3] = color[3]; - - game::R_AddCmdDrawStretchPic(x, y, w, h, 0.0f, 0.0f, 0.0f, 0.0f, color, material_white); - game::R_AddCmdDrawStretchPic(x, y, 2.0f, h, 0.0f, 0.0f, 0.0f, 0.0f, dark_color, material_white); - game::R_AddCmdDrawStretchPic((x + w) - 2.0f, y, 2.0f, h, 0.0f, 0.0f, 0.0f, 0.0f, dark_color, - material_white); - game::R_AddCmdDrawStretchPic(x, y, w, 2.0f, 0.0f, 0.0f, 0.0f, 0.0f, dark_color, material_white); - game::R_AddCmdDrawStretchPic(x, (y + h) - 2.0f, w, 2.0f, 0.0f, 0.0f, 0.0f, 0.0f, dark_color, - material_white); - } - - void draw_input_box(const int lines, float* color) - { - draw_box( - con.globals.x - 6.0f, - con.globals.y - 6.0f, - (con.screen_max[0] - con.screen_min[0]) - ((con.globals.x - 6.0f) - con.screen_min[0]), - (lines * con.globals.font_height) + 12.0f, - color); - } - - void draw_input_text_and_over(const char* str, float* color) - { - game::R_AddCmdDrawText(str, 0x7FFFFFFF, console_font, con.globals.x, - con.globals.y + con.globals.font_height, 1.0f, - 1.0f, 0.0f, color, 0); - con.globals.x = game::R_TextWidth(str, 0, console_font) + con.globals.x + 6.0f; - } - - void draw_hint_box(const int lines, float* color, [[maybe_unused]] float offset_x = 0.0f, - [[maybe_unused]] float offset_y = 0.0f) - { - const auto _h = lines * con.globals.font_height + 12.0f; - const auto _y = con.globals.y - 3.0f + con.globals.font_height + 12.0f; - const auto _w = (con.screen_max[0] - con.screen_min[0]) - ((con.globals.x - 6.0f) - con.screen_min[0]); - - draw_box(con.globals.x - 6.0f, _y, _w, _h, color); - } - - void draw_hint_text(const int line, const char* text, float* color, const float offset = 0.0f) - { - const auto _y = con.globals.font_height + con.globals.y + (con.globals.font_height * (line + 1)) + 15.0f; - - game::R_AddCmdDrawText(text, 0x7FFFFFFF, console_font, con.globals.x + offset, _y, 1.0f, 1.0f, 0.0f, color, 0); - } - - bool match_compare(const std::string& input, const std::string& text, const bool exact) - { - if (exact && text == input) return true; - if (!exact && text.find(input) != std::string::npos) return true; - return false; - } - - void find_matches(std::string input, std::vector& suggestions, const bool exact) - { - input = utils::string::to_lower(input); - - for (const auto& dvar : dvars::dvar_list) - { - auto name = utils::string::to_lower(dvar); - if (game::Dvar_FindVar(name.data()) && match_compare(input, name, exact)) - { - suggestions.push_back(dvar); - } - - if (exact && suggestions.size() > 1) - { - return; - } - } - - if (suggestions.size() == 0 && game::Dvar_FindVar(input.data())) - { - suggestions.push_back(input.data()); - } - - game::cmd_function_s* cmd = (*game::cmd_functions); - while (cmd) - { - if (cmd->name) - { - std::string name = utils::string::to_lower(cmd->name); - - if (match_compare(input, name, exact)) - { - suggestions.push_back(cmd->name); - } - - if (exact && suggestions.size() > 1) - { - return; - } - } - - cmd = cmd->next; - } - } - - void draw_input() - { - con.globals.font_height = static_cast(console_font->pixelHeight); - con.globals.x = con.screen_min[0] + 6.0f; - con.globals.y = con.screen_min[1] + 6.0f; - con.globals.left_x = con.screen_min[0] + 6.0f; - - draw_input_box(1, dvars::con_inputBoxColor->current.vector); - draw_input_text_and_over("H1-Mod: " VERSION ">", color_title); - - con.globals.left_x = con.globals.x; - con.globals.auto_complete_choice[0] = 0; - - game::R_AddCmdDrawTextWithCursor(con.buffer, 0x7FFFFFFF, console_font, 18, con.globals.x, - con.globals.y + con.globals.font_height, 1.0f, 1.0f, 0, color_white, 0, - con.cursor, '|'); - - // check if using a prefixed '/' or not - const auto input = con.buffer[1] && (con.buffer[0] == '/' || con.buffer[0] == '\\') - ? std::string(con.buffer).substr(1) - : std::string(con.buffer); - - if (!input.length()) - { - return; - } - - if (input != fixed_input) - { - matches.clear(); - - if (input.find(" ") != std::string::npos) - { - find_matches(input.substr(0, input.find(" ")), matches, true); - } - else - { - find_matches(input, matches, false); - } - - fixed_input = input; - } - - con.globals.may_auto_complete = false; - if (matches.size() > 24) - { - draw_hint_box(1, dvars::con_inputHintBoxColor->current.vector); - draw_hint_text(0, utils::string::va("%i matches (too many to show here)", matches.size()), - dvars::con_inputDvarMatchColor->current.vector); - } - else if (matches.size() == 1) - { - auto* const dvar = game::Dvar_FindVar(matches[0].data()); - const auto line_count = dvar ? 2 : 1; - - draw_hint_box(line_count, dvars::con_inputHintBoxColor->current.vector); - draw_hint_text(0, matches[0].data(), dvar - ? dvars::con_inputDvarMatchColor->current.vector - : dvars::con_inputCmdMatchColor->current.vector); - - if (dvar) - { - const auto offset = (con.screen_max[0] - con.globals.x) / 2.5f; - - draw_hint_text(0, game::Dvar_ValueToString(dvar, dvar->current), - dvars::con_inputDvarValueColor->current.vector, offset); - draw_hint_text(1, " default", dvars::con_inputDvarInactiveValueColor->current.vector); - draw_hint_text(1, game::Dvar_ValueToString(dvar, dvar->reset), - dvars::con_inputDvarInactiveValueColor->current.vector, offset); - } - - strncpy_s(con.globals.auto_complete_choice, matches[0].data(), 64); - con.globals.may_auto_complete = true; - } - else if (matches.size() > 1) - { - draw_hint_box(static_cast(matches.size()), dvars::con_inputHintBoxColor->current.vector); - - const auto offset = (con.screen_max[0] - con.globals.x) / 2.5f; - - for (size_t i = 0; i < matches.size(); i++) - { - auto* const dvar = game::Dvar_FindVar(matches[i].data()); - - draw_hint_text(static_cast(i), matches[i].data(), - dvar - ? dvars::con_inputDvarMatchColor->current.vector - : dvars::con_inputCmdMatchColor->current.vector); - - if (dvar) - { - draw_hint_text(static_cast(i), game::Dvar_ValueToString(dvar, dvar->current), - dvars::con_inputDvarValueColor->current.vector, offset); - } - } - - strncpy_s(con.globals.auto_complete_choice, matches[0].data(), 64); - con.globals.may_auto_complete = true; - } - } - - void draw_output_scrollbar(const float x, float y, const float width, const float height, output_queue& output) - { - const auto _x = (x + width) - 10.0f; - draw_box(_x, y, 10.0f, height, dvars::con_outputBarColor->current.vector); - - auto _height = height; - if (output.size() > con.visible_line_count) - { - const auto percentage = static_cast(con.visible_line_count) / output.size(); - _height *= percentage; - - const auto remainingSpace = height - _height; - const auto percentageAbove = static_cast(con.display_line_offset) / (output.size() - con. - visible_line_count); - - y = y + (remainingSpace * percentageAbove); - } - - draw_box(_x, y, 10.0f, _height, dvars::con_outputSliderColor->current.vector); - } - - void draw_output_text(const float x, float y, output_queue& output) - { - const auto offset = output.size() >= con.visible_line_count - ? 0.0f - : (con.font_height * (con.visible_line_count - output.size())); - - for (auto i = 0; i < con.visible_line_count; i++) - { - y = console_font->pixelHeight + y; - - const auto index = i + con.display_line_offset; - if (index >= output.size()) - { - break; - } - - game::R_AddCmdDrawText(output.at(index).data(), 0x7FFF, console_font, x, y + offset, 1.0f, 1.0f, - 0.0f, color_white, 0); - } - } - - void draw_output_window() - { - con.output.access([](output_queue& output) - { - draw_box(con.screen_min[0], con.screen_min[1] + 32.0f, con.screen_max[0] - con.screen_min[0], - (con.screen_max[1] - con.screen_min[1]) - 32.0f, dvars::con_outputWindowColor->current.vector); - - const auto x = con.screen_min[0] + 6.0f; - const auto y = (con.screen_min[1] + 32.0f) + 6.0f; - const auto width = (con.screen_max[0] - con.screen_min[0]) - 12.0f; - const auto height = ((con.screen_max[1] - con.screen_min[1]) - 32.0f) - 12.0f; - - game::R_AddCmdDrawText("H1-Mod 1.4", 0x7FFFFFFF, console_font, x, - ((height - 16.0f) + y) + console_font->pixelHeight, 1.0f, 1.0f, 0.0f, color_title, 0); - - draw_output_scrollbar(x, y, width, height, output); - draw_output_text(x, y, output); - }); - } - - void draw_console() - { - check_resize(); - - if (*game::keyCatchers & 1) - { - if (!(*game::keyCatchers & 1)) - { - con.output_visible = false; - } - - if (con.output_visible) - { - draw_output_window(); - } - - draw_input(); - } - } - } - - void print_internal(const char* fmt, ...) - { - char va_buffer[0x200] = {0}; - - va_list ap; - va_start(ap, fmt); - vsprintf_s(va_buffer, fmt, ap); - va_end(ap); - - const auto formatted = std::string(va_buffer); - const auto lines = utils::string::split(formatted, '\n'); - - for (const auto& line : lines) - { - print_internal(line); - } - } - - void print(const int type, const std::string& data) - { - try - { - if (game::environment::is_dedi()) - { - return; - } - } - catch (std::exception&) - { - return; - } - - const auto lines = utils::string::split(data, '\n'); - for (const auto& line : lines) - { - print_internal(type == console::con_type_info ? line : "^"s.append(std::to_string(type)).append(line)); - } - } - - bool console_char_event(const int local_client_num, const int key) - { - if (key == game::keyNum_t::K_GRAVE || - key == game::keyNum_t::K_TILDE || - key == '|' || - key == '\\') - { - return false; - } - - if (key > 127) - { - return true; - } - - if (*game::keyCatchers & 1) - { - if (key == game::keyNum_t::K_TAB) // tab (auto complete) - { - if (con.globals.may_auto_complete) - { - const auto first_char = con.buffer[0]; - - clear(); - - if (first_char == '\\' || first_char == '/') - { - con.buffer[0] = first_char; - con.buffer[1] = '\0'; - } - - strncat_s(con.buffer, con.globals.auto_complete_choice, 64); - con.cursor = static_cast(std::string(con.buffer).length()); - - if (con.cursor != 254) - { - con.buffer[con.cursor++] = ' '; - con.buffer[con.cursor] = '\0'; - } - } - } - - if (key == 'v' - 'a' + 1) // paste - { - const auto clipboard = utils::string::get_clipboard_data(); - if (clipboard.empty()) - { - return false; - } - - for (size_t i = 0; i < clipboard.length(); i++) - { - console_char_event(local_client_num, clipboard[i]); - } - - return false; - } - - if (key == 'c' - 'a' + 1) // clear - { - clear(); - con.line_count = 0; - con.display_line_offset = 0; - con.output.access([](output_queue& output) - { - output.clear(); - }); - history_index = -1; - history.clear(); - - return false; - } - - if (key == 'h' - 'a' + 1) // backspace - { - if (con.cursor > 0) - { - memmove(con.buffer + con.cursor - 1, con.buffer + con.cursor, - strlen(con.buffer) + 1 - con.cursor); - con.cursor--; - } - - return false; - } - - if (key < 32) - { - return false; - } - - if (con.cursor == 256 - 1) - { - return false; - } - - memmove(con.buffer + con.cursor + 1, con.buffer + con.cursor, strlen(con.buffer) + 1 - con.cursor); - con.buffer[con.cursor] = static_cast(key); - con.cursor++; - - if (con.cursor == strlen(con.buffer) + 1) - { - con.buffer[con.cursor] = 0; - } - } - - return true; - } - - bool console_key_event(const int local_client_num, const int key, const int down) - { - if (key == game::keyNum_t::K_F10) - { - if (!game::Com_InFrontEnd()) - { - return false; - } - - game::Cmd_ExecuteSingleCommand(local_client_num, 0, "lui_open menu_systemlink_join\n"); - } - - if (key == game::keyNum_t::K_GRAVE || key == game::keyNum_t::K_TILDE) - { - if (!down) - { - return false; - } - - if (game::playerKeys[local_client_num].keys[game::keyNum_t::K_SHIFT].down) - { - if (!(*game::keyCatchers & 1)) - toggle_console(); - - toggle_console_output(); - return false; - } - - toggle_console(); - - return false; - } - - if (*game::keyCatchers & 1) - { - if (down) - { - if (key == game::keyNum_t::K_UPARROW) - { - if (++history_index >= history.size()) - { - history_index = static_cast(history.size()) - 1; - } - - clear(); - - if (history_index != -1) - { - strncpy_s(con.buffer, history.at(history_index).c_str(), 0x100); - con.cursor = static_cast(strlen(con.buffer)); - } - } - else if (key == game::keyNum_t::K_DOWNARROW) - { - if (--history_index < -1) - { - history_index = -1; - } - - clear(); - - if (history_index != -1) - { - strncpy_s(con.buffer, history.at(history_index).c_str(), 0x100); - con.cursor = static_cast(strlen(con.buffer)); - } - } - - if (key == game::keyNum_t::K_RIGHTARROW) - { - if (con.cursor < strlen(con.buffer)) - { - con.cursor++; - } - - return false; - } - - if (key == game::keyNum_t::K_LEFTARROW) - { - if (con.cursor > 0) - { - con.cursor--; - } - - return false; - } - - //scroll through output - if (key == game::keyNum_t::K_MWHEELUP || key == game::keyNum_t::K_PGUP) - { - con.output.access([](output_queue& output) - { - if (output.size() > con.visible_line_count && con.display_line_offset > 0) - { - con.display_line_offset--; - } - }); - } - else if (key == game::keyNum_t::K_MWHEELDOWN || key == game::keyNum_t::K_PGDN) - { - con.output.access([](output_queue& output) - { - if (output.size() > con.visible_line_count - && con.display_line_offset < (output.size() - con.visible_line_count)) - { - con.display_line_offset++; - } - }); - } - - if (key == game::keyNum_t::K_ENTER) - { - game::Cbuf_AddText(0, utils::string::va("%s \n", fixed_input.data())); - - if (history_index != -1) - { - const auto itr = history.begin() + history_index; - - if (*itr == con.buffer) - { - history.erase(history.begin() + history_index); - } - } - - history.push_front(con.buffer); - - console::info("]%s\n", con.buffer); - - if (history.size() > 10) - { - history.erase(history.begin() + 10); - } - - history_index = -1; - - clear(); - } - } - } - - return true; - } - - - class component final : public component_interface - { - public: - void post_load() override - { - if (game::environment::is_dedi()) - { - return; - } - - //scheduler::loop(draw_console, scheduler::pipeline::renderer); - } - - void post_unpack() override - { - scheduler::loop(draw_console, scheduler::pipeline::renderer); - - - if (game::environment::is_dedi()) - { - return; - } - - // initialize our structs - con.cursor = 0; - con.visible_line_count = 0; - con.output_visible = false; - con.display_line_offset = 0; - con.line_count = 0; - strncpy_s(con.buffer, "", 256); - - con.globals.x = 0.0f; - con.globals.y = 0.0f; - con.globals.left_x = 0.0f; - con.globals.font_height = 0.0f; - con.globals.may_auto_complete = false; - con.globals.info_line_count = 0; - strncpy_s(con.globals.auto_complete_choice, "", 64); - - // add clear command - command::add("clear", [&]() - { - clear(); - con.line_count = 0; - con.display_line_offset = 0; - con.output.access([](output_queue& output) - { - output.clear(); - }); - history_index = -1; - history.clear(); - }); - - // add our dvars - dvars::con_inputBoxColor = dvars::register_vec4("con_inputBoxColor", 0.2f, 0.2f, 0.2f, 0.9f, 0.0f, 1.0f, - game::DVAR_FLAG_SAVED, - "color of console input box"); - dvars::con_inputHintBoxColor = dvars::register_vec4("con_inputHintBoxColor", 0.3f, 0.3f, 0.3f, 1.0f, - 0.0f, 1.0f, - game::DVAR_FLAG_SAVED, "color of console input hint box"); - dvars::con_outputBarColor = dvars::register_vec4("con_outputBarColor", 0.5f, 0.5f, 0.5f, 0.6f, 0.0f, - 1.0f, game::DVAR_FLAG_SAVED, - "color of console output bar"); - dvars::con_outputSliderColor = dvars::register_vec4("con_outputSliderColor", 1.0f, 0.8f, 0.0f, 1.0f, - 0.0f, 1.0f, - game::DVAR_FLAG_SAVED, "color of console output slider"); - dvars::con_outputWindowColor = dvars::register_vec4("con_outputWindowColor", 0.25f, 0.25f, 0.25f, 0.85f, - 0.0f, - 1.0f, game::DVAR_FLAG_SAVED, "color of console output window"); - dvars::con_inputDvarMatchColor = dvars::register_vec4("con_inputDvarMatchColor", 1.0f, 1.0f, 0.8f, 1.0f, - 0.0f, - 1.0f, game::DVAR_FLAG_SAVED, "color of console matched dvar"); - dvars::con_inputDvarValueColor = dvars::register_vec4("con_inputDvarValueColor", 1.0f, 1.0f, 0.8f, 1.0f, - 0.0f, - 1.0f, game::DVAR_FLAG_SAVED, "color of console matched dvar value"); - dvars::con_inputDvarInactiveValueColor = dvars::register_vec4( - "con_inputDvarInactiveValueColor", 0.8f, 0.8f, - 0.8f, 1.0f, 0.0f, 1.0f, game::DVAR_FLAG_SAVED, - "color of console inactive dvar value"); - dvars::con_inputCmdMatchColor = dvars::register_vec4("con_inputCmdMatchColor", 0.80f, 0.80f, 1.0f, 1.0f, - 0.0f, - 1.0f, game::DVAR_FLAG_SAVED, "color of console matched command"); - } - }; -} - -REGISTER_COMPONENT(game_console::component) diff --git a/src/client/component/game_console.hpp b/src/client/component/game_console.hpp deleted file mode 100644 index cdc001a7..00000000 --- a/src/client/component/game_console.hpp +++ /dev/null @@ -1,7 +0,0 @@ -#pragma once - -namespace game_console -{ - bool console_char_event(int local_client_num, int key); - bool console_key_event(int local_client_num, int key, int down); -} \ No newline at end of file diff --git a/src/client/component/game_module.cpp b/src/client/component/game_module.cpp index bd984624..9bc79de0 100644 --- a/src/client/component/game_module.cpp +++ b/src/client/component/game_module.cpp @@ -1,6 +1,7 @@ #include #include "loader/component_loader.hpp" #include "game_module.hpp" +#include "game/game.hpp" #include @@ -90,7 +91,7 @@ namespace game_module utils::nt::library get_game_module() { - static utils::nt::library game{HMODULE(0x140000000)}; + static utils::nt::library game{HMODULE(game::base_address)}; return game; } diff --git a/src/client/component/localized_strings.cpp b/src/client/component/localized_strings.cpp deleted file mode 100644 index 55b41d65..00000000 --- a/src/client/component/localized_strings.cpp +++ /dev/null @@ -1,52 +0,0 @@ -#include -#include "loader/component_loader.hpp" -#include "localized_strings.hpp" -#include -#include -#include -#include "game/game.hpp" - -namespace localized_strings -{ - namespace - { - utils::hook::detour seh_string_ed_get_string_hook; - - using localized_map = std::unordered_map; - utils::concurrency::container localized_overrides; - - const char* seh_string_ed_get_string(const char* reference) - { - return localized_overrides.access([&](const localized_map& map) - { - const auto entry = map.find(reference); - if (entry != map.end()) - { - return utils::string::va("%s", entry->second.data()); - } - - return seh_string_ed_get_string_hook.invoke(reference); - }); - } - } - - void override(const std::string& key, const std::string& value) - { - localized_overrides.access([&](localized_map& map) - { - map[key] = value; - }); - } - - class component final : public component_interface - { - public: - void post_unpack() override - { - // Change some localized strings - seh_string_ed_get_string_hook.create(SELECT_VALUE(0, 0x585DA0_b), &seh_string_ed_get_string); // H1-STEAM(1.15) - } - }; -} - -REGISTER_COMPONENT(localized_strings::component) diff --git a/src/client/component/localized_strings.hpp b/src/client/component/localized_strings.hpp deleted file mode 100644 index 01d15907..00000000 --- a/src/client/component/localized_strings.hpp +++ /dev/null @@ -1,6 +0,0 @@ -#pragma once - -namespace localized_strings -{ - void override(const std::string& key, const std::string& value); -} \ No newline at end of file diff --git a/src/client/component/logfile.cpp b/src/client/component/logfile.cpp deleted file mode 100644 index fc949d92..00000000 --- a/src/client/component/logfile.cpp +++ /dev/null @@ -1,317 +0,0 @@ -#include -#include "loader/component_loader.hpp" -#include "scheduler.hpp" - -#include "game/scripting/entity.hpp" -#include "game/scripting/execution.hpp" -#include "game/scripting/lua/value_conversion.hpp" -#include "game/scripting/lua/error.hpp" - -#include - -#include "logfile.hpp" - -namespace logfile -{ - std::unordered_map vm_execute_hooks; - - namespace - { - utils::hook::detour scr_player_killed_hook; - utils::hook::detour scr_player_damage_hook; - - std::vector player_killed_callbacks; - std::vector player_damage_callbacks; - - utils::hook::detour vm_execute_hook; - char empty_function[2] = {0x32, 0x34}; // CHECK_CLEAR_PARAMS, END - bool hook_enabled = true; - - sol::lua_value convert_entity(lua_State* state, const game::mp::gentity_s* ent) - { - if (!ent) - { - return {}; - } - - const scripting::entity player{game::Scr_GetEntityId(ent->s.entityNum, 0)}; - return scripting::lua::convert(state, player); - } - - std::string get_weapon_name(unsigned int weapon, bool isAlternate) - { - char output[1024] = {0}; - game::BG_GetWeaponNameComplete(weapon, isAlternate, output, 1024); - return output; - } - - sol::lua_value convert_vector(lua_State* state, const float* vec) - { - if (!vec) - { - return {}; - } - - const auto vec_ = scripting::vector(vec); - return scripting::lua::convert(state, vec_); - } - - std::string convert_mod(const int meansOfDeath) - { - const auto value = reinterpret_cast(0x140FEC3F0)[meansOfDeath]; - const auto string = game::SL_ConvertToString(*value); - return string; - } - - void scr_player_killed_stub(game::mp::gentity_s* self, const game::mp::gentity_s* inflictor, - game::mp::gentity_s* attacker, int damage, const int meansOfDeath, const unsigned int weapon, - const bool isAlternate, const float* vDir, const unsigned int hitLoc, int psTimeOffset, int deathAnimDuration) - { - { - const std::string hitloc = reinterpret_cast(0x140FEC4D0)[hitLoc]; - const auto mod_ = convert_mod(meansOfDeath); - - const auto weapon_ = get_weapon_name(weapon, isAlternate); - - for (const auto& callback : player_killed_callbacks) - { - const auto state = callback.lua_state(); - - const auto self_ = convert_entity(state, self); - const auto inflictor_ = convert_entity(state, inflictor); - const auto attacker_ = convert_entity(state, attacker); - - const auto dir = convert_vector(state, vDir); - - const auto result = callback(self_, inflictor_, attacker_, damage, - mod_, weapon_, dir, hitloc, psTimeOffset, deathAnimDuration); - - scripting::lua::handle_error(result); - - if (result.valid() && result.get_type() == sol::type::number) - { - damage = result.get(); - } - } - - if (damage == 0) - { - return; - } - } - - scr_player_killed_hook.invoke(self, inflictor, attacker, damage, meansOfDeath, - weapon, isAlternate, vDir, hitLoc, psTimeOffset, deathAnimDuration); - } - - void scr_player_damage_stub(game::mp::gentity_s* self, const game::mp::gentity_s* inflictor, - game::mp::gentity_s* attacker, int damage, int dflags, const int meansOfDeath, - const unsigned int weapon, const bool isAlternate, const float* vPoint, - const float* vDir, const unsigned int hitLoc, const int timeOffset) - { - { - const std::string hitloc = reinterpret_cast(0x140FEC4D0)[hitLoc]; - const auto mod_ = convert_mod(meansOfDeath); - - const auto weapon_ = get_weapon_name(weapon, isAlternate); - - for (const auto& callback : player_damage_callbacks) - { - const auto state = callback.lua_state(); - - const auto self_ = convert_entity(state, self); - const auto inflictor_ = convert_entity(state, inflictor); - const auto attacker_ = convert_entity(state, attacker); - - const auto point = convert_vector(state, vPoint); - const auto dir = convert_vector(state, vDir); - - const auto result = callback(self_, inflictor_, attacker_, - damage, dflags, mod_, weapon_, point, dir, hitloc); - - scripting::lua::handle_error(result); - - if (result.valid() && result.get_type() == sol::type::number) - { - damage = result.get(); - } - } - - if (damage == 0) - { - return; - } - } - - scr_player_damage_hook.invoke(self, inflictor, attacker, damage, dflags, - meansOfDeath, weapon, isAlternate, vPoint, vDir, hitLoc, timeOffset); - } - - void client_command_stub(const int clientNum) - { - auto self = &game::mp::g_entities[clientNum]; - char cmd[1024] = {0}; - - game::SV_Cmd_ArgvBuffer(0, cmd, 1024); - - if (cmd == "say"s || cmd == "say_team"s) - { - auto hidden = false; - std::string message(game::ConcatArgs(1)); - - hidden = message[1] == '/'; - message.erase(0, hidden ? 2 : 1); - - scheduler::once([cmd, message, self]() - { - const scripting::entity level{*game::levelEntityId}; - const scripting::entity player{game::Scr_GetEntityId(self->s.entityNum, 0)}; - - scripting::notify(level, cmd, {player, message}); - scripting::notify(player, cmd, {message}); - }, scheduler::pipeline::server); - - if (hidden) - { - return; - } - } - - // ClientCommand - return utils::hook::invoke(0x140336000, clientNum); - } - - void g_shutdown_game_stub(const int freeScripts) - { - { - const scripting::entity level{*game::levelEntityId}; - scripting::notify(level, "shutdownGame_called", {1}); - } - - // G_ShutdownGame - return utils::hook::invoke(0x140345A60, freeScripts); - } - - unsigned int local_id_to_entity(unsigned int local_id) - { - const auto variable = game::scr_VarGlob->objectVariableValue[local_id]; - return variable.u.f.next; - } - - bool execute_vm_hook(const char* pos) - { - if (vm_execute_hooks.find(pos) == vm_execute_hooks.end()) - { - hook_enabled = true; - return false; - } - - if (!hook_enabled && pos > reinterpret_cast(vm_execute_hooks.size())) - { - hook_enabled = true; - return false; - } - - const auto hook = vm_execute_hooks[pos]; - const auto state = hook.lua_state(); - - const scripting::entity self = local_id_to_entity(game::scr_VmPub->function_frame->fs.localId); - - std::vector args; - - const auto top = game::scr_function_stack->top; - - for (auto* value = top; value->type != game::SCRIPT_END; --value) - { - args.push_back(scripting::lua::convert(state, *value)); - } - - const auto result = hook(self, sol::as_args(args)); - scripting::lua::handle_error(result); - - return true; - } - - void vm_execute_stub(utils::hook::assembler& a) - { - const auto replace = a.newLabel(); - const auto end = a.newLabel(); - - a.pushad64(); - - a.mov(rcx, r14); - a.call_aligned(execute_vm_hook); - - a.cmp(al, 0); - a.jne(replace); - - a.popad64(); - a.jmp(end); - - a.bind(end); - - a.movzx(r15d, byte_ptr(r14)); - a.inc(r14); - a.mov(dword_ptr(rbp, 0xA4), r15d); - - a.jmp(SELECT_VALUE(0x140376663, 0x140444653)); - - a.bind(replace); - - a.popad64(); - a.mov(r14, reinterpret_cast(empty_function)); - a.jmp(end); - } - } - - void add_player_damage_callback(const sol::protected_function& callback) - { - player_damage_callbacks.push_back(callback); - } - - void add_player_killed_callback(const sol::protected_function& callback) - { - player_killed_callbacks.push_back(callback); - } - - void clear_callbacks() - { - player_damage_callbacks.clear(); - player_killed_callbacks.clear(); - vm_execute_hooks.clear(); - } - - void enable_vm_execute_hook() - { - hook_enabled = true; - } - - void disable_vm_execute_hook() - { - hook_enabled = false; - } - - class component final : public component_interface - { - public: - void post_unpack() override - { - if (game::environment::is_sp()) - { - return; - } - - utils::hook::call(0x14048191D, client_command_stub); - - scr_player_damage_hook.create(0x14037DC50, scr_player_damage_stub); - scr_player_killed_hook.create(0x14037DF30, scr_player_killed_stub); - - utils::hook::call(0x140484EC0, g_shutdown_game_stub); - utils::hook::call(0x1404853C1, g_shutdown_game_stub); - - utils::hook::jump(SELECT_VALUE(0x140376655, 0x140444645), utils::hook::assemble(vm_execute_stub), true); - } - }; -} - -REGISTER_COMPONENT(logfile::component) \ No newline at end of file diff --git a/src/client/component/logfile.hpp b/src/client/component/logfile.hpp deleted file mode 100644 index 77f699c8..00000000 --- a/src/client/component/logfile.hpp +++ /dev/null @@ -1,13 +0,0 @@ -#pragma once - -namespace logfile -{ - extern std::unordered_map vm_execute_hooks; - - void add_player_damage_callback(const sol::protected_function& callback); - void add_player_killed_callback(const sol::protected_function& callback); - void clear_callbacks(); - - void enable_vm_execute_hook(); - void disable_vm_execute_hook(); -} \ No newline at end of file diff --git a/src/client/component/lui.cpp b/src/client/component/lui.cpp deleted file mode 100644 index d3a7edca..00000000 --- a/src/client/component/lui.cpp +++ /dev/null @@ -1,58 +0,0 @@ -#include -#include "loader/component_loader.hpp" - -#include "game/game.hpp" - -#include "command.hpp" -#include "console.hpp" - -#include - -namespace lui -{ - class component final : public component_interface - { - public: - void post_unpack() override - { - // Don't show create cod account popup - //utils::hook::set(0x14017C957, 0); // H1(1.4) - -//#ifdef _DEBUG - // Enable development menus (causes issues in sp) - //utils::hook::set(SELECT_VALUE(0x1400B4ABC, 0x1401AB779), 1); -//#endif - - command::add("lui_open", [](const command::params& params) - { - if (params.size() <= 1) - { - console::info("usage: lui_open \n"); - return; - } - - game::LUI_OpenMenu(0, params[1], 0, 0, 0); - }); - - command::add("lui_open_popup", [](const command::params& params) - { - if (params.size() <= 1) - { - console::info("usage: lui_open_popup \n"); - return; - } - - game::LUI_OpenMenu(0, params[1], 1, 0, 0); - }); - - command::add("runMenuScript", [](const command::params& params) - { - const auto args_str = params.join(1); - const auto* args = args_str.data(); - game::UI_RunMenuScript(0, &args); - }); - } - }; -} - -REGISTER_COMPONENT(lui::component) diff --git a/src/client/component/map_rotation.cpp b/src/client/component/map_rotation.cpp deleted file mode 100644 index 216cbfcd..00000000 --- a/src/client/component/map_rotation.cpp +++ /dev/null @@ -1,180 +0,0 @@ -#include -#include "loader/component_loader.hpp" -#include "command.hpp" -#include "scheduler.hpp" -#include -#include -#include "game/game.hpp" -#include - -namespace map_rotation -{ - DWORD previousPriority; - namespace - { - void set_dvar(const std::string& dvar, const std::string& value) - { - command::execute(utils::string::va("%s \"%s\"", dvar.data(), value.data()), true); - } - - void set_gametype(const std::string& gametype) - { - set_dvar("g_gametype", gametype); - } - - void launch_map(const std::string& mapname) - { - command::execute(utils::string::va("map %s", mapname.data()), false); - } - - void launch_default_map() - { - auto* mapname = game::Dvar_FindVar("mapname"); - if (mapname && mapname->current.string && strlen(mapname->current.string) && mapname->current.string != - "mp_vlobby_room"s) - { - launch_map(mapname->current.string); - } - else - { - launch_map("mp_crash"); - } - } - - std::string load_current_map_rotation() - { - auto* rotation = game::Dvar_FindVar("sv_mapRotationCurrent"); - if (!strlen(rotation->current.string)) - { - rotation = game::Dvar_FindVar("sv_mapRotation"); - set_dvar("sv_mapRotationCurrent", rotation->current.string); - } - - return rotation->current.string; - } - - std::vector parse_current_map_rotation() - { - const auto rotation = load_current_map_rotation(); - return utils::string::split(rotation, ' '); - } - - void store_new_rotation(const std::vector& elements, const size_t index) - { - std::string value{}; - - for (auto i = index; i < elements.size(); ++i) - { - if (i != index) - { - value.push_back(' '); - } - - value.append(elements[i]); - } - - set_dvar("sv_mapRotationCurrent", value); - } - - void change_process_priority() - { - auto* const dvar = game::Dvar_FindVar("sv_autoPriority"); - if (dvar && dvar->current.enabled) - { - scheduler::on_game_initialized([]() - { - //printf("=======================setting OLD priority=======================\n"); - SetPriorityClass(GetCurrentProcess(), previousPriority); - }, scheduler::pipeline::main, 1s); - - previousPriority = GetPriorityClass(GetCurrentProcess()); - //printf("=======================setting NEW priority=======================\n"); - SetPriorityClass(GetCurrentProcess(), NORMAL_PRIORITY_CLASS); - } - } - - void perform_map_rotation() - { - if (game::Live_SyncOnlineDataFlags(0) != 0) - { - scheduler::on_game_initialized(perform_map_rotation, scheduler::pipeline::main, 1s); - return; - } - - const auto rotation = parse_current_map_rotation(); - - for (size_t i = 0; !rotation.empty() && i < (rotation.size() - 1); i += 2) - { - const auto& key = rotation[i]; - const auto& value = rotation[i + 1]; - - if (key == "gametype") - { - set_gametype(value); - } - else if (key == "map") - { - store_new_rotation(rotation, i + 2); - change_process_priority(); - if (!game::SV_MapExists(value.data())) - { - printf("map_rotation: '%s' map doesn't exist!\n", value.data()); - launch_default_map(); - return; - } - launch_map(value); - return; - } - else - { - printf("Invalid map rotation key: %s\n", key.data()); - } - } - - launch_default_map(); - } - - void trigger_map_rotation() - { - scheduler::schedule([]() - { - if (game::CL_IsCgameInitialized()) - { - return scheduler::cond_continue; - } - - command::execute("map_rotate", false); - return scheduler::cond_end; - }, scheduler::pipeline::main, 1s); - } - - } - - class component final : public component_interface - { - public: - void post_unpack() override - { - if (!game::environment::is_dedi()) - { - return; - } - - scheduler::once([]() - { - dvars::register_string("sv_mapRotation", "", game::DVAR_FLAG_NONE, true); - dvars::register_string("sv_mapRotationCurrent", "", game::DVAR_FLAG_NONE, true); - dvars::register_string("sv_autoPriority", "", game::DVAR_FLAG_NONE, true); - }, scheduler::pipeline::main); - - command::add("map_rotate", &perform_map_rotation); - - // Hook GScr_ExitLevel - utils::hook::jump(0x140376630, &trigger_map_rotation); // not sure if working - - previousPriority = GetPriorityClass(GetCurrentProcess()); - } - }; -} - -REGISTER_COMPONENT(map_rotation::component) diff --git a/src/client/component/network.cpp b/src/client/component/network.cpp index fb2a6f55..8069d61a 100644 --- a/src/client/component/network.cpp +++ b/src/client/component/network.cpp @@ -27,15 +27,8 @@ namespace network const auto cmd_string = utils::string::to_lower(command); auto& callbacks = get_callbacks(); const auto handler = callbacks.find(cmd_string); - - if (handler == callbacks.end()) - { - return false; - } - const auto offset = cmd_string.size() + 5; - - if (message->cursize <= offset) + if (message->cursize < offset || handler == callbacks.end()) { return false; } @@ -331,4 +324,4 @@ namespace network }; } -REGISTER_COMPONENT(network::component) +REGISTER_COMPONENT(network::component) \ No newline at end of file diff --git a/src/client/component/party.cpp b/src/client/component/party.cpp deleted file mode 100644 index 0605afad..00000000 --- a/src/client/component/party.cpp +++ /dev/null @@ -1,630 +0,0 @@ -#include -#include "loader/component_loader.hpp" - -#include "party.hpp" -#include "console.hpp" -#include "command.hpp" -#include "network.hpp" -#include "scheduler.hpp" -#include "server_list.hpp" - -#include "steam/steam.hpp" - -#include -#include -#include -#include - -namespace party -{ - namespace - { - struct - { - game::netadr_s host{}; - std::string challenge{}; - bool hostDefined{false}; - } connect_state; - - std::string sv_motd; - int sv_maxclients; - - void perform_game_initialization() - { - command::execute("onlinegame 1", true); - command::execute("xstartprivateparty", true); - command::execute("xblive_privatematch 1", true); - command::execute("startentitlements", true); - } - - void connect_to_party(const game::netadr_s& target, const std::string& mapname, const std::string& gametype) - { - if (game::environment::is_sp()) - { - return; - } - - if (game::Live_SyncOnlineDataFlags(0) != 0) - { - // initialize the game after onlinedataflags is 32 (workaround) - if (game::Live_SyncOnlineDataFlags(0) == 32) - { - scheduler::once([=]() - { - command::execute("xstartprivateparty", true); - command::execute("disconnect", true); // 32 -> 0 - - connect_to_party(target, mapname, gametype); - }, scheduler::pipeline::main, 1s); - return; - } - else - { - scheduler::once([=]() - { - connect_to_party(target, mapname, gametype); - }, scheduler::pipeline::main, 1s); - return; - } - } - - perform_game_initialization(); - - // exit from virtuallobby - utils::hook::invoke(0x140256D40, 1); - - // CL_ConnectFromParty - char session_info[0x100] = {}; - utils::hook::invoke(0x140251560, 0, session_info, &target, mapname.data(), gametype.data()); - } - - std::string get_dvar_string(const std::string& dvar) - { - auto* dvar_value = game::Dvar_FindVar(dvar.data()); - if (dvar_value && dvar_value->current.string) - { - return dvar_value->current.string; - } - - return {}; - } - - int get_dvar_int(const std::string& dvar) - { - auto* dvar_value = game::Dvar_FindVar(dvar.data()); - if (dvar_value && dvar_value->current.integer) - { - return dvar_value->current.integer; - } - - return -1; - } - - bool get_dvar_bool(const std::string& dvar) - { - auto* dvar_value = game::Dvar_FindVar(dvar.data()); - if (dvar_value && dvar_value->current.enabled) - { - return dvar_value->current.enabled; - } - - return false; - } - - void didyouknow_stub(const char* dvar_name, const char* string) - { - if (!party::sv_motd.empty()) - { - string = party::sv_motd.data(); - } - - // This function either does Dvar_SetString or Dvar_RegisterString for the given dvar - utils::hook::invoke(0x1404FB210, dvar_name, string); - } - - void disconnect_stub() - { - if (!game::VirtualLobby_Loaded()) - { - if (game::CL_IsCgameInitialized()) - { - // CL_ForwardCommandToServer - utils::hook::invoke(0x140253480, 0, "disconnect"); - // CL_WritePacket - utils::hook::invoke(0x14024DB10, 0); - } - // CL_Disconnect - utils::hook::invoke(0x140252060, 0); - } - } - - utils::hook::detour cldisconnect_hook; - - void cl_disconnect_stub(int a1) - { - party::sv_motd.clear(); - cldisconnect_hook.invoke(a1); - } - - const auto drop_reason_stub = utils::hook::assemble([](utils::hook::assembler& a) - { - a.mov(rdx, rdi); - a.mov(ecx, 2); - a.jmp(0x140251F78); - }); - - void menu_error(const std::string& error) - { - utils::hook::invoke(0x1400DACC0, error.data(), "MENU_NOTICE"); - utils::hook::set(0x142C1DA98, 1); - } - } - - int get_client_num_by_name(const std::string& name) - { - for (auto i = 0; !name.empty() && i < *game::mp::svs_numclients; ++i) - { - if (game::mp::g_entities[i].client) - { - char client_name[16] = {0}; - strncpy_s(client_name, game::mp::g_entities[i].client->name, sizeof(client_name)); - game::I_CleanStr(client_name); - - if (client_name == name) - { - return i; - } - } - } - return -1; - } - - void reset_connect_state() - { - connect_state = {}; - } - - int get_client_count() - { - auto count = 0; - for (auto i = 0; i < *game::mp::svs_numclients; ++i) - { - if (game::mp::svs_clients[i].header.state >= 1) - { - ++count; - } - } - - return count; - } - - int get_bot_count() - { - auto count = 0; - for (auto i = 0; i < *game::mp::svs_numclients; ++i) - { - if (game::mp::svs_clients[i].header.state >= 1 && - game::SV_BotIsBot(i)) - { - ++count; - } - } - - return count; - } - - void connect(const game::netadr_s& target) - { - if (game::environment::is_sp()) - { - return; - } - - command::execute("lui_open_popup popup_acceptinginvite", false); - - connect_state.host = target; - connect_state.challenge = utils::cryptography::random::get_challenge(); - connect_state.hostDefined = true; - - network::send(target, "getInfo", connect_state.challenge); - } - - void start_map(const std::string& mapname) - { - if (game::Live_SyncOnlineDataFlags(0) > 32) - { - scheduler::once([=]() - { - command::execute("map " + mapname, false); - }, scheduler::pipeline::main, 1s); - } - else - { - if (!game::SV_MapExists(mapname.data())) - { - console::info("Map '%s' doesn't exist.\n", mapname.data()); - return; - } - - auto* current_mapname = game::Dvar_FindVar("mapname"); - if (current_mapname && utils::string::to_lower(current_mapname->current.string) == - utils::string::to_lower(mapname) && (game::SV_Loaded() && !game::VirtualLobby_Loaded())) - { - console::info("Restarting map: %s\n", mapname.data()); - command::execute("map_restart", false); - return; - } - - if (!game::environment::is_dedi()) - { - if (game::SV_Loaded()) - { - const auto* args = "Leave"; - game::UI_RunMenuScript(0, &args); - } - - perform_game_initialization(); - } - - console::info("Starting map: %s\n", mapname.data()); - - auto* gametype = game::Dvar_FindVar("g_gametype"); - if (gametype && gametype->current.string) - { - command::execute(utils::string::va("ui_gametype %s", gametype->current.string), true); - } - command::execute(utils::string::va("ui_mapname %s", mapname.data()), true); - - /*auto* maxclients = game::Dvar_FindVar("sv_maxclients"); - if (maxclients) - { - command::execute(utils::string::va("ui_maxclients %i", maxclients->current.integer), true); - command::execute(utils::string::va("party_maxplayers %i", maxclients->current.integer), true); - }*/ - - const auto* args = "StartServer"; - game::UI_RunMenuScript(0, &args); - } - } - - int server_client_count() - { - return party::sv_maxclients; - } - - class component final : public component_interface - { - public: - void post_unpack() override - { - if (game::environment::is_sp()) - { - return; - } - - // hook disconnect command function - utils::hook::jump(0x1402521C7, disconnect_stub); - - // detour CL_Disconnect to clear motd - cldisconnect_hook.create(0x140252060, cl_disconnect_stub); - - if (game::environment::is_mp()) - { - // show custom drop reason - utils::hook::nop(0x140251EFB, 13); - utils::hook::jump(0x140251EFB, drop_reason_stub, true); - } - - // enable custom kick reason in GScr_KickPlayer - utils::hook::set(0x140376A1D, 0xEB); - - command::add("map", [](const command::params& argument) - { - if (argument.size() != 2) - { - return; - } - - start_map(argument[1]); - }); - - command::add("map_restart", []() - { - if (!game::SV_Loaded() || game::VirtualLobby_Loaded()) - { - return; - } - *reinterpret_cast(0x14A3A91D0) = 1; // sv_map_restart - *reinterpret_cast(0x14A3A91D4) = 1; // sv_loadScripts - *reinterpret_cast(0x14A3A91D8) = 0; // sv_migrate - - utils::hook::invoke(0x14047E7F0); // SV_CheckLoadGame - }); - - command::add("fast_restart", []() - { - if (game::SV_Loaded() && !game::VirtualLobby_Loaded()) - { - game::SV_FastRestart(0); - } - }); - - command::add("reconnect", [](const command::params& argument) - { - if (!connect_state.hostDefined) - { - console::info("Cannot connect to server.\n"); - return; - } - - if (game::CL_IsCgameInitialized()) - { - command::execute("disconnect"); - command::execute("reconnect"); - } - else - { - connect(connect_state.host); - } - }); - - command::add("connect", [](const command::params& argument) - { - if (argument.size() != 2) - { - return; - } - - game::netadr_s target{}; - if (game::NET_StringToAdr(argument[1], &target)) - { - connect(target); - } - }); - - command::add("kickClient", [](const command::params& params) - { - if (params.size() < 2) - { - console::info("usage: kickClient , (optional)\n"); - return; - } - - if (!game::SV_Loaded() || game::VirtualLobby_Loaded()) - { - return; - } - - std::string reason; - if (params.size() > 2) - { - reason = params.join(2); - } - if (reason.empty()) - { - reason = "EXE_PLAYERKICKED"; - } - - const auto client_num = atoi(params.get(1)); - if (client_num < 0 || client_num >= *game::mp::svs_numclients) - { - return; - } - - scheduler::once([client_num, reason]() - { - game::SV_KickClientNum(client_num, reason.data()); - }, scheduler::pipeline::server); - }); - - command::add("kick", [](const command::params& params) - { - if (params.size() < 2) - { - console::info("usage: kick , (optional)\n"); - return; - } - - if (!game::SV_Loaded() || game::VirtualLobby_Loaded()) - { - return; - } - - std::string reason; - if (params.size() > 2) - { - reason = params.join(2); - } - if (reason.empty()) - { - reason = "EXE_PLAYERKICKED"; - } - - const std::string name = params.get(1); - if (name == "all"s) - { - for (auto i = 0; i < *game::mp::svs_numclients; ++i) - { - scheduler::once([i, reason]() - { - game::SV_KickClientNum(i, reason.data()); - }, scheduler::pipeline::server); - } - return; - } - - const auto client_num = get_client_num_by_name(name); - if (client_num < 0 || client_num >= *game::mp::svs_numclients) - { - return; - } - - scheduler::once([client_num, reason]() - { - game::SV_KickClientNum(client_num, reason.data()); - }, scheduler::pipeline::server); - }); - - scheduler::once([]() - { - const auto hash = game::generateHashValue("sv_sayName"); - game::Dvar_RegisterString(hash, "sv_sayName", "console", game::DvarFlags::DVAR_FLAG_NONE); - }, scheduler::pipeline::main); - - command::add("tell", [](const command::params& params) - { - if (params.size() < 3) - { - return; - } - - const auto client_num = atoi(params.get(1)); - const auto message = params.join(2); - const auto* const name = game::Dvar_FindVar("sv_sayName")->current.string; - - game::SV_GameSendServerCommand(client_num, game::SV_CMD_CAN_IGNORE, - utils::string::va("%c \"%s: %s\"", 84, name, message.data())); - printf("%s -> %i: %s\n", name, client_num, message.data()); - }); - - command::add("tellraw", [](const command::params& params) - { - if (params.size() < 3) - { - return; - } - - const auto client_num = atoi(params.get(1)); - const auto message = params.join(2); - - game::SV_GameSendServerCommand(client_num, game::SV_CMD_CAN_IGNORE, - utils::string::va("%c \"%s\"", 84, message.data())); - printf("%i: %s\n", client_num, message.data()); - }); - - command::add("say", [](const command::params& params) - { - if (params.size() < 2) - { - return; - } - - const auto message = params.join(1); - const auto* const name = game::Dvar_FindVar("sv_sayName")->current.string; - - game::SV_GameSendServerCommand( - -1, game::SV_CMD_CAN_IGNORE, utils::string::va("%c \"%s: %s\"", 84, name, message.data())); - printf("%s: %s\n", name, message.data()); - }); - - command::add("sayraw", [](const command::params& params) - { - if (params.size() < 2) - { - return; - } - - const auto message = params.join(1); - - game::SV_GameSendServerCommand(-1, game::SV_CMD_CAN_IGNORE, - utils::string::va("%c \"%s\"", 84, message.data())); - printf("%s\n", message.data()); - }); - - utils::hook::call(0x1404C6E8D, didyouknow_stub); // allow custom didyouknow based on sv_motd - - network::on("getInfo", [](const game::netadr_s& target, const std::string_view& data) - { - utils::info_string info{}; - info.set("challenge", std::string{data}); - info.set("gamename", "H1"); - info.set("hostname", get_dvar_string("sv_hostname")); - info.set("gametype", get_dvar_string("g_gametype")); - info.set("sv_motd", get_dvar_string("sv_motd")); - info.set("xuid", utils::string::va("%llX", steam::SteamUser()->GetSteamID().bits)); - info.set("mapname", get_dvar_string("mapname")); - info.set("isPrivate", get_dvar_string("g_password").empty() ? "0" : "1"); - info.set("clients", utils::string::va("%i", get_client_count())); - info.set("bots", utils::string::va("%i", get_bot_count())); - info.set("sv_maxclients", utils::string::va("%i", *game::mp::svs_numclients)); - info.set("protocol", utils::string::va("%i", PROTOCOL)); - info.set("playmode", utils::string::va("%i", game::Com_GetCurrentCoDPlayMode())); - info.set("sv_running", utils::string::va("%i", get_dvar_bool("sv_running") && !game::VirtualLobby_Loaded())); - info.set("dedicated", utils::string::va("%i", get_dvar_bool("dedicated"))); - - network::send(target, "infoResponse", info.build(), '\n'); - }); - - network::on("infoResponse", [](const game::netadr_s& target, const std::string_view& data) - { - const utils::info_string info{data}; - server_list::handle_info_response(target, info); - - if (connect_state.host != target) - { - return; - } - - if (info.get("challenge") != connect_state.challenge) - { - const auto str = "Invalid challenge."; - printf("%s\n", str); - menu_error(str); - return; - } - - const auto gamename = info.get("gamename"); - if (gamename != "H1"s) - { - const auto str = "Invalid gamename."; - printf("%s\n", str); - menu_error(str); - return; - } - - const auto playmode = info.get("playmode"); - if (game::CodPlayMode(std::atoi(playmode.data())) != game::Com_GetCurrentCoDPlayMode()) - { - const auto str = "Invalid playmode."; - printf("%s\n", str); - menu_error(str); - return; - } - - const auto sv_running = info.get("sv_running"); - if (!std::atoi(sv_running.data())) - { - const auto str = "Server not running."; - printf("%s\n", str); - menu_error(str); - return; - } - - const auto mapname = info.get("mapname"); - if (mapname.empty()) - { - const auto str = "Invalid map."; - printf("%s\n", str); - menu_error(str); - return; - } - - const auto gametype = info.get("gametype"); - if (gametype.empty()) - { - const auto str = "Invalid gametype."; - printf("%s\n", str); - menu_error(str); - return; - } - - party::sv_motd = info.get("sv_motd"); - party::sv_maxclients = std::stoi(info.get("sv_maxclients")); - - connect_to_party(target, mapname, gametype); - }); - } - }; -} - -REGISTER_COMPONENT(party::component) \ No newline at end of file diff --git a/src/client/component/party.hpp b/src/client/component/party.hpp deleted file mode 100644 index cd90ae9f..00000000 --- a/src/client/component/party.hpp +++ /dev/null @@ -1,17 +0,0 @@ -#pragma once -#include "game/game.hpp" - -namespace party -{ - void reset_connect_state(); - - void connect(const game::netadr_s& target); - void start_map(const std::string& mapname); - - int server_client_count(); - - int get_client_num_by_name(const std::string& name); - - int get_client_count(); - int get_bot_count(); -} \ No newline at end of file diff --git a/src/client/component/patches.cpp b/src/client/component/patches.cpp deleted file mode 100644 index e9aaf21a..00000000 --- a/src/client/component/patches.cpp +++ /dev/null @@ -1,293 +0,0 @@ -#include -#include "loader/component_loader.hpp" - -#include "dvars.hpp" -#include "version.h" -#include "command.hpp" -#include "console.hpp" -#include "network.hpp" -#include "scheduler.hpp" -#include "filesystem.hpp" - -#include "game/game.hpp" -#include "game/dvars.hpp" - -#include -#include -#include - -namespace patches -{ - namespace - { - const char* live_get_local_client_name() - { - return game::Dvar_FindVar("name")->current.string; - } - - utils::hook::detour sv_kick_client_num_hook; - - void sv_kick_client_num(const int client_num, const char* reason) - { - // Don't kick bot to equalize team balance. - if (reason == "EXE_PLAYERKICKED_BOT_BALANCE"s) - { - return; - } - return sv_kick_client_num_hook.invoke(client_num, reason); - } - - std::string get_login_username() - { - char username[UNLEN + 1]; - DWORD username_len = UNLEN + 1; - if (!GetUserNameA(username, &username_len)) - { - return "Unknown Soldier"; - } - - return std::string{ username, username_len - 1 }; - } - - utils::hook::detour com_register_dvars_hook; - - void com_register_dvars_stub() - { - if (game::environment::is_mp()) - { - // Make name save - dvars::register_string("name", get_login_username().data(), game::DVAR_FLAG_SAVED, true); - - // Disable data validation error popup - dvars::register_int("data_validation_allow_drop", 0, 0, 0, game::DVAR_FLAG_NONE, true); - } - - return com_register_dvars_hook.invoke(); - } - - int is_item_unlocked() - { - return 0; // 0 == yes - } - - void set_client_dvar_from_server_stub(void* a1, void* a2, const char* dvar, const char* value) - { - if (dvar == "cg_fov"s) - { - return; - } - - // CG_SetClientDvarFromServer - utils::hook::invoke(0x140236120, a1, a2, dvar, value); - } - - const char* db_read_raw_file_stub(const char* filename, char* buf, const int size) - { - std::string file_name = filename; - if (file_name.find(".cfg") == std::string::npos) - { - file_name.append(".cfg"); - } - - const auto file = filesystem::file(file_name); - if (file.exists()) - { - snprintf(buf, size, "%s\n", file.get_buffer().data()); - return buf; - } - - // DB_ReadRawFile - return utils::hook::invoke(SELECT_VALUE(0x1401CD4F0, 0x1402BEF10), filename, buf, size); - } - - void bsp_sys_error_stub(const char* error, const char* arg1) - { - if (game::environment::is_dedi()) - { - game::Sys_Error(error, arg1); - } - else - { - scheduler::once([]() - { - command::execute("reconnect"); - }, scheduler::pipeline::main, 1s); - game::Com_Error(game::ERR_DROP, error, arg1); - } - } - - utils::hook::detour cmd_lui_notify_server_hook; - void cmd_lui_notify_server_stub(game::mp::gentity_s* ent) - { - command::params_sv params{}; - const auto menu_id = atoi(params.get(1)); - const auto client = &game::mp::svs_clients[ent->s.entityNum]; - - // 22 => "end_game" - if (menu_id == 22 && client->header.remoteAddress.type != game::NA_LOOPBACK) - { - return; - } - - cmd_lui_notify_server_hook.invoke(ent); - } - - void sv_execute_client_message_stub(game::mp::client_t* client, game::msg_t* msg) - { - if (client->reliableAcknowledge < 0) - { - client->reliableAcknowledge = client->reliableSequence; - console::info("Negative reliableAcknowledge from %s - cl->reliableSequence is %i, reliableAcknowledge is %i\n", - client->name, client->reliableSequence, client->reliableAcknowledge); - network::send(client->header.remoteAddress, "error", "EXE_LOSTRELIABLECOMMANDS", '\n'); - return; - } - - utils::hook::invoke(0x140481A00, client, msg); - } - - void aim_assist_add_to_target_list(void* a1, void* a2) - { - if (!dvars::aimassist_enabled->current.enabled) - return; - - game::AimAssist_AddToTargetList(a1, a2); - } - } - - class component final : public component_interface - { - public: - void post_unpack() override - { - // Register dvars - com_register_dvars_hook.create(SELECT_VALUE(0x140351B80, 0x1400D9320), &com_register_dvars_stub); // H1(1.4) - - // Unlock fps in main menu - utils::hook::set(SELECT_VALUE(0x14018D47B, 0x14025B86B), 0xEB); // H1(1.4) - - if (!game::environment::is_dedi()) - { - // Fix mouse lag - utils::hook::nop(SELECT_VALUE(0x1403E3C05, 0x1404DB1AF), 6); - scheduler::loop([]() - { - SetThreadExecutionState(ES_DISPLAY_REQUIRED); - }, scheduler::pipeline::main); - } - - // Make cg_fov and cg_fovscale saved dvars - dvars::override::register_float("cg_fov", 65.f, 40.f, 200.f, game::DvarFlags::DVAR_FLAG_SAVED); - dvars::override::register_float("cg_fovScale", 1.f, 0.1f, 2.f, game::DvarFlags::DVAR_FLAG_SAVED); - - // Allow kbam input when gamepad is enabled - utils::hook::nop(SELECT_VALUE(0x14018797E, 0x14024EF60), 2); - utils::hook::nop(SELECT_VALUE(0x1401856DC, 0x14024C6B0), 6); - - // Allow executing custom cfg files with the "exec" command - utils::hook::call(SELECT_VALUE(0x140343855, 0x140403E28), db_read_raw_file_stub); - - if (!game::environment::is_sp()) - { - patch_mp(); - } - } - - static void patch_mp() - { - // Use name dvar - utils::hook::jump(0x14050FF90, &live_get_local_client_name); // H1(1.4) - - // Patch SV_KickClientNum - sv_kick_client_num_hook.create(0x14047ED00, &sv_kick_client_num); // H1(1.4) - - // block changing name in-game - utils::hook::set(0x14047FC90, 0xC3); // H1(1.4) - - // patch "Couldn't find the bsp for this map." error to not be fatal in mp - utils::hook::call(0x1402BA26B, bsp_sys_error_stub); // H1(1.4) - - // client side aim assist dvar - dvars::aimassist_enabled = dvars::register_bool("aimassist_enabled", true, - game::DvarFlags::DVAR_FLAG_SAVED, - true); - utils::hook::call(0x14009EE9E, aim_assist_add_to_target_list); - - // unlock all items - utils::hook::jump(0x140413E60, is_item_unlocked); // LiveStorage_IsItemUnlockedFromTable_LocalClient H1(1.4) - utils::hook::jump(0x140413860, is_item_unlocked); // LiveStorage_IsItemUnlockedFromTable H1(1.4) - utils::hook::jump(0x140412B70, is_item_unlocked); // idk ( unlocks loot etc ) H1(1.4) - - // isProfanity - utils::hook::set(0x1402877D0, 0xC3C033); // MAY BE WRONG H1(1.4) - - // disable emblems - dvars::override::register_int("emblems_active", 0, 0, 0, game::DVAR_FLAG_NONE); - utils::hook::set(0x140479590, 0xC3); // don't register commands - - // disable elite_clan - dvars::override::register_int("elite_clan_active", 0, 0, 0, game::DVAR_FLAG_NONE); - utils::hook::set(0x140585680, 0xC3); // don't register commands H1(1.4) - - // disable codPointStore - dvars::override::register_int("codPointStore_enabled", 0, 0, 0, game::DVAR_FLAG_NONE); - - // don't register every replicated dvar as a network dvar - utils::hook::nop(0x14039E58E, 5); // dvar_foreach H1(1.4) - - // patch "Server is different version" to show the server client version - utils::hook::inject(0x140480952, VERSION); // H1(1.4) - - // prevent servers overriding our fov - utils::hook::call(0x14023279E, set_client_dvar_from_server_stub); - utils::hook::nop(0x1400DAF69, 5); - utils::hook::nop(0x140190C16, 5); - utils::hook::set(0x14021D22A, 0xEB); - - // unlock safeArea_* - utils::hook::jump(0x1402624F5, 0x140262503); // H1(1.4) - utils::hook::jump(0x14026251C, 0x140262547); // H1(1.4) - dvars::override::register_int("safeArea_adjusted_horizontal", 1, 0, 1, game::DVAR_FLAG_SAVED); - dvars::override::register_int("safeArea_adjusted_vertical", 1, 0, 1, game::DVAR_FLAG_SAVED); - dvars::override::register_int("safeArea_horizontal", 1, 0, 1, game::DVAR_FLAG_SAVED); - dvars::override::register_int("safeArea_vertical", 1, 0, 1, game::DVAR_FLAG_SAVED); - - // move chat position on the screen above menu splashes - dvars::override::register_vec2("cg_hudChatPosition", 5, 170, 0, 640, game::DVAR_FLAG_SAVED); - - // allow servers to check for new packages more often - dvars::override::register_int("sv_network_fps", 1000, 20, 1000, game::DVAR_FLAG_SAVED); - - // Massively increate timeouts - dvars::override::register_int("cl_timeout", 90, 90, 1800, game::DVAR_FLAG_NONE); // Seems unused - dvars::override::register_int("sv_timeout", 90, 90, 1800, game::DVAR_FLAG_NONE); // 30 - 0 - 1800 - dvars::override::register_int("cl_connectTimeout", 120, 120, 1800, game::DVAR_FLAG_NONE); // Seems unused - dvars::override::register_int("sv_connectTimeout", 120, 120, 1800, game::DVAR_FLAG_NONE); // 60 - 0 - 1800 - - dvars::register_int("scr_game_spectatetype", 1, 0, 99, game::DVAR_FLAG_REPLICATED); - - dvars::override::register_int("com_maxfps", 0, 10, 1000, game::DVAR_FLAG_SAVED); - - // Prevent clients from ending the game as non host by sending 'end_game' lui notification - // cmd_lui_notify_server_hook.create(0x140335A70, cmd_lui_notify_server_stub); // H1(1.4) - - // Prevent clients from sending invalid reliableAcknowledge - // utils::hook::call(0x1404899C6, sv_execute_client_message_stub); // H1(1.4) - - // "fix" for rare 'Out of memory error' error - if (utils::flags::has_flag("memoryfix")) - { - utils::hook::jump(0x140578BE0, malloc); - utils::hook::jump(0x140578B00, _aligned_malloc); - utils::hook::jump(0x140578C40, free); - utils::hook::jump(0x140578D30, realloc); - utils::hook::jump(0x140578B60, _aligned_realloc); - } - - // Change default hostname and make it replicated - dvars::override::register_string("sv_hostname", "^2H1-Mod^7 Default Server", game::DVAR_FLAG_REPLICATED); - } - }; -} - -REGISTER_COMPONENT(patches::component) diff --git a/src/client/component/renderer.cpp b/src/client/component/renderer.cpp deleted file mode 100644 index b315be76..00000000 --- a/src/client/component/renderer.cpp +++ /dev/null @@ -1,77 +0,0 @@ -#include -#include "loader/component_loader.hpp" -#include "game/game.hpp" -#include "game/dvars.hpp" - -#include - -namespace renderer -{ - namespace - { - utils::hook::detour r_init_draw_method_hook; - utils::hook::detour r_update_front_end_dvar_options_hook; - - int get_fullbright_technique() - { - return game::TECHNIQUE_UNLIT; - } - - void gfxdrawmethod() - { - game::gfxDrawMethod->drawScene = game::GFX_DRAW_SCENE_STANDARD; - - game::gfxDrawMethod->baseTechType = dvars::r_fullbright->current.enabled ? get_fullbright_technique() : game::TECHNIQUE_LIT; - game::gfxDrawMethod->emissiveTechType = dvars::r_fullbright->current.enabled ? get_fullbright_technique() : game::TECHNIQUE_EMISSIVE; - game::gfxDrawMethod->forceTechType = dvars::r_fullbright->current.enabled ? get_fullbright_technique() : 242; - } - - void r_init_draw_method_stub() - { - gfxdrawmethod(); - } - - bool r_update_front_end_dvar_options_stub() - { - if (dvars::r_fullbright->modified) - { - //game::Dvar_ClearModified(dvars::r_fullbright); - game::R_SyncRenderThread(); - - gfxdrawmethod(); - } - - return r_update_front_end_dvar_options_hook.invoke(); - } - } - - class component final : public component_interface - { - public: - void post_unpack() override - { - if (game::environment::is_dedi() || !game::environment::is_mp()) - { - return; - } - - dvars::r_fullbright = dvars::register_int("r_fullbright", 0, 0, 3, game::DVAR_FLAG_SAVED); - - r_init_draw_method_hook.create(SELECT_VALUE(0x1404BD140, 0x1405C46E0), &r_init_draw_method_stub); - r_update_front_end_dvar_options_hook.create(SELECT_VALUE(0x1404F8870, 0x1405FF9E0), &r_update_front_end_dvar_options_stub); - - // use "saved" flags for "r_normalMap" - utils::hook::set(SELECT_VALUE(0x1404CF5CA, 0x1405D460E), game::DVAR_FLAG_SAVED); - - // use "saved" flags for "r_specularMap" - utils::hook::set(SELECT_VALUE(0x1404CF5F5, 0x1405D4639), game::DVAR_FLAG_SAVED); - - // use "saved" flags for "r_specOccMap" - utils::hook::set(SELECT_VALUE(0x1404CF620, 0x1405D4664), game::DVAR_FLAG_SAVED); - } - }; -} - -#ifdef DEBUG -REGISTER_COMPONENT(renderer::component) -#endif \ No newline at end of file diff --git a/src/client/component/scheduler.cpp b/src/client/component/scheduler.cpp index ac837128..9a8911eb 100644 --- a/src/client/component/scheduler.cpp +++ b/src/client/component/scheduler.cpp @@ -180,9 +180,9 @@ namespace scheduler void post_unpack() override { - r_end_frame_hook.create(SELECT_VALUE(0, 0x6A6300_b), scheduler::r_end_frame_stub); // H1-STEAM(1.15) - g_run_frame_hook.create(SELECT_VALUE(0, 0x417940_b), scheduler::server_frame_stub); // H1(1.15) - //main_frame_hook.create(SELECT_VALUE(0x1401CE8D0, 0x1400D8310), scheduler::main_frame_stub); can't find + r_end_frame_hook.create(SELECT_VALUE(0, 0x6A6300_b), scheduler::r_end_frame_stub); + g_run_frame_hook.create(SELECT_VALUE(0, 0x417940_b), scheduler::server_frame_stub); + main_frame_hook.create(SELECT_VALUE(0, 0x1400D8310), scheduler::main_frame_stub); // I REPEAT, ARXAN IS PAIN } void pre_destroy() override @@ -196,4 +196,4 @@ namespace scheduler }; } -REGISTER_COMPONENT(scheduler::component) +REGISTER_COMPONENT(scheduler::component) \ No newline at end of file diff --git a/src/client/component/scripting.cpp b/src/client/component/scripting.cpp deleted file mode 100644 index e3116122..00000000 --- a/src/client/component/scripting.cpp +++ /dev/null @@ -1,141 +0,0 @@ -#include -#include "loader/component_loader.hpp" - -#include "game/game.hpp" -#include - -#include "game/scripting/entity.hpp" -#include "game/scripting/functions.hpp" -#include "game/scripting/event.hpp" -#include "game/scripting/lua/engine.hpp" -#include "game/scripting/execution.hpp" - -#include "scheduler.hpp" -#include "scripting.hpp" - -namespace scripting -{ - std::unordered_map> fields_table; - std::unordered_map> script_function_table; - - namespace - { - utils::hook::detour vm_notify_hook; - utils::hook::detour scr_load_level_hook; - utils::hook::detour g_shutdown_game_hook; - - utils::hook::detour scr_add_class_field_hook; - - utils::hook::detour scr_set_thread_position_hook; - utils::hook::detour process_script_hook; - - std::string current_file; - - void vm_notify_stub(const unsigned int notify_list_owner_id, const game::scr_string_t string_value, - game::VariableValue* top) - { - if (!game::VirtualLobby_Loaded()) - { - const auto* string = game::SL_ConvertToString(string_value); - if (string) - { - event e; - e.name = string; - e.entity = notify_list_owner_id; - - for (auto* value = top; value->type != game::SCRIPT_END; --value) - { - e.arguments.emplace_back(*value); - } - - if (e.name == "entitydeleted") - { - scripting::clear_entity_fields(e.entity); - } - - lua::engine::notify(e); - } - } - - vm_notify_hook.invoke(notify_list_owner_id, string_value, top); - } - - void scr_load_level_stub() - { - scr_load_level_hook.invoke(); - if (!game::VirtualLobby_Loaded()) - { - lua::engine::start(); - } - } - - void g_shutdown_game_stub(const int free_scripts) - { - lua::engine::stop(); - return g_shutdown_game_hook.invoke(free_scripts); - } - - void scr_add_class_field_stub(unsigned int classnum, game::scr_string_t _name, unsigned int canonicalString, unsigned int offset) - { - const auto name = game::SL_ConvertToString(_name); - - if (fields_table[classnum].find(name) == fields_table[classnum].end()) - { - fields_table[classnum][name] = offset; - } - - scr_add_class_field_hook.invoke(classnum, _name, canonicalString, offset); - } - - void process_script_stub(const char* filename) - { - const auto file_id = atoi(filename); - if (file_id) - { - current_file = scripting::find_token(file_id); - } - else - { - current_file = filename; - } - - process_script_hook.invoke(filename); - } - - void scr_set_thread_position_stub(unsigned int threadName, const char* codePos) - { - const auto function_name = scripting::find_token(threadName); - script_function_table[current_file][function_name] = codePos; - scr_set_thread_position_hook.invoke(threadName, codePos); - } - } - - class component final : public component_interface - { - public: - void post_unpack() override - { - if (game::environment::is_sp()) - { - return; - } - - vm_notify_hook.create(SELECT_VALUE(0x140379A00, 0x1404479F0), vm_notify_stub); - - scr_add_class_field_hook.create(SELECT_VALUE(0x140370370, 0x14043E2C0), scr_add_class_field_stub); - - scr_set_thread_position_hook.create(SELECT_VALUE(0x14036A180, 0x140437D10), scr_set_thread_position_stub); - process_script_hook.create(SELECT_VALUE(0x1403737E0, 0x1404417E0), process_script_stub); - - scr_load_level_hook.create(SELECT_VALUE(0x1402A5BE0, 0x1403727C0), scr_load_level_stub); - g_shutdown_game_hook.create(SELECT_VALUE(0x140277D40, 0x140345A60), g_shutdown_game_stub); - - scheduler::loop([]() - { - lua::engine::run_frame(); - }, scheduler::pipeline::server); - } - }; -} - -REGISTER_COMPONENT(scripting::component) \ No newline at end of file diff --git a/src/client/component/scripting.hpp b/src/client/component/scripting.hpp deleted file mode 100644 index 865ae858..00000000 --- a/src/client/component/scripting.hpp +++ /dev/null @@ -1,8 +0,0 @@ -#pragma once -#include - -namespace scripting -{ - extern std::unordered_map> fields_table; - extern std::unordered_map> script_function_table; -} \ No newline at end of file diff --git a/src/client/component/server_list.cpp b/src/client/component/server_list.cpp deleted file mode 100644 index 1b7e759e..00000000 --- a/src/client/component/server_list.cpp +++ /dev/null @@ -1,443 +0,0 @@ -#include -#include "loader/component_loader.hpp" -#include "server_list.hpp" -#include "localized_strings.hpp" -#include "network.hpp" -#include "scheduler.hpp" -#include "party.hpp" -#include "game/game.hpp" - -#include -#include -#include - -#include "console.hpp" -#include "command.hpp" - -namespace server_list -{ - namespace - { - const int server_limit = 18; - - struct server_info - { - // gotta add more to this - int clients; - int max_clients; - int bots; - int ping; - std::string host_name; - std::string map_name; - std::string game_type; - game::CodPlayMode play_mode; - char in_game; - game::netadr_s address; - }; - - struct - { - game::netadr_s address{}; - volatile bool requesting = false; - std::unordered_map queued_servers{}; - } master_state; - - std::mutex mutex; - std::vector servers; - - size_t server_list_page = 0; - volatile bool update_server_list = false; - std::chrono::high_resolution_clock::time_point last_scroll{}; - - size_t get_page_count() - { - const auto count = servers.size() / server_limit; - return count + (servers.size() % server_limit > 0); - } - - size_t get_page_base_index() - { - return server_list_page * server_limit; - } - - void refresh_server_list() - { - { - std::lock_guard _(mutex); - servers.clear(); - master_state.queued_servers.clear(); - server_list_page = 0; - } - - party::reset_connect_state(); - - if (get_master_server(master_state.address)) - { - master_state.requesting = true; - - network::send(master_state.address, "getservers", utils::string::va("H1 %i full empty", PROTOCOL)); - } - } - - void join_server(int, int, const int index) - { - std::lock_guard _(mutex); - - const auto i = static_cast(index) + get_page_base_index(); - if (i < servers.size()) - { - static auto last_index = ~0ull; - if (last_index != i) - { - last_index = i; - } - else - { - console::info("Connecting to (%d - %zu): %s\n", index, i, servers[i].host_name.data()); - party::connect(servers[i].address); - } - } - } - - void trigger_refresh() - { - update_server_list = true; - } - - int ui_feeder_count() - { - std::lock_guard _(mutex); - if (update_server_list) - { - update_server_list = false; - return 0; - } - const auto count = static_cast(servers.size()); - const auto index = get_page_base_index(); - const auto diff = count - index; - return diff > server_limit ? server_limit : static_cast(diff); - } - - const char* ui_feeder_item_text(int /*localClientNum*/, void* /*a2*/, void* /*a3*/, const int index, - const int column) - { - std::lock_guard _(mutex); - - const auto i = get_page_base_index() + index; - - if (i >= servers.size()) - { - return ""; - } - - if (column == 0) - { - return servers[i].host_name.empty() ? "" : utils::string::va("%s", servers[i].host_name.data()); - } - - if (column == 1) - { - return servers[i].map_name.empty() ? "Unknown" : utils::string::va("%s", servers[i].map_name.data()); - } - - if (column == 2) - { - return utils::string::va("%d/%d [%d]", servers[i].clients, servers[index].max_clients, - servers[i].bots); - } - - if (column == 3) - { - return servers[i].game_type.empty() ? "" : utils::string::va("%s", servers[i].game_type.data()); - } - - if (column == 4) - { - return servers[i].game_type.empty() ? "" : utils::string::va("%i", servers[i].ping); - } - - return ""; - } - - void sort_serverlist() - { - std::stable_sort(servers.begin(), servers.end(), [](const server_info& a, const server_info& b) - { - if (a.clients == b.clients) - { - return a.ping < b.ping; - } - - return a.clients > b.clients; - }); - } - - void insert_server(server_info&& server) - { - std::lock_guard _(mutex); - servers.emplace_back(std::move(server)); - sort_serverlist(); - trigger_refresh(); - } - - void do_frame_work() - { - auto& queue = master_state.queued_servers; - if (queue.empty()) - { - return; - } - - std::lock_guard _(mutex); - - size_t queried_servers = 0; - const size_t query_limit = 3; - - for (auto i = queue.begin(); i != queue.end();) - { - if (i->second) - { - const auto now = game::Sys_Milliseconds(); - if (now - i->second > 10'000) - { - i = queue.erase(i); - continue; - } - } - else if (queried_servers++ < query_limit) - { - i->second = game::Sys_Milliseconds(); - network::send(i->first, "getInfo", utils::cryptography::random::get_challenge()); - } - - ++i; - } - } - - bool is_server_list_open() - { - return game::Menu_IsMenuOpenAndVisible(0, "menu_systemlink_join"); - } - - bool is_scrolling_disabled() - { - return update_server_list || (std::chrono::high_resolution_clock::now() - last_scroll) < 500ms; - } - - bool scroll_down() - { - if (!is_server_list_open()) - { - return false; - } - - if (!is_scrolling_disabled() && server_list_page + 1 < get_page_count()) - { - last_scroll = std::chrono::high_resolution_clock::now(); - ++server_list_page; - trigger_refresh(); - } - - return true; - } - - bool scroll_up() - { - if (!is_server_list_open()) - { - return false; - } - - if (!is_scrolling_disabled() && server_list_page > 0) - { - last_scroll = std::chrono::high_resolution_clock::now(); - --server_list_page; - trigger_refresh(); - } - - return true; - } - - void resize_host_name(std::string& name) - { - name = utils::string::split(name, '\n').front(); - - game::Font_s* font = game::R_RegisterFont("fonts/default.otf", 18); - auto text_size = game::UI_TextWidth(name.data(), 32, font, 1.0f); - - while (text_size > 450) - { - text_size = game::UI_TextWidth(name.data(), 32, font, 1.0f); - name.pop_back(); - } - } - - utils::hook::detour lui_open_menu_hook; - - void lui_open_menu_stub(int controllerIndex, const char* menu, int a3, int a4, unsigned int a5) - { -#ifdef DEBUG - console::info("[LUI] %s\n", menu); -#endif - - if (!strcmp(menu, "menu_systemlink_join")) - { - refresh_server_list(); - } - - lui_open_menu_hook.invoke(controllerIndex, menu, a3, a4, a5); - } - } - - bool sl_key_event(const int key, const int down) - { - if (down) - { - if (key == game::keyNum_t::K_MWHEELUP) - { - return !scroll_up(); - } - - if (key == game::keyNum_t::K_MWHEELDOWN) - { - return !scroll_down(); - } - } - - return true; - } - - bool get_master_server(game::netadr_s& address) - { - return game::NET_StringToAdr("135.148.53.121:20810", &address); - // return game::NET_StringToAdr("master.xlabs.dev:20810", &address); - } - - void handle_info_response(const game::netadr_s& address, const utils::info_string& info) - { - // Don't show servers that aren't dedicated! - const auto dedicated = std::atoi(info.get("dedicated").data()); - if (!dedicated) - { - return; - } - - // Don't show servers that aren't running! - const auto sv_running = std::atoi(info.get("sv_running").data()); - if (!sv_running) - { - return; - } - - // Only handle servers of the same playmode! - const auto playmode = game::CodPlayMode(std::atoi(info.get("playmode").data())); - if (game::Com_GetCurrentCoDPlayMode() != playmode) - { - return; - } - - int start_time{}; - const auto now = game::Sys_Milliseconds(); - - { - std::lock_guard _(mutex); - const auto entry = master_state.queued_servers.find(address); - - if (entry == master_state.queued_servers.end() || !entry->second) - { - return; - } - - start_time = entry->second; - master_state.queued_servers.erase(entry); - } - - server_info server{}; - server.address = address; - server.host_name = info.get("hostname"); - server.map_name = game::UI_GetMapDisplayName(info.get("mapname").data()); - server.game_type = game::UI_GetGameTypeDisplayName(info.get("gametype").data()); - server.play_mode = playmode; - server.clients = atoi(info.get("clients").data()); - server.max_clients = atoi(info.get("sv_maxclients").data()); - server.bots = atoi(info.get("bots").data()); - server.ping = std::min(now - start_time, 999); - - server.in_game = 1; - - resize_host_name(server.host_name); - - insert_server(std::move(server)); - } - - class component final : public component_interface - { - public: - void post_unpack() override - { - if (!game::environment::is_mp()) return; - - localized_strings::override("PLATFORM_SYSTEM_LINK_TITLE", "SERVER LIST"); - - // hook LUI_OpenMenu to refresh server list for system link menu - lui_open_menu_hook.create(game::LUI_OpenMenu, lui_open_menu_stub); - - // replace UI_RunMenuScript call in LUI_CoD_LuaCall_RefreshServerList to our refresh_servers - utils::hook::call(0x14018A0C9, &refresh_server_list); - utils::hook::call(0x14018A5DE, &join_server); - utils::hook::nop(0x14018A5FD, 5); - - // do feeder stuff - utils::hook::call(0x14018A199, &ui_feeder_count); - utils::hook::call(0x14018A3B1, &ui_feeder_item_text); - - scheduler::loop(do_frame_work, scheduler::pipeline::main); - - network::on("getServersResponse", [](const game::netadr_s& target, const std::string_view& data) - { - { - std::lock_guard _(mutex); - if (!master_state.requesting || master_state.address != target) - { - return; - } - - master_state.requesting = false; - - std::optional start{}; - for (size_t i = 0; i + 6 < data.size(); ++i) - { - if (data[i + 6] == '\\') - { - start.emplace(i); - break; - } - } - - if (!start.has_value()) - { - return; - } - - for (auto i = start.value(); i + 6 < data.size(); i += 7) - { - if (data[i + 6] != '\\') - { - break; - } - - game::netadr_s address{}; - address.type = game::NA_IP; - address.localNetID = game::NS_CLIENT1; - memcpy(&address.ip[0], data.data() + i + 0, 4); - memcpy(&address.port, data.data() + i + 4, 2); - - master_state.queued_servers[address] = 0; - } - } - }); - } - }; -} - -REGISTER_COMPONENT(server_list::component) diff --git a/src/client/component/server_list.hpp b/src/client/component/server_list.hpp deleted file mode 100644 index d9974cfa..00000000 --- a/src/client/component/server_list.hpp +++ /dev/null @@ -1,12 +0,0 @@ -#pragma once - -#include "game/game.hpp" -#include - -namespace server_list -{ - bool get_master_server(game::netadr_s& address); - void handle_info_response(const game::netadr_s& address, const utils::info_string& info); - - bool sl_key_event(int key, int down); -} \ No newline at end of file diff --git a/src/client/component/shaders.cpp b/src/client/component/shaders.cpp deleted file mode 100644 index ec632115..00000000 --- a/src/client/component/shaders.cpp +++ /dev/null @@ -1,50 +0,0 @@ -#include -#include "loader/component_loader.hpp" - -#include "scheduler.hpp" -#include "dvars.hpp" - -#include "game/game.hpp" -#include "game/dvars.hpp" - -#include -#include -#include - -namespace shaders -{ - namespace - { - game::dvar_t* disable_shader_caching = nullptr; - - bool shader_should_show_dialog_stub() - { - return !disable_shader_caching->current.enabled; - } - } - - class component final : public component_interface - { - public: - void post_unpack() override - { - if (!game::environment::is_mp()) - { - return; - } - - const auto has_flag = utils::flags::has_flag("noshadercaching"); - - disable_shader_caching = dvars::register_bool("disable_shader_caching", has_flag, game::DVAR_FLAG_SAVED, true); - if (has_flag) - { - dvars::override::set_bool("disable_shader_caching", 1); - dvars::override::set_from_string("disable_shader_caching", "1"); - } - - utils::hook::jump(0x14007E710, shader_should_show_dialog_stub); - } - }; -} - -REGISTER_COMPONENT(shaders::component) diff --git a/src/client/component/slowmotion.cpp b/src/client/component/slowmotion.cpp deleted file mode 100644 index 71f66dbf..00000000 --- a/src/client/component/slowmotion.cpp +++ /dev/null @@ -1,53 +0,0 @@ -#include -#include "loader/component_loader.hpp" -#include "game/game.hpp" - -#include -#include - -namespace slowmotion -{ - namespace - { - void scr_cmd_set_slow_motion() - { - if (game::Scr_GetNumParam() < 1) - { - return; - } - - int duration = 1000; - float end = 1.0f; - const float start = game::Scr_GetFloat(0); - - if (game::Scr_GetNumParam() >= 2) - { - end = game::Scr_GetFloat(1u); - } - - if (game::Scr_GetNumParam() >= 3) - { - duration = static_cast(game::Scr_GetFloat(2u) * 1000.0f); - } - - game::SV_SetConfigstring(10, utils::string::va("%i %i %g %g", *game::mp::gameTime, duration, start, end)); - game::Com_SetSlowMotion(start, end, duration); - } - } - - class component final : public component_interface - { - public: - void post_unpack() override - { - if (!game::environment::is_dedi()) - { - return; - } - - utils::hook::jump(0x140365480, scr_cmd_set_slow_motion); // H1(1.4) - } - }; -} - -REGISTER_COMPONENT(slowmotion::component) diff --git a/src/client/component/splash.cpp b/src/client/component/splash.cpp deleted file mode 100644 index 3dfd6541..00000000 --- a/src/client/component/splash.cpp +++ /dev/null @@ -1,141 +0,0 @@ -#include -#include "loader/component_loader.hpp" -#include "game/game.hpp" -#include "game_module.hpp" - -#include -#include - -namespace splash -{ - class component final : public component_interface - { - public: - void post_start() override - { - const utils::nt::library self; - image_ = LoadImageA(self, MAKEINTRESOURCE(IMAGE_SPLASH), IMAGE_BITMAP, 0, 0, LR_DEFAULTCOLOR); - } - - void post_load() override - { - if (game::environment::is_dedi()) - { - return; - } - - this->show(); - } - - void post_unpack() override - { - // Disable native splash screen - //utils::hook::nop(SELECT_VALUE(0x1403E192E, 0x1405123E2), 5); // winmain doesn't even exist in 1.15? lmao - utils::hook::jump(SELECT_VALUE(0, 0x5BE1D0_b), destroy_stub); // H1-STEAM(1.15) - utils::hook::jump(SELECT_VALUE(0, 0x5BE210_b), destroy_stub); // H1-STEAM(1.15) - } - - void pre_destroy() override - { - this->destroy(); - - MSG msg; - while (this->window_ && IsWindow(this->window_)) - { - if (PeekMessageA(&msg, nullptr, NULL, NULL, PM_REMOVE)) - { - TranslateMessage(&msg); - DispatchMessage(&msg); - } - else - { - std::this_thread::sleep_for(1ms); - } - } - - this->window_ = nullptr; - } - - private: - HWND window_{}; - HANDLE image_{}; - - static void destroy_stub() - { - component_loader::get()->destroy(); - } - - void destroy() const - { - if (this->window_ && IsWindow(this->window_)) - { - ShowWindow(this->window_, SW_HIDE); - DestroyWindow(this->window_); - UnregisterClassA("H1 Splash Screen", utils::nt::library{}); - } - } - - void show() - { - WNDCLASSA wnd_class; - - const auto self = game_module::get_host_module(); - - wnd_class.style = CS_DROPSHADOW; - wnd_class.cbClsExtra = 0; - wnd_class.cbWndExtra = 0; - wnd_class.lpszMenuName = nullptr; - wnd_class.lpfnWndProc = DefWindowProcA; - wnd_class.hInstance = self; - wnd_class.hIcon = LoadIconA(self, reinterpret_cast(102)); - wnd_class.hCursor = LoadCursorA(nullptr, IDC_APPSTARTING); - wnd_class.hbrBackground = reinterpret_cast(6); - wnd_class.lpszClassName = "H1 Splash Screen"; - - if (RegisterClassA(&wnd_class)) - { - const auto x_pixels = GetSystemMetrics(SM_CXFULLSCREEN); - const auto y_pixels = GetSystemMetrics(SM_CYFULLSCREEN); - - if (image_) - { - this->window_ = CreateWindowExA(WS_EX_APPWINDOW, "H1 Splash Screen", "H1", - WS_POPUP | WS_SYSMENU, - (x_pixels - 320) / 2, (y_pixels - 100) / 2, 320, 100, nullptr, - nullptr, - self, nullptr); - - if (this->window_) - { - auto* const image_window = CreateWindowExA(0, "Static", nullptr, WS_CHILD | WS_VISIBLE | 0xEu, - 0, 0, - 320, 100, this->window_, nullptr, self, nullptr); - if (image_window) - { - RECT rect; - SendMessageA(image_window, 0x172u, 0, reinterpret_cast(image_)); - GetWindowRect(image_window, &rect); - - const int width = rect.right - rect.left; - rect.left = (x_pixels - width) / 2; - - const int height = rect.bottom - rect.top; - rect.top = (y_pixels - height) / 2; - - rect.right = rect.left + width; - rect.bottom = rect.top + height; - AdjustWindowRect(&rect, WS_CHILD | WS_VISIBLE | 0xEu, 0); - SetWindowPos(this->window_, nullptr, rect.left, rect.top, rect.right - rect.left, - rect.bottom - rect.top, SWP_NOZORDER); - - ShowWindow(this->window_, SW_SHOW); - UpdateWindow(this->window_); - } - } - } - } - } - }; -} - -REGISTER_COMPONENT(splash::component) diff --git a/src/client/component/system_check.cpp b/src/client/component/system_check.cpp index 9c88bd5c..e3631248 100644 --- a/src/client/component/system_check.cpp +++ b/src/client/component/system_check.cpp @@ -51,27 +51,28 @@ namespace system_check { static std::unordered_map mp_zone_hashes = { - {"patch_common_mp.ff", "3F44B0CFB0B8E0FBD9687C2942204AB7F11E66E6E15C73B8B4A5EB5920115A31"}, + {"patch_common_mp.ff", "E45EF5F29D12A5A47F405F89FBBEE479C0A90D02141ABF852D481689514134A1"}, }; static std::unordered_map sp_zone_hashes = { // Steam doesn't necessarily deliver this file :( - {"patch_common.ff", "BB0617DD94AF2F511571E7184BBEDE76E64D97E5D0DAFDB457F00717F035EBF0"}, + {"patch_common.ff", "1D32A9770F90ED022AA76F4859B4AB178E194A703383E61AC2CE83B1E828B18F"}, }; return verify_hashes(mp_zone_hashes) && (game::environment::is_dedi() || verify_hashes(sp_zone_hashes)); } - void verify_binary_version() - { - const auto value = *reinterpret_cast(0x140001337); - if (value != 0xFFB8006D && value != 0xFFB80080) - { - throw std::runtime_error("Unsupported Call of Duty: Modern Warfare Remastered version(1.4)"); - } - } + //void verify_binary_version() + //{ + // if (*(int*)(uint64_t(GetModuleHandle(NULL)) + 0x4CCD3D) != 1251288) + // { + // MessageBoxA(0, "UNSUPPORTED VERSION MWR(1.15)", "H1MP-STEAM", MB_ICONWARNING); + + // return; + // } + //} } bool is_valid() @@ -85,12 +86,12 @@ namespace system_check public: void post_load() override { - verify_binary_version(); + //verify_binary_version(); if (!is_valid()) { MessageBoxA(nullptr, "Your game files are outdated or unsupported.\n" - "Please get the latest officially supported Call of Duty: Modern Warfare Remastered 1.4 files, or you will get random crashes and issues.", + "Please get the latest officially supported Call of Duty: Modern Warfare Remastered 1.15 STEAM files, or you will get random crashes and issues.", "Invalid game files!", MB_ICONINFORMATION); } } diff --git a/src/client/component/thread_names.cpp b/src/client/component/thread_names.cpp deleted file mode 100644 index 84b5fa70..00000000 --- a/src/client/component/thread_names.cpp +++ /dev/null @@ -1,60 +0,0 @@ -#include -#include "loader/component_loader.hpp" - -#include "scheduler.hpp" - -#include "game/game.hpp" - -#include - -namespace thread_names -{ - namespace - { - void set_thread_names() - { - static std::unordered_map thread_names = - { - {game::THREAD_CONTEXT_MAIN, "Main"}, - {game::THREAD_CONTEXT_BACKEND, "Backend"}, // Renderer - {game::THREAD_CONTEXT_WORKER0, "Worker0"}, - {game::THREAD_CONTEXT_WORKER1, "Worker1"}, - {game::THREAD_CONTEXT_WORKER2, "Worker2"}, - {game::THREAD_CONTEXT_WORKER3, "Worker3"}, - {game::THREAD_CONTEXT_WORKER4, "Worker4"}, - {game::THREAD_CONTEXT_WORKER5, "Worker5"}, - {game::THREAD_CONTEXT_WORKER6, "Worker6"}, - {game::THREAD_CONTEXT_WORKER7, "Worker7"}, - {game::THREAD_CONTEXT_SERVER, "Server"}, - {game::THREAD_CONTEXT_CINEMATIC, "Cinematic"}, - {game::THREAD_CONTEXT_DATABASE, "Database"}, - {game::THREAD_CONTEXT_STREAM, "Stream"}, - {game::THREAD_CONTEXT_SNDSTREAMPACKETCALLBACK, "Snd stream packet callback"}, - {game::THREAD_CONTEXT_STATS_WRITE, "Stats write"}, - }; - - for (const auto& thread_name : thread_names) - { - const auto id = game::threadIds[thread_name.first]; - if (id) - { - utils::thread::set_name(id, thread_name.second); - } - } - } - } - - class component final : public component_interface - { - public: - void post_unpack() override - { - set_thread_names(); - scheduler::once(set_thread_names, scheduler::pipeline::main); - scheduler::once(set_thread_names, scheduler::pipeline::renderer); - scheduler::once(set_thread_names, scheduler::pipeline::server); - } - }; -} - -REGISTER_COMPONENT(thread_names::component) diff --git a/src/client/component/ui_scripting.cpp b/src/client/component/ui_scripting.cpp deleted file mode 100644 index 941dda10..00000000 --- a/src/client/component/ui_scripting.cpp +++ /dev/null @@ -1,180 +0,0 @@ -#include -#include "loader/component_loader.hpp" - -#include "game/game.hpp" -#include "game/dvars.hpp" - -#include "scheduler.hpp" -#include "command.hpp" - -#include "ui_scripting.hpp" - -#include "game/ui_scripting/lua/engine.hpp" -#include "game/ui_scripting/execution.hpp" -#include "game/ui_scripting/lua/error.hpp" - -#include -#include - -namespace ui_scripting -{ - namespace - { - std::unordered_map converted_functions; - - utils::hook::detour hksi_lual_error_hook; - utils::hook::detour hksi_lual_error_hook2; - utils::hook::detour hks_start_hook; - utils::hook::detour hks_shutdown_hook; - utils::hook::detour hks_allocator_hook; - utils::hook::detour hks_frame_hook; - - bool error_hook_enabled = false; - - void hksi_lual_error_stub(game::hks::lua_State* s, const char* fmt, ...) - { - char va_buffer[2048] = {0}; - - va_list ap; - va_start(ap, fmt); - vsprintf_s(va_buffer, fmt, ap); - va_end(ap); - - const auto formatted = std::string(va_buffer); - - if (!error_hook_enabled) - { - return hksi_lual_error_hook.invoke(s, formatted.data()); - } - else - { - throw std::runtime_error(formatted); - } - } - - void* hks_start_stub(char a1) - { - const auto _1 = gsl::finally([]() - { - ui_scripting::lua::engine::start(); - }); - - return hks_start_hook.invoke(a1); - } - - void hks_shutdown_stub() - { - ui_scripting::lua::engine::stop(); - hks_shutdown_hook.invoke(); - } - - void* hks_allocator_stub(void* userData, void* oldMemory, unsigned __int64 oldSize, unsigned __int64 newSize) - { - const auto closure = reinterpret_cast(oldMemory); - if (converted_functions.find(closure) != converted_functions.end()) - { - converted_functions.erase(closure); - } - - return hks_allocator_hook.invoke(userData, oldMemory, oldSize, newSize); - } - - void hks_frame_stub() - { - const auto state = *game::hks::lua_state; - if (state) - { - ui_scripting::lua::engine::run_frame(); - } - } - } - - int main_function_handler(game::hks::lua_State* state) - { - const auto value = state->m_apistack.base[-1]; - if (value.t != game::hks::TCFUNCTION) - { - return 0; - } - - const auto closure = reinterpret_cast(value.v.cClosure); - if (converted_functions.find(closure) == converted_functions.end()) - { - return 0; - } - - const auto function = converted_functions[closure]; - const auto count = static_cast(state->m_apistack.top - state->m_apistack.base); - const auto arguments = get_return_values(count); - const auto s = function.lua_state(); - - std::vector converted_args; - - for (const auto& argument : arguments) - { - converted_args.push_back(lua::convert(s, argument)); - } - - const auto results = function(sol::as_args(converted_args)); - lua::handle_error(results); - - for (const auto& result : results) - { - push_value(lua::convert({s, result})); - } - - return results.return_count(); - } - - void add_converted_function(game::hks::cclosure* closure, const sol::protected_function& function) - { - converted_functions[closure] = function; - } - - void clear_converted_functions() - { - converted_functions.clear(); - } - - void enable_error_hook() - { - error_hook_enabled = true; - } - - void disable_error_hook() - { - error_hook_enabled = false; - } - - class component final : public component_interface - { - public: - - void post_unpack() override - { - if (game::environment::is_dedi()) - { - return; - } - - hks_start_hook.create(SELECT_VALUE(0x1400E4B40, 0x140176A40), hks_start_stub); - hks_shutdown_hook.create(SELECT_VALUE(0x1400DD3D0, 0x14016CA80), hks_shutdown_stub); - hksi_lual_error_hook.create(SELECT_VALUE(0x1400A5EA0, 0x14012F300), hksi_lual_error_stub); - hks_allocator_hook.create(SELECT_VALUE(0x14009B570, 0x14012BAC0), hks_allocator_stub); - hks_frame_hook.create(SELECT_VALUE(0x1400E37F0, 0x1401755B0), hks_frame_stub); - - if (game::environment::is_mp()) - { - hksi_lual_error_hook2.create(0x1401366B0, hksi_lual_error_stub); - } - - command::add("lui_restart", []() - { - utils::hook::invoke(SELECT_VALUE(0x1400DD3D0, 0x14016CA80)); - utils::hook::invoke(SELECT_VALUE(0x1400E6170, 0x1401780D0)); - }); - } - }; -} - -REGISTER_COMPONENT(ui_scripting::component) \ No newline at end of file diff --git a/src/client/component/ui_scripting.hpp b/src/client/component/ui_scripting.hpp deleted file mode 100644 index 2a48f6ec..00000000 --- a/src/client/component/ui_scripting.hpp +++ /dev/null @@ -1,12 +0,0 @@ -#pragma once -#include "game/ui_scripting/lua/value_conversion.hpp" - -namespace ui_scripting -{ - int main_function_handler(game::hks::lua_State* state); - void add_converted_function(game::hks::cclosure* closure, const sol::protected_function& function); - void clear_converted_functions(); - - void enable_error_hook(); - void disable_error_hook(); -} \ No newline at end of file diff --git a/src/client/component/updater.cpp b/src/client/component/updater.cpp deleted file mode 100644 index 939dbd1c..00000000 --- a/src/client/component/updater.cpp +++ /dev/null @@ -1,474 +0,0 @@ -#include -#include "loader/component_loader.hpp" - -#include "scheduler.hpp" -#include "dvars.hpp" -#include "updater.hpp" - -#include "version.h" - -#include "game/game.hpp" -#include "game/dvars.hpp" - -#include -#include -#include -#include -#include -#include - -#define MASTER "https://master.fed0001.xyz/h1-mod/" - -#define FILES_PATH "files.json" -#define FILES_PATH_DEV "files-dev.json" - -#define DATA_PATH "data/" -#define DATA_PATH_DEV "data-dev/" - -#define ERR_UPDATE_CHECK_FAIL "Failed to check for updates" -#define ERR_DOWNLOAD_FAIL "Failed to download file " -#define ERR_WRITE_FAIL "Failed to write file " - -#define BINARY_NAME "h1-mod.exe" - -namespace updater -{ - namespace - { - game::dvar_t* cl_auto_update; - bool has_tried_update = false; - - struct status - { - bool done; - bool success; - }; - - struct file_data - { - std::string name; - std::string data; - }; - - struct update_data_t - { - bool restart_required{}; - bool cancelled{}; - status check{}; - status download{}; - std::string error{}; - std::string current_file{}; - std::vector required_files{}; - }; - - utils::concurrency::container update_data; - - std::string get_branch() - { - return GIT_BRANCH; - } - - std::string select(const std::string& main, const std::string& develop) - { - if (get_branch() == "develop") - { - return develop; - } - - return main; - } - - std::string get_data_path() - { - if (get_branch() == "develop") - { - return DATA_PATH_DEV; - } - - return DATA_PATH; - } - - void set_update_check_status(bool done, bool success, const std::string& error = {}) - { - update_data.access([done, success, error](update_data_t& data_) - { - data_.check.done = done; - data_.check.success = success; - data_.error = error; - }); - } - - void set_update_download_status(bool done, bool success, const std::string& error = {}) - { - update_data.access([done, success, error](update_data_t& data_) - { - data_.download.done = done; - data_.download.success = success; - data_.error = error; - }); - } - - bool check_file(const std::string& name, const std::string& sha) - { - std::string data; - if (!utils::io::read_file(name, &data)) - { - return false; - } - - if (utils::cryptography::sha1::compute(data, true) != sha) - { - return false; - } - - return true; - } - - std::string load_binary_name() - { - // utils::nt::library self; - // return self.get_name(); - // returns the game's name and not the client's - - return BINARY_NAME; - } - - std::string get_binary_name() - { - static const auto name = load_binary_name(); - return name; - } - - std::string get_time_str() - { - return utils::string::va("%i", uint32_t(time(nullptr))); - } - - std::optional download_file(const std::string& name) - { - return utils::http::get_data(MASTER + select(DATA_PATH, DATA_PATH_DEV) + name + "?" + get_time_str()); - } - - bool is_update_cancelled() - { - return update_data.access([](update_data_t& data_) - { - return data_.cancelled; - }); - } - - bool write_file(const std::string& name, const std::string& data) - { - if (get_binary_name() == name && - utils::io::file_exists(name) && - !utils::io::move_file(name, name + ".old")) - { - return false; - } - -#ifdef DEBUG - return utils::io::write_file("update_test/" + name, data); -#else - return utils::io::write_file(name, data); -#endif - } - - void delete_old_file() - { - utils::io::remove_file(get_binary_name() + ".old"); - } - - void reset_data() - { - update_data.access([](update_data_t& data_) - { - data_ = {}; - }); - } - - std::string get_mode_flag() - { - if (game::environment::is_mp()) - { - return "-multiplayer"; - } - - if (game::environment::is_sp()) - { - return "-singleplayer"; - } - - return {}; - } - } - - // workaround - void relaunch() - { - if (!utils::io::file_exists(BINARY_NAME)) - { - utils::nt::terminate(0); - return; - } - - STARTUPINFOA startup_info; - PROCESS_INFORMATION process_info; - - ZeroMemory(&startup_info, sizeof(startup_info)); - ZeroMemory(&process_info, sizeof(process_info)); - startup_info.cb = sizeof(startup_info); - - char current_dir[MAX_PATH]; - GetCurrentDirectoryA(sizeof(current_dir), current_dir); - - char buf[1024] = {0}; - const auto command_line = utils::string::va("%s %s", GetCommandLineA(), get_mode_flag().data()); - strcpy_s(buf, 1024, command_line); - - CreateProcess(BINARY_NAME, buf, nullptr, nullptr, false, NULL, nullptr, current_dir, - &startup_info, &process_info); - - if (process_info.hThread && process_info.hThread != INVALID_HANDLE_VALUE) CloseHandle(process_info.hThread); - if (process_info.hProcess && process_info.hProcess != INVALID_HANDLE_VALUE) CloseHandle(process_info.hProcess); - - utils::nt::terminate(0); - } - - void set_has_tried_update(bool tried) - { - has_tried_update = tried; - } - - bool get_has_tried_update() - { - return has_tried_update; - } - - bool auto_updates_enabled() - { - return cl_auto_update->current.enabled; - } - - bool is_update_check_done() - { - return update_data.access([](update_data_t& data_) - { - return data_.check.done; - }); - } - - bool is_update_download_done() - { - return update_data.access([](update_data_t& data_) - { - return data_.download.done; - }); - } - - bool get_update_check_status() - { - return update_data.access([](update_data_t& data_) - { - return data_.check.success; - }); - } - - bool get_update_download_status() - { - return update_data.access([](update_data_t& data_) - { - return data_.download.success; - }); - } - - bool is_update_available() - { - return update_data.access([](update_data_t& data_) - { - return data_.required_files.size() > 0; - }); - } - - bool is_restart_required() - { - return update_data.access([](update_data_t& data_) - { - return data_.restart_required; - }); - } - - std::string get_last_error() - { - return update_data.access([](update_data_t& data_) - { - return data_.error; - }); - } - - std::string get_current_file() - { - return update_data.access([](update_data_t& data_) - { - return data_.current_file; - }); - } - - void cancel_update() - { -#ifdef DEBUG - printf("[Updater] Cancelling update\n"); -#endif - - return update_data.access([](update_data_t& data_) - { - data_.cancelled = true; - }); - } - - void start_update_check() - { - cancel_update(); - reset_data(); - -#ifdef DEBUG - printf("[Updater] starting update check\n"); -#endif - - scheduler::once([]() - { - const auto files_data = utils::http::get_data(MASTER + select(FILES_PATH, FILES_PATH_DEV) + "?" + get_time_str()); - - if (is_update_cancelled()) - { - reset_data(); - return; - } - - if (!files_data.has_value()) - { - set_update_check_status(true, false, ERR_UPDATE_CHECK_FAIL); - return; - } - - rapidjson::Document j; - j.Parse(files_data.value().data()); - - if (!j.IsArray()) - { - set_update_check_status(true, false, ERR_UPDATE_CHECK_FAIL); - return; - } - - std::vector required_files; - - const auto files = j.GetArray(); - for (const auto& file : files) - { - if (!file.IsArray() || file.Size() != 3 || !file[0].IsString() || !file[2].IsString()) - { - continue; - } - - const auto name = file[0].GetString(); - const auto sha = file[2].GetString(); - - if (!check_file(name, sha)) - { - if (get_binary_name() == name) - { - update_data.access([](update_data_t& data_) - { - data_.restart_required = true; - }); - } - -#ifdef DEBUG - printf("[Updater] need file %s\n", name); -#endif - - required_files.push_back(name); - } - } - - update_data.access([&required_files](update_data_t& data_) - { - data_.check.done = true; - data_.check.success = true; - data_.required_files = required_files; - }); - }, scheduler::pipeline::async); - } - - void start_update_download() - { -#ifdef DEBUG - printf("[Updater] starting update download\n"); -#endif - - if (!is_update_check_done() || !get_update_check_status() || is_update_cancelled()) - { - return; - } - - scheduler::once([]() - { - const auto required_files = update_data.access>([](update_data_t& data_) - { - return data_.required_files; - }); - - std::vector downloads; - - for (const auto& file : required_files) - { - update_data.access([file](update_data_t& data_) - { - data_.current_file = file; - }); - -#ifdef DEBUG - printf("[Updater] downloading file %s\n", file.data()); -#endif - - const auto data = download_file(file); - - if (is_update_cancelled()) - { - reset_data(); - return; - } - - if (!data.has_value()) - { - set_update_download_status(true, false, ERR_DOWNLOAD_FAIL + file); - return; - } - - downloads.push_back({file, data.value()}); - } - - for (const auto& download : downloads) - { - if (!write_file(download.name, download.data)) - { - set_update_download_status(true, false, ERR_WRITE_FAIL + download.name); - return; - } - } - - set_update_download_status(true, true); - }, scheduler::pipeline::async); - } - - class component final : public component_interface - { - public: - void post_unpack() override - { - delete_old_file(); - cl_auto_update = dvars::register_bool("cg_auto_update", true, game::DVAR_FLAG_SAVED, true); - } - }; -} - -REGISTER_COMPONENT(updater::component) diff --git a/src/client/component/updater.hpp b/src/client/component/updater.hpp deleted file mode 100644 index 9a3dd45e..00000000 --- a/src/client/component/updater.hpp +++ /dev/null @@ -1,26 +0,0 @@ -#pragma once - -namespace updater -{ - void relaunch(); - - void set_has_tried_update(bool tried); - bool get_has_tried_update(); - bool auto_updates_enabled(); - - bool is_update_available(); - bool is_update_check_done(); - bool get_update_check_status(); - - bool is_update_download_done(); - bool get_update_download_status(); - - bool is_restart_required(); - - std::string get_last_error(); - std::string get_current_file(); - - void start_update_check(); - void start_update_download(); - void cancel_update(); -} \ No newline at end of file diff --git a/src/client/component/videos.cpp b/src/client/component/videos.cpp deleted file mode 100644 index a602cc8a..00000000 --- a/src/client/component/videos.cpp +++ /dev/null @@ -1,55 +0,0 @@ -#include -#include "loader/component_loader.hpp" - -#include "game/game.hpp" - -#include - -namespace videos -{ - namespace - { - utils::hook::detour playvid_hook; - std::unordered_map video_replaces; - - void playvid(const char* name, const int a2, const int a3) - { - const auto vid = video_replaces.find(name); - if (vid != video_replaces.end()) - { - char path[256]; - game::Sys_BuildAbsPath(path, sizeof(path), game::SF_VIDEO, vid->second.data(), ".bik"); - - if (game::Sys_FileExists(path)) - { - name = vid->second.data(); - } - } - - return playvid_hook.invoke(name, a2, a3); - } - } - - class component final : public component_interface - { - public: - void post_unpack() override - { - playvid_hook.create(SELECT_VALUE(0x1404A9D00, 0x1405B0AF0), &playvid); // H1(1.4) - - if (game::environment::is_mp()) - { - video_replaces["menus_bg_comp2"] = "menus_bg_h1mod"; - video_replaces["mp_menus_bg_options"] = "menus_bg_h1mod_blur"; - } - else if (game::environment::is_sp()) - { - video_replaces["sp_menus_bg_main_menu"] = "menus_bg_h1mod_sp"; - video_replaces["sp_menus_bg_campaign"] = "menus_bg_h1mod_sp"; - video_replaces["sp_menus_bg_options"] = "menus_bg_h1mod_sp"; - } - } - }; -} - -REGISTER_COMPONENT(videos::component) diff --git a/src/client/component/virtuallobby.cpp b/src/client/component/virtuallobby.cpp deleted file mode 100644 index eb6295f7..00000000 --- a/src/client/component/virtuallobby.cpp +++ /dev/null @@ -1,63 +0,0 @@ -#include -#include "loader/component_loader.hpp" - -#include "game/game.hpp" -#include "game/dvars.hpp" - -#include - -namespace virtuallobby -{ - namespace - { - game::dvar_t* virtualLobby_fovscale; - - const auto get_fovscale_stub = utils::hook::assemble([](utils::hook::assembler& a) - { - const auto ret = a.newLabel(); - const auto original = a.newLabel(); - - a.pushad64(); - a.mov(rax, qword_ptr(0x1425F7210)); // virtualLobbyInFiringRange - a.cmp(byte_ptr(rax, 0x10), 1); - a.je(original); - a.call_aligned(game::VirtualLobby_Loaded); - a.cmp(al, 0); - a.je(original); - - // virtuallobby - a.popad64(); - a.mov(rax, ptr(reinterpret_cast(&virtualLobby_fovscale))); - a.jmp(ret); - - // original - a.bind(original); - a.popad64(); - a.mov(rax, qword_ptr(0x1413A8580)); - a.jmp(ret); - - a.bind(ret); - a.mov(rcx, 0x142935000); - a.jmp(0x1400B556A); - }); - } - - class component final : public component_interface - { - public: - void post_unpack() override - { - if (!game::environment::is_mp()) - { - return; - } - - virtualLobby_fovscale = dvars::register_float("virtualLobby_fovScale", 0.7f, 0.0f, 2.0f, game::DVAR_FLAG_SAVED); - - utils::hook::nop(0x1400B555C, 14); - utils::hook::jump(0x1400B555C, get_fovscale_stub, true); - } - }; -} - -REGISTER_COMPONENT(virtuallobby::component) diff --git a/src/client/loader/loader.cpp b/src/client/loader/loader.cpp index 1bc7b41c..4ec12c7c 100644 --- a/src/client/loader/loader.cpp +++ b/src/client/loader/loader.cpp @@ -31,7 +31,7 @@ FARPROC loader::load(const utils::nt::library& library, const std::string& buffe return FARPROC(library.get_ptr() + source.get_relative_entry_point()); } -FARPROC loader::load_library(const std::string& filename) const +FARPROC loader::load_library(const std::string& filename, uint64_t* base_address) const { const auto target = utils::nt::library::load(filename); if (!target) @@ -40,10 +40,7 @@ FARPROC loader::load_library(const std::string& filename) const } const auto base = size_t(target.get_ptr()); - if(base != 0x140000000) - { - throw std::runtime_error{utils::string::va("Binary was mapped at 0x%llX (instead of 0x%llX). Something is severely broken :(", base, 0x140000000)}; - } + *base_address = base; this->load_imports(target, target); this->load_tls(target, target); diff --git a/src/client/loader/loader.hpp b/src/client/loader/loader.hpp index 2c5d86f9..0c0b5a12 100644 --- a/src/client/loader/loader.hpp +++ b/src/client/loader/loader.hpp @@ -5,7 +5,7 @@ class loader final { public: FARPROC load(const utils::nt::library& library, const std::string& buffer) const; - FARPROC load_library(const std::string& filename) const; + FARPROC load_library(const std::string& filename, uint64_t* base_address) const; void set_import_resolver(const std::function& resolver); diff --git a/src/client/resources/ui_scripts/common.lua b/src/client/resources/ui_scripts/common.lua deleted file mode 100644 index 8f68e96d..00000000 --- a/src/client/resources/ui_scripts/common.lua +++ /dev/null @@ -1,164 +0,0 @@ -menucallbacks = {} -originalmenus = {} -stack = {} - -LUI.MenuBuilder.m_types_build["generic_waiting_popup_"] = function (menu, event) - local oncancel = stack.oncancel - local popup = LUI.MenuBuilder.BuildRegisteredType("waiting_popup", { - message_text = stack.text, - isLiveWithCancel = true, - cancel_func = function(...) - local args = {...} - oncancel() - LUI.FlowManager.RequestLeaveMenu(args[1]) - end - }) - - local listchildren = popup:getChildById("LUIHorizontalList"):getchildren() - local children = listchildren[2]:getchildren() - popup.text = children[2] - - stack = { - ret = popup - } - - return popup -end - -LUI.MenuBuilder.m_types_build["generic_yes_no_popup_"] = function() - local callback = stack.callback - local popup = LUI.MenuBuilder.BuildRegisteredType("generic_yesno_popup", { - popup_title = stack.title, - message_text = stack.text, - yes_action = function() - callback(true) - end, - no_action = function() - callback(false) - end - }) - - stack = { - ret = popup - } - - return popup -end - -LUI.MenuBuilder.m_types_build["generic_confirmation_popup_"] = function() - local popup = LUI.MenuBuilder.BuildRegisteredType( "generic_confirmation_popup", { - cancel_will_close = false, - popup_title = stack.title, - message_text = stack.text, - button_text = stack.buttontext, - confirmation_action = stack.callback - }) - - stack = { - ret = popup - } - - return stack.ret -end - -LUI.onmenuopen = function(name, callback) - if (not LUI.MenuBuilder.m_types_build[name]) then - return - end - - if (not menucallbacks[name]) then - menucallbacks[name] = {} - end - - table.insert(menucallbacks[name], callback) - - if (not originalmenus[name]) then - originalmenus[name] = LUI.MenuBuilder.m_types_build[name] - LUI.MenuBuilder.m_types_build[name] = function(...) - local args = {...} - local menu = originalmenus[name](table.unpack(args)) - - for k, v in luiglobals.next, menucallbacks[name] do - v(menu, table.unpack(args)) - end - - return menu - end - end -end - -local addoptionstextinfo = LUI.Options.AddOptionTextInfo -LUI.Options.AddOptionTextInfo = function(menu) - local result = addoptionstextinfo(menu) - menu.optionTextInfo = result - return result -end - -LUI.addmenubutton = function(name, data) - LUI.onmenuopen(name, function(menu) - if (not menu.list) then - return - end - - local button = menu:AddButton(data.text, data.callback, nil, true, nil, { - desc_text = data.description - }) - - local buttonlist = menu:getChildById(menu.type .. "_list") - - if (data.id) then - button.id = data.id - end - - if (data.index) then - buttonlist:removeElement(button) - buttonlist:insertElement(button, data.index) - end - - local hintbox = menu.optionTextInfo - menu:removeElement(hintbox) - - LUI.Options.InitScrollingList(menu.list, nil) - menu.optionTextInfo = LUI.Options.AddOptionTextInfo(menu) - end) -end - -LUI.openmenu = function(menu, args) - stack = args - LUI.FlowManager.RequestAddMenu(nil, menu) - return stack.ret -end - -LUI.openpopupmenu = function(menu, args) - stack = args - LUI.FlowManager.RequestPopupMenu(nil, menu) - return stack.ret -end - -LUI.yesnopopup = function(data) - for k, v in luiglobals.next, data do - stack[k] = v - end - LUI.FlowManager.RequestPopupMenu(nil, "generic_yes_no_popup_") - return stack.ret -end - -LUI.confirmationpopup = function(data) - for k, v in luiglobals.next, data do - stack[k] = v - end - LUI.FlowManager.RequestPopupMenu(nil, "generic_confirmation_popup_") - return stack.ret -end - -function userdata_:getchildren() - local children = {} - local first = self:getFirstChild() - - while (first) do - table.insert(children, first) - first = first:getNextSibling() - end - - return children -end diff --git a/src/client/resources/ui_scripts/updater.lua b/src/client/resources/ui_scripts/updater.lua deleted file mode 100644 index 01d77360..00000000 --- a/src/client/resources/ui_scripts/updater.lua +++ /dev/null @@ -1,164 +0,0 @@ -updatecancelled = false -taskinterval = 100 - -updater.cancelupdate() - -function startupdatecheck(popup, autoclose) - updatecancelled = false - - local callback = function() - if (not updater.getupdatecheckstatus()) then - if (autoclose) then - LUI.FlowManager.RequestLeaveMenu(popup) - return - end - - popup.text:setText("Error: " .. updater.getlasterror()) - return - end - - if (not updater.isupdateavailable()) then - if (autoclose) then - LUI.FlowManager.RequestLeaveMenu(popup) - return - end - - popup.text:setText("No updates available") - return - end - - LUI.yesnopopup({ - title = "NOTICE", - text = "An update is available, proceed with installation?", - callback = function(result) - if (result) then - startupdatedownload(popup, autoclose) - else - LUI.FlowManager.RequestLeaveMenu(popup) - end - end - }) - end - - updater.startupdatecheck() - createtask({ - done = updater.isupdatecheckdone, - cancelled = isupdatecancelled, - callback = callback, - interval = taskinterval - }) -end - -function startupdatedownload(popup, autoclose) - updater.startupdatedownload() - - local textupdate = nil - local previousfile = nil - textupdate = game:oninterval(function() - local file = updater.getcurrentfile() - if (file == previousfile) then - return - end - - file = previousfile - popup.text:setText("Downloading file " .. updater.getcurrentfile() .. "...") - end, 10) - - local callback = function() - textupdate:clear() - - if (not updater.getupdatedownloadstatus()) then - if (autoclose) then - LUI.FlowManager.RequestLeaveMenu(popup) - return - end - - popup.text:setText("Error: " .. updater.getlasterror()) - return - end - - popup.text:setText("Update successful") - - if (updater.isrestartrequired()) then - LUI.confirmationpopup({ - title = "RESTART REQUIRED", - text = "Update requires restart", - buttontext = "RESTART", - callback = function() - updater.relaunch() - end - }) - else - if (LUI.mp_menus) then - Engine.Exec("lui_restart; lui_open mp_main_menu") - else - Engine.Exec("lui_restart") - end - end - - if (autoclose) then - LUI.FlowManager.RequestLeaveMenu(popup) - end - end - - createtask({ - done = updater.isupdatedownloaddone, - cancelled = isupdatecancelled, - callback = callback, - interval = taskinterval - }) -end - -function updaterpopup(oncancel) - return LUI.openpopupmenu("generic_waiting_popup_", { - oncancel = oncancel, - withcancel = true, - text = "Checking for updates..." - }) -end - -function createtask(data) - local interval = nil - interval = game:oninterval(function() - if (data.cancelled()) then - interval:clear() - return - end - - if (data.done()) then - interval:clear() - data.callback() - end - end, data.interval) - return interval -end - -function isupdatecancelled() - return updatecancelled -end - -function tryupdate(autoclose) - updatecancelled = false - local popup = updaterpopup(function() - updater.cancelupdate() - updatecancelled = true - end) - - startupdatecheck(popup, autoclose) -end - -function tryautoupdate() - if (not updater.autoupdatesenabled()) then - return - end - - if (not updater.gethastriedupdate()) then - game:ontimeout(function() - updater.sethastriedupdate(true) - tryupdate(true) - end, 100) - end -end - -LUI.onmenuopen("mp_main_menu", tryautoupdate) -LUI.onmenuopen("main_lockout", tryautoupdate) \ No newline at end of file