Basic mod installer implementation
This commit is contained in:
1 parent
0668d016bf
commit
f2566e3da5
14 files changed
+358
-89
No files matched your search
@@ -117,19 +117,19 @@ public final class Tools
|
||||
|
||||
// URLClassLoader loader = new URLClassLoader(urlList.toArray(new URL[0]), ClassLoader.getSystemClassLoader());
|
||||
|
||||
PojavClassLoader loader = (PojavClassLoader) ClassLoader.getSystemClassLoader();
|
||||
|
||||
for (String s : launchClassPath.split(":")) {
|
||||
if (!s.isEmpty()) {
|
||||
loader.addURL(new File(s).toURI().toURL());
|
||||
PojavClassLoader loader = (PojavClassLoader) ClassLoader.getSystemClassLoader();
|
||||
|
||||
for (String s : launchClassPath.split(":")) {
|
||||
if (!s.isEmpty()) {
|
||||
loader.addURL(new File(s).toURI().toURL());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Class<?> clazz = loader.loadClass(versionInfo.mainClass);
|
||||
Method method = clazz.getMethod("main", String[].class);
|
||||
method.invoke(null, new Object[]{launchArgs});
|
||||
|
||||
System.out.println("It went past main(). Should not reach here!");
|
||||
|
||||
// throw new RuntimeException("Game exited. Check latestlog.txt for more details.");
|
||||
} catch (Throwable th) {
|
||||
showError(th);
|
||||
}
|
||||
|
||||
@@ -1,7 +1,11 @@
|
||||
package net.kdt.pojavlaunch.uikit;
|
||||
|
||||
import java.io.*;
|
||||
import java.lang.reflect.*;
|
||||
import java.util.jar.*;
|
||||
import net.java.openjdk.cacio.ctc.CTCScreen;
|
||||
import net.kdt.pojavlaunch.utils.MCOptionUtils;
|
||||
import net.kdt.pojavlaunch.PLaunchApp;
|
||||
import net.kdt.pojavlaunch.*;
|
||||
import org.lwjgl.glfw.*;
|
||||
|
||||
public class UIKit {
|
||||
@@ -10,6 +14,59 @@ public class UIKit {
|
||||
public static final int ACTION_MOVE = 2;
|
||||
|
||||
private static int guiScale;
|
||||
|
||||
public static void callback_JavaGUIViewController_launchJarFile(final String filepath, int width, int height) {
|
||||
System.setProperty("cacio.managed.screensize", width + "x" + height);
|
||||
|
||||
// Thread for refreshing the AWT buffer
|
||||
new Thread(() -> {
|
||||
try {
|
||||
long lastTime = System.currentTimeMillis();
|
||||
while (true) {
|
||||
int[] pixelsArray = null;
|
||||
try{
|
||||
pixelsArray = CTCScreen.getCurrentScreenRGB();
|
||||
} catch (NullPointerException e) {
|
||||
Thread.sleep(500);
|
||||
}
|
||||
if (pixelsArray != null) {
|
||||
//System.out.println(java.util.Arrays.toString(pixelsArray));
|
||||
refreshAWTBuffer(pixelsArray);
|
||||
}
|
||||
long currentTime = System.currentTimeMillis();
|
||||
if (currentTime - lastTime < 16) {
|
||||
Thread.sleep(16 - (currentTime - lastTime));
|
||||
}
|
||||
lastTime = currentTime;
|
||||
}
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}, "AWTFBRefreshThread").start();
|
||||
|
||||
// Thread for launching the JAR file
|
||||
new Thread(() -> {
|
||||
String mainClassName = null;
|
||||
try {
|
||||
JarFile jarfile = new JarFile(filepath);
|
||||
String mainClass = jarfile.getManifest().getMainAttributes().getValue("Main-Class");
|
||||
jarfile.close();
|
||||
if (mainClass == null) {
|
||||
throw new IllegalArgumentException("no main manifest attribute, in \"" + filepath + "\"");
|
||||
}
|
||||
|
||||
PojavClassLoader loader = (PojavClassLoader) ClassLoader.getSystemClassLoader();
|
||||
loader.addURL(new File(filepath).toURI().toURL());
|
||||
Class<?> clazz = loader.loadClass(mainClass);
|
||||
Method method = clazz.getMethod("main", String[].class);
|
||||
method.invoke(null, new Object[]{new String[]{}});
|
||||
|
||||
// throw new RuntimeException("Application exited");
|
||||
} catch (Throwable th) {
|
||||
Tools.showError(th, true);
|
||||
}
|
||||
}, "ModInstallerThread").start();
|
||||
}
|
||||
|
||||
public static void callback_LauncherViewController_installMinecraft(String versionPath) {
|
||||
PLaunchApp.installMinecraft(versionPath);
|
||||
@@ -73,7 +130,9 @@ public class UIKit {
|
||||
static {
|
||||
System.loadLibrary("pojavexec");
|
||||
}
|
||||
|
||||
|
||||
public static native void refreshAWTBuffer(int[] array);
|
||||
|
||||
public static native int launchUI(String[] uiArgs);
|
||||
// public static native void runOnUIThread(UIKitCallback callback);
|
||||
|
||||
|
||||
@@ -107,14 +107,14 @@ native:
|
||||
-DCONFIG_COMMIT="$(COMMIT)" \
|
||||
..
|
||||
@cd Natives/build && cmake --build . --config Release --target awt_headless awt_xawt pojavexec PojavLauncher
|
||||
@rm Natives/build/libawt_headless.dylib || exit 1
|
||||
@rm Natives/build/libawt_headless.dylib
|
||||
@echo 'Finished build task - native application'
|
||||
|
||||
java:
|
||||
@echo 'Starting build task - java application'
|
||||
@cd JavaApp; \
|
||||
mkdir -p local_out/classes; \
|
||||
$(JDK)/javac -cp "libs/*" -d local_out/classes $(JAVAFILES) || exit 1; \
|
||||
$(JDK)/javac -cp "libs/*:libs_caciocavallo/*" -d local_out/classes $(JAVAFILES) || exit 1; \
|
||||
cd local_out/classes; \
|
||||
$(JDK)/jar -cf ../launcher.jar * || exit 1; \
|
||||
echo 'Finished build task - java application'
|
||||
@@ -135,7 +135,8 @@ package:
|
||||
@echo 'Starting build task - package for external devices'
|
||||
@if [ '$(IOS)' = '0' ]; then \
|
||||
cp -R Natives/resources/* Natives/build/PojavLauncher.app/ || exit 1; \
|
||||
cp Natives/build/*.dylib Natives/build/PojavLauncher.app/Frameworks/ || exit 1; \
|
||||
cp Natives/build/libawt_xawt.dylib Natives/build/PojavLauncher.app/Frameworks/ || exit 1; \
|
||||
cp Natives/build/libpojavexec.dylib Natives/build/PojavLauncher.app/Frameworks/ || exit 1; \
|
||||
mkdir Natives/build/PojavLauncher.app/{libs,libs_caciocavallo}; \
|
||||
cp JavaApp/local_out/launcher.jar Natives/build/PojavLauncher.app/libs/launcher.jar || exit 1; \
|
||||
cp -R JavaApp/libs/* Natives/build/PojavLauncher.app/libs/ || exit 1; \
|
||||
@@ -151,7 +152,8 @@ package:
|
||||
cp -R Natives/en.lproj/*.storyboardc Natives/build/PojavLauncher.app/Base.lproj/ || exit 1; \
|
||||
cp -R Natives/Info.plist Natives/build/PojavLauncher.app/Info.plist || exit 1;\
|
||||
cp -R Natives/PkgInfo Natives/build/PojavLauncher.app/PkgInfo || exit 1; \
|
||||
cp -R Natives/build/*.dylib Natives/build/PojavLauncher.app/Frameworks/ || exit 1; \
|
||||
cp Natives/build/libawt_xawt.dylib Natives/build/PojavLauncher.app/Frameworks/ || exit 1; \
|
||||
cp Natives/build/libpojavexec.dylib Natives/build/PojavLauncher.app/Frameworks/ || exit 1; \
|
||||
cp -R Natives/resources/* Natives/build/PojavLauncher.app/ || exit 1; \
|
||||
cp -R JavaApp/libs Natives/build/PojavLauncher.app/libs || exit 1; \
|
||||
cp -R JavaApp/libs_caciocavallo Natives/build/PojavLauncher.app/libs_caciocavallo || exit 1; \
|
||||
@@ -217,7 +219,8 @@ deploy:
|
||||
sudo ldid -Sentitlements.xml Natives/build/PojavLauncher.app/PojavLauncher; \
|
||||
sudo cp JavaApp/local_out/launcher.jar /Applications/PojavLauncher.app/libs/launcher.jar; \
|
||||
sudo cp Natives/build/PojavLauncher.app/PojavLauncher /Applications/PojavLauncher.app/PojavLauncher; \
|
||||
sudo cp Natives/build/*.dylib /Applications/PojavLauncher.app/Frameworks/; \
|
||||
sudo cp Natives/build/libawt_xawt.dylib /Applications/PojavLauncher.app/Frameworks/; \
|
||||
sudo cp Natives/build/libpojavexec.dylib /Applications/PojavLauncher.app/Frameworks/; \
|
||||
sudo killall PojavLauncher; \
|
||||
fi
|
||||
@echo 'Finished build task - deploy to local device'
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
#import <sys/utsname.h>
|
||||
|
||||
#ifndef NDEBUG
|
||||
#ifdef NDEBUG
|
||||
# define CONFIG_TYPE "release"
|
||||
#else
|
||||
# define CONFIG_TYPE "debug"
|
||||
|
||||
@@ -32,6 +32,7 @@ add_library(pojavexec SHARED
|
||||
AboutLauncherViewController.m
|
||||
AppDelegate.m
|
||||
CustomControlsViewController.m
|
||||
JavaGUIViewController.m
|
||||
LauncherFAQViewController.m
|
||||
LauncherPreferences.m
|
||||
LauncherPreferencesViewController.m
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
@interface SurfaceView : UIView {
|
||||
CALayer* layer;
|
||||
CGColorSpaceRef colorSpace;
|
||||
CGDataProviderDirectCallbacks callbacks;
|
||||
}
|
||||
@end
|
||||
|
||||
@interface JavaGUIViewController : UIViewController
|
||||
@property NSString* filepath;
|
||||
@end
|
||||
@@ -0,0 +1,170 @@
|
||||
#import "JavaGUIViewController.h"
|
||||
#import "ios_uikit_bridge.h"
|
||||
#include "utils.h"
|
||||
|
||||
static int* rgbArray;
|
||||
SurfaceView* surfaceView;
|
||||
|
||||
jclass class_CTCAndroidInput;
|
||||
jmethodID method_ReceiveInput;
|
||||
|
||||
JNIEXPORT void JNICALL Java_net_kdt_pojavlaunch_uikit_UIKit_refreshAWTBuffer(JNIEnv* env, jclass clazz, jintArray jreRgbArray) {
|
||||
int *tmpArray = (*env)->GetIntArrayElements(env, jreRgbArray, 0);
|
||||
memcpy(rgbArray, tmpArray, savedWidth * savedHeight * 4);
|
||||
(*env)->ReleaseIntArrayElements(env, jreRgbArray, tmpArray, JNI_ABORT);
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
[surfaceView displayLayer:surfaceView.layer];
|
||||
});
|
||||
}
|
||||
|
||||
@implementation SurfaceView
|
||||
const void * _CGDataProviderGetBytePointerCallback(void *info) {
|
||||
return (const void *)rgbArray;
|
||||
}
|
||||
|
||||
void _CGDataProviderReleaseBytePointerCallback(void *info,const void *pointer) {
|
||||
}
|
||||
|
||||
- (void)displayLayer:(CALayer *)theLayer
|
||||
{
|
||||
CGDataProviderRef bitmapProvider = CGDataProviderCreateDirect(NULL, savedWidth * savedHeight * 4, &callbacks);
|
||||
CGImageRef bitmap = CGImageCreate(savedWidth, savedHeight, 8, 32, 4 * savedWidth, colorSpace, kCGImageAlphaFirst | kCGBitmapByteOrder32Little, bitmapProvider, NULL, FALSE, kCGRenderingIntentDefault);
|
||||
|
||||
theLayer.contents = (__bridge id) bitmap;
|
||||
CGImageRelease(bitmap);
|
||||
CGDataProviderRelease(bitmapProvider);
|
||||
// CGColorSpaceRelease(colorSpace);
|
||||
}
|
||||
|
||||
- (id)initWithFrame:(CGRect)frame
|
||||
{
|
||||
self = [super initWithFrame:frame];
|
||||
layer = [self layer];
|
||||
layer.opaque = YES;
|
||||
|
||||
colorSpace = CGColorSpaceCreateDeviceRGB();
|
||||
|
||||
callbacks.version = 0;
|
||||
callbacks.getBytePointer = _CGDataProviderGetBytePointerCallback;
|
||||
callbacks.releaseBytePointer = _CGDataProviderReleaseBytePointerCallback;
|
||||
callbacks.getBytesAtPosition = NULL;
|
||||
callbacks.releaseInfo = NULL;
|
||||
|
||||
return self;
|
||||
}
|
||||
@end
|
||||
|
||||
@interface JavaGUIViewController ()<UIGestureRecognizerDelegate, UIScrollViewDelegate> {
|
||||
}
|
||||
|
||||
// - (void)method
|
||||
|
||||
@end
|
||||
|
||||
@implementation JavaGUIViewController
|
||||
|
||||
- (void)viewDidLoad
|
||||
{
|
||||
[super viewDidLoad];
|
||||
|
||||
[self.navigationController setNavigationBarHidden:YES animated:NO];
|
||||
[self setNeedsUpdateOfScreenEdgesDeferringSystemGestures];
|
||||
[self setNeedsUpdateOfHomeIndicatorAutoHidden];
|
||||
|
||||
CGRect screenBounds = [[UIScreen mainScreen] bounds];
|
||||
CGFloat screenScale = [[UIScreen mainScreen] scale];
|
||||
|
||||
int width = (int) roundf(screenBounds.size.width);
|
||||
int height = (int) roundf(screenBounds.size.height);
|
||||
|
||||
savedWidth = roundf(width * screenScale);
|
||||
savedHeight = roundf(height * screenScale);
|
||||
|
||||
UIScrollView *scrollView = [[UIScrollView alloc] initWithFrame:self.view.frame];
|
||||
scrollView.delegate = self;
|
||||
scrollView.minimumZoomScale = 1;
|
||||
scrollView.maximumZoomScale = 5;
|
||||
scrollView.zoomScale = 1;
|
||||
|
||||
surfaceView = [[SurfaceView alloc] initWithFrame:self.view.frame];
|
||||
[scrollView addSubview:surfaceView];
|
||||
|
||||
[self.view addSubview:scrollView];
|
||||
|
||||
// Update color mode once
|
||||
if(@available(iOS 13.0, *)) {
|
||||
[self traitCollectionDidChange:nil];
|
||||
} else {
|
||||
self.view.backgroundColor = [UIColor whiteColor];
|
||||
}
|
||||
|
||||
UITapGestureRecognizer *tapGesture = [[UITapGestureRecognizer alloc]
|
||||
initWithTarget:self action:@selector(surfaceOnClick:)];
|
||||
tapGesture.delegate = self;
|
||||
tapGesture.numberOfTapsRequired = 1;
|
||||
tapGesture.numberOfTouchesRequired = 1;
|
||||
tapGesture.cancelsTouchesInView = NO;
|
||||
[surfaceView addGestureRecognizer:tapGesture];
|
||||
|
||||
rgbArray = calloc(4, (size_t) (savedWidth * savedHeight));
|
||||
|
||||
UIKit_launchJarFile(self.filepath.UTF8String);
|
||||
}
|
||||
|
||||
- (void)surfaceOnClick:(UITapGestureRecognizer *)sender {
|
||||
if (method_ReceiveInput == NULL) {
|
||||
class_CTCAndroidInput = (*runtimeJNIEnvPtr_JRE)->FindClass(runtimeJNIEnvPtr_JRE, "net/java/openjdk/cacio/ctc/CTCAndroidInput");
|
||||
assert(class_CTCAndroidInput != NULL);
|
||||
method_ReceiveInput = (*runtimeJNIEnvPtr_JRE)->GetStaticMethodID(runtimeJNIEnvPtr_JRE, class_CTCAndroidInput, "receiveData", "(IIIII)V");
|
||||
assert(method_ReceiveInput != NULL);
|
||||
}
|
||||
|
||||
if (sender.state == UIGestureRecognizerStateRecognized) {
|
||||
CGFloat screenScale = [[UIScreen mainScreen] scale];
|
||||
CGPoint location = [sender locationInView:sender.view];
|
||||
CGFloat x = location.x * screenScale;
|
||||
CGFloat y = location.y * screenScale;
|
||||
(*runtimeJNIEnvPtr_JRE)->CallStaticVoidMethod(
|
||||
runtimeJNIEnvPtr_JRE,
|
||||
class_CTCAndroidInput,
|
||||
method_ReceiveInput,
|
||||
EVENT_TYPE_CURSOR_POS, (int)x, (int)y, 0, 0
|
||||
);
|
||||
(*runtimeJNIEnvPtr_JRE)->CallStaticVoidMethod(
|
||||
runtimeJNIEnvPtr_JRE,
|
||||
class_CTCAndroidInput,
|
||||
method_ReceiveInput,
|
||||
EVENT_TYPE_MOUSE_BUTTON, BUTTON1_DOWN_MASK, 1, 0, 0
|
||||
);
|
||||
(*runtimeJNIEnvPtr_JRE)->CallStaticVoidMethod(
|
||||
runtimeJNIEnvPtr_JRE,
|
||||
class_CTCAndroidInput,
|
||||
method_ReceiveInput,
|
||||
EVENT_TYPE_MOUSE_BUTTON, BUTTON1_DOWN_MASK, 0, 0, 0
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
- (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView {
|
||||
return surfaceView;
|
||||
}
|
||||
|
||||
- (UIRectEdge)preferredScreenEdgesDeferringSystemGestures {
|
||||
return UIRectEdgeBottom;
|
||||
}
|
||||
|
||||
- (BOOL)prefersHomeIndicatorAutoHidden {
|
||||
return NO;
|
||||
}
|
||||
|
||||
-(void)traitCollectionDidChange:(UITraitCollection *)previousTraitCollection {
|
||||
if(@available(iOS 13.0, *)) {
|
||||
if (UITraitCollection.currentTraitCollection.userInterfaceStyle == UIUserInterfaceStyleDark) {
|
||||
self.view.backgroundColor = [UIColor blackColor];
|
||||
} else {
|
||||
self.view.backgroundColor = [UIColor whiteColor];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -1,11 +1,12 @@
|
||||
#import "CustomControlsViewController.h"
|
||||
#import "JavaGUIViewController.h"
|
||||
#import "LauncherPreferences.h"
|
||||
#import "LauncherPreferencesViewController.h"
|
||||
#import "LauncherViewController.h"
|
||||
|
||||
#include "utils.h"
|
||||
|
||||
@interface LauncherViewController () <UIPickerViewDataSource, UIPickerViewDelegate> {
|
||||
@interface LauncherViewController () <UIDocumentPickerDelegate, UIPickerViewDataSource, UIPickerViewDelegate> {
|
||||
}
|
||||
|
||||
// - (void)method
|
||||
@@ -72,11 +73,23 @@ int versionSelectedAt = 0;
|
||||
|
||||
[scrollView addSubview:versionTextField];
|
||||
|
||||
self.navigationItem.rightBarButtonItems = @[
|
||||
[[UIBarButtonItem alloc] initWithTitle:@"Custom controls" style:UIBarButtonItemStyleDone target:self action:@selector(enterCustomControls)],
|
||||
[[UIBarButtonItem alloc] initWithTitle:@"Settings" style:UIBarButtonItemStyleDone target:self action:@selector(enterPreferences)]
|
||||
];
|
||||
|
||||
self.navigationItem.rightBarButtonItem =
|
||||
[[UIBarButtonItem alloc] initWithTitle:@"Options" style:UIBarButtonItemStyleDone target:self action:@selector(displayOptions:)];
|
||||
if (@available(iOS 14.0, *)) {
|
||||
// use UIMenu
|
||||
UIAction *option1 = [UIAction actionWithTitle:@"Launch a mod installer" image:nil identifier:nil
|
||||
handler:^(__kindof UIAction * _Nonnull action) {[self enterModInstaller];}];
|
||||
UIAction *option2 = [UIAction actionWithTitle:@"Custom controls" image:nil identifier:nil
|
||||
handler:^(__kindof UIAction * _Nonnull action) {[self enterCustomControls];}];
|
||||
UIAction *option3 = [UIAction actionWithTitle:@"Settings" image:nil identifier:nil
|
||||
handler:^(__kindof UIAction * _Nonnull action) {[self enterPreferences];}];
|
||||
UIMenu *menu = [UIMenu menuWithTitle:@"Options" image:nil identifier:nil
|
||||
options:UIMenuOptionsDisplayInline children:@[option1, option2, option3]];
|
||||
self.navigationItem.rightBarButtonItem.action = nil;
|
||||
self.navigationItem.rightBarButtonItem.primaryAction = nil;
|
||||
self.navigationItem.rightBarButtonItem.menu = menu;
|
||||
}
|
||||
|
||||
install_progress_bar = [[UIProgressView alloc] initWithFrame:CGRectMake(4.0, height - 58.0, width - 8.0, 6.0)];
|
||||
[scrollView addSubview:install_progress_bar];
|
||||
|
||||
@@ -181,23 +194,60 @@ int versionSelectedAt = 0;
|
||||
}
|
||||
|
||||
#pragma mark - Button click events
|
||||
- (void)displayOptions:(UIBarButtonItem*)sender {
|
||||
if (@available(iOS 14.0, *)) {
|
||||
// use UIMenu
|
||||
} else {
|
||||
// use UIAlertController
|
||||
UIAlertController *fullAlert = [UIAlertController alertControllerWithTitle:@"Options" message:@"" preferredStyle:UIAlertControllerStyleActionSheet];
|
||||
UIAlertAction *option1 = [UIAlertAction actionWithTitle:@"Launch a mod installer" style:UIAlertActionStyleDefault
|
||||
handler:^(UIAlertAction * _Nonnull action) {[self enterModInstaller];}];
|
||||
UIAlertAction *option2 = [UIAlertAction actionWithTitle:@"Custom controls" style:UIAlertActionStyleDefault
|
||||
handler:^(UIAlertAction * _Nonnull action) {[self enterCustomControls];}];
|
||||
UIAlertAction *option3 = [UIAlertAction actionWithTitle:@"Settings" style:UIAlertActionStyleDefault
|
||||
handler:^(UIAlertAction * _Nonnull action) {[self enterPreferences];}];
|
||||
fullAlert.popoverPresentationController.barButtonItem = sender;
|
||||
[self presentViewController:fullAlert animated:YES completion:nil];
|
||||
[fullAlert addAction:option1];
|
||||
[fullAlert addAction:option2];
|
||||
[fullAlert addAction:option3];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)enterCustomControls {
|
||||
CustomControlsViewController *vc = [[CustomControlsViewController alloc] init];
|
||||
[self.navigationController pushViewController:vc animated:YES];
|
||||
}
|
||||
|
||||
- (void)enterModInstaller {
|
||||
UIDocumentPickerViewController *documentPicker = [[UIDocumentPickerViewController alloc] initWithDocumentTypes:@[@"com.sun.java-archive"]
|
||||
inMode:UIDocumentPickerModeImport];
|
||||
documentPicker.delegate = self;
|
||||
documentPicker.modalPresentationStyle = UIModalPresentationFormSheet;
|
||||
[self presentViewController:documentPicker animated:YES completion:nil];
|
||||
}
|
||||
|
||||
- (void)documentPicker:(UIDocumentPickerViewController *)controller didPickDocumentAtURL:(NSURL *)url {
|
||||
if (controller.documentPickerMode == UIDocumentPickerModeImport) {
|
||||
JavaGUIViewController *vc = [[JavaGUIViewController alloc] init];
|
||||
vc.filepath = url.path;
|
||||
NSLog(@"ModInstaller: launching %@", vc.filepath);
|
||||
[self.navigationController pushViewController:vc animated:YES];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)enterPreferences {
|
||||
LauncherPreferencesViewController *vc = [[LauncherPreferencesViewController alloc] init];
|
||||
[self.navigationController pushViewController:vc animated:YES];
|
||||
}
|
||||
|
||||
- (void)launchMinecraft:(id)sender {
|
||||
[(UIButton*) sender setEnabled:NO];
|
||||
- (void)launchMinecraft:(UIButton *)sender {
|
||||
[sender setEnabled:NO];
|
||||
|
||||
NSObject *object = [versionList objectAtIndex:[versionPickerView selectedRowInComponent:0]];
|
||||
NSString *result;
|
||||
if ([object isKindOfClass:[NSString class]]) {
|
||||
result = (NSString*) object;
|
||||
result = (NSString *)object;
|
||||
} else {
|
||||
result = [object valueForKey:@"url"];
|
||||
}
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
|
||||
void loginAccountInput(UINavigationController *controller, int type, const char* data_c) {
|
||||
JNIEnv *env;
|
||||
(*runtimeJavaVMPtr)->AttachCurrentThread(runtimeJavaVMPtr, &env, NULL);
|
||||
(*runtimeJavaVMPtr)->GetEnv(runtimeJavaVMPtr, &env, JNI_VERSION_1_6);
|
||||
|
||||
jstring data = (*env)->NewStringUTF(env, data_c);
|
||||
|
||||
|
||||
@@ -168,6 +168,13 @@ void generateAndSaveDefaultControl() {
|
||||
@"${bottom} - ${margin}",
|
||||
BTN_RECT
|
||||
)];
|
||||
// Additional button for old versions that don't enter fullscreen automatically
|
||||
[dict[@"mControlDataList"] addObject:createButton(@"Fullscreen",
|
||||
(int[]){GLFW_KEY_F11,0,0,0},
|
||||
@"${right} - ${margin}",
|
||||
@"${bottom} - ${margin} * 2 - ${height}",
|
||||
BTN_RECT
|
||||
)];
|
||||
NSOutputStream *os = [[NSOutputStream alloc] initToFileAtPath:
|
||||
[@(getenv("POJAV_PATH_CONTROL")) stringByAppendingString:@"/default.json"] append:NO];
|
||||
[os open];
|
||||
|
||||
@@ -56,14 +56,6 @@ jint JNI_OnLoad(JavaVM* vm, void* reserved) {
|
||||
|
||||
// Should be?
|
||||
void JNI_OnUnload(JavaVM* vm, void* reserved) {
|
||||
/*
|
||||
if (dalvikJavaVMPtr == vm) {
|
||||
} else {
|
||||
}
|
||||
|
||||
DetachCurrentThread(vm);
|
||||
*/
|
||||
|
||||
runtimeJNIEnvPtr_JRE = NULL;
|
||||
}
|
||||
|
||||
@@ -88,24 +80,6 @@ ADD_CALLBACK_WWIN(WindowPos);
|
||||
|
||||
#undef ADD_CALLBACK_WWIN
|
||||
|
||||
jboolean attachThread(bool isAndroid, JNIEnv** secondJNIEnvPtr) {
|
||||
#ifdef DEBUG
|
||||
debug("Debug: Attaching %s thread to %s, javavm.isNull=%d\n", isAndroid ? "Android" : "JRE", isAndroid ? "JRE" : "Android", (isAndroid ? runtimeJavaVMPtr : dalvikJavaVMPtr) == NULL);
|
||||
#endif
|
||||
|
||||
if (*secondJNIEnvPtr != NULL || (!isUseStackQueueCall)) return JNI_TRUE;
|
||||
|
||||
if (isAndroid && runtimeJavaVMPtr) {
|
||||
(*runtimeJavaVMPtr)->AttachCurrentThread(runtimeJavaVMPtr, secondJNIEnvPtr, NULL);
|
||||
return JNI_TRUE;
|
||||
} else if (!isAndroid && dalvikJavaVMPtr) {
|
||||
(*dalvikJavaVMPtr)->AttachCurrentThread(dalvikJavaVMPtr, secondJNIEnvPtr, NULL);
|
||||
return JNI_TRUE;
|
||||
}
|
||||
|
||||
return JNI_FALSE;
|
||||
}
|
||||
|
||||
void getJavaInputBridge(jclass* clazz, jmethodID* method) {
|
||||
#ifdef DEBUG
|
||||
debug("Debug: Initializing input bridge, method.isNull=%d, jnienv.isNull=%d\n", *method == NULL, runtimeJNIEnvPtr_ANDROID == NULL);
|
||||
@@ -272,29 +246,6 @@ JNIEXPORT jint JNICALL Java_net_kdt_pojavlaunch_uikit_UIKit_launchUI(JNIEnv* env
|
||||
}
|
||||
}
|
||||
|
||||
JNIEXPORT jboolean JNICALL Java_org_lwjgl_glfw_CallbackBridge_nativeAttachThreadToOther(JNIEnv* env, jclass clazz, jboolean isAndroid, jboolean isUseStackQueueBool) {
|
||||
#ifdef DEBUG
|
||||
LOGD("Debug: JNI attaching thread, isUseStackQueue=%d\n", isUseStackQueue);
|
||||
#endif
|
||||
|
||||
jboolean result;
|
||||
|
||||
isUseStackQueueCall = (int) isUseStackQueueBool;
|
||||
if (isAndroid) {
|
||||
result = attachThread(true, &runtimeJNIEnvPtr_ANDROID);
|
||||
} else {
|
||||
result = attachThread(false, &dalvikJNIEnvPtr_JRE);
|
||||
// getJavaInputBridge(&inputBridgeClass_JRE, &inputBridgeMethod_JRE);
|
||||
}
|
||||
|
||||
if (isUseStackQueueCall && isAndroid && result) {
|
||||
isPrepareGrabPos = true;
|
||||
}
|
||||
getJavaInputBridge(&inputBridgeClass_ANDROID, &inputBridgeMethod_ANDROID);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
JNIEXPORT jstring JNICALL Java_org_lwjgl_glfw_CallbackBridge_nativeClipboard(JNIEnv* env, jclass clazz, jint action, jstring copySrc) {
|
||||
DEBUG_LOGD("Debug: Clipboard access is going on\n");
|
||||
return UIKit_accessClipboard(env, action, copySrc);
|
||||
|
||||
@@ -5,5 +5,6 @@
|
||||
void showDialog(UIViewController *viewController, NSString* title, NSString* message);
|
||||
jstring UIKit_accessClipboard(JNIEnv* env, jint action, jstring copySrc);
|
||||
jboolean UIKit_updateProgress(float progress, const char* message);
|
||||
void UIKit_launchJarFile(const char* filepath);
|
||||
void UIKit_launchMinecraftSurfaceVC();
|
||||
void UIKit_setButtonSkippable();
|
||||
+25
-13
@@ -13,6 +13,12 @@
|
||||
|
||||
jboolean skipDownloadAssets;
|
||||
|
||||
jclass class_CTCScreen;
|
||||
jmethodID method_GetRGB;
|
||||
|
||||
jclass class_CTCAndroidInput;
|
||||
jmethodID method_ReceiveInput;
|
||||
|
||||
void internal_showDialog(UIViewController *viewController, NSString* title, NSString* message) {
|
||||
UIAlertController* alert = [UIAlertController alertControllerWithTitle:title
|
||||
message:message
|
||||
@@ -45,12 +51,7 @@ JNIEXPORT void JNICALL Java_net_kdt_pojavlaunch_uikit_UIKit_showError(JNIEnv* en
|
||||
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
|
||||
UIViewController *viewController = nil;
|
||||
if (@available(iOS 13.0, *)) {
|
||||
viewController = UIApplication.sharedApplication.windows.lastObject.rootViewController;
|
||||
} else {
|
||||
viewController = [[(AppDelegate*) [[UIApplication sharedApplication]delegate] window] rootViewController];
|
||||
}
|
||||
UIViewController *viewController = UIApplication.sharedApplication.windows.lastObject.rootViewController;
|
||||
|
||||
UIAlertController* alert = [UIAlertController
|
||||
alertControllerWithTitle:title_o message:message_o
|
||||
@@ -128,15 +129,26 @@ void UIKit_setButtonSkippable() {
|
||||
skipDownloadAssets = JNI_FALSE;
|
||||
}
|
||||
|
||||
void UIKit_launchJarFile(const char* filepath) {
|
||||
jclass uikitBridgeClass = (*runtimeJNIEnvPtr_JRE)->FindClass(runtimeJNIEnvPtr_JRE, "net/kdt/pojavlaunch/uikit/UIKit");
|
||||
assert(uikitBridgeClass != NULL);
|
||||
|
||||
jstring filepathStr = (*runtimeJNIEnvPtr_JRE)->NewStringUTF(runtimeJNIEnvPtr_JRE, filepath);
|
||||
jmethodID method = (*runtimeJNIEnvPtr_JRE)->GetStaticMethodID(runtimeJNIEnvPtr_JRE, uikitBridgeClass, "callback_JavaGUIViewController_launchJarFile", "(Ljava/lang/String;II)V");
|
||||
assert(method != NULL);
|
||||
|
||||
(*runtimeJNIEnvPtr_JRE)->CallStaticVoidMethod(
|
||||
runtimeJNIEnvPtr_JRE,
|
||||
uikitBridgeClass, method,
|
||||
filepathStr,
|
||||
savedWidth, savedHeight
|
||||
);
|
||||
(*runtimeJNIEnvPtr_JRE)->DeleteLocalRef(runtimeJNIEnvPtr_JRE, filepathStr);
|
||||
}
|
||||
|
||||
void UIKit_launchMinecraftSurfaceVC() {
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
UIViewController *rootController = nil;
|
||||
if (@available(iOS 13.0, *)) {
|
||||
rootController = UIApplication.sharedApplication.windows.lastObject.rootViewController;
|
||||
} else {
|
||||
rootController = (UIViewController*) [[(AppDelegate*) [[UIApplication sharedApplication]delegate] window] rootViewController];
|
||||
}
|
||||
|
||||
UIViewController *rootController = UIApplication.sharedApplication.windows.lastObject.rootViewController;
|
||||
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"MinecraftSurface" bundle:nil];
|
||||
SurfaceViewController *vc = [storyboard instantiateViewControllerWithIdentifier:@"MinecraftSurfaceVC"];
|
||||
vc.modalPresentationStyle = UIModalPresentationFullScreen;
|
||||
|
||||
+4
-1
@@ -7,6 +7,10 @@
|
||||
#define ACTION_UP 1
|
||||
#define ACTION_MOVE 2
|
||||
|
||||
#define BUTTON1_DOWN_MASK 1 << 10 // left btn
|
||||
#define BUTTON2_DOWN_MASK 1 << 11 // mid btn
|
||||
#define BUTTON3_DOWN_MASK 1 << 12 // right btn
|
||||
|
||||
#define EVENT_TYPE_CHAR 1000
|
||||
#define EVENT_TYPE_CHAR_MODS 1001
|
||||
#define EVENT_TYPE_CURSOR_ENTER 1002
|
||||
@@ -33,7 +37,6 @@ JavaVM* runtimeJavaVMPtr;
|
||||
JNIEnv* runtimeJNIEnvPtr_ANDROID;
|
||||
JNIEnv* runtimeJNIEnvPtr_JRE;
|
||||
|
||||
JavaVM* dalvikJavaVMPtr;
|
||||
JNIEnv* dalvikJNIEnvPtr_ANDROID;
|
||||
JNIEnv* dalvikJNIEnvPtr_JRE;
|
||||
|
||||
|
||||
Reference in new issue
Block a user