From bcb220ce5db40137ab00ab3d27221ac5e3148353 Mon Sep 17 00:00:00 2001 From: Duy Tran Khanh Date: Sat, 30 Jan 2021 11:43:16 +0700 Subject: [PATCH] UI: add basic download progress --- .../java/net/kdt/pojavlaunch/PLaunchApp.java | 87 ++++++++++--------- .../java/net/kdt/pojavlaunch/uikit/UIKit.java | 22 ++++- Natives/LauncherViewController.h | 3 + Natives/LauncherViewController.m | 19 ++-- Natives/SurfaceViewController.m | 2 +- Natives/input_bridge_v3.c | 45 ++++++++-- Natives/ios_uikit_bridge.h | 2 + Natives/ios_uikit_bridge.m | 16 ++++ Natives/utils.h | 3 +- 9 files changed, 137 insertions(+), 62 deletions(-) diff --git a/JavaApp/src/main/java/net/kdt/pojavlaunch/PLaunchApp.java b/JavaApp/src/main/java/net/kdt/pojavlaunch/PLaunchApp.java index 494d1cf0..fdae3038 100644 --- a/JavaApp/src/main/java/net/kdt/pojavlaunch/PLaunchApp.java +++ b/JavaApp/src/main/java/net/kdt/pojavlaunch/PLaunchApp.java @@ -14,8 +14,11 @@ import net.kdt.pojavlaunch.value.*; public class PLaunchApp { public static JMinecraftVersionList mVersionList; + public static MinecraftAccount mAccount; + public static JMinecraftVersionList.Version mVersion; public static void main(String[] args) throws Throwable { // System.setProperty("os.name", "iOS"); +/* System.setProperty("javafx.verbose", "true"); System.setProperty("javafx.platform", "ios"); System.setProperty("glass.platform", "ios"); @@ -27,46 +30,38 @@ public class PLaunchApp { System.setProperty("prism.mintexturesize", "16"); System.setProperty("prism.static.libraries", "false"); System.setProperty("prism.useNativeIIO", "false"); +*/ if (args[0].startsWith("/Applications/")) { System.out.println("We are on java now! Starting UI..."); UIKit.launchUI(args); } else { + // Test on cmdline launchMinecraft(); } LauncherPreferences.loadPreferences(); } - - public static void applicationDidFinishLaunching() { -/* - Thread launchThread = new Thread() { - @Override - public void run() { - Application.launch(PLaunchJFXApp.class); - } - }; - launchThread.setDaemon(true); - launchThread.start(); -*/ - launchMinecraft(); - } - - public static void launchMinecraft() { - System.out.println("Saving GLES context"); - JREUtils.saveGLContext(); - - // Start Minecraft there! - System.out.println("Finding a version"); - String mcver = "1.13"; + public static void installMinecraft() { + new Thread(() -> { + + int currProgress, totalProgress; + + UIKit.updateProgressSafe(currProgress, "Finding a version"); + String mcver = "1.16.5"; try { mcver = Tools.read(Tools.DIR_GAME_NEW + "/config_ver.txt"); } catch (IOException e) { - System.out.println("config_ver.txt not found, defaulting to Minecraft 1.13"); + UIKit.updateProgressSafe(currProgress, "config_ver.txt not found, defaulting to Minecraft 1.16.5"); } + UIKit.updateProgressSafe(currProgress, "Selected Minecraft version: " + mcver); + + Thread.sleep(1000); + + // dummy account MinecraftAccount acc = new MinecraftAccount(); acc.selectedVersion = mcver; @@ -79,16 +74,17 @@ public class PLaunchApp { String minecraftMainJar = Tools.DIR_HOME_VERSION + downVName + ".jar"; String verJsonDir = Tools.DIR_HOME_VERSION + downVName + ".json"; - System.out.println("Downloading version list"); + UIKit.updateProgressSafe(currProgress, "Downloading version list"); mVersionList = Tools.GLOBAL_GSON.fromJson(DownloadUtils.downloadString("https://launchermeta.mojang.com/mc/game/version_manifest.json"), JMinecraftVersionList.class); verInfo = findVersion(mcver); if (verInfo.url != null && !new File(verJsonDir).exists()) { - System.out.println("Downloading " + mcver + ".json"); + UIKit.updateProgressSafe(currProgress, "Downloading " + mcver + ".json"); Tools.downloadFile(verInfo.url, verJsonDir); } verInfo = Tools.getVersionInfo(mcver); + totalProgress = verInfo.libraries.length + 1; // + verInfo.assetslength File outLib; String libPathURL; @@ -98,7 +94,7 @@ public class PLaunchApp { libItem.name.startsWith("net.java.jinput") || libItem.name.startsWith("org.lwjgl") ) { // Black list - System.out.println("Ignored " + libItem.name); + UIKit.updateProgressSafe(currProgress++, "Ignored " + libItem.name); // Thread.sleep(100); } else { String[] libInfo = libItem.name.split(":"); @@ -107,7 +103,7 @@ public class PLaunchApp { outLib.getParentFile().mkdirs(); if (!outLib.exists()) { - System.out.println("Downloading " + libItem.name); + UIKit.updateProgressSafe(currProgress++, "Downloading " + libItem.name); boolean skipIfFailed = false; @@ -122,33 +118,44 @@ public class PLaunchApp { libPathURL = libItem.downloads.artifact.url; Tools.downloadFile(libPathURL, outLib.getAbsolutePath()); } catch (Throwable th) { - /* - if (!skipIfFailed) { - throw th; - } else { - th.printStackTrace(); - publishProgress("0", th.getMessage()); - } - */ - - System.out.println("Download failed"); + th.printStackTrace(); + UIKit.updateProgressSafe(0, "Download failed"); } } } } - System.out.println("Downloading " + mcver + ".jar"); + UIKit.updateProgressSafe(currProgress++, "Downloading " + mcver + ".jar"); File minecraftMainFile = new File(minecraftMainJar); if (!minecraftMainFile.exists() || minecraftMainFile.length() == 0l) { Tools.downloadFile(verInfo.downloads.values().toArray(new MinecraftClientInfo[0])[0].url, minecraftMainJar); } + + // TODO download assets + } catch (IOException e) { - System.out.println("Download error, skipping"); + UIKit.updateProgressSafe(currProgress, "Download error, skipping"); + e.printStackTrace(); } + mAccount = acc; + mVersion = verInfo; + + UIKit.runOnUIThread(() -> { + UIKit.launchMinecraftSurface(); + }); + + }).start(); + } + + // Called from SurfaceViewController + public static void launchMinecraft() { + System.out.println("Saving GLES context"); + JREUtils.saveGLContext(); + System.out.println("Launching Minecraft " + mcver); try { - Tools.launchMinecraft(acc, verInfo); + Tools.launchMinecraft(mAccount, mVersion); } catch (Throwable th) { throw new RuntimeException(th); } diff --git a/JavaApp/src/main/java/net/kdt/pojavlaunch/uikit/UIKit.java b/JavaApp/src/main/java/net/kdt/pojavlaunch/uikit/UIKit.java index afca7c41..f9eb4911 100644 --- a/JavaApp/src/main/java/net/kdt/pojavlaunch/uikit/UIKit.java +++ b/JavaApp/src/main/java/net/kdt/pojavlaunch/uikit/UIKit.java @@ -1,5 +1,6 @@ package net.kdt.pojavlaunch.uikit; +import net.kdt.pojavlaunch.PLaunchApp; import org.lwjgl.glfw.*; public class UIKit { @@ -7,12 +8,16 @@ public class UIKit { public static final int ACTION_UP = 1; public static final int ACTION_MOVE = 2; - public static void callback_AppDelegate_didFinishLaunching(int width, int height) { + public static void callback_LauncherViewController_installMinecraft() { + PLaunchApp.installMinecraft(); + } + + public static void callback_SurfaceViewController_launchMinecraft(int width, int height) { GLFW.mGLFWWindowWidth = width; GLFW.mGLFWWindowHeight = height; CallbackBridge.mouseX = width / 2; CallbackBridge.mouseY = height / 2; - net.kdt.pojavlaunch.PLaunchApp.applicationDidFinishLaunching(); + launchMinecraft(); } public static void callback_SurfaceViewController_onTouch(int event, int x, int y) { @@ -40,10 +45,23 @@ public class UIKit { CallbackBridge.sendCursorPos(CallbackBridge.mouseX, CallbackBridge.mouseY); } + public static void updateProgressSafe(final int percent, final String message) { + System.out.println(message); + runOnUIThread(() -> { + updateProgress(percent, message); + }); + } + static { System.loadLibrary("pojavexec"); } public static native int launchUI(String[] uiArgs); public static native void runOnUIThread(UIKitCallback callback); + + // Update progress + public static native void updateProgress(int percent, String message); + + // Start SurfaceViewController + public static native void launchMinecraftSurface(); } diff --git a/Natives/LauncherViewController.h b/Natives/LauncherViewController.h index 8c136d6e..be88ba0d 100644 --- a/Natives/LauncherViewController.h +++ b/Natives/LauncherViewController.h @@ -1,5 +1,8 @@ #import +UIProgressView* install_progress_bar; +UILabel* install_progress_text; + @interface LauncherViewController : UIViewController @end diff --git a/Natives/LauncherViewController.m b/Natives/LauncherViewController.m index a016e88d..e41d63f7 100644 --- a/Natives/LauncherViewController.m +++ b/Natives/LauncherViewController.m @@ -1,5 +1,4 @@ #import "LauncherViewController.h" -#import "SurfaceViewController.h" #include "utils.h" @@ -19,28 +18,26 @@ CGRect screenBounds = [[UIScreen mainScreen] bounds]; CGFloat screenScale = [[UIScreen mainScreen] scale]; - UIScrollView *scrollView = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 0, screenBounds.size.width, screenBounds.size.height)]; + UIScrollView *scrollView = self.view = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 0, screenBounds.size.width, screenBounds.size.height)]; scrollView.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth; - UIProgressView *progress = [[UIProgressView alloc] initWithFrame:CGRectMake(4.0, 4.0, screenBounds.size.width - 8.0, 40.0)]; - progress.progress = 0.5; - [scrollView addSubview:progress]; + install_progress_bar = [[UIProgressView alloc] initWithFrame:CGRectMake(4.0, 4.0, screenBounds.size.width - 8.0, 40.0)]; + [scrollView addSubview:install_progress_bar]; UIButton *button = [UIButton buttonWithType:UIButtonTypeRoundedRect]; button.autoresizingMask = UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleWidth; [button setTitle:@"Play" forState:UIControlStateNormal]; - button.frame = CGRectMake(10.0, 10.0, 100.0, 50.0); + button.frame = CGRectMake(10.0, 20.0, 100.0, 50.0); [button addTarget:self action:@selector(launchMinecraft:) forControlEvents:UIControlEventTouchUpInside]; [scrollView addSubview:button]; - - self.view = scrollView; + + install_progress_text = [[UILabel alloc] initWithFrame:CGRectMake(120.0, 20.0, screenBounds.size.width - 124.0, 50.0)]; + [scrollView addSubview:install_progress_text]; } - (void)launchMinecraft:(id)sender { - UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"MinecraftSurface" bundle:nil]; - SurfaceViewController *vc = [storyboard instantiateViewControllerWithIdentifier:@"MinecraftSurfaceVC"]; - [self presentViewController:vc animated:YES completion:nil]; + callback_LauncherViewController_installMinecraft(); } - (void)viewWillAppear:(BOOL)animated diff --git a/Natives/SurfaceViewController.m b/Natives/SurfaceViewController.m index 0d8f44b6..4b76a082 100644 --- a/Natives/SurfaceViewController.m +++ b/Natives/SurfaceViewController.m @@ -72,7 +72,7 @@ int width_c = (int) roundf(screenBounds.size.width * screenScale); int height_c = (int) roundf(screenBounds.size.height * screenScale); // glViewport(0, 0, width_c, height_c); - callback_AppDelegate_didFinishLaunching(width_c, height_c); + callback_SurfaceViewController_launchMinecraft(width_c, height_c); } - (void)mglkView:(MGLKView *)view drawInRect:(CGRect)rect { diff --git a/Natives/input_bridge_v3.c b/Natives/input_bridge_v3.c index f1564449..3e5f68c1 100644 --- a/Natives/input_bridge_v3.c +++ b/Natives/input_bridge_v3.c @@ -158,21 +158,42 @@ void closeGLFWWindow() { exit(-1); } -void callback_AppDelegate_didFinishLaunching(int width, int height) { - debug("Received AppDelegate callback, width=%d, height=%d\n", width, height); - +void callback_LauncherViewController_installMinecraft() { + // Because UI init after JVM init, this should not be null assert(runtimeJNIEnvPtr_JRE != NULL); - jclass clazz = (*runtimeJNIEnvPtr_JRE)->FindClass(runtimeJNIEnvPtr_JRE, "net/kdt/pojavlaunch/uikit/UIKit"); - assert(clazz != NULL); + if (!uikitBridgeClass) { + uikitBridgeClass = (*runtimeJNIEnvPtr_JRE)->FindClass(runtimeJNIEnvPtr_JRE, "net/kdt/pojavlaunch/uikit/UIKit"); + assert(uikitBridgeClass != NULL); + } - jmethodID method = (*runtimeJNIEnvPtr_JRE)->GetStaticMethodID(runtimeJNIEnvPtr_JRE, clazz, "callback_AppDelegate_didFinishLaunching", "(II)V"); + jmethodID method = (*runtimeJNIEnvPtr_JRE)->GetStaticMethodID(runtimeJNIEnvPtr_JRE, uikitBridgeClass, "callback_LauncherViewController_installMinecraft", "(II)V"); assert(method != NULL); (*runtimeJNIEnvPtr_JRE)->CallStaticVoidMethod( runtimeJNIEnvPtr_JRE, - clazz, method, + uikitBridgeClass, method + ); +} + +void callback_SurfaceViewController_launchMinecraft(int width, int height) { + debug("Received SurfaceViewController callback, width=%d, height=%d\n", width, height); + + // Because UI init after JVM init, this should not be null + assert(runtimeJNIEnvPtr_JRE != NULL); + + if (!uikitBridgeClass) { + uikitBridgeClass = (*runtimeJNIEnvPtr_JRE)->FindClass(runtimeJNIEnvPtr_JRE, "net/kdt/pojavlaunch/uikit/UIKit"); + assert(uikitBridgeClass != NULL); + } + + jmethodID method = (*runtimeJNIEnvPtr_JRE)->GetStaticMethodID(runtimeJNIEnvPtr_JRE, uikitBridgeClass, "callback_SurfaceViewController_launchMinecraft", "(II)V"); + assert(method != NULL); + + (*runtimeJNIEnvPtr_JRE)->CallStaticVoidMethod( + runtimeJNIEnvPtr_JRE, + uikitBridgeClass, method, width, height ); } @@ -198,6 +219,16 @@ void callback_SurfaceViewController_onTouch(int event, int x, int y) { ); } +JNIEXPORT void JNICALL Java_net_kdt_pojavlaunch_uikit_UIKit_updateProgress(JNIEnv* env, jclass clazz, jint percent, jstring message) { + const char *message_c = (*env)->GetStringUTFChars(env, message, 0); + UIKit_updateProgress((float) percent / 100.0, message_c); + (*env)->ReleaseStringUTFChars(env, message, message_c); +} + +JNIEXPORT void JNICALL Java_net_kdt_pojavlaunch_uikit_UIKit_launchMinecraftSurface(JNIEnv* env, jclass clazz) { + UIKit_launchMinecraftSurfaceVC(); +} + JNIEXPORT void JNICALL Java_net_kdt_pojavlaunch_uikit_UIKit_runOnUIThread(JNIEnv* env, jclass clazz, jobject callback) { UIKit_runOnUIThread(callback); } diff --git a/Natives/ios_uikit_bridge.h b/Natives/ios_uikit_bridge.h index 0f74e8cc..c2b81bc5 100644 --- a/Natives/ios_uikit_bridge.h +++ b/Natives/ios_uikit_bridge.h @@ -2,3 +2,5 @@ #include "jni.h" void UIKit_runOnUIThread(jobject callback); +void UIKit_updateProgress(float progress, char* message); +void UIKit_launchMinecraftSurfaceVC(); diff --git a/Natives/ios_uikit_bridge.m b/Natives/ios_uikit_bridge.m index 3b1b34db..e8eb7cc8 100644 --- a/Natives/ios_uikit_bridge.m +++ b/Natives/ios_uikit_bridge.m @@ -1,5 +1,9 @@ #import +#import "AppDelegate.h" +#import "LauncherViewController.h" +#import "SurfaceViewController.h" + #include "ios_uikit_bridge.h" #include "utils.h" @@ -14,3 +18,15 @@ void UIKit_runOnUIThread(jobject callback) { ); }); } + +void UIKit_updateProgress(float progress, char* message) { + install_progress_bar.progress = progress; + install_progress_text.text = [NSString stringWithUTF8String:message]; +} + +void UIKit_launchMinecraftSurfaceVC() { + LauncherViewController *rootController = (LauncherViewController*)[[(AppDelegate*) [[UIApplication sharedApplication]delegate] window] rootViewController]; + UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"MinecraftSurface" bundle:nil]; + SurfaceViewController *vc = [storyboard instantiateViewControllerWithIdentifier:@"MinecraftSurfaceVC"]; + [rootController presentViewController:vc animated:YES completion:nil]; +} diff --git a/Natives/utils.h b/Natives/utils.h index d4e0aef7..6d2d82da 100644 --- a/Natives/utils.h +++ b/Natives/utils.h @@ -30,7 +30,8 @@ jobjectArray convert_from_char_array(JNIEnv *env, char **charArray, int num_rows void free_char_array(JNIEnv *env, jobjectArray jstringArray, const char **charArray); void closeGLFWWindow(); -void callback_AppDelegate_didFinishLaunching(int width, int height); +void callback_LauncherViewController_installMinecraft(); +void callback_SurfaceViewController_launchMinecraft(int width, int height); void callback_SurfaceViewController_onTouch(int event, int x, int y); #endif // _BINARY_UTILS_H_