cleanup and more

This commit is contained in:
quaK 2022-10-18 06:39:26 +03:00
parent a9ddb83380
commit b131b28075
18 changed files with 515 additions and 259 deletions

View File

@ -8,6 +8,7 @@
#include "console.hpp"
#include "game_console.hpp"
#include "scheduler.hpp"
#include "dvars.hpp"
#include <utils/hook.hpp>
#include <utils/string.hpp>
@ -107,6 +108,47 @@ namespace command
parsed = true;
}
void parse_startup_variables()
{
auto& com_num_console_lines = *reinterpret_cast<int*>(0x6006DB0_b);
auto* com_console_lines = reinterpret_cast<char**>(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<void>();
}
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();
}

View File

@ -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 <utils/hook.hpp>
#include <utils/string.hpp>
#include "game/dvars.hpp"
#include <utils/flags.hpp>
namespace dedicated
{
namespace
{
std::vector<std::string>& get_startup_command_queue()
{
static std::vector<std::string> 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<void>(0xDF62C0_b);
@ -53,7 +85,6 @@ namespace dedicated
{
if (handle == *reinterpret_cast<HANDLE*>(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<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(0xC93120_b, 0xC3C033); // init sound system (1) // done SND_InitDriver
utils::hook::set<uint8_t>(0xD597C0_b, 0xC3); // init sound system (2) // done Voice_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::set<uint8_t>(0x9D49C0_b, 0xC3); // disable self-registration
utils::hook::set<uint8_t>(0xE574E0_b, 0xC3); // render thread
utils::hook::set<uint8_t>(0x3471A0_b, 0xC3); // called from Com_Frame, seems to do renderer stuff
utils::hook::set<uint8_t>(0x9AA9A0_b, 0xC3); // CL_CheckForResend, which tries to connect to the local server constantly
utils::hook::set<uint8_t>(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<uint8_t>(0xC93206_b, 0); // snd_active
utils::hook::set<uint8_t>(0xD597C0_b, 0xC3); // init voice system
//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::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<uint8_t>(0xE08360_b, 0xC3); // don't shutdown renderer
//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
utils::hook::set<uint8_t>(0xC5A200_b, 0xC3); // disable host migration
// iw7 patches
utils::hook::set(0xE06060_b, 0xC3C033); //utils::hook::set<uint8_t>(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<uint8_t>(0xE114A0_b, 0xC3); // ^
//utils::hook::set<uint8_t>(0xE11380_b, 0xC3); // ^
@ -249,26 +230,69 @@ namespace dedicated
// R_LoadWorld
utils::hook::set<uint8_t>(0xDD14C0_b, 0xC3);
// vls shit
// something to do with vls?
utils::hook::set<uint8_t>(0xD02CB0_b, 0xC3);
// renderer
//utils::hook::set<uint8_t>(0xDD4370_b, 0xC3);
// image stream (pak)
utils::hook::set<uint8_t>(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<int>(strlen(sv_hostname->current.string) + 1));
utils::string::strip(sv_hostname->current.string, cleaned_hostname.data(),
static_cast<int>(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);
}
};
}

View File

@ -6,6 +6,7 @@
#include "game/dvars.hpp"
#include <utils/hook.hpp>
#include <utils/string.hpp>
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);
}

View File

@ -0,0 +1,29 @@
#include <std_include.hpp>
#include "loader/component_loader.hpp"
#include "filesystem.hpp"
#include "game/game.hpp"
#include "dvars.hpp"
#include <utils/hook.hpp>
#include <utils/string.hpp>
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)

View File

@ -0,0 +1,6 @@
#pragma once
namespace filesystem
{
}

View File

@ -6,6 +6,8 @@
#include "game/game.hpp"
#include "game/dvars.hpp"
#include "dvars.hpp"
#include <utils/nt.hpp>
#include <utils/hook.hpp>
#include <utils/flags.hpp>
@ -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<void>(entity);
}
@ -51,20 +53,52 @@ namespace gameplay
});
}
void* g_gravity_stub()
int get_gravity()
{
return static_cast<int>(game::BG_GetGravity());
}
void* bg_gravity_stub()
{
return utils::hook::assemble([](utils::hook::assembler& a)
{
a.mov(rax, qword_ptr(reinterpret_cast<int64_t>(&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<int64_t>(&*reinterpret_cast<game::dvar_t**>(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);
}
};
}

View File

@ -0,0 +1,181 @@
#include <std_include.hpp>
#include "loader/component_loader.hpp"
#include "command.hpp"
#include "scheduler.hpp"
#include <utils/hook.hpp>
#include <utils/string.hpp>
#include "game/game.hpp"
#include <game/dvars.hpp>
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<std::string> parse_current_map_rotation()
{
const auto rotation = load_current_map_rotation();
return utils::string::split(rotation, ' ');
}
void store_new_rotation(const std::vector<std::string>& 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)

View File

@ -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<sockaddr*>(&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<uint8_t>(0x_b, 0xEB);
// disable xuid verification
//utils::hook::nop(0x_b, 2);
//utils::hook::set<uint8_t>(0x_b, 0xEB);
// ignore configstring mismatch
utils::hook::set<uint8_t>(0x9B6F91_b, 0xEB);
@ -378,54 +346,19 @@ namespace network
utils::hook::set<int>(0xBB4E22_b, max_packet_size);
utils::hook::set<int>(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<uint8_t>(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<uint8_t>(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<uint8_t>(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<uint8_t>(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
}
};
}

View File

@ -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<void*>(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<void>(0x9D8900_b, game::Party_GetActiveParty(), true);
utils::hook::invoke<void>(0xE4DDC0_b); // Sys_WaitWorkerCmds
utils::hook::invoke<void>(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<void>(0x9D8900_b, game::Party_GetActiveParty(), true);
utils::hook::invoke<void>(0xE4DDC0_b); // Sys_WaitWorkerCmds
utils::hook::invoke<void>(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<int*>(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);

View File

@ -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();

View File

@ -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;
}

View File

@ -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<const game::dvar_t*, const char*> dvar_names;
std::unordered_map<const game::dvar_t*, std::string> 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<const game::dvar_t*, const char*> dvar_descriptions;
std::unordered_map<const game::dvar_t*, std::string> 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;
}

View File

@ -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);
}

View File

@ -24,6 +24,7 @@ namespace game
enum Com_GameMode_Feature : std::int32_t
{
FEATURE_GRAVITY = 33,
FEATURE_TIMESCALE = 69,
};

View File

@ -8,6 +8,8 @@ namespace game
* Functions
**************************************************************/
WEAK symbol<float()> BG_GetGravity{ 0x68DD0 };
WEAK symbol<void(errorParm code, const char* message, ...)> Com_Error{ 0xB8D830 };
WEAK symbol<void()> Com_Quit_f{ 0xBADC90 };
@ -33,6 +35,8 @@ namespace game
WEAK symbol<void(int localClientNum, const char* text)> Cbuf_AddText{ 0xB7C290 };
WEAK symbol<void(int localClientNum, void(*))> Cbuf_AddCall{ 0xB7C220 };
WEAK symbol<void(int localClientNum, int controllerIndex, const char* buffer)> Cbuf_ExecuteBuffer{ 0xB7C3B0 };
WEAK symbol<void(int localClientNum, int controllerIndex, const char* buffer, void(int, int, const char*))> Cbuf_ExecuteBufferInternal{ 0xB7C3C0 };
WEAK symbol<void(int localClientNum, const char* msg, int flags)> CG_Utils_GameMessage{ 0x1D7FC0 };
WEAK symbol<void(int localClientNum, const char* msg, int flags)> CG_Utils_BoldGameMessage{ 0x1D7F10 };
@ -132,6 +136,9 @@ namespace game
WEAK symbol<int(int length, void const* data, const netadr_s* to)> Sys_SendPacket{ 0xD57DE0 };
WEAK symbol<int(netadr_s* net_from, msg_t* net_message)> Sys_GetPacket{ 0xD57D50 };
WEAK symbol<void(int)> Scr_AddInt{ 0xC0A580 };
WEAK symbol<int()> Scr_GetInt{ 0xC0B950 };
WEAK symbol<ScreenPlacement* ()> ScrPlace_GetViewPlacement{ 0x9E4090 };
WEAK symbol<void(const char* string)> SV_Cmd_TokenizeString{ 0xB7DD00 };

View File

@ -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__)

View File

@ -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;

View File

@ -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 = " ");