experiments pt6
This commit is contained in:
parent
f2f93efbb5
commit
5d058f79c5
@ -181,87 +181,6 @@ namespace command
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
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");
|
||||
|
||||
game::Com_FrontEndScene_ShutdownAndDisable();
|
||||
|
||||
if (!game::environment::is_dedi() && !game::Com_FrontEndScene_IsActive())
|
||||
{
|
||||
game::Com_Shutdown("EXE_ENDOFGAME");
|
||||
}
|
||||
|
||||
game::SV_CmdsMP_StartMapForParty(
|
||||
mapname->current.string,
|
||||
gametype->current.string,
|
||||
clients->current.integer,
|
||||
private_clients->current.integer,
|
||||
hardcore->current.enabled,
|
||||
false,
|
||||
false);
|
||||
}
|
||||
|
||||
void perform_game_initialization()
|
||||
{
|
||||
command::execute("onlinegame 1", true);
|
||||
command::execute("xstartprivatematch", true); //command::execute("xstartprivateparty", true);
|
||||
command::execute("xblive_privatematch 1", true);
|
||||
}
|
||||
|
||||
bool 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()), true);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (mapname.empty())
|
||||
{
|
||||
console::error("No map specified.\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!game::SV_MapExists(mapname.data()))
|
||||
{
|
||||
console::error("Map \"%s\" doesn't exist.\n", mapname.data());
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!game::Com_GameMode_SupportsMap(mapname.data()))
|
||||
{
|
||||
console::error("Cannot load map \"%s\" in current game mode.\n", mapname.data());
|
||||
return false;
|
||||
}
|
||||
|
||||
auto* current_mapname = game::Dvar_FindVar("mapname");
|
||||
|
||||
command::execute((dev ? "set sv_cheats 1" : "set sv_cheats 0"), true);
|
||||
|
||||
if (current_mapname && utils::string::to_lower(current_mapname->current.string) ==
|
||||
utils::string::to_lower(mapname) && (game::SV_Loaded() && !game::Com_FrontEndScene_IsActive()))
|
||||
{
|
||||
console::info("Restarting map: %s\n", mapname.data());
|
||||
command::execute("map_restart", false);
|
||||
return 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;
|
||||
}
|
||||
}
|
||||
|
||||
params::params()
|
||||
@ -437,89 +356,6 @@ namespace command
|
||||
game::Com_GameMode_SetDesiredGameMode(game::GAME_MODE_CP);
|
||||
});
|
||||
|
||||
static const char* a1 = "map_sp";
|
||||
static const char* a2 = "map_restart_sp";
|
||||
static const char* a3 = "fast_restart_sp";
|
||||
|
||||
// patch singleplayer "map" -> "map_sp"
|
||||
utils::hook::set(0x1BBA800_b + 0, a1);
|
||||
utils::hook::set(0x1BBA800_b + 24, a1);
|
||||
utils::hook::set(0x1BBA800_b + 56, a1);
|
||||
|
||||
// patch singleplayer map_restart -> "map_restart_sp"
|
||||
utils::hook::set(0x1BBA740_b + 0, a2);
|
||||
utils::hook::set(0x1BBA740_b + 24, a2);
|
||||
utils::hook::set(0x1BBA740_b + 56, a2);
|
||||
|
||||
// patch singleplayer fast_restart -> "fast_restart_sp"
|
||||
utils::hook::set(0x1BBA700_b + 0, a3);
|
||||
utils::hook::set(0x1BBA700_b + 24, a3);
|
||||
utils::hook::set(0x1BBA700_b + 56, a3);
|
||||
|
||||
add("map", [](const params& args)
|
||||
{
|
||||
if (args.size() != 2)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (game::Com_GameMode_GetActiveGameMode() == game::GAME_MODE_SP)
|
||||
{
|
||||
command::execute(utils::string::va("spmap %s", args.get(1)));
|
||||
return;
|
||||
}
|
||||
|
||||
start_map(args.get(1), false);
|
||||
});
|
||||
|
||||
add("devmap", [](const params& args)
|
||||
{
|
||||
if (args.size() != 2)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (game::Com_GameMode_GetActiveGameMode() == game::GAME_MODE_SP)
|
||||
{
|
||||
command::execute(utils::string::va("spmap %s", args.get(1)));
|
||||
return;
|
||||
}
|
||||
|
||||
start_map(args.get(1), true);
|
||||
});
|
||||
|
||||
add("map_restart", [](const params&)
|
||||
{
|
||||
if (!game::SV_Loaded() || game::Com_FrontEnd_IsInFrontEnd())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (game::Com_GameMode_GetActiveGameMode() == game::GAME_MODE_SP)
|
||||
{
|
||||
game::Cbuf_AddCall(0, game::SV_CmdsSP_MapRestart_f);
|
||||
return;
|
||||
}
|
||||
|
||||
game::SV_CmdsMP_RequestMapRestart(1, 0);
|
||||
});
|
||||
|
||||
add("fast_restart", [](const params&)
|
||||
{
|
||||
if (!game::SV_Loaded() || game::Com_FrontEnd_IsInFrontEnd())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (game::Com_GameMode_GetActiveGameMode() == game::GAME_MODE_SP)
|
||||
{
|
||||
game::Cbuf_AddCall(0, game::SV_CmdsSP_FastRestart_f);
|
||||
return;
|
||||
}
|
||||
|
||||
game::SV_CmdsMP_RequestMapRestart(0, 0);
|
||||
});
|
||||
|
||||
add_sv("god", [](const int client_num, const params_sv&)
|
||||
{
|
||||
if (!cheats_ok(client_num))
|
||||
|
283
src/client/component/dedicated.cpp
Normal file
283
src/client/component/dedicated.cpp
Normal file
@ -0,0 +1,283 @@
|
||||
#include <std_include.hpp>
|
||||
#include "loader/component_loader.hpp"
|
||||
|
||||
#include "game/game.hpp"
|
||||
|
||||
#include "dvars.hpp"
|
||||
#include "command.hpp"
|
||||
#include "console.hpp"
|
||||
#include "scheduler.hpp"
|
||||
|
||||
#include <utils/hook.hpp>
|
||||
#include <utils/string.hpp>
|
||||
|
||||
#include "game/dvars.hpp"
|
||||
|
||||
namespace dedicated
|
||||
{
|
||||
namespace
|
||||
{
|
||||
void sync_gpu_stub()
|
||||
{
|
||||
std::this_thread::sleep_for(1ms);
|
||||
}
|
||||
|
||||
void init_dedicated_server()
|
||||
{
|
||||
static bool initialized = false;
|
||||
if (initialized) return;
|
||||
initialized = true;
|
||||
|
||||
// R_RegisterDvars
|
||||
//utils::hook::invoke<void>(0xDF62C0_b);
|
||||
|
||||
// R_RegisterCmds
|
||||
//utils::hook::invoke<void>(0xDD7E50_b);
|
||||
|
||||
// R_LoadGraphicsAssets
|
||||
utils::hook::invoke<void>(0xE06220_b);
|
||||
}
|
||||
|
||||
utils::hook::detour dvar_set_float_from_source_hook;
|
||||
void dvar_set_float_from_source_stub(const game::dvar_t* dvar, double value, game::DvarSetSource source)
|
||||
{
|
||||
if (dvar)
|
||||
{
|
||||
printf("%s\n", dvars::dvar_get_name(dvar).data());
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("fuck\n");
|
||||
return;
|
||||
}
|
||||
dvar_set_float_from_source_hook.invoke<void>(dvar, value, source);
|
||||
}
|
||||
|
||||
utils::hook::detour cmd_add_client_command_list_hook;
|
||||
void cmd_add_client_command_list_stub(game::SvCommandInfo* cmds, unsigned int size)
|
||||
{
|
||||
printf("add: %p, %d\n", cmds, size);
|
||||
|
||||
for (auto i = 0u; i < size; i++)
|
||||
{
|
||||
/*printf("cmd[%d]: name: %s, func: %p, svvar.name: %s, svvar.func: %p, svvar.next: %p\n",
|
||||
i,
|
||||
cmds[i].name,
|
||||
cmds[i].function,
|
||||
cmds[i].svvar.name,
|
||||
cmds[i].svvar.function,
|
||||
cmds[i].svvar.next);*/
|
||||
|
||||
//memset(&cmds[i].svvar, 0, sizeof(game::cmd_function_s));
|
||||
}
|
||||
|
||||
cmd_add_client_command_list_hook.invoke<void>(cmds, size);
|
||||
}
|
||||
}
|
||||
|
||||
DWORD __stdcall wait_for_single_object_stub(HANDLE handle, DWORD ms)
|
||||
{
|
||||
if (handle == *reinterpret_cast<HANDLE*>(0x8B1BC98_b))
|
||||
{
|
||||
//printf("not waiting for mutex\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
return WaitForSingleObject(handle, ms);
|
||||
}
|
||||
|
||||
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
|
||||
{
|
||||
if (game::environment::is_dedi())
|
||||
{
|
||||
if (function == "WaitForSingleObject")
|
||||
{
|
||||
return wait_for_single_object_stub;
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void post_unpack() override
|
||||
{
|
||||
if (!game::environment::is_dedi())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
printf("Starting dedicated server\n");
|
||||
#endif
|
||||
|
||||
dvar_set_float_from_source_hook.create(0xCECD00_b, dvar_set_float_from_source_stub);
|
||||
cmd_add_client_command_list_hook.create(0xB7C840_b, cmd_add_client_command_list_stub);
|
||||
//utils::hook::set<uint8_t>(0xB7C840_b, 0xC3);
|
||||
|
||||
// Register dedicated dvar
|
||||
game::Dvar_RegisterBool("dedicated", true, game::DVAR_FLAG_READ, "Dedicated server");
|
||||
|
||||
// Add lanonly mode
|
||||
game::Dvar_RegisterBool("sv_lanOnly", false, game::DVAR_FLAG_NONE, "Don't send heartbeat");
|
||||
|
||||
// Disable frontend
|
||||
dvars::override::register_bool("frontEndSceneEnabled", false, game::DVAR_FLAG_READ);
|
||||
|
||||
// Disable shader preload
|
||||
dvars::override::register_bool("r_preloadShaders", false, game::DVAR_FLAG_READ);
|
||||
|
||||
// Disable 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);
|
||||
|
||||
// Hook R_SyncGpu
|
||||
utils::hook::jump(0xE08AE0_b, sync_gpu_stub, true);
|
||||
|
||||
utils::hook::jump(0x341B60_b, init_dedicated_server, true);
|
||||
|
||||
utils::hook::nop(0xCDD5D3_b, 5); // don't load config file
|
||||
utils::hook::nop(0xB7CE46_b, 5); // ^
|
||||
utils::hook::set<uint8_t>(0xBB0930_b, 0xC3); // don't save config file
|
||||
|
||||
utils::hook::set<uint8_t>(0x9D49C0_b, 0xC3); // disable self-registration // done
|
||||
//utils::hook::set<uint8_t>(0xD597C0_b, 0xC3); // init sound system (1) // done Voice_Init
|
||||
//utils::hook::set<uint8_t>(0x701820_b, 0xC3); // init sound system (2) // can't find ( arxan'd ) SND_Init?
|
||||
utils::hook::set<uint8_t>(0xE574E0_b, 0xC3); // render thread // done RB_RenderThread
|
||||
utils::hook::set<uint8_t>(0x3471A0_b, 0xC3); // called from Com_Frame, seems to do renderer stuff // done CL_Screen_Update
|
||||
utils::hook::set<uint8_t>(0x9AA9A0_b, 0xC3); // CL_CheckForResend, which tries to connect to the local server constantly // done CL_MainMP_CheckForResend
|
||||
//utils::hook::set<uint8_t>(0x67ADCE_b, 0x00); // r_loadForRenderer default to 0 // done via dvar override
|
||||
utils::hook::set<uint8_t>(0xD2EBB0_b, 0xC3); // recommended settings check // done
|
||||
//utils::hook::set<uint8_t>(0x5BE850_b, 0xC3); // some mixer-related function called on shutdown // not needed, only called from Voice_Init
|
||||
//utils::hook::set<uint8_t>(0x4DEA50_b, 0xC3); // dont load ui gametype stuff // don't add this for now
|
||||
|
||||
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? )
|
||||
|
||||
//utils::hook::set<uint8_t>(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::set<uint8_t>(0x1D8A20_b, 0xC3); // cpu detection stuff? // can't find
|
||||
//utils::hook::set<uint8_t>(0x690F30_b, 0xC3); // gfx stuff during fastfile loading // not there
|
||||
//utils::hook::set<uint8_t>(0x690E00_b, 0xC3); // ^
|
||||
//utils::hook::set<uint8_t>(0x690ED0_b, 0xC3); // ^
|
||||
//utils::hook::set<uint8_t>(0x39B980_b, 0xC3); // ^
|
||||
//utils::hook::set<uint8_t>(0x690E50_b, 0xC3); // ^
|
||||
//utils::hook::set<uint8_t>(0xDD26E0_b, 0xC3); // directx stuff // done
|
||||
//utils::hook::set<uint8_t>(0xE00FC0_b, 0xC3); // ^
|
||||
//utils::hook::set<uint8_t>(0x6CE390_b, 0xC3); // ^ - mutex // not done
|
||||
//utils::hook::set<uint8_t>(0x681ED0_b, 0xC3); // ^
|
||||
|
||||
//utils::hook::set<uint8_t>(0x0A3CD0_b, 0xC3); // rendering stuff // not done
|
||||
//utils::hook::set<uint8_t>(0x682150_b, 0xC3); // ^
|
||||
//utils::hook::set<uint8_t>(0x682260_b, 0xC3); // ^
|
||||
//utils::hook::set<uint8_t>(0x6829C0_b, 0xC3); // ^
|
||||
//utils::hook::set<uint8_t>(0x6834A0_b, 0xC3); // ^
|
||||
//utils::hook::set<uint8_t>(0x683B40_b, 0xC3); // ^
|
||||
|
||||
// shaders
|
||||
//utils::hook::set<uint8_t>(0x5F0610_b, 0xC3); // ^ // done
|
||||
//utils::hook::set<uint8_t>(0x5F0580_b, 0xC3); // ^ // done
|
||||
//utils::hook::set<uint8_t>(0xE51020_b, 0xC3); // ^ - mutex // done
|
||||
|
||||
//utils::hook::set<uint8_t>(0x5BFD10_b, 0xC3); // idk // not done
|
||||
//utils::hook::set<uint8_t>(0xDD4430_b, 0xC3); // ^ // R_ReleaseBuffer
|
||||
|
||||
//utils::hook::set<uint8_t>(0xE08360_b, 0xC3); // R_Shutdown
|
||||
//utils::hook::set<uint8_t>(0x652BA0_b, 0xC3); // shutdown stuff // not done
|
||||
//utils::hook::set<uint8_t>(0x687DF0_b, 0xC3); // ^ // not done
|
||||
//utils::hook::set<uint8_t>(0x686DE0_b, 0xC3); // ^ // not done
|
||||
|
||||
// utils::hook::set<uint8_t>(0x1404B67E0, 0xC3); // sound crashes (H1 - questionable, function looks way different)
|
||||
|
||||
utils::hook::set<uint8_t>(0xC5A200_b, 0xC3); // disable host migration // done SV_MigrationStart
|
||||
|
||||
//utils::hook::set<uint8_t>(0xBB66B0_b, 0xC3); // render synchronization lock // done
|
||||
//utils::hook::set<uint8_t>(0xBB64A0_b, 0xC3); // render synchronization unlock // done
|
||||
|
||||
//utils::hook::set<uint8_t>(0x615359_b, 0xEB); // LUI: Unable to start the LUI system due to errors in main.lua // done
|
||||
//utils::hook::set<uint8_t>(0x27AAC5_b, 0xEB); // LUI: Unable to start the LUI system due to errors in depot.lua // no
|
||||
//utils::hook::set<uint8_t>(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<uint8_t>(0x3A0BA0_b, 0xC3); // Disable image pak file loading // not done
|
||||
|
||||
// Reduce min required memory
|
||||
//utils::hook::set<uint64_t>(0x5B7F37_b, 0x80000000); // not done
|
||||
|
||||
//utils::hook::set<uint8_t>(0x399E10_b, 0xC3); // some loop // not done
|
||||
//utils::hook::set<uint8_t>(0x1D48B0_b, 0xC3); // related to shader caching / techsets / fastfilesc // not done
|
||||
//utils::hook::set<uint8_t>(0x3A1940_b, 0xC3); // DB_ReadPackedLoadedSounds // not done
|
||||
|
||||
// iw7 patches
|
||||
utils::hook::set<uint8_t>(0xE06060_b, 0xC3); // directx
|
||||
utils::hook::set<uint8_t>(0xE05B80_b, 0xC3); // ^
|
||||
utils::hook::set<uint8_t>(0xDD2760_b, 0xC3); // ^
|
||||
utils::hook::set<uint8_t>(0xE05E20_b, 0xC3); // ^ buffer
|
||||
utils::hook::set<uint8_t>(0xE11270_b, 0xC3); // ^
|
||||
utils::hook::set<uint8_t>(0xDD3C50_b, 0xC3); // ^
|
||||
utils::hook::set<uint8_t>(0x0C1210_b, 0xC3); // ^ idk
|
||||
utils::hook::set<uint8_t>(0x0C12B0_b, 0xC3); // ^ idk
|
||||
utils::hook::set<uint8_t>(0xE423A0_b, 0xC3); // directx
|
||||
utils::hook::set<uint8_t>(0xE04680_b, 0xC3); // ^
|
||||
|
||||
utils::hook::set<uint8_t>(0xE00ED0_b, 0xC3); // Image_Create1DTexture_PC
|
||||
utils::hook::set<uint8_t>(0xE00FC0_b, 0xC3); // Image_Create2DTexture_PC
|
||||
utils::hook::set<uint8_t>(0xE011A0_b, 0xC3); // Image_Create3DTexture_PC
|
||||
utils::hook::set<uint8_t>(0xE015C0_b, 0xC3); // Image_CreateCubeTexture_PC
|
||||
utils::hook::set<uint8_t>(0xE01300_b, 0xC3); // Image_CreateArrayTexture_PC
|
||||
|
||||
utils::hook::set<uint8_t>(0x5F1EA0_b, 0xC3); // renderer
|
||||
utils::hook::set<uint8_t>(0x0C1370_b, 0xC3); // ^
|
||||
utils::hook::set<uint8_t>(0xDD26E0_b, 0xC3); // directx
|
||||
utils::hook::set<uint8_t>(0x5F0610_b, 0xC3); // ^
|
||||
utils::hook::set<uint8_t>(0x5F0580_b, 0xC3); // ^
|
||||
utils::hook::set<uint8_t>(0x5F0820_b, 0xC3); // ^
|
||||
utils::hook::set<uint8_t>(0x5F0790_b, 0xC3); // ^
|
||||
|
||||
utils::hook::set<uint8_t>(0x3B9E72_b, 0xEB); // skip R_GetFrameIndex check in DB_LoadLevelXAssets
|
||||
|
||||
// release buffer
|
||||
utils::hook::set<uint8_t>(0xDD4430_b, 0xEB);
|
||||
|
||||
// R_LoadWorld
|
||||
utils::hook::set<uint8_t>(0xDD14C0_b, 0xC3);
|
||||
|
||||
scheduler::loop([]() // maybe not needed
|
||||
{
|
||||
// snd_enabled
|
||||
*reinterpret_cast<DWORD*>(0x7201A88_b) = 0;
|
||||
|
||||
|
||||
}, scheduler::pipeline::async);
|
||||
|
||||
command::add("startserver", []()
|
||||
{
|
||||
initialize();
|
||||
|
||||
console::info("==================================\n");
|
||||
console::info("Server started!\n");
|
||||
console::info("==================================\n");
|
||||
});
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
REGISTER_COMPONENT(dedicated::component)
|
@ -28,6 +28,14 @@ namespace party
|
||||
bool hostDefined{ false };
|
||||
} connect_state;
|
||||
|
||||
void perform_game_initialization()
|
||||
{
|
||||
command::execute("onlinegame 1", true);
|
||||
command::execute("xblive_privatematch 1", true);
|
||||
command::execute("xstartprivateparty", true);
|
||||
//command::execute("xstartprivatematch", true);
|
||||
}
|
||||
|
||||
void connect_to_party(const game::netadr_s& target, const std::string& mapname, const std::string& gametype)
|
||||
{
|
||||
if (game::Com_GameMode_GetActiveGameMode() != game::GAME_MODE_MP &&
|
||||
@ -60,7 +68,7 @@ namespace party
|
||||
}
|
||||
}*/
|
||||
|
||||
//perform_game_initialization();
|
||||
perform_game_initialization();
|
||||
|
||||
// shutdown frontend
|
||||
game::Com_FrontEndScene_ShutdownAndDisable();
|
||||
@ -104,6 +112,85 @@ 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");
|
||||
|
||||
game::Com_FrontEndScene_ShutdownAndDisable();
|
||||
|
||||
if (!game::environment::is_dedi() && !game::Com_FrontEndScene_IsActive())
|
||||
{
|
||||
game::Com_Shutdown("EXE_ENDOFGAME");
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
if (mapname.empty())
|
||||
{
|
||||
console::error("No map specified.\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!game::SV_MapExists(mapname.data()))
|
||||
{
|
||||
console::error("Map \"%s\" doesn't exist.\n", mapname.data());
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!game::Com_GameMode_SupportsMap(mapname.data()))
|
||||
{
|
||||
console::error("Cannot load map \"%s\" in current game mode.\n", mapname.data());
|
||||
return false;
|
||||
}
|
||||
|
||||
auto* current_mapname = game::Dvar_FindVar("mapname");
|
||||
|
||||
command::execute((dev ? "set sv_cheats 1" : "set sv_cheats 0"), true);
|
||||
|
||||
if (current_mapname && utils::string::to_lower(current_mapname->current.string) ==
|
||||
utils::string::to_lower(mapname) && (game::SV_Loaded() && !game::Com_FrontEndScene_IsActive()))
|
||||
{
|
||||
console::info("Restarting map: %s\n", mapname.data());
|
||||
command::execute("map_restart", false);
|
||||
return 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;
|
||||
}
|
||||
|
||||
int get_client_num_by_name(const std::string& name)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int get_client_count()
|
||||
{
|
||||
return 0;
|
||||
@ -145,6 +232,94 @@ namespace party
|
||||
public:
|
||||
void post_unpack() override
|
||||
{
|
||||
command::add("live", []()
|
||||
{
|
||||
console::info("%d\n", game::Live_SyncOnlineDataFlags(0));
|
||||
});
|
||||
|
||||
static const char* a1 = "map_sp";
|
||||
static const char* a2 = "map_restart_sp";
|
||||
static const char* a3 = "fast_restart_sp";
|
||||
|
||||
// patch singleplayer "map" -> "map_sp"
|
||||
utils::hook::set(0x1BBA800_b + 0, a1);
|
||||
utils::hook::set(0x1BBA800_b + 24, a1);
|
||||
utils::hook::set(0x1BBA800_b + 56, a1);
|
||||
|
||||
// patch singleplayer map_restart -> "map_restart_sp"
|
||||
utils::hook::set(0x1BBA740_b + 0, a2);
|
||||
utils::hook::set(0x1BBA740_b + 24, a2);
|
||||
utils::hook::set(0x1BBA740_b + 56, a2);
|
||||
|
||||
// patch singleplayer fast_restart -> "fast_restart_sp"
|
||||
utils::hook::set(0x1BBA700_b + 0, a3);
|
||||
utils::hook::set(0x1BBA700_b + 24, a3);
|
||||
utils::hook::set(0x1BBA700_b + 56, a3);
|
||||
|
||||
command::add("map", [](const command::params& args)
|
||||
{
|
||||
if (args.size() != 2)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (game::Com_GameMode_GetActiveGameMode() == game::GAME_MODE_SP)
|
||||
{
|
||||
command::execute(utils::string::va("spmap %s", args.get(1)));
|
||||
return;
|
||||
}
|
||||
|
||||
start_map(args.get(1), false);
|
||||
});
|
||||
|
||||
command::add("devmap", [](const command::params& args)
|
||||
{
|
||||
if (args.size() != 2)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (game::Com_GameMode_GetActiveGameMode() == game::GAME_MODE_SP)
|
||||
{
|
||||
command::execute(utils::string::va("spmap %s", args.get(1)));
|
||||
return;
|
||||
}
|
||||
|
||||
start_map(args.get(1), true);
|
||||
});
|
||||
|
||||
command::add("map_restart", []()
|
||||
{
|
||||
if (!game::SV_Loaded() || game::Com_FrontEnd_IsInFrontEnd())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (game::Com_GameMode_GetActiveGameMode() == game::GAME_MODE_SP)
|
||||
{
|
||||
game::Cbuf_AddCall(0, game::SV_CmdsSP_MapRestart_f);
|
||||
return;
|
||||
}
|
||||
|
||||
game::SV_CmdsMP_RequestMapRestart(1, 0);
|
||||
});
|
||||
|
||||
command::add("fast_restart", []()
|
||||
{
|
||||
if (!game::SV_Loaded() || game::Com_FrontEnd_IsInFrontEnd())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (game::Com_GameMode_GetActiveGameMode() == game::GAME_MODE_SP)
|
||||
{
|
||||
game::Cbuf_AddCall(0, game::SV_CmdsSP_FastRestart_f);
|
||||
return;
|
||||
}
|
||||
|
||||
game::SV_CmdsMP_RequestMapRestart(0, 0);
|
||||
});
|
||||
|
||||
command::add("connect", [](const command::params& argument)
|
||||
{
|
||||
if (argument.size() != 2)
|
||||
@ -152,6 +327,12 @@ namespace party
|
||||
return;
|
||||
}
|
||||
|
||||
if (game::CL_IsGameClientActive(0))
|
||||
{
|
||||
console::info("Cannot use \"connect\" command while ingame.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
game::netadr_s target{};
|
||||
if (game::NET_StringToAdr(argument[1], &target))
|
||||
{
|
||||
|
@ -3,12 +3,12 @@
|
||||
|
||||
namespace party
|
||||
{
|
||||
void menu_error(const std::string& error);
|
||||
void info_response_error(const std::string& error);
|
||||
|
||||
void reset_connect_state();
|
||||
|
||||
void connect(const game::netadr_s& target);
|
||||
void start_map(const std::string& mapname, bool dev = false);
|
||||
bool start_map(const std::string& mapname, bool dev = false);
|
||||
|
||||
void clear_sv_motd();
|
||||
game::netadr_s get_state_host();
|
||||
|
@ -42,6 +42,15 @@ namespace game
|
||||
return sv_cmd_args->argv[sv_cmd_args->nesting][index];
|
||||
}
|
||||
|
||||
bool CL_IsGameClientActive(const int localClientNum)
|
||||
{
|
||||
if (game::clientUIActives[localClientNum].frontEndSceneState[0])
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return game::clientUIActives[localClientNum].cgameInitialized;
|
||||
}
|
||||
|
||||
const char* g_assetNames[ASSET_TYPE_COUNT] =
|
||||
{
|
||||
"physicslibrary",
|
||||
|
@ -48,6 +48,8 @@ namespace game
|
||||
int SV_Cmd_Argc();
|
||||
const char* SV_Cmd_Argv(int index);
|
||||
|
||||
bool CL_IsGameClientActive(const int localClientNum);
|
||||
|
||||
extern const char* g_assetNames[ASSET_TYPE_COUNT];
|
||||
const char* DB_GetXAssetName(const XAsset* asset);
|
||||
void DB_EnumXAssets(const std::int32_t type, const std::function<void(XAssetHeader)>& callback);
|
||||
|
@ -57,14 +57,13 @@ namespace game
|
||||
{
|
||||
cmd_function_s* next;
|
||||
const char* name;
|
||||
void(__cdecl* function)();
|
||||
void(__fastcall* function)();
|
||||
};
|
||||
|
||||
struct SvCommandInfo
|
||||
{
|
||||
const char* name;
|
||||
void(__fastcall* func)();
|
||||
cmd_function_s clvar;
|
||||
void(__fastcall* function)();
|
||||
cmd_function_s svvar;
|
||||
};
|
||||
|
||||
@ -409,6 +408,37 @@ namespace game
|
||||
|
||||
namespace entity
|
||||
{
|
||||
enum connstate_t : std::uint32_t
|
||||
{
|
||||
CA_DISCONNECTED = 0x0,
|
||||
CA_CONNECTING = 0x1,
|
||||
CA_CHALLENGING = 0x2,
|
||||
CA_CONNECTED = 0x3,
|
||||
CA_SENDINGSTATS = 0x4,
|
||||
CA_REQUESTING_MATCH_RULES = 0x5,
|
||||
CA_STARTING = 0x6,
|
||||
CA_LOADING = 0x7,
|
||||
CA_PRIMED = 0x8,
|
||||
CA_ACTIVE = 0x9,
|
||||
CA_MAP_RESTART = 0xA,
|
||||
};
|
||||
|
||||
struct clientUIActive_t
|
||||
{
|
||||
bool active;
|
||||
bool isRunning;
|
||||
int keyCatchers;
|
||||
connstate_t connectionState;
|
||||
char __pad0[20];
|
||||
BYTE frontEndSceneState[1];
|
||||
bool cgameInitialized;
|
||||
bool cgameInitCalled;
|
||||
char __pad1[161];
|
||||
}; static_assert(sizeof(clientUIActive_t) == 196);
|
||||
static_assert(offsetof(clientUIActive_t, connectionState) == 8);
|
||||
static_assert(offsetof(clientUIActive_t, frontEndSceneState) == 32);
|
||||
static_assert(offsetof(clientUIActive_t, cgameInitialized) == 33);
|
||||
|
||||
struct entityState_t
|
||||
{
|
||||
__int16 number; // 0
|
||||
|
@ -162,6 +162,8 @@ namespace game
|
||||
WEAK symbol<int> svs_numclients{ 0x6B229E0 };
|
||||
WEAK symbol<client_t> svs_clients{ 0x6B22950 };
|
||||
|
||||
WEAK symbol<clientUIActive_t> clientUIActives{ 0x2246C30 };
|
||||
|
||||
WEAK symbol<int> sv_map_restart{ 0x6B2C9D4 };
|
||||
WEAK symbol<int> sv_loadScripts{ 0x6B2C9D8 };
|
||||
WEAK symbol<int> sv_migrate{ 0x6B2C9DC };
|
||||
|
Loading…
x
Reference in New Issue
Block a user