Compare commits
	
		
			No commits in common. "2c5a10262a6a98ab24d50ff8a3a1a0991058b756" and "c28e05e271a14c8c739dd4a38f071f3c502ccfee" have entirely different histories.
		
	
	
		
			2c5a10262a
			...
			c28e05e271
		
	
		| 
						 | 
				
			
			@ -39,8 +39,7 @@ 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);                      \
 | 
			
		||||
    if (Config::lazyInit) UnityResolveProgress::classProgress.current++
 | 
			
		||||
    else GakumasLocal::Log::ErrorFmt("Hook failed: %s is NULL", #name, addr)
 | 
			
		||||
 | 
			
		||||
void UnHookAll() {
 | 
			
		||||
    for (const auto i: hookedStubs) {
 | 
			
		||||
| 
						 | 
				
			
			@ -98,7 +97,7 @@ namespace GakumasLocal::HookMain {
 | 
			
		|||
    UnityResolve::UnityType::Transform* cameraTransformCache = nullptr;
 | 
			
		||||
    void CheckAndUpdateMainCamera() {
 | 
			
		||||
        if (!Config::enableFreeCamera) return;
 | 
			
		||||
        if (IsNativeObjectAlive(mainCameraCache) && IsNativeObjectAlive(cameraTransformCache)) return;
 | 
			
		||||
        if (IsNativeObjectAlive(mainCameraCache)) return;
 | 
			
		||||
 | 
			
		||||
        mainCameraCache = UnityResolve::UnityType::Camera::GetMain();
 | 
			
		||||
        cameraTransformCache = mainCameraCache->GetTransform();
 | 
			
		||||
| 
						 | 
				
			
			@ -828,8 +827,7 @@ 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, Config::lazyInit);
 | 
			
		||||
        UnityResolve::Init(xdl_open(hookInstaller->m_il2cppLibraryPath.c_str(), RTLD_NOW), UnityResolve::Mode::Il2Cpp);
 | 
			
		||||
 | 
			
		||||
        ADD_HOOK(AssetBundle_LoadAssetAsync, Il2cppUtils::il2cpp_resolve_icall(
 | 
			
		||||
                "UnityEngine.AssetBundle::LoadAssetAsync_Internal(System.String,System.Type)"));
 | 
			
		||||
| 
						 | 
				
			
			@ -961,30 +959,10 @@ 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,7 +7,6 @@ namespace GakumasLocal::Config {
 | 
			
		|||
 | 
			
		||||
    bool dbgMode = false;
 | 
			
		||||
    bool enabled = true;
 | 
			
		||||
    bool lazyInit = true;
 | 
			
		||||
    bool replaceFont = true;
 | 
			
		||||
    bool forceExportResource = true;
 | 
			
		||||
    bool textTest = false;
 | 
			
		||||
| 
						 | 
				
			
			@ -56,7 +55,6 @@ namespace GakumasLocal::Config {
 | 
			
		|||
 | 
			
		||||
            GetConfigItem(dbgMode);
 | 
			
		||||
            GetConfigItem(enabled);
 | 
			
		||||
            GetConfigItem(lazyInit);
 | 
			
		||||
            GetConfigItem(replaceFont);
 | 
			
		||||
            GetConfigItem(forceExportResource);
 | 
			
		||||
            GetConfigItem(gameOrientation);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -5,7 +5,6 @@ namespace GakumasLocal::Config {
 | 
			
		|||
 | 
			
		||||
    extern bool dbgMode;
 | 
			
		||||
    extern bool enabled;
 | 
			
		||||
    extern bool lazyInit;
 | 
			
		||||
    extern bool replaceFont;
 | 
			
		||||
    extern bool forceExportResource;
 | 
			
		||||
    extern int gameOrientation;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -47,18 +47,6 @@
 | 
			
		|||
#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;
 | 
			
		||||
| 
						 | 
				
			
			@ -81,16 +69,8 @@ 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;
 | 
			
		||||
			if (lazyInit_) {
 | 
			
		||||
                return FillClass_Il2ccpp(const_cast<Assembly *>(this), strNamespace.c_str(), strClass.c_str());
 | 
			
		||||
            }
 | 
			
		||||
            return nullptr;
 | 
			
		||||
			return nullptr;
 | 
			
		||||
		}
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -299,17 +279,14 @@ public:
 | 
			
		|||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	static auto Init(void* hmodule, const Mode mode = Mode::Mono, const bool lazyInit = false) -> void {
 | 
			
		||||
	static auto Init(void* hmodule, const Mode mode = Mode::Mono) -> 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");
 | 
			
		||||
| 
						 | 
				
			
			@ -584,11 +561,7 @@ 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 };
 | 
			
		||||
| 
						 | 
				
			
			@ -596,9 +569,7 @@ 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);
 | 
			
		||||
                if (!lazyInit_) {
 | 
			
		||||
                    ForeachClass(assembly, image);
 | 
			
		||||
                }
 | 
			
		||||
				ForeachClass(assembly, image);
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		else {
 | 
			
		||||
| 
						 | 
				
			
			@ -619,60 +590,11 @@ 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();
 | 
			
		||||
| 
						 | 
				
			
			@ -2664,7 +2586,6 @@ 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,10 +15,6 @@ 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
 | 
			
		||||
| 
						 | 
				
			
			@ -118,37 +114,8 @@ Java_io_github_chinosk_gakumas_localify_GakumasHookMain_loadConfig(JNIEnv *env,
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
extern "C"
 | 
			
		||||
JNIEXPORT jint JNICALL
 | 
			
		||||
JNIEXPORT void 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);
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -17,7 +17,6 @@ interface ConfigListener {
 | 
			
		|||
    fun onForceExportResourceChanged(value: Boolean)
 | 
			
		||||
    fun onTextTestChanged(value: Boolean)
 | 
			
		||||
    fun onReplaceFontChanged(value: Boolean)
 | 
			
		||||
    fun onLazyInitChanged(value: Boolean)
 | 
			
		||||
    fun onEnableFreeCameraChanged(value: Boolean)
 | 
			
		||||
    fun onTargetFpsChanged(s: CharSequence, start: Int, before: Int, count: Int)
 | 
			
		||||
    fun onUnlockAllLiveChanged(value: Boolean)
 | 
			
		||||
| 
						 | 
				
			
			@ -112,11 +111,6 @@ interface ConfigUpdateListener: ConfigListener, IHasConfigItems {
 | 
			
		|||
        pushKeyEvent(KeyEvent(1145, 30))
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    override fun onLazyInitChanged(value: Boolean) {
 | 
			
		||||
        config.lazyInit = value
 | 
			
		||||
        saveConfig()
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    override fun onTextTestChanged(value: Boolean) {
 | 
			
		||||
        config.textTest = value
 | 
			
		||||
        saveConfig()
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -34,9 +34,7 @@ import java.util.Locale
 | 
			
		|||
import kotlin.system.measureTimeMillis
 | 
			
		||||
import io.github.chinosk.gakumas.localify.hookUtils.FileHotUpdater
 | 
			
		||||
import io.github.chinosk.gakumas.localify.mainUtils.json
 | 
			
		||||
import io.github.chinosk.gakumas.localify.models.NativeInitProgress
 | 
			
		||||
import io.github.chinosk.gakumas.localify.models.ProgramConfig
 | 
			
		||||
import io.github.chinosk.gakumas.localify.ui.game_attach.InitProgressUI
 | 
			
		||||
 | 
			
		||||
val TAG = "GakumasLocalify"
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -51,7 +49,6 @@ class GakumasHookMain : IXposedHookLoadPackage, IXposedHookZygoteInit {
 | 
			
		|||
 | 
			
		||||
    private var getConfigError: Exception? = null
 | 
			
		||||
    private var externalFilesChecked: Boolean = false
 | 
			
		||||
    private var gameActivity: Activity? = null
 | 
			
		||||
 | 
			
		||||
    override fun handleLoadPackage(lpparam: XC_LoadPackage.LoadPackageParam) {
 | 
			
		||||
//        if (lpparam.packageName == "io.github.chinosk.gakumas.localify") {
 | 
			
		||||
| 
						 | 
				
			
			@ -138,7 +135,6 @@ class GakumasHookMain : IXposedHookLoadPackage, IXposedHookZygoteInit {
 | 
			
		|||
                super.beforeHookedMethod(param)
 | 
			
		||||
                Log.d(TAG, "onStart")
 | 
			
		||||
                val currActivity = param.thisObject as Activity
 | 
			
		||||
                gameActivity = currActivity
 | 
			
		||||
                if (getConfigError != null) {
 | 
			
		||||
                    showGetConfigFailed(currActivity)
 | 
			
		||||
                }
 | 
			
		||||
| 
						 | 
				
			
			@ -152,7 +148,6 @@ class GakumasHookMain : IXposedHookLoadPackage, IXposedHookZygoteInit {
 | 
			
		|||
            override fun beforeHookedMethod(param: MethodHookParam) {
 | 
			
		||||
                Log.d(TAG, "onResume")
 | 
			
		||||
                val currActivity = param.thisObject as Activity
 | 
			
		||||
                gameActivity = currActivity
 | 
			
		||||
                if (getConfigError != null) {
 | 
			
		||||
                    showGetConfigFailed(currActivity)
 | 
			
		||||
                }
 | 
			
		||||
| 
						 | 
				
			
			@ -211,30 +206,9 @@ class GakumasHookMain : IXposedHookLoadPackage, IXposedHookZygoteInit {
 | 
			
		|||
    private fun startLoop() {
 | 
			
		||||
        GlobalScope.launch {
 | 
			
		||||
            val interval = 1000L / 30
 | 
			
		||||
            var lastFrameStartInit = NativeInitProgress.startInit
 | 
			
		||||
            val initProgressUI = InitProgressUI()
 | 
			
		||||
 | 
			
		||||
            while (isActive) {
 | 
			
		||||
                val timeTaken = measureTimeMillis {
 | 
			
		||||
                    val returnValue = pluginCallbackLooper()  // plugin main thread loop
 | 
			
		||||
                    if (returnValue == 9) {
 | 
			
		||||
                        NativeInitProgress.startInit = true
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
                    if (NativeInitProgress.startInit) {  // if init, update data
 | 
			
		||||
                        NativeInitProgress.pluginInitProgressLooper(NativeInitProgress)
 | 
			
		||||
                        gameActivity?.let { initProgressUI.updateData(it) }
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
                    if ((gameActivity != null) && (lastFrameStartInit != NativeInitProgress.startInit)) {  // change status
 | 
			
		||||
                        if (NativeInitProgress.startInit) {
 | 
			
		||||
                            initProgressUI.createView(gameActivity!!)
 | 
			
		||||
                        }
 | 
			
		||||
                        else {
 | 
			
		||||
                            initProgressUI.finishLoad(gameActivity!!)
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                    lastFrameStartInit = NativeInitProgress.startInit
 | 
			
		||||
                    pluginCallbackLooper()
 | 
			
		||||
                }
 | 
			
		||||
                delay(interval - timeTaken)
 | 
			
		||||
            }
 | 
			
		||||
| 
						 | 
				
			
			@ -439,7 +413,7 @@ class GakumasHookMain : IXposedHookLoadPackage, IXposedHookZygoteInit {
 | 
			
		|||
        }
 | 
			
		||||
 | 
			
		||||
        @JvmStatic
 | 
			
		||||
        external fun pluginCallbackLooper(): Int
 | 
			
		||||
        external fun pluginCallbackLooper()
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    init {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -6,7 +6,6 @@ import kotlinx.serialization.Serializable
 | 
			
		|||
data class GakumasConfig (
 | 
			
		||||
    var dbgMode: Boolean = false,
 | 
			
		||||
    var enabled: Boolean = true,
 | 
			
		||||
    var lazyInit: Boolean = true,
 | 
			
		||||
    var replaceFont: Boolean = true,
 | 
			
		||||
    var textTest: Boolean = false,
 | 
			
		||||
    var dumpText: Boolean = false,
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,25 +0,0 @@
 | 
			
		|||
package io.github.chinosk.gakumas.localify.models
 | 
			
		||||
 | 
			
		||||
data class ProgressData(
 | 
			
		||||
    var current: Long = 0,
 | 
			
		||||
    var total: Long = 1
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
object NativeInitProgress {
 | 
			
		||||
    var assembliesProgress = ProgressData()
 | 
			
		||||
    var classProgress = ProgressData()
 | 
			
		||||
    var startInit: Boolean = false
 | 
			
		||||
 | 
			
		||||
    fun setAssembliesProgressData(current: Long, total: Long) {
 | 
			
		||||
        assembliesProgress.current = current
 | 
			
		||||
        assembliesProgress.total = total
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fun setClassProgressData(current: Long, total: Long) {
 | 
			
		||||
        classProgress.current = current
 | 
			
		||||
        classProgress.total = total
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @JvmStatic
 | 
			
		||||
    external fun pluginInitProgressLooper(progress: NativeInitProgress)
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1,176 +0,0 @@
 | 
			
		|||
package io.github.chinosk.gakumas.localify.ui.game_attach
 | 
			
		||||
 | 
			
		||||
import android.annotation.SuppressLint
 | 
			
		||||
import android.app.Activity
 | 
			
		||||
import android.content.Context
 | 
			
		||||
import android.content.res.ColorStateList
 | 
			
		||||
import android.content.res.Resources
 | 
			
		||||
import android.graphics.Color
 | 
			
		||||
import android.graphics.Typeface
 | 
			
		||||
import android.graphics.drawable.GradientDrawable
 | 
			
		||||
import android.graphics.drawable.LayerDrawable
 | 
			
		||||
import android.graphics.drawable.ShapeDrawable
 | 
			
		||||
import android.graphics.drawable.shapes.RectShape
 | 
			
		||||
import android.util.Log
 | 
			
		||||
import android.view.Gravity
 | 
			
		||||
import android.view.ViewGroup
 | 
			
		||||
import android.widget.FrameLayout
 | 
			
		||||
import android.widget.ImageButton
 | 
			
		||||
import android.widget.ImageView
 | 
			
		||||
import android.widget.LinearLayout
 | 
			
		||||
import android.widget.ProgressBar
 | 
			
		||||
import android.widget.TextView
 | 
			
		||||
import io.github.chinosk.gakumas.localify.TAG
 | 
			
		||||
import io.github.chinosk.gakumas.localify.models.NativeInitProgress
 | 
			
		||||
import kotlinx.coroutines.DelicateCoroutinesApi
 | 
			
		||||
import kotlinx.coroutines.GlobalScope
 | 
			
		||||
import kotlinx.coroutines.delay
 | 
			
		||||
import kotlinx.coroutines.launch
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class InitProgressUI {
 | 
			
		||||
    private var uiCreated = false
 | 
			
		||||
    private lateinit var rootView: ViewGroup
 | 
			
		||||
    private lateinit var container: LinearLayout
 | 
			
		||||
    private lateinit var assembliesProgressBar: ProgressBar
 | 
			
		||||
    private lateinit var classProgressBar: ProgressBar
 | 
			
		||||
    private lateinit var titleText: TextView
 | 
			
		||||
    private lateinit var assembliesProgressText: TextView
 | 
			
		||||
    private lateinit var classProgressText: TextView
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    @SuppressLint("SetTextI18n")
 | 
			
		||||
    fun createView(context: Context) {
 | 
			
		||||
        if (uiCreated) return
 | 
			
		||||
        uiCreated = true
 | 
			
		||||
        val activity = context as? Activity ?: return
 | 
			
		||||
        rootView = activity.findViewById<ViewGroup>(android.R.id.content)
 | 
			
		||||
 | 
			
		||||
        container = LinearLayout(context).apply {
 | 
			
		||||
            orientation = LinearLayout.VERTICAL
 | 
			
		||||
            layoutParams = FrameLayout.LayoutParams(
 | 
			
		||||
                FrameLayout.LayoutParams.MATCH_PARENT,
 | 
			
		||||
                FrameLayout.LayoutParams.WRAP_CONTENT
 | 
			
		||||
            ).apply {
 | 
			
		||||
                gravity = Gravity.TOP or Gravity.END
 | 
			
		||||
                marginEnd = 20
 | 
			
		||||
                marginStart = 20
 | 
			
		||||
                topMargin = 100
 | 
			
		||||
            }
 | 
			
		||||
            setBackgroundColor(Color.WHITE)
 | 
			
		||||
            setPadding(20, 20, 20, 20)
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Set up the container layout
 | 
			
		||||
        assembliesProgressBar = ProgressBar(context, null, android.R.attr.progressBarStyleHorizontal).apply {
 | 
			
		||||
            layoutParams = LinearLayout.LayoutParams(
 | 
			
		||||
                LinearLayout.LayoutParams.MATCH_PARENT,
 | 
			
		||||
                LinearLayout.LayoutParams.WRAP_CONTENT
 | 
			
		||||
            ).apply {
 | 
			
		||||
                topMargin = 20
 | 
			
		||||
            }
 | 
			
		||||
            max = 100
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Set up the class progress bar
 | 
			
		||||
        classProgressBar = ProgressBar(context, null, android.R.attr.progressBarStyleHorizontal).apply {
 | 
			
		||||
            layoutParams = LinearLayout.LayoutParams(
 | 
			
		||||
                LinearLayout.LayoutParams.MATCH_PARENT,
 | 
			
		||||
                LinearLayout.LayoutParams.WRAP_CONTENT
 | 
			
		||||
            ).apply {
 | 
			
		||||
                topMargin = 20
 | 
			
		||||
            }
 | 
			
		||||
            max = 100
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        assembliesProgressBar.progressTintList = ColorStateList.valueOf(Color.parseColor("#FFF89400"))
 | 
			
		||||
        classProgressBar.progressTintList = ColorStateList.valueOf(Color.parseColor("#FFF89400"))
 | 
			
		||||
 | 
			
		||||
        // Set up the text views
 | 
			
		||||
        titleText = TextView(context).apply {
 | 
			
		||||
            layoutParams = FrameLayout.LayoutParams(
 | 
			
		||||
                FrameLayout.LayoutParams.WRAP_CONTENT,
 | 
			
		||||
                FrameLayout.LayoutParams.WRAP_CONTENT
 | 
			
		||||
            ).apply {
 | 
			
		||||
                topMargin = 20
 | 
			
		||||
                gravity = Gravity.CENTER_HORIZONTAL
 | 
			
		||||
            }
 | 
			
		||||
            setTextColor(Color.BLACK)
 | 
			
		||||
            text = "Initializing"
 | 
			
		||||
            textSize = 20f
 | 
			
		||||
            setTypeface(typeface, Typeface.BOLD)
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        val textLayout = FrameLayout.LayoutParams(
 | 
			
		||||
            FrameLayout.LayoutParams.WRAP_CONTENT,
 | 
			
		||||
            FrameLayout.LayoutParams.WRAP_CONTENT
 | 
			
		||||
        ).apply {
 | 
			
		||||
            topMargin = 20
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        assembliesProgressText = TextView(context).apply {
 | 
			
		||||
            layoutParams = textLayout
 | 
			
		||||
            setTextColor(Color.BLACK)
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        classProgressText = TextView(context).apply {
 | 
			
		||||
            layoutParams = textLayout
 | 
			
		||||
            setTextColor(Color.BLACK)
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Add container to the root view
 | 
			
		||||
        context.runOnUiThread {
 | 
			
		||||
            // Add views to the container
 | 
			
		||||
            container.addView(titleText)
 | 
			
		||||
            container.addView(assembliesProgressText)
 | 
			
		||||
            container.addView(assembliesProgressBar)
 | 
			
		||||
            container.addView(classProgressText)
 | 
			
		||||
            container.addView(classProgressBar)
 | 
			
		||||
 | 
			
		||||
            rootView.addView(container)
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @SuppressLint("SetTextI18n")
 | 
			
		||||
    @OptIn(DelicateCoroutinesApi::class)
 | 
			
		||||
    fun finishLoad(context: Activity) {
 | 
			
		||||
        if (!uiCreated) return
 | 
			
		||||
        uiCreated = false
 | 
			
		||||
        GlobalScope.launch {
 | 
			
		||||
            context.runOnUiThread {
 | 
			
		||||
                assembliesProgressBar.progressTintList = ColorStateList.valueOf(Color.parseColor("#FF28B463"))
 | 
			
		||||
                classProgressBar.progressTintList = ColorStateList.valueOf(Color.parseColor("#FF28B463"))
 | 
			
		||||
                titleText.text = "Finished"
 | 
			
		||||
            }
 | 
			
		||||
            delay(1500L)
 | 
			
		||||
            context.runOnUiThread {
 | 
			
		||||
                rootView.removeView(container)
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fun removeView(context: Activity) {
 | 
			
		||||
        if (!uiCreated) return
 | 
			
		||||
        uiCreated = false
 | 
			
		||||
        context.runOnUiThread {
 | 
			
		||||
            rootView.removeView(container)
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @SuppressLint("SetTextI18n")
 | 
			
		||||
    fun updateData(context: Activity) {
 | 
			
		||||
        if (!uiCreated) return
 | 
			
		||||
        //return
 | 
			
		||||
 | 
			
		||||
        context.runOnUiThread {
 | 
			
		||||
            val assembliesProgress = NativeInitProgress.assembliesProgress
 | 
			
		||||
            val classProgress = NativeInitProgress.classProgress
 | 
			
		||||
 | 
			
		||||
            assembliesProgressText.text = "${assembliesProgress.current}/${assembliesProgress.total}"
 | 
			
		||||
            classProgressText.text = "${classProgress.current}/${classProgress.total}"
 | 
			
		||||
 | 
			
		||||
            assembliesProgressBar.setProgress((assembliesProgress.current * 100 / assembliesProgress.total).toInt(), true)
 | 
			
		||||
            classProgressBar.setProgress((classProgress.current * 100 / classProgress.total).toInt(), true)
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -141,14 +141,9 @@ fun HomePage(modifier: Modifier = Modifier,
 | 
			
		|||
                            v -> context?.onEnabledChanged(v)
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
                    GakuSwitch(modifier, stringResource(R.string.lazy_init), checked = config.value.lazyInit) {
 | 
			
		||||
                            v -> context?.onLazyInitChanged(v)
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
                    GakuSwitch(modifier, stringResource(R.string.replace_font), checked = config.value.replaceFont) {
 | 
			
		||||
                            v -> context?.onReplaceFontChanged(v)
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            Spacer(Modifier.height(6.dp))
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -3,7 +3,6 @@
 | 
			
		|||
    <string name="gakumas_localify">Gakumas Localify</string>
 | 
			
		||||
    <string name="enable_plugin">启用插件 (不可热重载)</string>
 | 
			
		||||
    <string name="replace_font">替换字体</string>
 | 
			
		||||
    <string name="lazy_init">快速初始化(懒加载配置)</string>
 | 
			
		||||
    <string name="enable_free_camera">启用自由视角(可热重载; 需使用实体键盘)</string>
 | 
			
		||||
    <string name="start_game">以上述配置启动游戏/重载配置</string>
 | 
			
		||||
    <string name="setFpsTitle">最大 FPS (0 为保持游戏原设置)</string>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -3,7 +3,6 @@
 | 
			
		|||
    <string name="gakumas_localify">Gakumas Localify</string>
 | 
			
		||||
    <string name="enable_plugin">Enable Plugin (Not Hot Reloadable)</string>
 | 
			
		||||
    <string name="replace_font">Replace Font</string>
 | 
			
		||||
    <string name="lazy_init">Fast Initialization (Lazy loading)</string>
 | 
			
		||||
    <string name="enable_free_camera">Enable Free Camera</string>
 | 
			
		||||
    <string name="start_game">Start Game / Hot Reload Config</string>
 | 
			
		||||
    <string name="setFpsTitle">Max FPS (0 is Use Original Settings)</string>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue