Skip to content

Commit

Permalink
Merge branch 'praydog:master' into master
Browse files Browse the repository at this point in the history
  • Loading branch information
joeyhodge authored Apr 21, 2024
2 parents 0b11f07 + 6f66b80 commit 67dab7c
Show file tree
Hide file tree
Showing 7 changed files with 365 additions and 131 deletions.
358 changes: 240 additions & 118 deletions include/reframework/API.hpp

Large diffs are not rendered by default.

7 changes: 7 additions & 0 deletions shared/sdk/REManagedObject.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,13 @@ struct RETypeDefinition;
}

namespace utility::re_managed_object {
// Exposed because these take forever to scan for
// Maybe we can just do some clever scanning through some reflected methods in the future.
namespace detail {
void resolve_add_ref();
void resolve_release();
}

// Forward declarations
struct ParamWrapper;
bool is_managed_object(Address address);
Expand Down
40 changes: 37 additions & 3 deletions shared/sdk/RETypeDefinition.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -465,19 +465,48 @@ sdk::REMethodDefinition* RETypeDefinition::get_method(std::string_view name) con
}
}
}

// first pass, do not use function prototypes

// This is probably a hacky way of doing it but whatever.
// I haven't checked if IsGenericMethodDefinition is implemented.
auto is_generic_method_definition = [](sdk::REMethodDefinition& m) {
const auto return_type = m.get_return_type();

if (return_type != nullptr && return_type->get_name() != nullptr) {
if (std::string_view{return_type->get_name()}.contains("!")) {
return true;
}
}

const auto method_param_types = m.get_param_types();

// Go through any of the params and look for ! in the name
for (auto& param : method_param_types) {
if (param != nullptr && param->get_name() != nullptr) {
if (std::string_view{param->get_name()}.contains("!")) {
return true;
}
}
}

return false;
};

for (auto super = this; super != nullptr; super = super->get_parent_type()) {
for (auto& m : super->get_methods()) {
if (name == m.get_name()) {
if (is_generic_method_definition(m)) {
// This is a generic method (definition), we need to skip it because it's not a direct match
continue;
}

std::unique_lock _{g_method_mtx};

g_method_map[this][name_hash] = &m;
return g_method_map[this][name_hash];
}
}
}

