dedicated and map experiments

This commit is contained in:
quaK 2023-02-10 23:32:33 +02:00
parent 247109707f
commit b34de0d848
3 changed files with 129 additions and 17 deletions

View File

@ -112,6 +112,7 @@ namespace dedicated
// Disable frontend
dvars::override::register_bool("frontEndSceneEnabled", false, game::DVAR_FLAG_READ);
utils::hook::set<uint8_t>(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<uint8_t>(0xD2EBB0_b, 0xC3); // recommended settings check
// sound initialization
utils::hook::nop(0xC93213_b, 5); // snd stream thread
utils::hook::set<uint8_t>(0xC93206_b, 0); // snd_active
// crashes in cp_disco
//utils::hook::nop(0xC93213_b, 5); // snd stream thread
//utils::hook::set<uint8_t>(0xC93206_b, 0); // snd_active
utils::hook::set<uint8_t>(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<uint8_t>(0xA7DB10_b, 0xC3); // DB_CreateGfxImageStreamInternal
// recipe save threads
utils::hook::set<uint8_t>(0xE7C970_b, 0xC3);
// set game mode
scheduler::once([]()
{

View File

@ -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<game::XAssetHeader>(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<unsigned int>(type)],

View File

@ -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<bool>(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<void>(0xC19B00_b, gametype.data());
preloaded_map = false;
// connect
char session_info[0x100] = {};
game::CL_MainMP_ConnectAndPreloadMap(0, reinterpret_cast<void*>(session_info), &target, mapname.data(), gametype.data());
}
void pre_disaster()
{
utils::hook::set<uint8_t>(0x5EBED0_b, 0xC3); // ret // client snapshot
utils::hook::set<uint8_t>(0xC69890_b, 0xC3); // ret // nav mesh
}
void post_disaster()
{
utils::hook::set<uint8_t>(0xC69890_b, 0x48); // restore // client snapshot
//utils::hook::set<uint8_t>(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<void>(0x5AEFB0_b);
if (game::Com_FrontEnd_IsInFrontEnd())
{
// Com_FrontEndScene_ShutdownAndDisable
utils::hook::invoke<void>(0x5AEFB0_b);
}
utils::hook::set<uint8_t>(0x5EBED0_b, 0xC3); // ret
utils::hook::set<uint8_t>(0xC69890_b, 0xC3); // ret
if (game::CL_IsGameClientActive(0))
{
//utils::hook::invoke<void>(0xC58E20_b, game::Lobby_GetPartyData()); // SV_MainMP_MatchEnd
//utils::hook::invoke<void>(0xB200F0_b); // G_MainMP_ExitLevel
}
utils::hook::invoke<void>(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<uint8_t>(0xC69890_b, 0x48); // restore
utils::hook::set<uint8_t>(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<void>(0x5B0130_b, mapname, gametype, 0);
}
else
{
// DB_LoadLevelXAssets
utils::hook::invoke<void>(0x3B9C90_b, mapname, 0);
}
}
void com_restart_for_frontend_stub()
{
if (preloaded_map)
{
// Com_RestartForFrontend
utils::hook::invoke<void>(0xBAF0B0_b);
}
else
{
// Com_Restart
utils::hook::invoke<void>(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<void>(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<uint8_t>(0xC562FD_b, 0xEB); // allow mapname to be changed while server is running
utils::hook::set<uint8_t>(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)