diff --git a/JavaApp/src/main/java/org/lwjgl/opengl/GLFWInputImplementation.java b/JavaApp/src/main/java/org/lwjgl/opengl/GLFWInputImplementation.java
index ed775b99..25c387eb 100644
--- a/JavaApp/src/main/java/org/lwjgl/opengl/GLFWInputImplementation.java
+++ b/JavaApp/src/main/java/org/lwjgl/opengl/GLFWInputImplementation.java
@@ -178,6 +178,7 @@ public class GLFWInputImplementation implements InputImplementation {
last_event_nanos = nanos;
}
public void putKeyboardEvent(int keycode, byte state, int ch, long nanos, boolean repeat) {
+ System.out.println("LWJGL2: debug keyboard=" + keycode + ", state=" + state + ", repeat=" + repeat);
key_down_buffer[keycode] = state;
keyboardEvent.clear();
keyboardEvent.putInt(keycode).put(state).putInt(ch).putLong(nanos).put(repeat ? (byte)1 : (byte)0);
diff --git a/Natives/CMakeLists.txt b/Natives/CMakeLists.txt
index 92d4070d..779d17b3 100644
--- a/Natives/CMakeLists.txt
+++ b/Natives/CMakeLists.txt
@@ -19,5 +19,5 @@ target_link_libraries(pojavexec
"-framework UIKit"
"-framework MetalANGLE"
"-framework CoreGraphics"
- "-framework SafariServices"
+ "-framework AuthenticationServices"
)
diff --git a/Natives/Info.plist b/Natives/Info.plist
index b9e16f3b..3484c48f 100644
--- a/Natives/Info.plist
+++ b/Natives/Info.plist
@@ -66,17 +66,6 @@
- CFBundleURLTypes
-
-
- CFBundleURLName
- net.kdt.pojavlaunch
- CFBundleURLSchemes
-
- ms-xal-00000000402b5328
-
-
-
LSRequiresIPhoneOS
MinimumOSVersion
diff --git a/Natives/JavaLauncher.c b/Natives/JavaLauncher.c
index 3c4be932..c0d1c53e 100644
--- a/Natives/JavaLauncher.c
+++ b/Natives/JavaLauncher.c
@@ -59,10 +59,6 @@ int launchJVM(int argc, char *argv[]) {
setenv("LIBGL_NORMALIZE", "1", 1);
chdir("/var/mobile/Documents/minecraft");
-
- if (chmod("/usr/lib/jvm/java-16-openjdk/bin/java", S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH) == -1) {
- debug("Warning: chmod +x java failed");
- }
char classpath[10000];
diff --git a/Natives/LoginViewController.m b/Natives/LoginViewController.m
index 1c215e08..6ba3f218 100644
--- a/Natives/LoginViewController.m
+++ b/Natives/LoginViewController.m
@@ -1,7 +1,7 @@
#include
#include
-#import
+#import
#import "AppDelegate.h"
#import "LauncherViewController.h"
@@ -39,7 +39,8 @@ void loginAccountInput(UINavigationController *controller, int type, const char*
}
}
-@interface LoginViewController (){
+#pragma mark - LoginViewController
+@interface LoginViewController () {
}
@end
@@ -170,9 +171,44 @@ void loginAccountInput(UINavigationController *controller, int type, const char*
- (void)loginMicrosoft {
NSURL *url = [NSURL URLWithString:@"https://login.live.com/oauth20_authorize.srf?client_id=00000000402b5328&response_type=code&scope=service%3A%3Auser.auth.xboxlive.com%3A%3AMBI_SSL&redirect_url=https%3A%2F%2Flogin.live.com%2Foauth20_desktop.srf"];
- SFSafariViewController *vc = [[SFSafariViewController alloc] initWithURL:url];
- vc.delegate = self;
- [self presentViewController:vc animated:YES completion:nil];
+
+ ASWebAuthenticationSession *authVC =
+ [[ASWebAuthenticationSession alloc] initWithURL:url
+ callbackURLScheme:@"ms-xal-00000000402b5328://"
+ completionHandler:^(NSURL * _Nullable callbackURL,
+ NSError * _Nullable error) {
+ if (callbackURL != nil) {
+ NSString *urlString = [callbackURL absoluteString];
+ NSLog(@"URL returned = %@", [callbackURL absoluteString]);
+
+ if ([urlString containsString:@"/auth/?code="] == YES) {
+ NSArray *components = [urlString componentsSeparatedByString:@"/auth/?code="];
+ dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(void){
+ loginAccountInput(self.navigationController, TYPE_MICROSOFT, [components[1] UTF8String]);
+ });
+ } else {
+ NSArray *components = [urlString componentsSeparatedByString:@"/auth/?error="];
+ if ([components[1] hasPrefix:@"access_denied"] == NO) {
+ NSString *outError = [components[1]
+ stringByReplacingOccurrencesOfString:@"&error_description=" withString:@": "];
+ outError = [outError stringByRemovingPercentEncoding];
+ showDialog(self, @"Error", outError);
+ }
+ }
+ } else {
+ if (error.code != ASWebAuthenticationSessionErrorCodeCanceledLogin) {
+ showDialog(self, @"Error", error.localizedDescription);
+ }
+ }
+ }];
+
+ if (@available(iOS 13.0, *)) {
+ authVC.presentationContextProvider = self;
+ }
+
+ if ([authVC start] == NO) {
+ showDialog(self, @"Error", @"Unable to open Safari");
+ }
}
- (void)loginOffline {
@@ -184,20 +220,6 @@ void loginAccountInput(UINavigationController *controller, int type, const char*
[self.navigationController pushViewController:vc animated:YES];
}
-- (void)safariViewControllerDidFinish:(SFSafariViewController *)controller {
- [controller dismissViewControllerAnimated:true completion:nil];
-}
-
-- (void)msaLoginCallback:(NSNotification *)notification {
- [self dismissViewControllerAnimated:YES completion:nil];
-
- NSDictionary *dict = [notification userInfo];
- NSURL *url = [dict objectForKey:@"url"];
- NSArray *components = [[url absoluteString] componentsSeparatedByString:@"?code="];
- // NSLog(@"URL returned = %@", components[1]);
- loginAccountInput(self.navigationController, TYPE_MICROSOFT, [components[1] UTF8String]);
-}
-
-(void)loginMojangWithUsername:(NSString*)input_username password:(NSString*)input_password {
NSString *input_uuid = [[NSUUID UUID] UUIDString];
@@ -254,8 +276,14 @@ void loginAccountInput(UINavigationController *controller, int type, const char*
[postDataTask resume];
}
+#pragma mark - ASWebAuthenticationPresentationContextProviding
+- (ASPresentationAnchor)presentationAnchorForWebAuthenticationSession:(ASWebAuthenticationSession *)session API_AVAILABLE(ios(13.0)){
+ return UIApplication.sharedApplication.keyWindow;
+}
+
@end
+#pragma mark - LoginListViewController
@interface LoginListViewController () {
}
diff --git a/Natives/SurfaceViewController.m b/Natives/SurfaceViewController.m
index f258abed..f6d3d5fc 100644
--- a/Natives/SurfaceViewController.m
+++ b/Natives/SurfaceViewController.m
@@ -10,6 +10,9 @@
#include "GLES2/gl2.h"
#include "GLES2/gl2ext.h"
+// Debugging purposes
+// #define DEBUG_VISIBLE_TEXT_FIELD
+
#define ADD_BUTTON(NAME, KEY, RECT) \
UIButton *button_##KEY = [UIButton buttonWithType:UIButtonTypeRoundedRect]; \
button_##KEY.autoresizingMask = UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleWidth; \
@@ -42,11 +45,19 @@
#define BTN_RECT 80.0, 30.0
#define BTN_SQUARE 50.0, 50.0
+#define INPUT_SPACE_CHAR @" "
+#define INPUT_SPACE_LENGTH 20
int togglableVisibleButtonIndex = -1;
UIButton* togglableVisibleButtons[100];
+
UIView *touchView;
+#ifdef DEBUG_VISIBLE_TEXT_FIELD
+UILabel *inputLengthView;
+#endif
UITextField *inputView;
+int inputTextLength;
+
BOOL shouldTriggerClick = NO;
int notchOffset;
@@ -108,9 +119,19 @@ int notchOffset;
[touchView addGestureRecognizer:mouseWheelGesture];
}
+#ifndef DEBUG_VISIBLE_TEXT_FIELD
inputView = [[UITextField alloc] initWithFrame:CGRectMake(5 * 3 + 80 * 2, 5, BTN_RECT)];
- inputView.delegate = self;
inputView.backgroundColor = [UIColor colorWithWhite:0.0f alpha:0.0f];
+#else
+ inputView = [[UITextField alloc] initWithFrame:CGRectMake(5 * 3 + 80 * 2, 5 * 2 + 30, 200, 30)];
+ inputView.backgroundColor = [UIColor colorWithWhite:0.0f alpha:0.5f];
+
+ inputLengthView = [[UILabel alloc] initWithFrame:CGRectMake(5 * 2 + 80, 5 * 2 + 30, BTN_RECT)];
+ inputLengthView.text = @"length=?";
+ inputLengthView.backgroundColor = [UIColor colorWithWhite:1.0f alpha:0.6f];
+ [self.view addSubview:inputLengthView];
+#endif
+ inputView.delegate = self;
[inputView addTarget:self action:@selector(inputViewDidChange) forControlEvents:UIControlEventEditingChanged];
[inputView addTarget:self action:@selector(inputViewDidClick) forControlEvents:UIControlEventTouchDown];
@@ -283,6 +304,9 @@ BOOL isNotifRemoved;
int hotbarItem = callback_SurfaceViewController_touchHotbar(location.x * screenScale, location.y * screenScale);
if (hotbarItem == -1) {
+ inputView.text = INPUT_SPACE_CHAR;
+ inputTextLength = 0;
+
Java_org_lwjgl_glfw_CallbackBridge_nativeSendMouseButton(NULL, NULL,
isGrabbing == JNI_TRUE ? GLFW_MOUSE_BUTTON_RIGHT : GLFW_MOUSE_BUTTON_LEFT, 1, 0);
Java_org_lwjgl_glfw_CallbackBridge_nativeSendMouseButton(NULL, NULL,
@@ -317,6 +341,10 @@ BOOL isNotifRemoved;
}
}
+-(BOOL)prefersHomeIndicatorAutoHidden {
+ return YES;
+}
+
-(void)surfaceOnLongpress:(UILongPressGestureRecognizer *)sender
{
CGFloat screenScale = [[UIScreen mainScreen] scale];
@@ -324,6 +352,9 @@ BOOL isNotifRemoved;
int hotbarItem = callback_SurfaceViewController_touchHotbar(location.x * screenScale, location.y * screenScale);
if (sender.state == UIGestureRecognizerStateBegan) {
if (hotbarItem == -1) {
+ inputView.text = INPUT_SPACE_CHAR;
+ inputTextLength = 0;
+
Java_org_lwjgl_glfw_CallbackBridge_nativeSendMouseButton(NULL, NULL, GLFW_MOUSE_BUTTON_LEFT, 1, 0);
} else {
Java_org_lwjgl_glfw_CallbackBridge_nativeSendKey(NULL, NULL, GLFW_KEY_Q, 0, 1, 0);
@@ -338,6 +369,9 @@ BOOL isNotifRemoved;
|| sender.state == UIGestureRecognizerStateEnded)
{
if (hotbarItem == -1) {
+ inputView.text = INPUT_SPACE_CHAR;
+ inputTextLength = 0;
+
Java_org_lwjgl_glfw_CallbackBridge_nativeSendMouseButton(NULL, NULL, GLFW_MOUSE_BUTTON_LEFT, 0, 0);
} else {
Java_org_lwjgl_glfw_CallbackBridge_nativeSendKey(NULL, NULL, GLFW_KEY_Q, 0, 0, 0);
@@ -346,27 +380,86 @@ BOOL isNotifRemoved;
}
}
+NSString* inputStringBefore;
-(void)inputViewDidChange {
- if ([inputView.text length] <= 1) {
+ if ([inputView.text length] < INPUT_SPACE_LENGTH) {
Java_org_lwjgl_glfw_CallbackBridge_nativeSendKey(NULL, NULL, GLFW_KEY_BACKSPACE, 0, 1, 0);
Java_org_lwjgl_glfw_CallbackBridge_nativeSendKey(NULL, NULL, GLFW_KEY_BACKSPACE, 0, 0, 0);
- } else {
- NSString *newText = [inputView.text substringFromIndex:2];
+ inputView.text = [@" " stringByAppendingString:inputView.text];
+
+ if (inputTextLength > 0) {
+ --inputTextLength;
+ }
+
+#ifdef DEBUG_VISIBLE_TEXT_FIELD
+ inputLengthView.text = [@"length=" stringByAppendingFormat:@"%i",
+ inputTextLength];
+#endif
+ } else if ([inputView.text length] > INPUT_SPACE_LENGTH) {
+ NSString *newText = [inputView.text substringFromIndex:INPUT_SPACE_LENGTH];
int charLength = [newText length];
for (int i = 0; i < charLength; i++) {
// Directly convert unichar to jchar which both are in UTF-16 encoding.
Java_org_lwjgl_glfw_CallbackBridge_nativeSendCharMods(NULL, NULL, (jchar) [newText characterAtIndex:i] /* charText[i] */, /* mods */ 0);
+ inputView.text = [inputView.text substringFromIndex:1];
+ if (inputTextLength < INPUT_SPACE_LENGTH) {
+ ++inputTextLength;
+ }
+#ifdef DEBUG_VISIBLE_TEXT_FIELD
+ inputLengthView.text = [@"length=" stringByAppendingFormat:@"%i",
+ inputTextLength];
+#endif
}
+ inputStringBefore = inputView.text;
+ // [inputView.text substringFromIndex:inputTextLength - 1];
+ } else {
+#ifdef DEBUG_VISIBLE_TEXT_FIELD
+ NSLog(@"Compare \"%@\" vs \"%@\"", inputView.text, inputStringBefore);
+#endif
+ for (int i = 0; i < INPUT_SPACE_LENGTH; i++) {
+ if ([inputView.text characterAtIndex:i] != [inputStringBefore characterAtIndex:i]) {
+ NSString *inputStringNow = [inputView.text substringFromIndex:i];
+/*
+ inputView.text = [inputView.text substringToIndex:i];
+ // self notify
+ [self inputViewDidChange];
+
+ inputView.text = [inputView.text stringByAppendingString:inputStringNow];
+ // self notify
+ [self inputViewDidChange];
+*/
+
+ for (int i2 = 0; i2 < [inputStringNow length]; i2++) {
+ Java_org_lwjgl_glfw_CallbackBridge_nativeSendKey(NULL, NULL, GLFW_KEY_BACKSPACE, 0, 1, 0);
+ Java_org_lwjgl_glfw_CallbackBridge_nativeSendKey(NULL, NULL, GLFW_KEY_BACKSPACE, 0, 0, 0);
+ }
+
+ for (int i2 = 0; i2 < [inputStringNow length]; i2++) {
+ Java_org_lwjgl_glfw_CallbackBridge_nativeSendCharMods(NULL, NULL, (jchar) [inputStringNow characterAtIndex:i2], /* mods */ 0);
+ }
+
+ break;
+ }
+ }
+
+#ifdef DEBUG_VISIBLE_TEXT_FIELD
+ inputLengthView.text = @"length =";
+#endif
+ inputStringBefore = inputView.text;
+ // [inputView.text substringFromIndex:inputTextLength - 1];
}
// Reset to default value
- inputView.text = @" ";
+ // inputView.text = INPUT_SPACE_CHAR;
}
-(void)inputViewDidClick {
// Zero the input field so user will no longer able to select text inside.
+#ifndef DEBUG_VISIBLE_TEXT_FIELD
inputView.alpha = 0.0f;
- inputView.text = @" ";
+#endif
+ inputView.text = INPUT_SPACE_CHAR;
+ inputTextLength = 0;
}
-(BOOL)textFieldShouldReturn:(UITextField *)textField {
@@ -384,8 +477,10 @@ ADD_BUTTON_DEF(special_togglebtn) {
for (int i = 0; i < togglableVisibleButtonIndex + 1; i++) {
togglableVisibleButtons[i].hidden = currentVisibility;
}
-
+
+#ifndef DEBUG_VISIBLE_TEXT_FIELD
inputView.hidden = currentVisibility;
+#endif
}
}
diff --git a/Natives/aminimake.sh b/Natives/aminimake.sh
index 82790c31..45ab7233 100644
--- a/Natives/aminimake.sh
+++ b/Natives/aminimake.sh
@@ -6,7 +6,7 @@ set -e
CFLAGS="-fmessage-length=0 -fdiagnostics-show-note-include-stack -fmacro-backtrace-limit=0 -Wno-trigraphs -fpascal-strings -O3 -Wno-missing-field-initializers -Wno-missing-prototypes -Wno-return-type -Wno-missing-braces -Wparentheses -Wswitch -Wno-unused-function -Wno-unused-label -Wno-unused-parameter -Wno-unused-variable -Wunused-value -Wno-empty-body -Wno-uninitialized -Wno-unknown-pragmas -Wno-shadow -Wno-four-char-constants -Wno-conversion -Wno-constant-conversion -Wno-int-conversion -Wno-bool-conversion -Wno-enum-conversion -Wno-float-conversion -Wno-non-literal-null-conversion -Wno-objc-literal-conversion -Wshorten-64-to-32 -Wpointer-sign -Wno-newline-eof -Wl,-rpath,/Applications/PojavLauncher.app/Frameworks -fobjc-arc -x objective-c -Fresources/Frameworks -Iresources/Frameworks/MetalANGLE.framework/Headers -isysroot /var/mobile/theos/sdks/iPhoneOS13.4.sdk"
clang -framework UIKit $CFLAGS -o PojavLauncher main.c log.m JavaLauncher.c
-clang -framework UIKit -framework MetalANGLE -framework CoreGraphics -framework SafariServices -dynamiclib $CFLAGS -o libpojavexec.dylib log.m AppDelegate.m SceneDelegate.m UILauncher.m LauncherViewController.m LoginViewController.m SurfaceViewController.m egl_bridge_ios.m ios_uikit_bridge.m egl_bridge.c input_bridge_v3.c utils.c -DGLES_TESTZ -DUSE_EGLZ
+clang -framework UIKit -framework MetalANGLE -framework CoreGraphics -framework AuthenticationServices -dynamiclib $CFLAGS -o libpojavexec.dylib log.m AppDelegate.m SceneDelegate.m UILauncher.m LauncherViewController.m LoginViewController.m SurfaceViewController.m egl_bridge_ios.m ios_uikit_bridge.m egl_bridge.c input_bridge_v3.c utils.c -DGLES_TESTZ -DUSE_EGLZ
ldid -S../entitlements.xml PojavLauncher
ldid -S../entitlements.xml libpojavexec.dylib
diff --git a/README.md b/README.md
index 5e8340fd..16a4945f 100644
--- a/README.md
+++ b/README.md
@@ -4,6 +4,8 @@
# PojavLauncher_iOS
Minecraft: Java Edition launcher for iOS, based on [PojavLauncher Android](https://github.com/PojavLauncherTeam/PojavLauncher).
+This launcher is now available at Procursus repository, thanks to @Diatrus!
+
## Navigation
- [Introduction](#introduction)
- [Building](#building)
@@ -21,7 +23,8 @@ Minecraft: Java Edition launcher for iOS, based on [PojavLauncher Android](https
## Building
Requirements:
- Mac OS X (tested: 10.15)
-- XCode (tested: 11.7.0)
+- Xcode (tested: 11.7.0)
+- Minimum iOS SDK: 13.4.
- JDK 8 installed
- `gradle` to build Java part.
- `cmake`, `wget`, `ldid`, `dpkg` and `fakeroot` to package.
@@ -66,14 +69,13 @@ chmod 755 *.sh
- Forge (1.13+), Fabric and OptiFine works well.
## Known issues
-- Mojang authentication might not work, but copying logged in account json from Android will work.
- (Some versions) Camera position will be jumped to random location on first time touch.
- It might crash sometimes, but try launch again until you get it works.
## Installing OpenJDK 16
### For Chimera/Odyssey bootstrap
-- Add Procursus repository (https://apt.procurs.us).
-- Find and install `java-16-openjdk`.
+- Add Procursus repository (https://apt.procurs.us) (usually Sileo package manager already come with Procursus repo).
+- Find and install `openjdk-jre`.
### For other jailbreak bootstrap
- Download [openjdk-16-jre.deb](https://github.com/PojavLauncherTeam/PojavLauncher_iOS/releases/tag/v16-openjdk).
@@ -95,9 +97,9 @@ Contributions are welcome! We welcome any type of contribution, not only code. A
## Credits & Third party components and their licenses
- [Contributors of PojavLauncher Android](https://github.com/PojavLauncherTeam/PojavLauncher/graphs/contributors) and here.
-- Apache Commons.
-- jsr305
-- org.json
+- [Apache Commons](https://commons.apache.org): [Apache License 2.0](http://www.apache.org/licenses/LICENSE-2.0.txt).
+- [jsr305](https://code.google.com/p/jsr-305): [3-Clause BSD License](http://opensource.org/licenses/BSD-3-Clause).
+- [org.json](https://github.com/stleary/JSON-java): [The JSON License](https://www.json.org/license.html).
- [Boardwalk](https://github.com/zhuowei/Boardwalk) (JVM Launcher): Unknown License/[Apache License 2.0](https://github.com/zhuowei/Boardwalk/blob/master/LICENSE) or GNU GPLv2.
- [GL4ES](https://github.com/ptitSeb/gl4es) by @lunixbochs @ptitSeb: [MIT License](https://github.com/ptitSeb/gl4es/blob/master/LICENSE).
- [MetalANGLE](https://github.com/kakashidinho/metalangle) by @kakashidinho and ANGLE team: [BSD License 2.0](https://github.com/kakashidinho/metalangle/blob/master/LICENSE).
diff --git a/control b/control
index 627d004b..d78d5c3a 100644
--- a/control
+++ b/control
@@ -5,4 +5,5 @@ Version: 1.1
Depends: openjdk-16-jre
Section: Games
Priority: optional
+Homepage: https://github.com/PojavLauncherTeam/PojavLauncher_iOS
Description: Minecraft: Java Edition launcher for iOS, based on PojavLauncher Android.