Skip to content

Commit 67dab7c

Browse files
authored
Merge branch 'praydog:master' into master
2 parents 0b11f07 + 6f66b80 commit 67dab7c

7 files changed

Lines changed: 365 additions & 131 deletions

File tree

include/reframework/API.hpp

Lines changed: 240 additions & 118 deletions
Large diffs are not rendered by default.

shared/sdk/REManagedObject.hpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,13 @@ struct RETypeDefinition;
1818
}
1919

2020
namespace utility::re_managed_object {
21+
// Exposed because these take forever to scan for
22+
// Maybe we can just do some clever scanning through some reflected methods in the future.
23+
namespace detail {
24+
void resolve_add_ref();
25+
void resolve_release();
26+
}
27+
2128
// Forward declarations
2229
struct ParamWrapper;
2330
bool is_managed_object(Address address);

shared/sdk/RETypeDefinition.cpp

Lines changed: 37 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -465,19 +465,48 @@ sdk::REMethodDefinition* RETypeDefinition::get_method(std::string_view name) con
465465
}
466466
}
467467
}
468-
469-
// first pass, do not use function prototypes
468+
469+
// This is probably a hacky way of doing it but whatever.
470+
// I haven't checked if IsGenericMethodDefinition is implemented.
471+
auto is_generic_method_definition = [](sdk::REMethodDefinition& m) {
472+
const auto return_type = m.get_return_type();
473+
474+
if (return_type != nullptr && return_type->get_name() != nullptr) {
475+
if (std::string_view{return_type->get_name()}.contains("!")) {
476+
return true;
477+
}
478+
}
479+
480+
const auto method_param_types = m.get_param_types();
481+
482+
// Go through any of the params and look for ! in the name
483+
for (auto& param : method_param_types) {
484+
if (param != nullptr && param->get_name() != nullptr) {
485+
if (std::string_view{param->get_name()}.contains("!")) {
486+
return true;
487+
}
488+
}
489+
}
490+
491+
return false;
492+
};
493+
470494
for (auto super = this; super != nullptr; super = super->get_parent_type()) {
471495
for (auto& m : super->get_methods()) {
472496
if (name == m.get_name()) {
497+
if (is_generic_method_definition(m)) {
498+
// This is a generic method (definition), we need to skip it because it's not a direct match
499+
continue;
500+
}
501+
473502
std::unique_lock _{g_method_mtx};
474503

475504
g_method_map[this][name_hash] = &m;
476505
return g_method_map[this][name_hash];
477506
}
478507
}
479508
}
480-
509+
481510
// second pass, build a function prototype
482511
for (auto super = this; super != nullptr; super = super->get_parent_type()) {
483512
for (auto& m : super->get_methods()) {
@@ -498,6 +527,11 @@ sdk::REMethodDefinition* RETypeDefinition::get_method(std::string_view name) con
498527
const auto method_prototype = ss.str();
499528

500529
if (name == method_prototype) {
530+
if (is_generic_method_definition(m)) {
531+
// This is a generic method (definition), we need to skip it because it's not a direct match
532+
continue;
533+
}
534+
501535
std::unique_lock _{g_method_mtx};
502536

503537
g_method_map[this][name_hash] = &m;

shared/sdk/SDK.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,5 +17,8 @@ void initialize_sdk() {
1717

1818
reframework::get_types();
1919
reframework::get_globals();
20+
21+
utility::re_managed_object::detail::resolve_add_ref();
22+
utility::re_managed_object::detail::resolve_release();
2023
}
2124
}

src/REFramework.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,16 @@ using namespace std::literals;
4747
std::unique_ptr<REFramework> g_framework{};
4848

4949
void REFramework::hook_monitor() {
50+
if (!m_hook_monitor_mutex.try_lock()) {
51+
// If this happens then we can assume execution is going as planned
52+
// so we can just reset the times so we dont break something
53+
m_last_present_time = std::chrono::steady_clock::now() + std::chrono::seconds(5);
54+
m_last_chance_time = std::chrono::steady_clock::now() + std::chrono::seconds(1);
55+
m_has_last_chance = true;
56+
} else {
57+
m_hook_monitor_mutex.unlock();
58+
}
59+
5060
std::scoped_lock _{ m_hook_monitor_mutex };
5161

5262
if (g_framework == nullptr) {

src/mods/LooseFileLoader.cpp

Lines changed: 60 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,16 @@ void LooseFileLoader::on_draw_ui() {
4848
return;
4949
}
5050

51+
auto clear_existence_cache = [&]() {
52+
std::unique_lock _{m_files_on_disk_mutex};
53+
m_files_on_disk.clear();
54+
m_seen_files.clear();
55+
m_cache_hits = 0;
56+
m_uncached_hits = 0;
57+
};
58+
5159
if (m_enabled->draw("Enable Loose File Loader")) {
60+
clear_existence_cache();
5261
}
5362

5463
if (m_hook_success) {
@@ -66,6 +75,18 @@ void LooseFileLoader::on_draw_ui() {
6675
m_all_loose_files.clear();
6776
}
6877

78+
if (ImGui::TreeNode("Debug")) {
79+
ImGui::Checkbox("Enable file cache", &m_enable_file_cache);
80+
ImGui::TextWrapped("Cache hits: %d", m_cache_hits);
81+
ImGui::TextWrapped("Uncached hits: %d", m_uncached_hits);
82+
83+
if (ImGui::Button("Clear existence cache")) {
84+
clear_existence_cache();
85+
}
86+
87+
ImGui::TreePop();
88+
}
89+
6990
ImGui::Checkbox("Show recent files", &m_show_recent_files);
7091

7192
if (m_show_recent_files) {
@@ -175,7 +196,7 @@ void LooseFileLoader::hook() {
175196
m_hook_success = true;
176197
}
177198

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

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

201-
if (enabled && std::filesystem::exists(path)) {
202-
if (m_show_recent_files) {
222+
if (enabled) {
223+
bool exists_in_cache{false};
224+
bool exists_on_disk{false};
225+
226+
if (m_enable_file_cache) {
227+
{
228+
std::shared_lock _{m_files_on_disk_mutex};
229+
exists_on_disk = m_files_on_disk.contains(hash);
230+
exists_in_cache = exists_on_disk || m_seen_files.contains(hash);
231+
}
232+
233+
if (!exists_in_cache) {
234+
std::unique_lock _{m_files_on_disk_mutex};
235+
236+
if (std::filesystem::exists(path)) {
237+
m_files_on_disk.insert(hash);
238+
exists_on_disk = true;
239+
}
240+
241+
m_seen_files.insert(hash);
242+
++m_uncached_hits;
243+
} else {
244+
++m_cache_hits;
245+
}
246+
} else {
247+
exists_on_disk = std::filesystem::exists(path);
248+
++m_uncached_hits;
249+
}
250+
251+
if (m_show_recent_files && exists_on_disk) {
203252
std::unique_lock _{m_mutex};
204253

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

213-
++g_loose_file_loader->m_loose_files_loaded;
214-
return true;
262+
if (exists_on_disk) {
263+
++g_loose_file_loader->m_loose_files_loaded;
264+
return true;
265+
}
215266
}
216267

217268
return false;
218269
}
219270

220271
uint64_t LooseFileLoader::path_to_hash_hook(const wchar_t* path) {
272+
const auto og = g_loose_file_loader->m_path_to_hash_hook->get_original<decltype(path_to_hash_hook)>();
273+
const auto result = og(path);
274+
221275
// true to skip.
222-
if (g_loose_file_loader->handle_path(path)) {
276+
if (g_loose_file_loader->handle_path(path, result)) {
223277
return 4294967296;
224278
}
225279

226-
const auto og = g_loose_file_loader->m_path_to_hash_hook->get_original<decltype(path_to_hash_hook)>();
227-
const auto result = og(path);
228-
229280
return result;
230281
}

src/mods/LooseFileLoader.hpp

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,12 +23,14 @@ class LooseFileLoader : public Mod {
2323

2424
private:
2525
void hook();
26-
bool handle_path(const wchar_t* path);
26+
bool handle_path(const wchar_t* path, size_t hash);
2727
static uint64_t path_to_hash_hook(const wchar_t* path);
2828

2929
bool m_hook_success{false};
3030
bool m_attempted_hook{false};
3131
uint32_t m_files_encountered{};
32+
uint32_t m_uncached_hits{};
33+
uint32_t m_cache_hits{};
3234
uint32_t m_loose_files_loaded{};
3335

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

42+
std::unordered_set<size_t> m_files_on_disk{};
43+
std::unordered_set<size_t> m_seen_files{};
44+
std::shared_mutex m_files_on_disk_mutex{};
45+
4046
std::unique_ptr<FunctionHook> m_path_to_hash_hook{nullptr};
4147

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

4552
ValueList m_options{
4653
*m_enabled

0 commit comments

Comments
 (0)