dvar stuff

-Read dvar names and hashes from file and copy dvar name to each known dvar from pool.
-Hook dvar_foreach functions to show them in the ingame client console.
-Patch some dvar flags checks to show them in dvarlist/dvardump command
-Patch a dvar flag check that doesn't allow some dvars to be recognized when typed in console.
This commit is contained in:
BrentVL-1952840 2023-02-26 22:45:48 +01:00
parent bd609d45b9
commit 7c755c106a
4 changed files with 4114 additions and 10 deletions

File diff suppressed because it is too large Load Diff

View File

@ -14,13 +14,108 @@ namespace dvars
namespace namespace
{ {
bool initial_config_read = false; bool initial_config_read = false;
utils::hook::detour dvar_register_new_hook;
utils::hook::detour dvar_set_variant_hook; utils::hook::detour dvar_set_variant_hook;
utils::hook::detour set_config_dvar_hook; void dvar_for_each_name_stub(void (*callback)(const char*))
utils::hook::detour for_each_name_match_hook; {
utils::hook::detour get_debug_name_hook; for (int i = 0; i < *game::g_dvarCount; ++i)
{
const auto offset = game::is_server() ? 136 : 160;
const auto* dvar = reinterpret_cast<game::dvar_t*>(&game::s_dvarPool[offset * i]);
if ((!game::Com_SessionMode_IsMode(game::MODE_COUNT) ||
!game::Dvar_IsSessionModeBaseDvar(dvar)) &&
(dvar->flags & 0x8000) == 0)
{
if (dvar->debugName)
{
callback(dvar->debugName);
}
}
}
}
void dvar_for_each_name_client_num_stub(int localClientNum, void (*callback)(int, const char*))
{
for (int i = 0; i < *game::g_dvarCount; ++i)
{
const auto offset = game::is_server() ? 136 : 160;
const auto* dvar = reinterpret_cast<game::dvar_t*>(&game::s_dvarPool[offset * i]);
if ((!game::Com_SessionMode_IsMode(game::MODE_COUNT) ||
!game::Dvar_IsSessionModeBaseDvar(dvar)) &&
(dvar->flags & 0x8000) == 0)
{
if (dvar->debugName)
{
callback(localClientNum, dvar->debugName);
}
}
}
}
void read_dvar_name_hashes_data(std::unordered_map<std::uint32_t, std::string>& map)
{
const auto path = game::get_appdata_path() / "data" / "lookup_tables" / "dvar_lookup_table.csv";
std::string data;
if (!utils::io::read_file(path, &data))
{
printf("Failed to read Dvar lookup table\n");
return;
}
std::istringstream stream(data);
std::string line;
while (std::getline(stream, line, '\n'))
{
if (utils::string::starts_with(line, "//"))
{
continue;
}
const auto separator = line.find(',');
if (separator == std::string::npos)
{
continue;
}
const auto debug_name = line.substr(separator + 1);
if (!debug_name.empty())
{
std::istringstream hash_string(line.substr(0, separator));
std::uint32_t hash_value;
hash_string >> hash_value;
map.emplace(hash_value, debug_name);
}
}
}
void copy_dvar_names_to_pool()
{
std::unordered_map<std::uint32_t, std::string> dvar_hash_name_map;
read_dvar_name_hashes_data(dvar_hash_name_map);
for (int i = 0; i < *game::g_dvarCount; ++i)
{
const auto offset = game::is_server() ? 136 : 160;
auto* dvar = reinterpret_cast<game::dvar_t*>(&game::s_dvarPool[offset * i]);
if (!dvar->debugName)
{
const auto it = dvar_hash_name_map.find(dvar->name);
if (it != dvar_hash_name_map.end())
{
dvar->debugName = game::CopyString(it->second.data());
}
}
}
}
const std::string get_config_file_path() const std::string get_config_file_path()
{ {
@ -79,14 +174,29 @@ namespace dvars
} }
} }
class component final : public client_component class component final : public generic_component
{ {
public: public:
void post_unpack() override void post_unpack() override
{
if (!game::is_server())
{ {
scheduler::once(read_archive_dvars, scheduler::pipeline::main); scheduler::once(read_archive_dvars, scheduler::pipeline::main);
dvar_set_variant_hook.create(0x1422C9A90_g, dvar_set_variant_stub); dvar_set_variant_hook.create(0x1422C9A90_g, dvar_set_variant_stub);
// Show all known dvars in console
utils::hook::jump(0x1422BD890_g, dvar_for_each_name_stub);
utils::hook::jump(0x1422BD7E0_g, dvar_for_each_name_client_num_stub);
}
scheduler::once(copy_dvar_names_to_pool, scheduler::pipeline::main);
// All dvars are recognized as command
utils::hook::nop(game::select(0x14215297A, 0x14050949A), 2);
// Show all dvars in dvarlist command
utils::hook::nop(game::select(0x142152C87, 0x140509797), 6);
// Show all dvars in dvardump command
utils::hook::nop(game::select(0x142152659, 0x140509179), 6);
} }
}; };
} }