// second pass, build a function prototype
for (auto super = this; super != nullptr; super = super->get_parent_type()) {
for (auto& m : super->get_methods()) {
Expand All @@ -498,6 +527,11 @@ sdk::REMethodDefinition* RETypeDefinition::get_method(std::string_view name) con
const auto method_prototype = ss.str();

if (name == method_prototype) {
if (is_generic_method_definition(m)) {
// This is a generic method (definition), we need to skip it because it's not a direct match
continue;
}

std::unique_lock _{g_method_mtx};

g_method_map[this][name_hash] = &m;
Expand Down
3 changes: 3 additions & 0 deletions shared/sdk/SDK.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,5 +17,8 @@ void initialize_sdk() {

reframework::get_types();
reframework::get_globals();

utility::re_managed_object::detail::resolve_add_ref();
utility::re_managed_object::detail::resolve_release();
}
}
10 changes: 10 additions & 0 deletions src/REFramework.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,16 @@ using namespace std::literals;
std::unique_ptr<REFramework> g_framework{};

void REFramework::hook_monitor() {
if (!m_hook_monitor_mutex.try_lock()) {
// If this happens then we can assume execution is going as planned
// so we can just reset the times so we dont break something
m_last_present_time = std::chrono::steady_clock::now() + std::chrono::seconds(5);
m_last_chance_time = std::chrono::steady_clock::now() + std::chrono::seconds(1);
m_has_last_chance = true;
} else {
m_hook_monitor_mutex.unlock();
}

std::scoped_lock _{ m_hook_monitor_mutex };

if (g_framework == nullptr) {
Expand Down
69 changes: 60 additions & 9 deletions src/mods/LooseFileLoader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,16 @@ void LooseFileLoader::on_draw_ui() {
return;
}

auto clear_existence_cache = [&]() {
std::unique_lock _{m_files_on_disk_mutex};
m_files_on_disk.clear();
m_seen_files.clear();
m_cache_hits = 0;
m_uncached_hits = 0;
};

if (m_enabled->draw("Enable Loose File Loader")) {
clear_existence_cache();
}

if (m_hook_success) {
Expand All @@ -66,6 +75,18 @@ void LooseFileLoader::on_draw_ui() {
m_all_loose_files.clear();
}

if (ImGui::TreeNode("Debug")) {
ImGui::Checkbox("Enable file cache", &m_enable_file_cache);
ImGui::TextWrapped("Cache hits: %d", m_cache_hits);
ImGui::TextWrapped("Uncached hits: %d", m_uncached_hits);

if (ImGui::Button("Clear existence cache")) {
clear_existence_cache();
}

ImGui::TreePop();
}

ImGui::Checkbox("Show recent files", &m_show_recent_files);

if (m_show_recent_files) {
Expand Down Expand Up @@ -175,7 +196,7 @@ void LooseFileLoader::hook() {
m_hook_success = true;
}

bool LooseFileLoader::handle_path(const wchar_t* path) {
bool LooseFileLoader::handle_path(const wchar_t* path, size_t hash) {
if (path == nullptr || path[0] == L'\0') {
return false;
}
Expand All @@ -198,8 +219,36 @@ bool LooseFileLoader::handle_path(const wchar_t* path) {

//spdlog::info("[LooseFileLoader] path_to_hash_hook called with path: {}", utility::narrow(path));

if (enabled && std::filesystem::exists(path)) {
if (m_show_recent_files) {
if (enabled) {
bool exists_in_cache{false};
bool exists_on_disk{false};

if (m_enable_file_cache) {
{
std::shared_lock _{m_files_on_disk_mutex};
exists_on_disk = m_files_on_disk.contains(hash);
exists_in_cache = exists_on_disk || m_seen_files.contains(hash);
}

if (!exists_in_cache) {
std::unique_lock _{m_files_on_disk_mutex};

if (std::filesystem::exists(path)) {
m_files_on_disk.insert(hash);
exists_on_disk = true;
}

m_seen_files.insert(hash);
++m_uncached_hits;
} else {
++m_cache_hits;
}
} else {
exists_on_disk = std::filesystem::exists(path);
++m_uncached_hits;
}

if (m_show_recent_files && exists_on_disk) {
std::unique_lock _{m_mutex};

m_all_loose_files.insert(path);
Expand All @@ -210,21 +259,23 @@ bool LooseFileLoader::handle_path(const wchar_t* path) {
}
}

++g_loose_file_loader->m_loose_files_loaded;
return true;
if (exists_on_disk) {
++g_loose_file_loader->m_loose_files_loaded;
return true;
}
}

return false;
}

uint64_t LooseFileLoader::path_to_hash_hook(const wchar_t* path) {
const auto og = g_loose_file_loader->m_path_to_hash_hook->get_original<decltype(path_to_hash_hook)>();
const auto result = og(path);

// true to skip.
if (g_loose_file_loader->handle_path(path)) {
if (g_loose_file_loader->handle_path(path, result)) {
return 4294967296;
}

const auto og = g_loose_file_loader->m_path_to_hash_hook->get_original<decltype(path_to_hash_hook)>();
const auto result = og(path);

return result;
}
9 changes: 8 additions & 1 deletion src/mods/LooseFileLoader.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,14 @@ class LooseFileLoader : public Mod {

private:
void hook();
bool handle_path(const wchar_t* path);
bool handle_path(const wchar_t* path, size_t hash);
static uint64_t path_to_hash_hook(const wchar_t* path);

bool m_hook_success{false};
bool m_attempted_hook{false};
uint32_t m_files_encountered{};
uint32_t m_uncached_hits{};
uint32_t m_cache_hits{};
uint32_t m_loose_files_loaded{};

std::shared_mutex m_mutex{};
Expand All @@ -37,10 +39,15 @@ class LooseFileLoader : public Mod {
std::unordered_set<std::wstring> m_all_accessed_files{};
std::unordered_set<std::wstring> m_all_loose_files{};

std::unordered_set<size_t> m_files_on_disk{};
std::unordered_set<size_t> m_seen_files{};
std::shared_mutex m_files_on_disk_mutex{};

std::unique_ptr<FunctionHook> m_path_to_hash_hook{nullptr};

ModToggle::Ptr m_enabled{ ModToggle::create(generate_name("Enabled")) };
bool m_show_recent_files{false}; // Not persistent because its for dev purposes
bool m_enable_file_cache{true};

ValueList m_options{
*m_enabled
Expand Down

0 comments on commit 67dab7c

Please sign in to comment.