Add plugin initialization progress (#2)

* add plugin init progress

* add lazy initializing

* fix: lazy initializing - can't get class from `*` namespace

* fix: lazy mode - can't get class with empty namespace

* update build.yml - Adapt to Gitea Actions
This commit is contained in:
chinosk
2024-07-08 20:13:23 +08:00
committed by GitHub
parent c28e05e271
commit 6ddf4212d4
14 changed files with 423 additions and 24 deletions
@@ -47,6 +47,18 @@
#include "../../GakumasLocalify/Log.h"
#include "../../GakumasLocalify/Misc.hpp"
class UnityResolveProgress final {
public:
struct Progress {
long current = 0;
long total = 1;
};
static bool startInit;
static Progress assembliesProgress;
static Progress classProgress;
};
class UnityResolve final {
public:
struct Assembly;
@@ -69,8 +81,16 @@ public:
[[nodiscard]] auto Get(const std::string& strClass, const std::string& strNamespace = "*", const std::string& strParent = "*") const -> Class* {
if (!this) return nullptr;
/*
if (lazyInit_ && classes.empty()) {
const auto image = Invoke<void*>("il2cpp_assembly_get_image", address);
ForeachClass(const_cast<Assembly *>(this), image);
}*/
for (const auto pClass : classes) if (strClass == pClass->name && (strNamespace == "*" || pClass->namespaze == strNamespace) && (strParent == "*" || pClass->parent == strParent)) return pClass;
return nullptr;
if (lazyInit_) {
return FillClass_Il2ccpp(const_cast<Assembly *>(this), strNamespace.c_str(), strClass.c_str());
}
return nullptr;
}
};
@@ -279,14 +299,17 @@ public:
}
}
static auto Init(void* hmodule, const Mode mode = Mode::Mono) -> void {
static auto Init(void* hmodule, const Mode mode = Mode::Mono, const bool lazyInit = false) -> void {
mode_ = mode;
hmodule_ = hmodule;
lazyInit_ = lazyInit;
if (mode_ == Mode::Il2Cpp) {
if (!lazyInit) UnityResolveProgress::startInit = true;
pDomain = Invoke<void*>("il2cpp_domain_get");
Invoke<void*>("il2cpp_thread_attach", pDomain);
ForeachAssembly();
if (!lazyInit) UnityResolveProgress::startInit = false;
}
else {
pDomain = Invoke<void*>("mono_get_root_domain");
@@ -561,7 +584,11 @@ private:
if (mode_ == Mode::Il2Cpp) {
size_t nrofassemblies = 0;
const auto assemblies = Invoke<void**>("il2cpp_domain_get_assemblies", pDomain, &nrofassemblies);
if (!lazyInit_) UnityResolveProgress::assembliesProgress.total = nrofassemblies;
for (auto i = 0; i < nrofassemblies; i++) {
if (!lazyInit_) UnityResolveProgress::assembliesProgress.current = i + 1;
const auto ptr = assemblies[i];
if (ptr == nullptr) continue;
auto assembly = new Assembly{ .address = ptr };
@@ -569,7 +596,9 @@ private:
assembly->file = Invoke<const char*>("il2cpp_image_get_filename", image);
assembly->name = Invoke<const char*>("il2cpp_image_get_name", image);
UnityResolve::assembly.push_back(assembly);
ForeachClass(assembly, image);
if (!lazyInit_) {
ForeachClass(assembly, image);
}
}
}
else {
@@ -590,11 +619,60 @@ private:
}
}
static auto GetPClassFromUnknownNamespace(void* image, const char* klassName) -> void* {
const auto count = Invoke<int>("il2cpp_image_get_class_count", image);
for (auto i = 0; i < count; i++) {
const auto pClass = Invoke<void*>("il2cpp_image_get_class", image, i);
const auto className = Invoke<const char*>("il2cpp_class_get_name", pClass);
if (strcmp(className, klassName) == 0) {
return pClass;
}
}
return nullptr;
}
static auto FillClass_Il2ccpp(Assembly* assembly, const char* namespaze, const char* klassName) -> Class* {
auto image = Invoke<void*>("il2cpp_assembly_get_image", assembly->address);
void* pClass;
if (strcmp(namespaze, "*") == 0) {
pClass = GetPClassFromUnknownNamespace(image, klassName);
}
else {
pClass = Invoke<void*>("il2cpp_class_from_name", image, namespaze, klassName);
}
if (!pClass && (strlen(namespaze) == 0)) {
pClass = GetPClassFromUnknownNamespace(image, klassName);
}
if (pClass == nullptr) return nullptr;
const auto pAClass = new Class();
pAClass->address = pClass;
pAClass->name = Invoke<const char*>("il2cpp_class_get_name", pClass);
if (const auto pPClass = Invoke<void*>("il2cpp_class_get_parent", pClass)) pAClass->parent = Invoke<const char*>("il2cpp_class_get_name", pPClass);
// pAClass->namespaze = Invoke<const char*>("il2cpp_class_get_namespace", pClass);
pAClass->namespaze = namespaze;
assembly->classes.push_back(pAClass);
ForeachFields(pAClass, pClass);
ForeachMethod(pAClass, pClass);
void* i_class{};
void* iter{};
do {
if ((i_class = Invoke<void*>("il2cpp_class_get_interfaces", pClass, &iter))) {
ForeachFields(pAClass, i_class);
ForeachMethod(pAClass, i_class);
}
} while (i_class);
return pAClass;
}
static auto ForeachClass(Assembly* assembly, void* image) -> void {
// 遍历类
if (mode_ == Mode::Il2Cpp) {
const auto count = Invoke<int>("il2cpp_image_get_class_count", image);
if (!lazyInit_) UnityResolveProgress::classProgress.total = count;
for (auto i = 0; i < count; i++) {
if (!lazyInit_) UnityResolveProgress::classProgress.current = i + 1;
const auto pClass = Invoke<void*>("il2cpp_image_get_class", image, i);
if (pClass == nullptr) continue;
const auto pAClass = new Class();
@@ -2586,6 +2664,7 @@ public:
private:
inline static Mode mode_{};
inline static void* hmodule_;
inline static bool lazyInit_;
inline static std::unordered_map<std::string, void*> address_{};
inline static void* pDomain{};
};