From b131b280754372c325bd5317cb5511258148b19c Mon Sep 17 00:00:00 2001 From: quaK <38787176+Joelrau@users.noreply.github.com> Date: Tue, 18 Oct 2022 06:39:26 +0300 Subject: [PATCH] cleanup and more --- src/client/component/command.cpp | 44 ++++++ src/client/component/dedicated.cpp | 194 +++++++++++++++----------- src/client/component/dvars.cpp | 3 +- src/client/component/filesystem.cpp | 29 ++++ src/client/component/filesystem.hpp | 6 + src/client/component/gameplay.cpp | 66 +++++++-- src/client/component/map_rotation.cpp | 181 ++++++++++++++++++++++++ src/client/component/network.cpp | 79 +---------- src/client/component/party.cpp | 127 +++++++---------- src/client/component/party.hpp | 2 +- src/client/component/patches.cpp | 6 +- src/client/game/dvars.cpp | 13 +- src/client/game/dvars.hpp | 8 +- src/client/game/structs.hpp | 1 + src/client/game/symbols.hpp | 7 + src/client/std_include.hpp | 2 +- src/common/utils/string.cpp | 5 + src/common/utils/string.hpp | 1 + 18 files changed, 515 insertions(+), 259 deletions(-) create mode 100644 src/client/component/filesystem.cpp create mode 100644 src/client/component/filesystem.hpp create mode 100644 src/client/component/map_rotation.cpp diff --git a/src/client/component/command.cpp b/src/client/component/command.cpp index 85fa6298..be41ffab 100644 --- a/src/client/component/command.cpp +++ b/src/client/component/command.cpp @@ -8,6 +8,7 @@ #include "console.hpp" #include "game_console.hpp" #include "scheduler.hpp" +#include "dvars.hpp" #include #include @@ -107,6 +108,47 @@ namespace command parsed = true; } + void parse_startup_variables() + { + auto& com_num_console_lines = *reinterpret_cast(0x6006DB0_b); + auto* com_console_lines = reinterpret_cast(0x6006DC0_b); + + 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(0) == "seta"s)) + { + const std::string& dvar_name = game::Cmd_Argv(1); + const std::string& value = game::Cmd_Argv(2); + + const auto* dvar = game::Dvar_FindVar(dvar_name.data()); + if (dvar) + { + game::Dvar_SetCommand(dvar_name.data(), value.data()); + } + else + { + dvars::callback::on_register(dvar_name, [dvar_name, value]() + { + game::Dvar_SetCommand(dvar_name.data(), value.data()); + }); + } + } + + game::Cmd_EndTokenizeString(); + } + } + + void parse_commandline() + { + parse_command_line(); + parse_startup_variables(); + + parse_commandline_hook.invoke(); + } + game::dvar_t* dvar_command_stub() { const params args; @@ -324,6 +366,8 @@ namespace command client_command_mp_hook.create(0xB105D0_b, &client_command_mp); client_command_sp_hook.create(0x483130_b, &client_command_sp); + parse_commandline_hook.create(0xF2F67B_b, parse_commandline); + add_commands(); } diff --git a/src/client/component/dedicated.cpp b/src/client/component/dedicated.cpp index 309373bf..0590ecee 100644 --- a/src/client/component/dedicated.cpp +++ b/src/client/component/dedicated.cpp @@ -2,6 +2,7 @@ #include "loader/component_loader.hpp" #include "game/game.hpp" +#include "game/dvars.hpp" #include "dvars.hpp" #include "command.hpp" @@ -10,13 +11,41 @@ #include #include - -#include "game/dvars.hpp" +#include namespace dedicated { namespace { + 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); + } + } + bool party_is_server_dedicated_stub() { return true; @@ -27,10 +56,13 @@ namespace dedicated std::this_thread::sleep_for(1ms); } + void gscr_is_using_match_rules_data_stub() + { + game::Scr_AddInt(0); + } + void init_dedicated_server() { - printf("init called...\n"); - // R_RegisterDvars utils::hook::invoke(0xDF62C0_b); @@ -53,7 +85,6 @@ namespace dedicated { if (handle == *reinterpret_cast(0x8B1BC98_b)) { - //printf("not waiting for mutex\n"); return 0; } @@ -62,7 +93,6 @@ namespace dedicated void initialize() { - //command::execute("exec default_xboxlive.cfg", true); command::execute("onlinegame 1", true); command::execute("xblive_privatematch 1", true); } @@ -76,7 +106,7 @@ namespace dedicated { if (function == "WaitForSingleObject") { - return wait_for_single_object_stub; + // return wait_for_single_object_stub; } } @@ -109,95 +139,44 @@ namespace dedicated // Disable load for renderer dvars::override::register_bool("r_loadForRenderer", false, game::DVAR_FLAG_READ); - // Preload game mode fastfiles on launch - //dvars::override::register_bool("fastfilePreloadGamemode", true, game::DVAR_FLAG_NONE); - dvars::override::register_bool("intro", false, game::DVAR_FLAG_READ); // Is party dedicated utils::hook::jump(0x5DFC10_b, party_is_server_dedicated_stub); + // Make GScr_IsUsingMatchRulesData return 0 so the game doesn't override the cfg + utils::hook::jump(0xB53950_b, gscr_is_using_match_rules_data_stub); + // Hook R_SyncGpu utils::hook::jump(0xE08AE0_b, sync_gpu_stub, true); utils::hook::jump(0x341B60_b, init_dedicated_server, true); + // delay startup commands until the initialization is done + utils::hook::call(0xB8D20F_b, execute_startup_command); + utils::hook::nop(0xCDD5D3_b, 5); // don't load config file utils::hook::nop(0xB7CE46_b, 5); // ^ utils::hook::set(0xBB0930_b, 0xC3); // don't save config file - utils::hook::set(0x9D49C0_b, 0xC3); // disable self-registration // done - utils::hook::set(0xC93120_b, 0xC3C033); // init sound system (1) // done SND_InitDriver - utils::hook::set(0xD597C0_b, 0xC3); // init sound system (2) // done Voice_Init - utils::hook::set(0xE574E0_b, 0xC3); // render thread // done RB_RenderThread - utils::hook::set(0x3471A0_b, 0xC3); // called from Com_Frame, seems to do renderer stuff // done CL_Screen_Update - utils::hook::set(0x9AA9A0_b, 0xC3); // CL_CheckForResend, which tries to connect to the local server constantly // done CL_MainMP_CheckForResend - //utils::hook::set(0x67ADCE_b, 0x00); // r_loadForRenderer default to 0 // done via dvar override - //utils::hook::set(0xD2EBB0_b, 0xC3); // recommended settings check // done - //utils::hook::set(0x5BE850_b, 0xC3); // some mixer-related function called on shutdown // not needed, only called from Voice_Init - //utils::hook::set(0x4DEA50_b, 0xC3); // dont load ui gametype stuff // don't add this for now + utils::hook::set(0x9D49C0_b, 0xC3); // disable self-registration + utils::hook::set(0xE574E0_b, 0xC3); // render thread + utils::hook::set(0x3471A0_b, 0xC3); // called from Com_Frame, seems to do renderer stuff + utils::hook::set(0x9AA9A0_b, 0xC3); // CL_CheckForResend, which tries to connect to the local server constantly + utils::hook::set(0xD2EBB0_b, 0xC3); // recommended settings check - utils::hook::nop(0xC5007B_b, 6); // unknown check in SV_ExecuteClientMessage // done - utils::hook::nop(0xC4F407_b, 3); // allow first slot to be occupied // done - utils::hook::nop(0x3429A7_b, 2); // properly shut down dedicated servers // done - utils::hook::nop(0x34296F_b, 2); // ^ // done - utils::hook::nop(0x3429CD_b, 5); // don't shutdown renderer // done ( maybe need to add R_ShutdownWorld to this too? ) + // sound initialization + utils::hook::nop(0xC93213_b, 5); // snd stream thread + utils::hook::set(0xC93206_b, 0); // snd_active + utils::hook::set(0xD597C0_b, 0xC3); // init voice system - //utils::hook::set(0xAA290_b, 0xC3); // something to do with blendShapeVertsView // not a thing in iw7 - //utils::hook::nop(0x70465D_b, 8); // sound thing // dunno if needed + utils::hook::nop(0xC5007B_b, 6); // unknown check in SV_ExecuteClientMessage + utils::hook::nop(0xC4F407_b, 3); // allow first slot to be occupied + utils::hook::nop(0x3429A7_b, 2); // properly shut down dedicated servers + utils::hook::nop(0x34296F_b, 2); // ^ + utils::hook::set(0xE08360_b, 0xC3); // don't shutdown renderer - //utils::hook::set(0x1D8A20_b, 0xC3); // cpu detection stuff? // can't find - //utils::hook::set(0x690F30_b, 0xC3); // gfx stuff during fastfile loading // not there - //utils::hook::set(0x690E00_b, 0xC3); // ^ - //utils::hook::set(0x690ED0_b, 0xC3); // ^ - //utils::hook::set(0x39B980_b, 0xC3); // ^ - //utils::hook::set(0x690E50_b, 0xC3); // ^ - //utils::hook::set(0xDD26E0_b, 0xC3); // directx stuff // done - //utils::hook::set(0xE00FC0_b, 0xC3); // ^ - //utils::hook::set(0x6CE390_b, 0xC3); // ^ - mutex // not done - //utils::hook::set(0x681ED0_b, 0xC3); // ^ - - //utils::hook::set(0x0A3CD0_b, 0xC3); // rendering stuff // not done - //utils::hook::set(0x682150_b, 0xC3); // ^ - //utils::hook::set(0x682260_b, 0xC3); // ^ - //utils::hook::set(0x6829C0_b, 0xC3); // ^ - //utils::hook::set(0x6834A0_b, 0xC3); // ^ - //utils::hook::set(0x683B40_b, 0xC3); // ^ - - // shaders - //utils::hook::set(0x5F0610_b, 0xC3); // ^ // done - //utils::hook::set(0x5F0580_b, 0xC3); // ^ // done - //utils::hook::set(0xE51020_b, 0xC3); // ^ - mutex // done - - //utils::hook::set(0x5BFD10_b, 0xC3); // idk // not done - //utils::hook::set(0xDD4430_b, 0xC3); // ^ // R_ReleaseBuffer - - //utils::hook::set(0xE08360_b, 0xC3); // R_Shutdown - //utils::hook::set(0x652BA0_b, 0xC3); // shutdown stuff // not done - //utils::hook::set(0x687DF0_b, 0xC3); // ^ // not done - //utils::hook::set(0x686DE0_b, 0xC3); // ^ // not done - - // utils::hook::set(0x1404B67E0, 0xC3); // sound crashes (H1 - questionable, function looks way different) - - utils::hook::set(0xC5A200_b, 0xC3); // disable host migration // done SV_MigrationStart - - //utils::hook::set(0xBB66B0_b, 0xC3); // render synchronization lock // done - //utils::hook::set(0xBB64A0_b, 0xC3); // render synchronization unlock // done - - //utils::hook::set(0x615359_b, 0xEB); // LUI: Unable to start the LUI system due to errors in main.lua // done - //utils::hook::set(0x27AAC5_b, 0xEB); // LUI: Unable to start the LUI system due to errors in depot.lua // no - //utils::hook::set(0x27AADC_b, 0xEB); // ^ - - //utils::hook::nop(0xCFDA7E_b, 5); // Disable sound pak file loading // done - //utils::hook::nop(0xCFDA97_b, 2); // ^ // done - //utils::hook::set(0x3A0BA0_b, 0xC3); // Disable image pak file loading // not done - - // Reduce min required memory - //utils::hook::set(0x5B7F37_b, 0x80000000); // not done - - //utils::hook::set(0x399E10_b, 0xC3); // some loop // not done - //utils::hook::set(0x1D48B0_b, 0xC3); // related to shader caching / techsets / fastfilesc // not done - //utils::hook::set(0x3A1940_b, 0xC3); // DB_ReadPackedLoadedSounds // not done + utils::hook::set(0xC5A200_b, 0xC3); // disable host migration // iw7 patches utils::hook::set(0xE06060_b, 0xC3C033); //utils::hook::set(0xE06060_b, 0xC3); // directx @@ -230,6 +209,8 @@ namespace dedicated utils::hook::set(0xDD42E0_b, 0xC3C033); // ^ utils::hook::set(0xDD4280_b, 0xC3C033); // ^ + utils::hook::set(0xDD4230_b, 0xC3C033); // ^ + // r_loadForRenderer //utils::hook::set(0xE114A0_b, 0xC3); // ^ //utils::hook::set(0xE11380_b, 0xC3); // ^ @@ -249,26 +230,69 @@ namespace dedicated // R_LoadWorld utils::hook::set(0xDD14C0_b, 0xC3); - // vls shit + // something to do with vls? utils::hook::set(0xD02CB0_b, 0xC3); - // renderer - //utils::hook::set(0xDD4370_b, 0xC3); - // image stream (pak) utils::hook::set(0xA7DB10_b, 0xC3); // DB_CreateGfxImageStreamInternal // sound stream (sabl, sabs) //utils::hook::nop(0xCFDC03_b, 2); - command::add("startserver", []() + // set game mode + scheduler::once([]() + { + if (utils::flags::has_flag("cpMode") || utils::flags::has_flag("zombies")) + { + game::Com_GameMode_SetDesiredGameMode(game::GAME_MODE_CP); + } + else + { + game::Com_GameMode_SetDesiredGameMode(game::GAME_MODE_MP); + } + }, scheduler::pipeline::main); + + // initialization + 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(); + }, scheduler::pipeline::main, 1s); + + // dedicated info + scheduler::loop([]() + { + auto* sv_running = game::Dvar_FindVar("sv_running"); + if (!sv_running || !sv_running->current.enabled) + { + console::set_title("IW7-Mod Dedicated Server"); + return; + } + + auto* const sv_hostname = game::Dvar_FindVar("sv_hostname"); + auto* const mapname = game::Dvar_FindVar("mapname"); + + if (!sv_hostname || !mapname) + { + return; + } + + 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", cleaned_hostname.data(), mapname->current.string)); + }, scheduler::pipeline::main, 1s); } }; } diff --git a/src/client/component/dvars.cpp b/src/client/component/dvars.cpp index 2a356c99..9f22ee2f 100644 --- a/src/client/component/dvars.cpp +++ b/src/client/component/dvars.cpp @@ -6,6 +6,7 @@ #include "game/dvars.hpp" #include +#include namespace dvars { @@ -358,7 +359,7 @@ namespace dvars if (dvar) { - if (name) + if (name && !utils::string::is_numeric(name)) { dvars::dvar_set_name(dvar, name); } diff --git a/src/client/component/filesystem.cpp b/src/client/component/filesystem.cpp new file mode 100644 index 00000000..910ef8ce --- /dev/null +++ b/src/client/component/filesystem.cpp @@ -0,0 +1,29 @@ +#include +#include "loader/component_loader.hpp" +#include "filesystem.hpp" + +#include "game/game.hpp" + +#include "dvars.hpp" + +#include +#include + +namespace filesystem +{ + namespace + { + + } + + class component final : public component_interface + { + public: + void post_unpack() override + { + dvars::override::register_string("fs_basegame", "iw7-mod", 2048); + } + }; +} + +REGISTER_COMPONENT(filesystem::component) \ No newline at end of file diff --git a/src/client/component/filesystem.hpp b/src/client/component/filesystem.hpp new file mode 100644 index 00000000..f4efb73c --- /dev/null +++ b/src/client/component/filesystem.hpp @@ -0,0 +1,6 @@ +#pragma once + +namespace filesystem +{ + +} \ No newline at end of file diff --git a/src/client/component/gameplay.cpp b/src/client/component/gameplay.cpp index ffcf30f4..269c2437 100644 --- a/src/client/component/gameplay.cpp +++ b/src/client/component/gameplay.cpp @@ -6,6 +6,8 @@ #include "game/game.hpp" #include "game/dvars.hpp" +#include "dvars.hpp" + #include #include #include @@ -18,7 +20,7 @@ namespace gameplay void stuck_in_client_stub(void* entity) { - if (dvars::g_playerEjection->current.enabled) + if (dvars::bg_playerEjection->current.enabled) { stuck_in_client_hook.invoke(entity); } @@ -51,20 +53,52 @@ namespace gameplay }); } - void* g_gravity_stub() + int get_gravity() + { + return static_cast(game::BG_GetGravity()); + } + + void* bg_gravity_stub() { return utils::hook::assemble([](utils::hook::assembler& a) { - a.mov(rax, qword_ptr(reinterpret_cast(&dvars::g_gravity))); - a.mov(eax, dword_ptr(rax, 0x10)); - a.mov(dword_ptr(rdi, 0x78), eax); - + // do moveSpeedScaleMultiplier first (xmm0) a.call(0xBB3030_b); a.mov(ptr(rdi, 0x32C), eax); + // get bg_gravity as int + a.pushad64(); + a.push(rdi); + a.call_aligned(get_gravity); + a.pop(rdi); + a.mov(dword_ptr(rdi, 0x78), eax); + a.popad64(); + a.jmp(0xAFA342_b); }); } + + void* g_speed_stub() + { + return utils::hook::assemble([](utils::hook::assembler& a) + { + // original code + a.add(eax, ptr(rdi, 0x1FD0)); + + a.push(rax); + a.push(eax); + + a.mov(rax, qword_ptr(reinterpret_cast(&*reinterpret_cast(0x3C98330_b)))); + a.mov(eax, dword_ptr(rax, 0x10)); + + a.mov(dword_ptr(rdi, 0x7C), eax); + + a.pop(rax); + a.pop(eax); + + a.jmp(0xAFB1EC_b); + }); + } } class component final : public component_interface @@ -72,17 +106,23 @@ namespace gameplay public: void post_unpack() override { - // Implement bounces + // Implement ejection dvar + dvars::bg_playerEjection = game::Dvar_RegisterBool("bg_playerEjection", true, game::DVAR_FLAG_REPLICATED, "Flag whether player ejection is on or off"); + stuck_in_client_hook.create(0xAFD9B0_b, stuck_in_client_stub); + + // Implement bounces dvar dvars::bg_bounces = game::Dvar_RegisterBool("bg_bounces", false, game::DVAR_FLAG_REPLICATED, "Enables bounces"); utils::hook::jump(0x70FBB7_b, bg_bounces_stub(), true); - // Implement gravity dvar - dvars::g_gravity = game::Dvar_RegisterInt("g_gravity", 800, 0, 1000, game::DVAR_FLAG_REPLICATED, "Game gravity in inches per second squared"); - utils::hook::nop(0xAFA330_b, 13); - utils::hook::jump(0xAFA330_b, g_gravity_stub(), true); + // Modify gravity dvar + dvars::override::register_float("bg_gravity", 800, 0, 1000, 0xC0 | game::DVAR_FLAG_REPLICATED); + utils::hook::nop(0xAFA330_b, 18); + utils::hook::jump(0xAFA330_b, bg_gravity_stub(), true); - dvars::g_playerEjection = game::Dvar_RegisterBool("g_playerEjection", true, game::DVAR_FLAG_REPLICATED, "Flag whether player ejection is on or off"); - stuck_in_client_hook.create(0xAFD9B0_b, stuck_in_client_stub); + // Modify speed dvar + dvars::override::register_int("g_speed", 190, 0x80000000, 0x7FFFFFFF, 0xC0 | game::DVAR_FLAG_REPLICATED); + utils::hook::nop(0xAFB1DF_b, 13); + utils::hook::jump(0xAFB1DF_b, g_speed_stub(), true); } }; } diff --git a/src/client/component/map_rotation.cpp b/src/client/component/map_rotation.cpp new file mode 100644 index 00000000..17d35145 --- /dev/null +++ b/src/client/component/map_rotation.cpp @@ -0,0 +1,181 @@ +#include +#include "loader/component_loader.hpp" +#include "command.hpp" +#include "scheduler.hpp" +#include +#include +#include "game/game.hpp" +#include + +namespace map_rotation +{ + namespace + { + DWORD previous_priority{}; + + 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_frontend"s && + mapname->current.string != "cp_frontend"s) + { + launch_map(mapname->current.string); + } + else + { + launch_map(game::Com_GameMode_GetActiveGameMode() == game::GAME_MODE_CP ? "cp_zmb" : "mp_frontier"); + } + } + + 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(), previous_priority); + }, scheduler::pipeline::main, 1s); + + previous_priority = 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_IsGameClientActive(0)) + { + 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([]() + { + game::Dvar_RegisterString("sv_mapRotation", "", game::DVAR_FLAG_NONE, ""); + game::Dvar_RegisterString("sv_mapRotationCurrent", "", game::DVAR_FLAG_NONE, ""); + game::Dvar_RegisterString("sv_autoPriority", "", game::DVAR_FLAG_NONE, "Lowers the process priority during map changes to not cause lags on other servers."); + }, scheduler::pipeline::main); + + command::add("map_rotate", &perform_map_rotation); + + // Hook GScr_ExitLevel + utils::hook::jump(0xB52E50_b, &trigger_map_rotation, true); + + previous_priority = GetPriorityClass(GetCurrentProcess()); + } + }; +} + +REGISTER_COMPONENT(map_rotation::component) \ No newline at end of file diff --git a/src/client/component/network.cpp b/src/client/component/network.cpp index 71e4e348..ffa957ff 100644 --- a/src/client/component/network.cpp +++ b/src/client/component/network.cpp @@ -26,7 +26,6 @@ namespace network bool handle_command(game::netadr_s* address, const char* command, game::msg_t* message) { - printf("hamdle_cmd: %s\n", command); const auto cmd_string = utils::string::to_lower(command); auto& callbacks = get_callbacks(); const auto handler = callbacks.find(cmd_string); @@ -51,7 +50,6 @@ namespace network utils::hook::detour cl_dispatch_connectionless_packet_hook; bool cl_dispatch_connectionless_packet_stub(int client_num, game::netadr_s* from, game::msg_t* msg, int time) { - printf("connectionless packet: type: %d, adr: %s\n", from->type, net_adr_to_string(*from)); if (handle_command(from, game::Cmd_Argv(0), msg)) { return true; @@ -62,16 +60,8 @@ namespace network int dw_send_to_stub(const int length, const char* data, game::netadr_s* to) { - if (!*game::query_socket || *game::query_socket == INVALID_SOCKET) - { - printf("query socket is not initialized\n"); - } sockaddr s = {}; game::NetadrToSockadr(to, &s); - if (to->type == game::NA_IP) - { - //printf("sendto: size: %i\n", length); - } return sendto(*game::query_socket, data, length, 0, &s, sizeof(sockaddr)); } @@ -97,10 +87,6 @@ namespace network return -2; } sockadr_to_netadr(&s, from); - if (from->type == game::NA_IP) - { - //printf("recv: size: %i\n", ret); - } datalen = ret; if (!datalen) { @@ -165,27 +151,23 @@ namespace network if (sock == INVALID_SOCKET) { - console::warn("WARNING: UDP_OpenSocket: socket\n"); return 0; } u_long arg = 1; if (ioctlsocket(sock, FIONBIO, &arg) == SOCKET_ERROR) { - console::warn("WARNING: UDP_OpenSocket: ioctl FIONBIO\n"); return 0; } char optval[4] = { 1, 0, 0, 0 }; if (setsockopt(sock, SOL_SOCKET, SO_BROADCAST, optval, sizeof(optval)) == SOCKET_ERROR) { - console::warn("WARNING: UDP_OpenSocket: setsockopt SO_BROADCAST\n"); return 0; } if (bind(sock, reinterpret_cast(&address), sizeof(address)) == SOCKET_ERROR) { - console::warn("WARNING: UDP_OpenSocket: bind\n"); closesocket(sock); return 0; } @@ -215,7 +197,6 @@ namespace network return; } - printf("net_port: %d\n", port_diff); game::Dvar_SetInt(net_port, net_port->current.integer + port_diff); } @@ -230,11 +211,6 @@ namespace network return PROTOCOL; } - int dw_get_addr_handle_connection_task_status_stub() - { - return 1; // TASK_COMPLETE - } - void reconnect_migratated_client(void*, game::netadr_s* from, const int, const int, const char*, const char*, bool) { @@ -271,7 +247,6 @@ namespace network } else { - printf("send_data: type: %d, data: %s, size: %i\n", address.type, data.data(), size); game::Sys_SendPacket(size, data.data(), &address); } } @@ -341,13 +316,6 @@ namespace network utils::hook::jump(0xC4F200_b, 0xC4F1AB_b); utils::hook::jump(0xC4F2F6_b, 0xC4F399_b); - // disable xuid verification - //utils::hook::set(0x_b, 0xEB); - - // disable xuid verification - //utils::hook::nop(0x_b, 2); - //utils::hook::set(0x_b, 0xEB); - // ignore configstring mismatch utils::hook::set(0x9B6F91_b, 0xEB); @@ -378,54 +346,19 @@ namespace network utils::hook::set(0xBB4E22_b, max_packet_size); utils::hook::set(0xBB4F31_b, max_packet_size); - // increase cl_maxpackets - dvars::override::register_int("cl_maxpackets", 1000, 1, 1000, game::DVAR_FLAG_SAVED); - - // increase snaps - //dvars::override::register_int("sv_remote_client_snapshot_msec", 33, 33, 100, game::DVAR_FLAG_NONE); - - dvars::override::register_float("cl_timeout", 3600.0f, 0.0f, 3600.0f, game::DVAR_FLAG_NONE); - dvars::override::register_float("cl_connectTimeout", 3600.0f, 0.0f, 3600.0f, game::DVAR_FLAG_NONE); - - dvars::override::register_int("sv_timeout", 1800, 0, 1800, game::DVAR_FLAG_NONE); // no work - dvars::override::register_int("sv_connectTimeout", 1800, 0, 1800, game::DVAR_FLAG_NONE); // ^ - - //dvars::override::register_int("sv_zombietime", 1800, 0, 1800, game::DVAR_FLAG_NONE); // ^ - - dvars::override::register_int("pt_connectTimeout", 60000, 0, 60000, game::DVAR_FLAG_READ); - - dvars::override::register_int("ds_serverConnectTimeout", 60000, 0, -1, game::DVAR_FLAG_READ); - - dvars::override::register_int("dw_addrHandleTimeout", -1, 0, -1, game::DVAR_FLAG_READ); - // ignore built in "print" oob command and add in our own - //utils::hook::set(0x9B0326_b, 0xEB); - //network::on("print", [](const game::netadr_s&, const std::string_view& data) - //{ - // const std::string message{ data }; - // console::info(message.data()); - //}); + utils::hook::set(0x9B0326_b, 0xEB); + network::on("print", [](const game::netadr_s&, const std::string_view& data) + { + const std::string message{ data }; + console::info(message.data()); + }); // initialize query_socket utils::hook::jump(0xD57C7E_b, net_init_stub); // use our own protocol version utils::hook::jump(0xCE8290_b, get_protocol_version_stub); - - //utils::hook::set(0x4030F0_b, 0xC3); - //utils::hook::nop(0x9B014B_b, 2); - - // don't establish secure conenction pt2 - /*utils::hook::nop(0xC572A2_b, 2); - utils::hook::nop(0xC72980_b, 2); - utils::hook::nop(0xC73512_b, 2); - utils::hook::nop(0xC739C9_b, 2); - utils::hook::set(0xCFD928_b, 0xEB);*/ - //utils::hook::jump(0xD93390_b, dw_get_addr_handle_connection_task_status_stub); - -#ifdef DEBUG - //dvars::override::register_bool("frontEndSceneEnabled", false, game::DVAR_FLAG_READ); -#endif } }; } diff --git a/src/client/component/party.cpp b/src/client/component/party.cpp index 4783382a..a478574c 100644 --- a/src/client/component/party.cpp +++ b/src/client/component/party.cpp @@ -31,13 +31,10 @@ namespace party void perform_game_initialization() { command::execute("onlinegame 1", true); - //command::execute("exec default_xboxlive.cfg", true); command::execute("xblive_privatematch 1", true); - //command::execute("xstopparty 0", true); - //command::execute("xstartprivateparty 0", true); - command::execute("xstartprivatematch 0", true); + //command::execute("xstartprivateparty", true); + command::execute("xstartprivatematch", true); command::execute("uploadstats", true); - //command::execute("entitlements_delay 0", true); } void connect_to_party(const game::netadr_s& target, const std::string& mapname, const std::string& gametype, int sv_maxclients) @@ -50,26 +47,11 @@ namespace party if (game::Live_SyncOnlineDataFlags(0) != 0) { - // initialize the game after onlinedataflags is 32 (workaround) - if (game::Live_SyncOnlineDataFlags(0) == 32) + scheduler::once([=]() { - scheduler::once([=]() - { - command::execute("xstartprivateparty", true); - command::execute("disconnect", true); // 32 -> 0 - - connect_to_party(target, mapname, gametype, sv_maxclients); - }, scheduler::pipeline::main, 1s); - return; - } - else - { - scheduler::once([=]() - { - connect_to_party(target, mapname, gametype, sv_maxclients); - }, scheduler::pipeline::main, 1s); - return; - } + connect_to_party(target, mapname, gametype, sv_maxclients); + }, scheduler::pipeline::main, 1s); + return; } const auto ui_maxclients = game::Dvar_FindVar("ui_maxclients"); @@ -85,6 +67,28 @@ namespace party game::CL_MainMP_ConnectAndPreloadMap(0, reinterpret_cast(session_info), &target, mapname.data(), gametype.data()); } + void start_map_for_party() + { + auto* mapname = game::Dvar_FindVar("ui_mapname"); + auto* gametype = game::Dvar_FindVar("ui_gametype"); + auto* clients = game::Dvar_FindVar("ui_maxclients"); + auto* private_clients = game::Dvar_FindVar("ui_privateClients"); + auto* hardcore = game::Dvar_FindVar("ui_hardcore"); + + //utils::hook::invoke(0x9D8900_b, game::Party_GetActiveParty(), true); + + utils::hook::invoke(0xE4DDC0_b); // Sys_WaitWorkerCmds + utils::hook::invoke(0xBAFFD0_b, ""); // Com_ShutdownInternal + game::SV_CmdsMP_StartMapForParty( + mapname->current.string, + gametype->current.string, + clients->current.integer, + private_clients->current.integer, + hardcore->current.enabled, + false, + false); + } + std::string get_dvar_string(const std::string& dvar) { auto* dvar_value = game::Dvar_FindVar(dvar.data()); @@ -119,53 +123,40 @@ namespace party } } - void start_map_for_party() - { - auto* mapname = game::Dvar_FindVar("ui_mapname"); - auto* gametype = game::Dvar_FindVar("ui_gametype"); - auto* clients = game::Dvar_FindVar("ui_maxclients"); - auto* private_clients = game::Dvar_FindVar("ui_privateClients"); - auto* hardcore = game::Dvar_FindVar("ui_hardcore"); - - //utils::hook::invoke(0x9D8900_b, game::Party_GetActiveParty(), true); - - utils::hook::invoke(0xE4DDC0_b); // Sys_WaitWorkerCmds - utils::hook::invoke(0xBAFFD0_b, ""); // Com_ShutdownInternal - game::SV_CmdsMP_StartMapForParty( - mapname->current.string, - gametype->current.string, - clients->current.integer, - private_clients->current.integer, - hardcore->current.enabled, - false, - false); - } - - bool start_map(const std::string& mapname, bool dev) + void start_map(const std::string& mapname, bool dev) { if (game::Com_GameMode_GetActiveGameMode() == game::GAME_MODE_SP) { console::info("Starting sp map: %s\n", mapname.data()); command::execute(utils::string::va("spmap %s", mapname.data()), false); - return true; + return; + } + + if (game::Live_SyncOnlineDataFlags(0) != 0) + { + scheduler::once([=]() + { + start_map(mapname, dev); + }, scheduler::pipeline::main, 1s); + return; } if (mapname.empty()) { console::error("No map specified.\n"); - return false; + return; } if (!game::SV_MapExists(mapname.data())) { console::error("Map \"%s\" doesn't exist.\n", mapname.data()); - return false; + return; } if (!game::Com_GameMode_SupportsMap(mapname.data())) { console::error("Cannot load map \"%s\" in current game mode.\n", mapname.data()); - return false; + return; } auto* current_mapname = game::Dvar_FindVar("mapname"); @@ -177,17 +168,22 @@ namespace party { console::info("Restarting map: %s\n", mapname.data()); command::execute("map_restart", false); - return true; + return; } + 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); - console::info("Starting map: %s\n", mapname.data()); - perform_game_initialization(); - game::Cbuf_AddCall(0, start_map_for_party); - return true; + console::info("Starting map: %s\n", mapname.data()); + + start_map_for_party(); + return; } int get_client_num_by_name(const std::string& name) @@ -209,8 +205,6 @@ namespace party { //command::execute("lui_open_popup popup_acceptinginvite", false); - printf("connect called...\n"); - connect_state.host = target; connect_state.challenge = utils::cryptography::random::get_challenge(); connect_state.hostDefined = true; @@ -227,7 +221,6 @@ namespace party //} game::Com_SetLocalizedErrorMessage(error.data(), "MENU_NOTICE"); - //*reinterpret_cast(0x0) = 1; } @@ -236,16 +229,6 @@ namespace party public: void post_unpack() override { - command::add("live", []() - { - console::info("%d\n", game::Live_SyncOnlineDataFlags(0)); - }); - - command::add("connstate", []() - { - console::info("%d\n", game::clientUIActives[0].connectionState); - }); - static const char* a1 = "map_sp"; static const char* a2 = "map_restart_sp"; static const char* a3 = "fast_restart_sp"; @@ -265,6 +248,7 @@ namespace party utils::hook::set(0x1BBA700_b + 24, a3); utils::hook::set(0x1BBA700_b + 56, a3); + // need to fix this, currently it will disconnect everyone from the server when a new map is rotated command::add("map", [](const command::params& args) { if (args.size() != 2) @@ -297,6 +281,7 @@ namespace party start_map(args.get(1), true); }); + // need to fix this, currently game will freeze in loadingnewmap command command::add("map_restart", []() { if (!game::SV_Loaded() || game::Com_FrontEnd_IsInFrontEnd()) @@ -351,8 +336,6 @@ namespace party network::on("getInfo", [](const game::netadr_s& target, const std::string_view& data) { - printf("getInfo called...\n"); - utils::info_string info{}; info.set("challenge", std::string{ data }); info.set("gamename", "IW7"); @@ -375,8 +358,6 @@ namespace party network::on("infoResponse", [](const game::netadr_s& target, const std::string_view& data) { - printf("infoResponse called...\n"); - const utils::info_string info{ data }; //server_list::handle_info_response(target, info); diff --git a/src/client/component/party.hpp b/src/client/component/party.hpp index 958b1866..9f44f52a 100644 --- a/src/client/component/party.hpp +++ b/src/client/component/party.hpp @@ -8,7 +8,7 @@ namespace party void reset_connect_state(); void connect(const game::netadr_s& target); - bool start_map(const std::string& mapname, bool dev = false); + void start_map(const std::string& mapname, bool dev = false); void clear_sv_motd(); game::netadr_s get_state_host(); diff --git a/src/client/component/patches.cpp b/src/client/component/patches.cpp index e5733144..975b83b3 100644 --- a/src/client/component/patches.cpp +++ b/src/client/component/patches.cpp @@ -63,7 +63,11 @@ namespace patches bool com_game_mode_supports_feature_stub(game::Com_GameMode_Feature feature) { - if (feature == game::FEATURE_TIMESCALE) + if (feature == game::FEATURE_GRAVITY) + { + return true; + } + else if (feature == game::FEATURE_TIMESCALE) { return true; } diff --git a/src/client/game/dvars.cpp b/src/client/game/dvars.cpp index b4f69635..621f201a 100644 --- a/src/client/game/dvars.cpp +++ b/src/client/game/dvars.cpp @@ -26,9 +26,10 @@ namespace dvars game::dvar_t* r_fullbright = nullptr; game::dvar_t* bg_bounces = nullptr; - game::dvar_t* g_gravity = nullptr; + game::dvar_t* bg_gravity = nullptr; + game::dvar_t* bg_playerEjection = nullptr; - game::dvar_t* g_playerEjection = nullptr; + game::dvar_t* g_speed = nullptr; std::string dvar_get_vector_domain(const int components, const game::DvarLimits& domain) { @@ -138,7 +139,7 @@ namespace dvars } } - std::unordered_map dvar_names; + std::unordered_map dvar_names; std::string dvar_get_name(const game::dvar_t* dvar) { @@ -151,12 +152,12 @@ namespace dvars return ""; } - void dvar_set_name(const game::dvar_t* dvar, const char* name) + void dvar_set_name(const game::dvar_t* dvar, const std::string& name) { dvar_names[dvar] = name; } - std::unordered_map dvar_descriptions; + std::unordered_map dvar_descriptions; std::string dvar_get_description(const game::dvar_t* dvar) { @@ -169,7 +170,7 @@ namespace dvars return ""; } - void dvar_set_description(const game::dvar_t* dvar, const char* description) + void dvar_set_description(const game::dvar_t* dvar, const std::string& description) { dvar_descriptions[dvar] = description; } diff --git a/src/client/game/dvars.hpp b/src/client/game/dvars.hpp index adb4344b..0f5d59d0 100644 --- a/src/client/game/dvars.hpp +++ b/src/client/game/dvars.hpp @@ -22,14 +22,12 @@ namespace dvars extern game::dvar_t* r_fullbright; extern game::dvar_t* bg_bounces; - extern game::dvar_t* g_gravity; - - extern game::dvar_t* g_playerEjection; + extern game::dvar_t* bg_playerEjection; std::string dvar_get_vector_domain(const int components, const game::DvarLimits& domain); std::string dvar_get_domain(const game::DvarType type, const game::DvarLimits& domain); std::string dvar_get_name(const game::dvar_t* dvar); std::string dvar_get_description(const game::dvar_t* dvar); - void dvar_set_name(const game::dvar_t* dvar, const char* name); - void dvar_set_description(const game::dvar_t* dvar, const char* description); + void dvar_set_name(const game::dvar_t* dvar, const std::string& name); + void dvar_set_description(const game::dvar_t* dvar, const std::string& description); } diff --git a/src/client/game/structs.hpp b/src/client/game/structs.hpp index 6c0c762e..916a8e56 100644 --- a/src/client/game/structs.hpp +++ b/src/client/game/structs.hpp @@ -24,6 +24,7 @@ namespace game enum Com_GameMode_Feature : std::int32_t { + FEATURE_GRAVITY = 33, FEATURE_TIMESCALE = 69, }; diff --git a/src/client/game/symbols.hpp b/src/client/game/symbols.hpp index 3a852249..778424f7 100644 --- a/src/client/game/symbols.hpp +++ b/src/client/game/symbols.hpp @@ -8,6 +8,8 @@ namespace game * Functions **************************************************************/ + WEAK symbol BG_GetGravity{ 0x68DD0 }; + WEAK symbol Com_Error{ 0xB8D830 }; WEAK symbol Com_Quit_f{ 0xBADC90 }; @@ -33,6 +35,8 @@ namespace game WEAK symbol Cbuf_AddText{ 0xB7C290 }; WEAK symbol Cbuf_AddCall{ 0xB7C220 }; + WEAK symbol Cbuf_ExecuteBuffer{ 0xB7C3B0 }; + WEAK symbol Cbuf_ExecuteBufferInternal{ 0xB7C3C0 }; WEAK symbol CG_Utils_GameMessage{ 0x1D7FC0 }; WEAK symbol CG_Utils_BoldGameMessage{ 0x1D7F10 }; @@ -132,6 +136,9 @@ namespace game WEAK symbol Sys_SendPacket{ 0xD57DE0 }; WEAK symbol Sys_GetPacket{ 0xD57D50 }; + WEAK symbol Scr_AddInt{ 0xC0A580 }; + WEAK symbol Scr_GetInt{ 0xC0B950 }; + WEAK symbol ScrPlace_GetViewPlacement{ 0x9E4090 }; WEAK symbol SV_Cmd_TokenizeString{ 0xB7DD00 }; diff --git a/src/client/std_include.hpp b/src/client/std_include.hpp index 284af27b..8f1936b4 100644 --- a/src/client/std_include.hpp +++ b/src/client/std_include.hpp @@ -103,7 +103,7 @@ using namespace std::literals; #ifdef DEBUG -#define DW_DEBUG +//#define DW_DEBUG #endif #define __FILENAME__ (strrchr(__FILE__, '\\') ? strrchr(__FILE__, '\\') + 1 : __FILE__) diff --git a/src/common/utils/string.cpp b/src/common/utils/string.cpp index 42486cf3..8323c778 100644 --- a/src/common/utils/string.cpp +++ b/src/common/utils/string.cpp @@ -65,6 +65,11 @@ namespace utils::string return std::equal(substring.rbegin(), substring.rend(), text.rbegin()); } + bool is_numeric(const std::string& text) + { + return std::to_string(atoi(text.data())) == text; + } + std::string dump_hex(const std::string& data, const std::string& separator) { std::string result; diff --git a/src/common/utils/string.hpp b/src/common/utils/string.hpp index 322ce9ce..6ea06926 100644 --- a/src/common/utils/string.hpp +++ b/src/common/utils/string.hpp @@ -86,6 +86,7 @@ namespace utils::string std::string to_upper(std::string text); bool starts_with(const std::string& text, const std::string& substring); bool ends_with(const std::string& text, const std::string& substring); + bool is_numeric(const std::string& text); std::string dump_hex(const std::string& data, const std::string& separator = " ");