From f3f8f2ac5da32d3551a339e646c29c151de1f224 Mon Sep 17 00:00:00 2001 From: quaK <38787176+Joelrau@users.noreply.github.com> Date: Fri, 10 Feb 2023 23:30:51 +0200 Subject: [PATCH 1/3] add thread names --- src/client/component/thread_names.cpp | 62 +++++++++++++++++++++++++++ src/client/game/structs.hpp | 25 +++++++++++ 2 files changed, 87 insertions(+) create mode 100644 src/client/component/thread_names.cpp diff --git a/src/client/component/thread_names.cpp b/src/client/component/thread_names.cpp new file mode 100644 index 00000000..ceda5e8e --- /dev/null +++ b/src/client/component/thread_names.cpp @@ -0,0 +1,62 @@ +#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_WINDOW, "Window"}, + {game::THREAD_CONTEXT_WINDOW, "Input"}, + {game::THREAD_CONTEXT_DATABASE, "Database"}, + {game::THREAD_CONTEXT_SOUND_STREAM, "Sound Stream"}, + {game::THREAD_CONTEXT_SOUND, "Snd stream packet callback"}, + {game::THREAD_CONTEXT_RECIPE, "Recipe"}, + }; + + 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) \ No newline at end of file diff --git a/src/client/game/structs.hpp b/src/client/game/structs.hpp index d321dd5b..d81126e2 100644 --- a/src/client/game/structs.hpp +++ b/src/client/game/structs.hpp @@ -412,6 +412,31 @@ namespace game CRITSECT_DEMONWARE = 39, }; + enum ThreadContext + { + THREAD_CONTEXT_MAIN = 0, + THREAD_CONTEXT_BACKEND = 1, + THREAD_CONTEXT_WORKER0 = 2, + THREAD_CONTEXT_WORKER1 = 3, + THREAD_CONTEXT_WORKER2 = 4, + THREAD_CONTEXT_WORKER3 = 5, + THREAD_CONTEXT_WORKER4 = 6, + THREAD_CONTEXT_WORKER5 = 7, + THREAD_CONTEXT_WORKER6 = 8, + THREAD_CONTEXT_WORKER7 = 9, + THREAD_CONTEXT_SERVER = 10, + THREAD_CONTEXT_CINEMATIC = 11, + THREAD_CONTEXT_WINDOW = 12, + THREAD_CONTEXT_INPUT = 13, + THREAD_CONTEXT_DATABASE = 14, + THREAD_CONTEXT_SOUND_STREAM = 15, + THREAD_CONTEXT_SOUND = 16, + THREAD_CONTEXT_UNKNOWN17 = 17, + THREAD_CONTEXT_UNKNOWN18 = 18, + THREAD_CONTEXT_UNKNOWN19 = 19, + THREAD_CONTEXT_RECIPE = 20, + }; + namespace entity { enum connstate_t : std::uint32_t From 247109707fed4fa608e785b6d6b76ac17328dac7 Mon Sep 17 00:00:00 2001 From: quaK <38787176+Joelrau@users.noreply.github.com> Date: Fri, 10 Feb 2023 23:32:02 +0200 Subject: [PATCH 2/3] symbols --- src/client/game/symbols.hpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/client/game/symbols.hpp b/src/client/game/symbols.hpp index 44495595..dc10af64 100644 --- a/src/client/game/symbols.hpp +++ b/src/client/game/symbols.hpp @@ -93,6 +93,8 @@ namespace game WEAK symbol FS_FreeFile{ 0xCDE1F0 }; WEAK symbol FS_Printf{ 0xCDD1C0 }; + WEAK symbol I_CleanStr{ 0xCFACC0 }; + WEAK symbol Key_KeynumToString{ 0x9A95E0 }; WEAK symbol LUI_CoD_InFrontEnd{ 0x615080 }; @@ -154,6 +156,7 @@ namespace game WEAK symbol SV_GameSendServerCommand{ 0xC54780 }; WEAK symbol SV_Loaded{ 0xC114C0 }; WEAK symbol SV_MapExists{ 0xCDB620 }; + WEAK symbol SV_BotIsBot{ 0xC3BC90 }; WEAK symbol SND_StopSounds{ 0xCA06E0 }; WEAK symbol SND_SetMusicState{ 0xC9E110 }; @@ -187,4 +190,6 @@ namespace game WEAK symbol sv_migrate{ 0x6B2C9DC }; WEAK symbol query_socket{ 0x779FDC8 }; + + WEAK symbol threadIds{ 0x602BAB0 }; } From b34de0d8480cb74a9d577a15bcfe9ab783ac596a Mon Sep 17 00:00:00 2001 From: quaK <38787176+Joelrau@users.noreply.github.com> Date: Fri, 10 Feb 2023 23:32:33 +0200 Subject: [PATCH 3/3] dedicated and map experiments --- src/client/component/dedicated.cpp | 9 +- src/client/component/fastfiles.cpp | 2 +- src/client/component/party.cpp | 135 ++++++++++++++++++++++++++--- 3 files changed, 129 insertions(+), 17 deletions(-) diff --git a/src/client/component/dedicated.cpp b/src/client/component/dedicated.cpp index c5247d89..5466df5a 100644 --- a/src/client/component/dedicated.cpp +++ b/src/client/component/dedicated.cpp @@ -112,6 +112,7 @@ namespace dedicated // Disable frontend dvars::override::register_bool("frontEndSceneEnabled", false, game::DVAR_FLAG_READ); + utils::hook::set(0x5AC8F0_b, 0xC3); // Com_FastFile_Frame_FrontEnd // Disable shader preload dvars::override::register_bool("r_preloadShaders", false, game::DVAR_FLAG_READ); @@ -146,8 +147,9 @@ namespace dedicated utils::hook::set(0xD2EBB0_b, 0xC3); // recommended settings check // sound initialization - utils::hook::nop(0xC93213_b, 5); // snd stream thread - utils::hook::set(0xC93206_b, 0); // snd_active + // crashes in cp_disco + //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::nop(0xC5007B_b, 6); // unknown check in SV_ExecuteClientMessage @@ -216,6 +218,9 @@ namespace dedicated // image stream (pak) utils::hook::set(0xA7DB10_b, 0xC3); // DB_CreateGfxImageStreamInternal + // recipe save threads + utils::hook::set(0xE7C970_b, 0xC3); + // set game mode scheduler::once([]() { diff --git a/src/client/component/fastfiles.cpp b/src/client/component/fastfiles.cpp index 101b524b..ef78b49e 100644 --- a/src/client/component/fastfiles.cpp +++ b/src/client/component/fastfiles.cpp @@ -59,7 +59,7 @@ namespace fastfiles game::XAssetHeader db_find_xasset_header_stub(game::XAssetType type, const char* name, const int allow_create_default) { auto result = db_find_xasset_header_hook.invoke(type, name, allow_create_default); - if (!result.data) + if (!result.data && type != game::ASSET_TYPE_LOCALIZE_ENTRY) { console::error("Error: Could not find %s \"%s\"\n", game::g_assetNames[static_cast(type)], diff --git a/src/client/component/party.cpp b/src/client/component/party.cpp index 2acb8aff..c634e55e 100644 --- a/src/client/component/party.cpp +++ b/src/client/component/party.cpp @@ -28,6 +28,8 @@ namespace party bool hostDefined{ false }; } connect_state; + bool preloaded_map = false; + void perform_game_initialization() { command::execute("onlinegame 1", true); @@ -45,7 +47,7 @@ namespace party return; } - if (game::Live_SyncOnlineDataFlags(0) != 0) + if (game::Live_SyncOnlineDataFlags(0) != 0/* || !utils::hook::invoke(0xBB5E70_b)*/) { scheduler::once([=]() { @@ -55,18 +57,37 @@ namespace party } const auto ui_maxclients = game::Dvar_FindVar("ui_maxclients"); + const auto party_maxplayers = game::Dvar_FindVar("party_maxplayers"); game::Dvar_SetInt(ui_maxclients, sv_maxclients); + game::Dvar_SetInt(party_maxplayers, sv_maxclients); + + command::execute(utils::string::va("ui_mapname %s", mapname.data()), true); + command::execute(utils::string::va("ui_gametype %s", gametype.data()), true); perform_game_initialization(); // setup agent count utils::hook::invoke(0xC19B00_b, gametype.data()); + preloaded_map = false; + // connect char session_info[0x100] = {}; game::CL_MainMP_ConnectAndPreloadMap(0, reinterpret_cast(session_info), &target, mapname.data(), gametype.data()); } + void pre_disaster() + { + utils::hook::set(0x5EBED0_b, 0xC3); // ret // client snapshot + utils::hook::set(0xC69890_b, 0xC3); // ret // nav mesh + } + + void post_disaster() + { + utils::hook::set(0xC69890_b, 0x48); // restore // client snapshot + //utils::hook::set(0x5EBED0_b, 0x40); // restore // nav mesh + } + void start_map_for_party(std::string map_name) { [[maybe_unused]]auto* mapname = game::Dvar_FindVar("ui_mapname"); @@ -75,11 +96,21 @@ namespace party auto* private_clients = game::Dvar_FindVar("ui_privateClients"); auto* hardcore = game::Dvar_FindVar("ui_hardcore"); - // Com_FrontEndScene_ShutdownAndDisable - utils::hook::invoke(0x5AEFB0_b); + if (game::Com_FrontEnd_IsInFrontEnd()) + { + // Com_FrontEndScene_ShutdownAndDisable + utils::hook::invoke(0x5AEFB0_b); + } - utils::hook::set(0x5EBED0_b, 0xC3); // ret - utils::hook::set(0xC69890_b, 0xC3); // ret + if (game::CL_IsGameClientActive(0)) + { + //utils::hook::invoke(0xC58E20_b, game::Lobby_GetPartyData()); // SV_MainMP_MatchEnd + //utils::hook::invoke(0xB200F0_b); // G_MainMP_ExitLevel + } + + utils::hook::invoke(0xC12850_b); // SV_GameMP_ShutdownGameProgs + + pre_disaster(); game::SV_CmdsMP_StartMapForParty( map_name.data(), gametype->current.string, @@ -88,8 +119,7 @@ namespace party hardcore->current.enabled, false, false); - utils::hook::set(0xC69890_b, 0x48); // restore - utils::hook::set(0x5EBED0_b, 0x40); // restore + post_disaster(); } std::string get_dvar_string(const std::string& dvar) @@ -124,6 +154,42 @@ namespace party return false; } + + void com_gamestart_beginclient_stub(const char* mapname, const char* gametype, char a3) + { + if (preloaded_map) + { + // Com_GameStart_BeginClient + utils::hook::invoke(0x5B0130_b, mapname, gametype, 0); + } + else + { + // DB_LoadLevelXAssets + utils::hook::invoke(0x3B9C90_b, mapname, 0); + } + } + + void com_restart_for_frontend_stub() + { + if (preloaded_map) + { + // Com_RestartForFrontend + utils::hook::invoke(0xBAF0B0_b); + } + else + { + // Com_Restart + utils::hook::invoke(0xBAF0A0_b); + } + } + + utils::hook::detour sv_start_map_for_party_hook; + void sv_start_map_for_party_stub(const char* map, const char* game_type, int client_count, int agent_count, bool hardcore, + bool map_is_preloaded, bool migrate) + { + preloaded_map = map_is_preloaded; + sv_start_map_for_party_hook.invoke(map, game_type, client_count, agent_count, hardcore, map_is_preloaded, migrate); + } } void start_map(const std::string& mapname, bool dev) @@ -190,17 +256,50 @@ namespace party int get_client_num_by_name(const std::string& name) { - return 0; + for (auto i = 0; !name.empty() && i < *game::svs_numclients; ++i) + { + if (game::g_entities[i].client) + { + char client_name[32] = { 0 }; + strncpy_s(client_name, game::g_entities[i].client->name, sizeof(client_name)); + game::I_CleanStr(client_name); + + if (client_name == name) + { + return i; + } + } + } + return -1; } int get_client_count() { - return 0; + auto count = 0; + for (auto i = 0; i < *game::svs_numclients; ++i) + { + if (game::svs_clients[i].header.state >= 1) + { + ++count; + } + } + + return count; } int get_bot_count() { - return 0; + auto count = 0; + for (auto i = 0; i < *game::svs_numclients; ++i) + { + if (game::svs_clients[i].header.state >= 1 && + game::SV_BotIsBot(i)) + { + ++count; + } + } + + return count; } void connect(const game::netadr_s& target) @@ -225,7 +324,6 @@ namespace party game::Com_SetLocalizedErrorMessage(error.data(), "MENU_NOTICE"); } - class component final : public component_interface { public: @@ -251,9 +349,15 @@ namespace party utils::hook::set(0x1BBA700_b + 56, a3); utils::hook::set(0xC562FD_b, 0xEB); // allow mapname to be changed while server is running - utils::hook::set(0x9B37B0_b, 0xC3); // CL_MainMp_PreloadMap ( map restart issue ) - // need to fix this, currently it will disconnect everyone from the server when a new map is rotated + utils::hook::nop(0xA7A8DF_b, 5); // R_SyncRenderThread inside CL_MainMp_PreloadMap ( freezes ) + + utils::hook::call(0x9AFE84_b, com_gamestart_beginclient_stub); // blackscreen issue on connect + utils::hook::call(0x9B4077_b, com_gamestart_beginclient_stub); // crash on map rotate + utils::hook::call(0x9B404A_b, com_restart_for_frontend_stub); // crash on map rotate + + // TODO: fix disaster shit, those patches are shite. + command::add("map", [](const command::params& args) { if (args.size() != 2) @@ -286,7 +390,6 @@ 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()) @@ -300,7 +403,9 @@ namespace party return; } + pre_disaster(); game::SV_CmdsMP_RequestMapRestart(1, 0); + post_disaster(); }); command::add("fast_restart", []() @@ -316,7 +421,9 @@ namespace party return; } + pre_disaster(); game::SV_CmdsMP_RequestMapRestart(0, 0); + post_disaster(); }); command::add("connect", [](const command::params& argument)