diff --git a/shared/sdk/CVar.cpp b/shared/sdk/CVar.cpp index 9f2b2b6b..33889cee 100644 --- a/shared/sdk/CVar.cpp +++ b/shared/sdk/CVar.cpp @@ -695,7 +695,7 @@ float IConsoleVariable::GetFloat() { return func(this); } -std::optional IConsoleVariable::locate_vtable_indices() { +std::optional IConsoleObject::locate_vtable_indices() { std::scoped_lock _{ s_vtable_mutex }; const auto vtable = *(uintptr_t**)this; @@ -708,16 +708,16 @@ std::optional IConsoleVariable::locate_vtable_indi // in most cases the +2 function will be the Set function (the +1 function is Release) // from there, GetInt, GetFloat, etc will be the next subsequent functions // THIS MUST BE CALLED FROM AN ACTUAL IConsoleVariable INSTANCE, NOT A CONSOLE COMMAND!!! - SPDLOG_INFO("Locating IConsoleVariable vtable indices..."); + SPDLOG_INFO("Locating IConsoleObject vtable indices..."); std::optional previous_nullptr_index{}; - SPDLOG_INFO("Vtable: {:x} (cvar {:x})", (uintptr_t)vtable, (uintptr_t)this); + SPDLOG_INFO("Vtable: {:x} (console obj {:x})", (uintptr_t)vtable, (uintptr_t)this); for (auto i = 0; i < 20; ++i) { const auto func = vtable[i]; if (func == 0 || IsBadReadPtr((void*)func, 1)) { - SPDLOG_ERROR("Reached end of IConsoleVariable vtable at index {}", i); + SPDLOG_ERROR("Reached end of IConsoleObject vtable at index {}", i); break; } @@ -815,6 +815,8 @@ std::optional IConsoleVariable::locate_vtable_indi auto& vtable_info = s_vtable_infos[vtable]; + vtable_info.as_console_command_index = destructor_index - 1; + vtable_info.release_index = destructor_index; vtable_info.set_vtable_index = destructor_index + 1; auto potential_get_int_index = vtable_info.set_vtable_index + 1; @@ -868,6 +870,8 @@ std::optional IConsoleVariable::locate_vtable_indi vtable_info.get_int_vtable_index = potential_get_int_index; vtable_info.get_float_vtable_index = vtable_info.get_int_vtable_index + 1; SPDLOG_INFO("Encountered final nullptr at index {}", *previous_nullptr_index); + SPDLOG_INFO("IConsoleObject::AsConsoleCommand vtable index: {}", vtable_info.as_console_command_index); + SPDLOG_INFO("IConsoleObject::Release vtable index: {}", vtable_info.release_index); SPDLOG_INFO("IConsoleVariable::Set vtable index: {}", vtable_info.set_vtable_index); SPDLOG_INFO("IConsoleVariable::GetInt vtable index: {}", vtable_info.get_int_vtable_index); SPDLOG_INFO("IConsoleVariable::GetFloat vtable index: {}", vtable_info.get_float_vtable_index); diff --git a/shared/sdk/CVar.hpp b/shared/sdk/CVar.hpp index e95d0ce4..295eecb3 100644 --- a/shared/sdk/CVar.hpp +++ b/shared/sdk/CVar.hpp @@ -51,20 +51,34 @@ struct TConsoleVariableData { T values[2]; }; +struct IConsoleCommand; + // Dummy interface for IConsoleObject // The functions will actually dynamically scan the vtable for the right index struct IConsoleObject { virtual ~IConsoleObject() {} virtual wchar_t* GetHelp() const = 0; -}; + virtual uint32_t GetFlags() const = 0; + virtual void SetFlags(uint32_t flags) = 0; -struct IConsoleVariable : IConsoleObject { - void Set(const wchar_t* in, uint32_t set_by_flags = 0x8000000); - int32_t GetInt(); - float GetFloat(); + // Everything past this point needs to be dynamically scanned + IConsoleCommand* AsCommand() { + const auto vtable_info = this->locate_vtable_indices(); -private: + if (!vtable_info.has_value() || vtable_info->as_console_command_index == 0) { + return nullptr; + } + + const auto vtable = *(void***)this; + const auto func = ((IConsoleCommand*(__thiscall*)(void*))vtable[vtable_info->as_console_command_index]); + + return func(this); + } + +protected: struct VtableInfo { + uint32_t as_console_command_index; + uint32_t release_index; uint32_t set_vtable_index; uint32_t get_int_vtable_index; uint32_t get_float_vtable_index; @@ -76,6 +90,16 @@ struct IConsoleVariable : IConsoleObject { static inline std::unordered_map s_vtable_infos{}; }; +struct IConsoleCommand : IConsoleObject { + // TODO: Implement +}; + +struct IConsoleVariable : IConsoleObject { + void Set(const wchar_t* in, uint32_t set_by_flags = 0x8000000); + int32_t GetInt(); + float GetFloat(); +}; + struct FConsoleVariableBase : public IConsoleVariable { struct { wchar_t* data; diff --git a/shared/sdk/ConsoleManager.cpp b/shared/sdk/ConsoleManager.cpp index 98d5d458..127f7162 100644 --- a/shared/sdk/ConsoleManager.cpp +++ b/shared/sdk/ConsoleManager.cpp @@ -11,6 +11,8 @@ FConsoleManager* FConsoleManager::get() { static auto result = []() -> FConsoleManager** { SPDLOG_INFO("Finding IConsoleManager..."); + const auto now = std::chrono::steady_clock::now(); + const auto core_module = sdk::get_ue_module(L"Core"); const auto r_dumping_movie_string = utility::scan_string(core_module, L"r.DumpingMovie"); @@ -67,6 +69,9 @@ FConsoleManager* FConsoleManager::get() { SPDLOG_INFO("Found IConsoleManager**: {:x}", (uintptr_t)std::get<0>(*highest_global_variable_reference)); SPDLOG_INFO("Points to IConsoleManager*: {:x}", *(uintptr_t*)std::get<0>(*highest_global_variable_reference)); + const auto diff = std::chrono::duration_cast(std::chrono::steady_clock::now() - now).count(); + SPDLOG_INFO("Took {}ms to find IConsoleManager", diff); + return (FConsoleManager**)std::get<0>(*highest_global_variable_reference); }();