mirror of
https://git.chinosk6.cn/chinosk/gkms-local.git
synced 2026-02-05 01:14:05 +00:00
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:
@@ -39,7 +39,8 @@ std::unordered_set<void*> hookedStubs{};
|
||||
GakumasLocal::Log::InfoFmt("ADD_HOOK: %s at %p", #name, addr); \
|
||||
} \
|
||||
} \
|
||||
else GakumasLocal::Log::ErrorFmt("Hook failed: %s is NULL", #name, addr)
|
||||
else GakumasLocal::Log::ErrorFmt("Hook failed: %s is NULL", #name, addr); \
|
||||
if (Config::lazyInit) UnityResolveProgress::classProgress.current++
|
||||
|
||||
void UnHookAll() {
|
||||
for (const auto i: hookedStubs) {
|
||||
@@ -97,7 +98,7 @@ namespace GakumasLocal::HookMain {
|
||||
UnityResolve::UnityType::Transform* cameraTransformCache = nullptr;
|
||||
void CheckAndUpdateMainCamera() {
|
||||
if (!Config::enableFreeCamera) return;
|
||||
if (IsNativeObjectAlive(mainCameraCache)) return;
|
||||
if (IsNativeObjectAlive(mainCameraCache) && IsNativeObjectAlive(cameraTransformCache)) return;
|
||||
|
||||
mainCameraCache = UnityResolve::UnityType::Camera::GetMain();
|
||||
cameraTransformCache = mainCameraCache->GetTransform();
|
||||
@@ -827,7 +828,8 @@ namespace GakumasLocal::HookMain {
|
||||
|
||||
void StartInjectFunctions() {
|
||||
const auto hookInstaller = Plugin::GetInstance().GetHookInstaller();
|
||||
UnityResolve::Init(xdl_open(hookInstaller->m_il2cppLibraryPath.c_str(), RTLD_NOW), UnityResolve::Mode::Il2Cpp);
|
||||
UnityResolve::Init(xdl_open(hookInstaller->m_il2cppLibraryPath.c_str(), RTLD_NOW),
|
||||
UnityResolve::Mode::Il2Cpp, Config::lazyInit);
|
||||
|
||||
ADD_HOOK(AssetBundle_LoadAssetAsync, Il2cppUtils::il2cpp_resolve_icall(
|
||||
"UnityEngine.AssetBundle::LoadAssetAsync_Internal(System.String,System.Type)"));
|
||||
@@ -959,10 +961,30 @@ namespace GakumasLocal::HookMain {
|
||||
|
||||
Log::Info("Start init plugin...");
|
||||
|
||||
if (Config::lazyInit) {
|
||||
UnityResolveProgress::startInit = true;
|
||||
UnityResolveProgress::assembliesProgress.total = 2;
|
||||
UnityResolveProgress::assembliesProgress.current = 1;
|
||||
UnityResolveProgress::classProgress.total = 36;
|
||||
UnityResolveProgress::classProgress.current = 0;
|
||||
}
|
||||
|
||||
StartInjectFunctions();
|
||||
GKCamera::initCameraSettings();
|
||||
|
||||
if (Config::lazyInit) {
|
||||
UnityResolveProgress::assembliesProgress.current = 2;
|
||||
UnityResolveProgress::classProgress.total = 1;
|
||||
UnityResolveProgress::classProgress.current = 0;
|
||||
}
|
||||
|
||||
Local::LoadData();
|
||||
|
||||
if (Config::lazyInit) {
|
||||
UnityResolveProgress::classProgress.current = 1;
|
||||
UnityResolveProgress::startInit = false;
|
||||
}
|
||||
|
||||
Log::Info("Plugin init finished.");
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ namespace GakumasLocal::Config {
|
||||
|
||||
bool dbgMode = false;
|
||||
bool enabled = true;
|
||||
bool lazyInit = true;
|
||||
bool replaceFont = true;
|
||||
bool forceExportResource = true;
|
||||
bool textTest = false;
|
||||
@@ -55,6 +56,7 @@ namespace GakumasLocal::Config {
|
||||
|
||||
GetConfigItem(dbgMode);
|
||||
GetConfigItem(enabled);
|
||||
GetConfigItem(lazyInit);
|
||||
GetConfigItem(replaceFont);
|
||||
GetConfigItem(forceExportResource);
|
||||
GetConfigItem(gameOrientation);
|
||||
|
||||
@@ -5,6 +5,7 @@ namespace GakumasLocal::Config {
|
||||
|
||||
extern bool dbgMode;
|
||||
extern bool enabled;
|
||||
extern bool lazyInit;
|
||||
extern bool replaceFont;
|
||||
extern bool forceExportResource;
|
||||
extern int gameOrientation;
|
||||
|
||||
@@ -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{};
|
||||
};
|
||||
|
||||
@@ -15,6 +15,10 @@ JavaVM* g_javaVM = nullptr;
|
||||
jclass g_gakumasHookMainClass = nullptr;
|
||||
jmethodID showToastMethodId = nullptr;
|
||||
|
||||
bool UnityResolveProgress::startInit = false;
|
||||
UnityResolveProgress::Progress UnityResolveProgress::assembliesProgress{};
|
||||
UnityResolveProgress::Progress UnityResolveProgress::classProgress{};
|
||||
|
||||
namespace
|
||||
{
|
||||
class AndroidHookInstaller : public GakumasLocal::HookInstaller
|
||||
@@ -114,8 +118,37 @@ Java_io_github_chinosk_gakumas_localify_GakumasHookMain_loadConfig(JNIEnv *env,
|
||||
}
|
||||
|
||||
extern "C"
|
||||
JNIEXPORT void JNICALL
|
||||
JNIEXPORT jint JNICALL
|
||||
Java_io_github_chinosk_gakumas_localify_GakumasHookMain_pluginCallbackLooper(JNIEnv *env,
|
||||
jclass clazz) {
|
||||
GakumasLocal::Log::ToastLoop(env, clazz);
|
||||
|
||||
if (UnityResolveProgress::startInit) {
|
||||
return 9;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
extern "C"
|
||||
JNIEXPORT void JNICALL
|
||||
Java_io_github_chinosk_gakumas_localify_models_NativeInitProgress_pluginInitProgressLooper(
|
||||
JNIEnv *env, jclass clazz, jobject progress) {
|
||||
|
||||
// jclass progressClass = env->GetObjectClass(progress);
|
||||
|
||||
static jfieldID startInitFieldID = env->GetStaticFieldID(clazz, "startInit", "Z");
|
||||
|
||||
static jmethodID setAssembliesProgressDataMethodID = env->GetMethodID(clazz, "setAssembliesProgressData", "(JJ)V");
|
||||
static jmethodID setClassProgressDataMethodID = env->GetMethodID(clazz, "setClassProgressData", "(JJ)V");
|
||||
|
||||
// jboolean startInit = env->GetStaticBooleanField(clazz, startInitFieldID);
|
||||
|
||||
env->SetStaticBooleanField(clazz, startInitFieldID, UnityResolveProgress::startInit);
|
||||
|
||||
env->CallVoidMethod(progress, setAssembliesProgressDataMethodID,
|
||||
UnityResolveProgress::assembliesProgress.current, UnityResolveProgress::assembliesProgress.total);
|
||||
env->CallVoidMethod(progress, setClassProgressDataMethodID,
|
||||
UnityResolveProgress::classProgress.current, UnityResolveProgress::classProgress.total);
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user