Skip to content

Commit

Permalink
Minor startup time improvements by using console manager
Browse files Browse the repository at this point in the history
  • Loading branch information
praydog committed Jun 23, 2023
1 parent e246729 commit ed3c9f0
Show file tree
Hide file tree
Showing 2 changed files with 85 additions and 20 deletions.
46 changes: 30 additions & 16 deletions shared/sdk/CVar.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -311,13 +311,39 @@ std::optional<ConsoleVariableDataWrapper> find_cvar_data(std::wstring_view modul
SPDLOG_INFO("Found {} at {:x}", utility::narrow(name.data()), (uintptr_t)*result);
}

return result;
return ConsoleVariableDataWrapper{*result, name.data()};
}

IConsoleVariable** find_cvar(std::wstring_view module_name, std::wstring_view name, bool stop_at_first_mov) {
SPDLOG_INFO("Attempting to locate {} {} cvar", utility::narrow(module_name.data()), utility::narrow(name.data()));


const auto module = sdk::get_ue_module(module_name.data());

// Attempt to locate it by way of the console manager first.
try {
const auto console_manager = sdk::FConsoleManager::get();

if (console_manager != nullptr) {
const auto cvar = console_manager->find(name.data());

if (cvar != nullptr) {
const auto module_data = utility::scan_ptr(module, (uintptr_t)cvar);

if (module_data) {
SPDLOG_INFO("Found {} at {:x} (via console manager)", utility::narrow(name.data()), (uintptr_t)*module_data);
return (IConsoleVariable**)*module_data;
} else {
SPDLOG_ERROR("Failed to find {} in module data!", utility::narrow(name.data()));
}
} else {
SPDLOG_ERROR("Failed to find {} in console manager!", utility::narrow(name.data()));
}
}
} catch(...) {

}

const auto str = utility::scan_string(module, name.data());

if (!str) {
Expand All @@ -328,7 +354,7 @@ IConsoleVariable** find_cvar(std::wstring_view module_name, std::wstring_view na
const auto str_ref = utility::scan_displacement_reference(module, *str);

if (!str_ref) {
SPDLOG_ERROR("Failed to find {} string reference!");
SPDLOG_ERROR("Failed to find {} string reference!", utility::narrow(name.data()));
return nullptr;
}

Expand Down Expand Up @@ -387,13 +413,7 @@ bool set_cvar_data_int(std::wstring_view module, std::wstring_view name, int val
return false;
}

auto cvar = cvar_data->get<int>();

if (cvar == nullptr) {
return false;
}

cvar->set(value);
cvar_data->set(value);
return true;
} catch (...) {
static std::unordered_map<std::wstring, bool> bad_cvars{};
Expand All @@ -414,13 +434,7 @@ bool set_cvar_data_float(std::wstring_view module, std::wstring_view name, float
return false;
}

auto cvar = cvar_data->get<float>();

if (cvar == nullptr) {
return false;
}

cvar->set(value);
cvar_data->set(value);
return true;
} catch (...) {
static std::unordered_map<std::wstring, bool> bad_cvars{};
Expand Down
59 changes: 55 additions & 4 deletions shared/sdk/CVar.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@
#include <spdlog/spdlog.h>
#include <windows.h>

#include <utility/String.hpp>

#include "threading/GameThreadWorker.hpp"
#include "ConsoleManager.hpp"
#include "TArray.hpp"

namespace sdk {
Expand All @@ -17,7 +21,7 @@ struct TConsoleVariableData {
static inline std::recursive_mutex s_mutex{};
static inline std::unordered_map<TConsoleVariableData*, bool> s_valid_states{};

void set(T value) {
bool set(T value) {
{
std::scoped_lock _{s_mutex};

Expand All @@ -34,12 +38,13 @@ struct TConsoleVariableData {
}

if (!s_valid_states[this]) {
return;
return false;
}
}

this->values[0] = value;
this->values[1] = value;
return true;
}

T get(int index = 0) const {
Expand Down Expand Up @@ -135,14 +140,51 @@ class ConsoleVariableDataWrapper {
return *(TConsoleVariableData<T>**)this->m_cvar;
}

template<typename T>
void set_via_console_manager(T value) {
if (m_name.empty()) {
return;
}

if (m_real_cvar != nullptr) {
GameThreadWorker::get().enqueue([cvar = m_real_cvar, value]() {
cvar->Set(std::to_wstring(value).c_str());
});

return;
}

try {
const auto console_manager = sdk::FConsoleManager::get();

if (console_manager != nullptr) {
auto cvar = (sdk::IConsoleVariable*)console_manager->find(m_name);

if (cvar != nullptr) {
m_real_cvar = cvar;
spdlog::info("Fallback to real cvar for {}", utility::narrow(m_name));

GameThreadWorker::get().enqueue([cvar, value]() {
cvar->Set(std::to_wstring(value).c_str());
});
}
}
} catch(...) {

}
}

template<typename T>
void set(T value) {
if (this->m_cvar == nullptr || *this->m_cvar == nullptr) {
set_via_console_manager(value);
return;
}

auto data = *(TConsoleVariableData<T>**)this->m_cvar;
data->set(value);
if (!data->set(value)) {
set_via_console_manager(value);
}
}

ConsoleVariableDataWrapper(uintptr_t address)
Expand All @@ -151,12 +193,21 @@ class ConsoleVariableDataWrapper {

}

ConsoleVariableDataWrapper(uintptr_t address, const std::wstring& name)
: m_cvar{ (void**)address },
m_name{ name }
{

}

uintptr_t address() const {
return (uintptr_t)m_cvar;
}

private:
void** m_cvar;
void** m_cvar{nullptr};
std::wstring m_name{L""};
sdk::IConsoleVariable* m_real_cvar{nullptr};
};

// In some games, likely due to obfuscation, the cvar description is missing
Expand Down

0 comments on commit ed3c9f0

Please sign in to comment.