View File

@ -736,6 +736,7 @@ namespace game
struct dvar_t struct dvar_t
{ {
dvarStrHash_t name; dvarStrHash_t name;
char _pad[0x4];
const char* debugName; const char* debugName;
const char* description; const char* description;
unsigned int flags; unsigned int flags;

View File

@ -78,7 +78,11 @@ namespace game
WEAK symbol<TLSData*()> Sys_GetTLS{0x142184210, 0x140525EB0}; WEAK symbol<TLSData*()> Sys_GetTLS{0x142184210, 0x140525EB0};
WEAK symbol<TLSData*()> Sys_IsDatabaseReady{0x1421844C0}; WEAK symbol<TLSData*()> Sys_IsDatabaseReady{0x1421844C0};
// Unnamed
WEAK symbol<const char* (const char* name)> CopyString{0x1422ACC80, 0x14056BD70};
// Dvar // Dvar
WEAK symbol<bool(const dvar_t* dvar)> Dvar_IsSessionModeBaseDvar{0x1422C2E00, 0x140576890};
WEAK symbol<dvar_t*(const char* dvarName)> Dvar_FindVar{0x1422BD730, 0x140575540}; WEAK symbol<dvar_t*(const char* dvarName)> Dvar_FindVar{0x1422BD730, 0x140575540};
WEAK symbol<unsigned int(const char* str)> Dvar_GenerateHash{0x14133DBF0}; WEAK symbol<unsigned int(const char* str)> Dvar_GenerateHash{0x14133DBF0};
WEAK symbol<dvar_t*(unsigned int hash)> Dvar_FindMalleableVar{0x1422BD6A0}; WEAK symbol<dvar_t*(unsigned int hash)> Dvar_FindMalleableVar{0x1422BD6A0};
@ -93,8 +97,6 @@ namespace game
WEAK symbol<void(const char* dvarName, const char* string, bool createIfMissing)> Dvar_SetFromStringByName{ WEAK symbol<void(const char* dvarName, const char* string, bool createIfMissing)> Dvar_SetFromStringByName{
0x1422C7F60 0x1422C7F60
}; };
WEAK symbol<char> s_dvarPool{0x157AC8220};
WEAK symbol<int> g_dvarCount{0x157AC81CC};
// UI // UI
WEAK symbol<void(bool frontend)> UI_CoD_Init{0x141F298B0, 0x0}; WEAK symbol<void(bool frontend)> UI_CoD_Init{0x141F298B0, 0x0};
@ -136,7 +138,6 @@ namespace game
WEAK symbol<const char* (char* str)> I_CleanStr{0x1422E9C10, 0x140580E80}; WEAK symbol<const char* (char* str)> I_CleanStr{0x1422E9C10, 0x140580E80};
// Variables // Variables
WEAK symbol<cmd_function_s> cmd_functions{0x15689FF58, 0x14946F860}; WEAK symbol<cmd_function_s> cmd_functions{0x15689FF58, 0x14946F860};
WEAK symbol<CmdArgs> sv_cmd_args{0x15689CE30, 0x14944C740}; WEAK symbol<CmdArgs> sv_cmd_args{0x15689CE30, 0x14944C740};
@ -148,6 +149,9 @@ namespace game
WEAK symbol<Join> s_join{0x15574C640}; WEAK symbol<Join> s_join{0x15574C640};
WEAK symbol<char> s_dvarPool{0x157AC8220, 0x14A3CB620};
WEAK symbol<int> g_dvarCount{0x157AC81CC, 0x14A3CB5FC};
namespace s_wcd namespace s_wcd
{ {
WEAK symbol<HWND> codLogo{0x157E77A50, 0x14A640BC0}; WEAK symbol<HWND> codLogo{0x157E77A50, 0x14A640BC0};