Many changes and fixes

Changes:
- Decreased multithreaded download max threads to 10
- Moved launcher buttons to match Android UI
- Moved UIKit hooking code to separate file
- The Launcher tab is now marked as under construction.
- Updated README.md to avoid confusion between self-JIT and auto-JIT.

New settings section: UI debugging
- Unlock iPadOS UI: allow iPhone users to unlock every iPadOS-only
features (floating keyboard, popover alert, sheet-styled view
controllers, etc.)
- Show layout bounds, like the one in Android's developer setting
- Show layout overlapping

Fixes:
- App container data is not shown in the Files app due to
`no-container` entitlement, replaced it with `no-sandbox`.
- Ignore jinput-platform libraries to avoid download error
- Multithreaded assets download breaks
- `Send your logs` crashes on iPadOS
This commit is contained in:
Duy Tran Khanh committed 2022-09-22 09:52:56 +07:00
1 parent f404ddd2cb
commit b806c5df3c
14 files changed
+266 -147

No files matched your search

+1
View File
@@ -91,6 +91,7 @@ add_executable(PojavLauncher
log.m log.m
JavaLauncher.m JavaLauncher.m
external/fishhook/fishhook.c external/fishhook/fishhook.c
UIKit+hook.m
authenticator/BaseAuthenticator.m authenticator/BaseAuthenticator.m
authenticator/LocalAuthenticator.m authenticator/LocalAuthenticator.m
+2
View File
@@ -115,5 +115,7 @@
</array> </array>
<key>UIViewControllerBasedStatusBarAppearance</key> <key>UIViewControllerBasedStatusBarAppearance</key>
<false/> <false/>
<key>UISupportsDocumentBrowser</key>
<true/>
</dict> </dict>
</plist> </plist>
+28 -11
View File
@@ -3,13 +3,17 @@
NSMutableDictionary *prefDict; NSMutableDictionary *prefDict;
NSString* prefPath; NSString* prefPath;
// developer debug dict
NSMutableDictionary *debugPrefDict;
// environment variables dict // environment variables dict
NSMutableDictionary *envPrefDict; NSMutableDictionary *envPrefDict;
// warnings dict // warnings dict
NSMutableDictionary *warnPrefDict; NSMutableDictionary *warnPrefDict;
id getPreference(NSString* key) { id getPreference(NSString* key) {
if (!(envPrefDict[key] == [NSNull null] || envPrefDict[key] == nil)) { if (!(debugPrefDict[key] == [NSNull null] || debugPrefDict[key] == nil)) {
return debugPrefDict[key];
} else if (!(envPrefDict[key] == [NSNull null] || envPrefDict[key] == nil)) {
return envPrefDict[key]; return envPrefDict[key];
} else if (!(warnPrefDict[key] == [NSNull null] || warnPrefDict[key] == nil)) { } else if (!(warnPrefDict[key] == [NSNull null] || warnPrefDict[key] == nil)) {
return warnPrefDict[key]; return warnPrefDict[key];
@@ -58,7 +62,10 @@ void setDefaultValueForPref(NSMutableDictionary *dict, NSString* key, id value)
} }
void setPreference(NSString* key, id value) { void setPreference(NSString* key, id value) {
if (!(envPrefDict[key] == [NSNull null] || envPrefDict[key] == nil)) { if (!(debugPrefDict[key] == [NSNull null] || debugPrefDict[key] == nil)) {
debugPrefDict[key] = value;
prefDict[@"debugs"] = debugPrefDict;
} else if (!(envPrefDict[key] == [NSNull null] || envPrefDict[key] == nil)) {
envPrefDict[key] = value; envPrefDict[key] = value;
prefDict[@"env_vars"] = envPrefDict; prefDict[@"env_vars"] = envPrefDict;
} else if (!(warnPrefDict[key] == [NSNull null] || warnPrefDict[key] == nil)) { } else if (!(warnPrefDict[key] == [NSNull null] || warnPrefDict[key] == nil)) {
@@ -79,11 +86,17 @@ void fillDefaultWarningDict() {
setDefaultValueForPref(warnPrefDict, @"java_warn", @YES); setDefaultValueForPref(warnPrefDict, @"java_warn", @YES);
setDefaultValueForPref(warnPrefDict, @"demo_warn", @YES); setDefaultValueForPref(warnPrefDict, @"demo_warn", @YES);
setDefaultValueForPref(warnPrefDict, @"jb_warn", @YES); setDefaultValueForPref(warnPrefDict, @"jb_warn", @YES);
setDefaultValueForPref(warnPrefDict, @"customctrl_warn", @YES);
setDefaultValueForPref(warnPrefDict, @"int_warn", @YES); setDefaultValueForPref(warnPrefDict, @"int_warn", @YES);
setDefaultValueForPref(warnPrefDict, @"auto_ram_warn", @YES); setDefaultValueForPref(warnPrefDict, @"auto_ram_warn", @YES);
} }
NSMutableDictionary* getDictionarySafe(NSString* key) {
if (prefDict[key] == nil) {
return [[NSMutableDictionary alloc] init];
}
return prefDict[key];
}
void loadPreferences(BOOL reset) { void loadPreferences(BOOL reset) {
assert(getenv("POJAV_HOME")); assert(getenv("POJAV_HOME"));
prefPath = [@(getenv("POJAV_HOME")) prefPath = [@(getenv("POJAV_HOME"))
@@ -91,16 +104,14 @@ void loadPreferences(BOOL reset) {
NSFileManager *fileManager = [NSFileManager defaultManager]; NSFileManager *fileManager = [NSFileManager defaultManager];
prefDict = [NSMutableDictionary dictionaryWithContentsOfFile:prefPath]; prefDict = [NSMutableDictionary dictionaryWithContentsOfFile:prefPath];
if (reset || ![fileManager fileExistsAtPath:prefPath]) { if (reset) {
[prefDict removeAllObjects];
} else if (![fileManager fileExistsAtPath:prefPath]) {
prefDict = [[NSMutableDictionary alloc] init]; prefDict = [[NSMutableDictionary alloc] init];
envPrefDict = [[NSMutableDictionary alloc] init];
warnPrefDict = [[NSMutableDictionary alloc] init];
} else {
envPrefDict = prefDict[@"env_vars"];
warnPrefDict = prefDict[@"warnings"];
} }
debugPrefDict = getDictionarySafe(@"debugs");
assert(prefDict); envPrefDict = getDictionarySafe(@"env_vars");
warnPrefDict = getDictionarySafe(@"warnings");
// set default value // set default value
setDefaultValueForPref(envPrefDict, @"resolution", @(100)); setDefaultValueForPref(envPrefDict, @"resolution", @(100));
@@ -132,9 +143,15 @@ void loadPreferences(BOOL reset) {
setDefaultValueForPref(prefDict, @"disable_home_symlink", @YES); setDefaultValueForPref(prefDict, @"disable_home_symlink", @YES);
} }
// Debug settings
setDefaultValueForPref(debugPrefDict, @"debug_ipad_ui", @(UIDevice.currentDevice.userInterfaceIdiom == UIUserInterfaceIdiomPad));
setDefaultValueForPref(debugPrefDict, @"debug_show_layout_bounds", @NO);
setDefaultValueForPref(debugPrefDict, @"debug_show_layout_overlap", @NO);
// Migrate some prefs // Migrate some prefs
setPreference(@"java_home", [getPreference(@"java_home") lastPathComponent]); setPreference(@"java_home", [getPreference(@"java_home") lastPathComponent]);
prefDict[@"debugs"] = debugPrefDict;
prefDict[@"env_vars"] = envPrefDict; prefDict[@"env_vars"] = envPrefDict;
prefDict[@"warnings"] = warnPrefDict; prefDict[@"warnings"] = warnPrefDict;
+23 -1
View File
@@ -41,7 +41,7 @@ typedef void(^CreateView)(UITableViewCell *, NSString *, NSDictionary *);
return self.navigationController != nil; return self.navigationController != nil;
}; };
self.prefSections = @[@"general", @"video", @"control", @"java"]; self.prefSections = @[@"general", @"video", @"control", @"java", @"debug"];
self.prefContents = @[ self.prefContents = @[
@[ @[
@@ -209,6 +209,28 @@ typedef void(^CreateView)(UITableViewCell *, NSString *, NSDictionary *);
}, },
@"warnKey": @"mem_warn" @"warnKey": @"mem_warn"
} }
], @[
@{@"key": @"debug_ipad_ui",
@"hasDetail": @YES,
@"icon": @"ipad",
@"type": self.typeSwitch,
@"enableCondition": whenNotInGame
},
@{@"key": @"debug_show_layout_bounds",
@"hasDetail": @YES,
@"icon": @"square.dashed",
@"type": self.typeSwitch,
@"enableCondition": whenNotInGame,
@"requestReload": @YES
},
@{@"key": @"debug_show_layout_overlap",
@"hasDetail": @YES,
@"icon": @"square.on.square",
@"type": self.typeSwitch,
@"enableCondition": ^BOOL(){
return [getPreference(@"debug_show_layout_bounds") boolValue] && whenNotInGame();
}
}
] ]
]; ];
+1
View File
@@ -18,6 +18,7 @@
LauncherMenuViewController *masterVc = [[LauncherMenuViewController alloc] init]; LauncherMenuViewController *masterVc = [[LauncherMenuViewController alloc] init];
UINavigationController *detailVc = [[UINavigationController alloc] init]; UINavigationController *detailVc = [[UINavigationController alloc] init];
detailVc.toolbarHidden = NO;
self.presentsWithGesture = YES; self.presentsWithGesture = YES;
self.preferredDisplayMode = UISplitViewControllerDisplayModeOneBesideSecondary; self.preferredDisplayMode = UISplitViewControllerDisplayModeOneBesideSecondary;
+55 -75
View File
@@ -8,6 +8,8 @@
#include "utils.h" #include "utils.h"
#define AUTORESIZE_MASKS UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin
@interface LauncherViewController () <UIDocumentPickerDelegate, UIPickerViewDataSource, UIPickerViewDelegate, UIPopoverPresentationControllerDelegate> { @interface LauncherViewController () <UIDocumentPickerDelegate, UIPickerViewDataSource, UIPickerViewDelegate, UIPopoverPresentationControllerDelegate> {
} }
@@ -29,28 +31,25 @@ int versionSelectedAt = 0;
[self setNeedsUpdateOfScreenEdgesDeferringSystemGestures]; [self setNeedsUpdateOfScreenEdgesDeferringSystemGestures];
[self setNeedsUpdateOfHomeIndicatorAutoHidden]; [self setNeedsUpdateOfHomeIndicatorAutoHidden];
CGRect screenBounds = self.view.frame; UIToolbar *toolbar = self.navigationController.toolbar;
CGFloat splitWidth = toolbar.frame.size.width / 3;
int width = (int) roundf(screenBounds.size.width);
int height = (int) roundf(screenBounds.size.height) - self.navigationController.navigationBar.frame.size.height;
UIScrollView *scrollView = [[UIScrollView alloc] initWithFrame:self.view.frame]; UIScrollView *scrollView = [[UIScrollView alloc] initWithFrame:self.view.frame];
[self.view addSubview:scrollView]; [self.view addSubview:scrollView];
scrollView.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth; scrollView.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth;
UILabel *versionTextView = [[UILabel alloc] initWithFrame:CGRectMake(4.0, 4.0, 0.0, 0.0)]; UILabel *versionTextView = [[UILabel alloc] initWithFrame:CGRectMake(4.0, 4.0, 0.0, 0.0)];
versionTextView.text = @"Minecraft version: "; versionTextView.text = @"[under construction]";
versionTextView.numberOfLines = 0; versionTextView.numberOfLines = 0;
[versionTextView sizeToFit]; [versionTextView sizeToFit];
[scrollView addSubview:versionTextView]; [scrollView addSubview:versionTextView];
versionTextField = [[UITextField alloc] initWithFrame:CGRectMake(versionTextView.bounds.size.width + 4.0, 4.0, width - versionTextView.bounds.size.width - 8.0, height - 58.0)]; versionTextField = [[UITextField alloc] initWithFrame:CGRectMake(0, 4, splitWidth, toolbar.frame.size.height/2 - 4)];
[versionTextField addTarget:versionTextField action:@selector(resignFirstResponder) forControlEvents:UIControlEventEditingDidEndOnExit]; [versionTextField addTarget:versionTextField action:@selector(resignFirstResponder) forControlEvents:UIControlEventEditingDidEndOnExit];
versionTextField.autoresizingMask = AUTORESIZE_MASKS;
versionTextField.placeholder = @"Specify version..."; versionTextField.placeholder = @"Specify version...";
versionTextField.text = (NSString *) getPreference(@"selected_version"); versionTextField.text = (NSString *) getPreference(@"selected_version");
versionTextField.contentVerticalAlignment = UIControlContentVerticalAlignmentTop; versionTextField.textAlignment = NSTextAlignmentCenter;
versionTextField.contentHorizontalAlignment = UIControlContentHorizontalAlignmentLeft;
self.versionList = [[NSMutableArray alloc] init]; self.versionList = [[NSMutableArray alloc] init];
versionPickerView = [[UIPickerView alloc] init]; versionPickerView = [[UIPickerView alloc] init];
@@ -75,40 +74,47 @@ int versionSelectedAt = 0;
versionTextField.inputAccessoryView = versionPickToolbar; versionTextField.inputAccessoryView = versionPickToolbar;
versionTextField.inputView = versionPickerView; versionTextField.inputView = versionPickerView;
[scrollView addSubview:versionTextField]; [toolbar addSubview:versionTextField];
if (@available(iOS 14.0, *)) { self.progressViewMain = [[UIProgressView alloc] initWithFrame:CGRectMake(0, 0, toolbar.frame.size.width, 4.0)];
// use UIMenu self.progressViewSub = [[UIProgressView alloc] initWithFrame:CGRectMake(0, toolbar.frame.size.height - 4.0, toolbar.frame.size.width, 4.0)];
self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithImage:[[UIImage systemImageNamed:@"ellipsis.circle"] imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate] style:UIBarButtonItemStyleDone target:self action:@selector(displayOptions:)]; self.progressViewMain.autoresizingMask = self.progressViewSub.autoresizingMask = AUTORESIZE_MASKS;
UIAction *option1 = [UIAction actionWithTitle:@"Launch a mod installer" image:[[UIImage systemImageNamed:@"internaldrive"] imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate] identifier:nil self.progressViewMain.hidden = self.progressViewSub.hidden = YES;
handler:^(__kindof UIAction * _Nonnull action) {[self enterModInstaller:self.navigationItem.rightBarButtonItem];}]; [toolbar addSubview:self.progressViewMain];
UIAction *option2 = [UIAction actionWithTitle:@"Custom controls" image:[[UIImage systemImageNamed:@"dpad.right.fill"] imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate] identifier:nil [toolbar addSubview:self.progressViewSub];
handler:^(__kindof UIAction * _Nonnull action) {[self enterCustomControls];}];
UIMenu *menu = [UIMenu menuWithTitle:@"" image:nil identifier:nil
options:UIMenuOptionsDisplayInline children:@[option1, option2]];
self.navigationItem.rightBarButtonItem.action = nil;
self.navigationItem.rightBarButtonItem.primaryAction = nil;
self.navigationItem.rightBarButtonItem.menu = menu;
} else {
self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:@"Options" style:UIBarButtonItemStyleDone target:self action:@selector(displayOptions:)];
}
self.progressViewMain = [[UIProgressView alloc] initWithFrame:CGRectMake(4.0, height - 58.0, width - 8.0, 6.0)]; self.buttonInstall = [UIButton buttonWithType:UIButtonTypeSystem];
self.progressViewSub = [[UIProgressView alloc] initWithFrame:CGRectMake(4.0, height - 58.0, width - 8.0, 6.0)];
self.progressViewMain.alpha = 0.6;
self.progressViewSub.alpha = 0.4;
[scrollView addSubview:self.progressViewSub];
[scrollView addSubview:self.progressViewMain];
self.buttonInstall = [UIButton buttonWithType:UIButtonTypeRoundedRect];
self.buttonInstall.enabled = NO; self.buttonInstall.enabled = NO;
[self.buttonInstall setTitle:@"Play" forState:UIControlStateNormal]; [self.buttonInstall setTitle:NSLocalizedString(@"Play", nil) forState:UIControlStateNormal];
self.buttonInstall.frame = CGRectMake(10.0, height - 54.0, 100.0, 50.0); self.buttonInstall.autoresizingMask = AUTORESIZE_MASKS;
self.buttonInstall.backgroundColor = [UIColor colorWithRed:54/255.0 green:176/255.0 blue:48/255.0 alpha:1.0];
self.buttonInstall.layer.cornerRadius = 5;
self.buttonInstall.frame = CGRectMake(splitWidth, 6.0, splitWidth, toolbar.frame.size.height - 12.0);
self.buttonInstall.tintColor = UIColor.whiteColor;
[self.buttonInstall addTarget:self action:@selector(launchMinecraft:) forControlEvents:UIControlEventTouchUpInside]; [self.buttonInstall addTarget:self action:@selector(launchMinecraft:) forControlEvents:UIControlEventTouchUpInside];
[scrollView addSubview:self.buttonInstall]; [toolbar addSubview:self.buttonInstall];
self.progressText = [[UILabel alloc] initWithFrame:CGRectMake(120.0, height - 54.0, width - 124.0, 50.0)]; UIButton *buttonCustomControls = [UIButton buttonWithType:UIButtonTypeSystem];
[scrollView addSubview:self.progressText]; [buttonCustomControls setTitle:NSLocalizedString(@"launcher.menu.custom_controls", nil) forState:UIControlStateNormal];
buttonCustomControls.autoresizingMask = AUTORESIZE_MASKS;
buttonCustomControls.frame = CGRectMake(0, toolbar.frame.size.height/2, splitWidth, toolbar.frame.size.height/2);
[buttonCustomControls addTarget:self action:@selector(enterCustomControls) forControlEvents:UIControlEventTouchUpInside];
[toolbar addSubview:buttonCustomControls];
UIButton *buttonInstallJar = [UIButton buttonWithType:UIButtonTypeSystem];
[buttonInstallJar setTitle:NSLocalizedString(@"launcher.menu.install_jar", nil) forState:UIControlStateNormal];
buttonInstallJar.autoresizingMask = AUTORESIZE_MASKS;
buttonInstallJar.frame = CGRectMake(splitWidth*2, toolbar.frame.size.height/2, splitWidth, toolbar.frame.size.height/2);
[buttonInstallJar addTarget:self action:@selector(enterModInstaller) forControlEvents:UIControlEventTouchUpInside];
[toolbar addSubview:buttonInstallJar];
self.progressText = [[UILabel alloc] initWithFrame:CGRectMake(0, 4, toolbar.frame.size.width, 20)];
self.progressText.adjustsFontSizeToFitWidth = YES;
self.progressText.autoresizingMask = AUTORESIZE_MASKS;
self.progressText.font = [self.progressText.font fontWithSize:16];
self.progressText.textAlignment = NSTextAlignmentCenter;
self.progressText.userInteractionEnabled = NO;
[toolbar addSubview:self.progressText];
} }
- (void)viewWillAppear:(BOOL)animated { - (void)viewWillAppear:(BOOL)animated {
@@ -216,45 +222,14 @@ int versionSelectedAt = 0;
[self reloadVersionList:sender.selectedSegmentIndex]; [self reloadVersionList:sender.selectedSegmentIndex];
} }
#pragma mark - Button click events #pragma mark - Options
- (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:self.navigationItem.rightBarButtonItem];}];
UIAlertAction *option2 = [UIAlertAction actionWithTitle:@"Custom controls" style:UIAlertActionStyleDefault
handler:^(UIAlertAction * _Nonnull action) {[self enterCustomControls];}];
fullAlert.popoverPresentationController.barButtonItem = sender;
[self presentViewController:fullAlert animated:YES completion:nil];
[fullAlert addAction:option1];
[fullAlert addAction:option2];
}
}
- (void)enterCustomControls { - (void)enterCustomControls {
if (![getPreference(@"customctrl_warn") boolValue]) { CustomControlsViewController *vc = [[CustomControlsViewController alloc] init];
CustomControlsViewController *vc = [[CustomControlsViewController alloc] init]; vc.modalPresentationStyle = UIModalPresentationOverFullScreen;
vc.modalPresentationStyle = UIModalPresentationOverFullScreen; [self presentViewController:vc animated:YES completion:nil];
[self presentViewController:vc animated:YES completion:nil];
return;
}
setPreference(@"customctrl_warn", @(NO));
UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"Warning" message:@"This option is unfinished, some might be incomplete or missing." preferredStyle:UIAlertControllerStyleActionSheet];
if (alert.popoverPresentationController != nil) {
alert.popoverPresentationController.sourceView = self.view;
alert.popoverPresentationController.sourceRect = CGRectMake(self.view.frame.size.width-10.0, 0, 10, 10);
}
UIAlertAction *ok = [UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleCancel handler:^(UIAlertAction * _Nonnull action) {
[self enterCustomControls];
}];
[self presentViewController:alert animated:YES completion:nil];
[alert addAction:ok];
} }
- (void)enterModInstaller:(UIBarButtonItem*)sender { - (void)enterModInstaller {
UIDocumentPickerViewController *documentPicker = [[UIDocumentPickerViewController alloc] initWithDocumentTypes:@[@"com.sun.java-archive"] UIDocumentPickerViewController *documentPicker = [[UIDocumentPickerViewController alloc] initWithDocumentTypes:@[@"com.sun.java-archive"]
inMode:UIDocumentPickerModeImport]; inMode:UIDocumentPickerModeImport];
documentPicker.delegate = self; documentPicker.delegate = self;
@@ -277,7 +252,9 @@ int versionSelectedAt = 0;
return; return;
} }
sender.alpha = 0.5;
sender.enabled = NO; sender.enabled = NO;
self.progressViewMain.hidden = self.progressViewSub.hidden = NO;
NSObject *object = [self.versionList objectAtIndex:[versionPickerView selectedRowInComponent:0]]; NSObject *object = [self.versionList objectAtIndex:[versionPickerView selectedRowInComponent:0]];
@@ -288,7 +265,10 @@ int versionSelectedAt = 0;
self.progressViewMain.observedProgress = mainProgress; self.progressViewMain.observedProgress = mainProgress;
self.progressViewSub.observedProgress = progress; self.progressViewSub.observedProgress = progress;
if (stage == nil) { if (stage == nil) {
sender.alpha = 1;
sender.enabled = YES; sender.enabled = YES;
self.progressText.text = nil;
self.progressViewMain.hidden = self.progressViewSub.hidden = YES;
if (mainProgress != nil) { if (mainProgress != nil) {
UIKit_launchMinecraftSurfaceVC(); UIKit_launchMinecraftSurfaceVC();
} }
+4 -8
View File
@@ -24,15 +24,10 @@
extern NSMutableDictionary *prefDict; extern NSMutableDictionary *prefDict;
#pragma mark - LoginViewController #pragma mark - LoginViewController
@interface LoginViewController () <ASWebAuthenticationPresentationContextProviding>{ @interface LoginViewController () <ASWebAuthenticationPresentationContextProviding> {}
}
@property (nonatomic, strong) ASWebAuthenticationSession *authVC;
@property (nonatomic, strong) UIActivityViewController *activityViewController;
@end @end
@implementation LoginViewController @implementation LoginViewController
@synthesize authVC;
@synthesize activityViewController;
- (void)viewDidLoad { - (void)viewDidLoad {
[super viewDidLoad]; [super viewDidLoad];
@@ -268,7 +263,7 @@ extern NSMutableDictionary *prefDict;
- (void)loginMicrosoft { - (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"]; 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"];
authVC = ASWebAuthenticationSession *authVC =
[[ASWebAuthenticationSession alloc] initWithURL:url [[ASWebAuthenticationSession alloc] initWithURL:url
callbackURLScheme:@"ms-xal-00000000402b5328" callbackURLScheme:@"ms-xal-00000000402b5328"
completionHandler:^(NSURL * _Nullable callbackURL, completionHandler:^(NSURL * _Nullable callbackURL,
@@ -434,7 +429,8 @@ extern NSMutableDictionary *prefDict;
{ {
NSString *latestlogPath = [NSString stringWithFormat:@"file://%s/latestlog.old.txt", getenv("POJAV_HOME")]; NSString *latestlogPath = [NSString stringWithFormat:@"file://%s/latestlog.old.txt", getenv("POJAV_HOME")];
NSLog(@"Path is %@", latestlogPath); NSLog(@"Path is %@", latestlogPath);
activityViewController = [[UIActivityViewController alloc] initWithActivityItems:@[@"latestlog.txt", [NSURL URLWithString:latestlogPath]] applicationActivities:nil]; UIActivityViewController *activityViewController = [[UIActivityViewController alloc] initWithActivityItems:@[@"latestlog.txt", [NSURL URLWithString:latestlogPath]] applicationActivities:nil];
activityViewController.popoverPresentationController.barButtonItem = self.navigationItem.rightBarButtonItems[0];
[self presentViewController:activityViewController animated:YES completion:nil]; [self presentViewController:activityViewController animated:YES completion:nil];
} }
+6 -2
View File
@@ -283,6 +283,7 @@ static AFURLSessionManager* manager;
library[@"skip"] = @( library[@"skip"] = @(
// Exclude platform-dependant libraries // Exclude platform-dependant libraries
library[@"downloads"][@"classifiers"] != nil || library[@"downloads"][@"classifiers"] != nil ||
library[@"natives"] != nil ||
// Exclude LWJGL libraries // Exclude LWJGL libraries
[library[@"name"] hasPrefix:@"org.lwjgl"] [library[@"name"] hasPrefix:@"org.lwjgl"]
); );
@@ -379,12 +380,15 @@ static AFURLSessionManager* manager;
dispatch_group_t group = dispatch_group_create(); dispatch_group_t group = dispatch_group_create();
int downloadIndex = -1; int downloadIndex = -1;
__block int jobsAvailable = 20; __block int jobsAvailable = 10;
for (NSString *name in assets[@"objects"]) { for (NSString *name in assets[@"objects"]) {
if (jobsAvailable < 0) { if (jobsAvailable < 0) {
break; break;
} else if (jobsAvailable == 0) { } else if (jobsAvailable == 0) {
dispatch_group_wait(group, DISPATCH_TIME_FOREVER); //dispatch_group_wait(group, DISPATCH_TIME_FOREVER);
while (jobsAvailable == 0) {
usleep(50000);
}
} }
NSString *hash = assets[@"objects"][name][@"hash"]; NSString *hash = assets[@"objects"][name][@"hash"];
+124
View File
@@ -0,0 +1,124 @@
#import <UIKit/UIKit.h>
#import <objc/runtime.h>
#import "LauncherPreferences.h"
void swizzle(Class class, SEL originalAction, SEL swizzledAction) {
method_exchangeImplementations(class_getInstanceMethod(class, originalAction), class_getInstanceMethod(class, swizzledAction));
}
__attribute__((constructor)) void hookConstructor(void) {
swizzle(UIDevice.class, @selector(userInterfaceIdiom), @selector(hook_userInterfaceIdiom));
swizzle(UIToolbar.class, @selector(sizeThatFits:), @selector(hook_sizeThatFits:));
swizzle(UIView.class, @selector(didMoveToSuperview), @selector(hook_didMoveToSuperview));
swizzle(UIView.class, @selector(setFrame:), @selector(hook_setFrame:));
}
@implementation UIDevice(hook)
- (UIUserInterfaceIdiom)hook_userInterfaceIdiom {
id value = getPreference(@"debug_ipad_ui");
if (value == nil) {
return self.hook_userInterfaceIdiom;
}
return [value boolValue] ? UIUserInterfaceIdiomPad : UIUserInterfaceIdiomPhone;
}
@end
@implementation UIToolbar(hook)
- (CGSize)hook_sizeThatFits:(CGSize)size {
// Make the toolbar taller
CGSize ret = [self hook_sizeThatFits:size];
ret.height += 50;
return ret;
}
@end
@implementation UIView(hook)
const NSString *cornerLayerKey = @"cornerLayer";
- (void)updateCornerLayer {
CAShapeLayer *cornerLayer = objc_getAssociatedObject(self, &cornerLayerKey);
NSNumber *cornerWidth = @5;
NSNumber *cornerSpaceW = @(self.frame.size.width-10);
NSNumber *cornerSpaceH = @(self.frame.size.height-10);
cornerLayer.lineDashPattern = @[cornerWidth,cornerSpaceW,cornerWidth,@0,cornerWidth,cornerSpaceH,cornerWidth,@0,cornerWidth,cornerSpaceW,cornerWidth,@0,cornerWidth,cornerSpaceH,cornerWidth];
cornerLayer.path = [UIBezierPath bezierPathWithRect:CGRectMake(0, 0, self.frame.size.width, self.frame.size.height)].CGPath;
if ([getPreference(@"debug_show_layout_overlap") boolValue]) {
cornerLayer.fillColor = [UIColor.yellowColor colorWithAlphaComponent:0.1].CGColor;
} else {
cornerLayer.fillColor = nil;
}
}
- (void)hook_didMoveToSuperview {
if ([getPreference(@"debug_show_layout_bounds") boolValue]) {
self.layer.borderWidth = 1;
self.layer.borderColor = UIColor.redColor.CGColor;
if (self.layer.sublayers.count == 0) {
CAShapeLayer *cornerLayer = [CAShapeLayer layer];
cornerLayer.strokeColor = UIColor.blueColor.CGColor;
cornerLayer.lineWidth = 1;
[self.layer addSublayer:cornerLayer];
objc_setAssociatedObject(self, &cornerLayerKey, cornerLayer, OBJC_ASSOCIATION_ASSIGN);
[self updateCornerLayer];
}
}
[self hook_didMoveToSuperview];
}
- (void)hook_setFrame:(CGRect)frame {
[self hook_setFrame:frame];
[self updateCornerLayer];
}
@end
@implementation UIWindow(hook)
// Simulate safe area on iPhones without notch
/*
- (UIEdgeInsets)safeAreaInsets {
return UIEdgeInsetsMake(0, 44, 21, 44);
}
*/
- (UIViewController *)visibleViewController {
UIViewController *current = self.rootViewController;
while (current.presentedViewController) {
if ([current.presentedViewController isKindOfClass:UIAlertController.class] || [current.presentedViewController isKindOfClass:NSClassFromString(@"UIInputWindowController")]) {
break;
}
current = current.presentedViewController;
}
if ([current isKindOfClass:UINavigationController.class]) {
return [(UINavigationController *)self.rootViewController visibleViewController];
} else {
return current;
}
}
@end
// This forces the navigation bar to keep its height (44dp) in landscape
@implementation UINavigationBar(forceFullHeightInLandscape)
- (BOOL)forceFullHeightInLandscape {
return YES;
//UIScreen.mainScreen.traitCollection.userInterfaceIdiom == UIUserInterfaceIdiomPhone;
}
@end
UIWindow* currentWindow() {
id delegate = UIApplication.sharedApplication.delegate;
if (@available(iOS 13.0, *)) {
delegate = UIApplication.sharedApplication.connectedScenes.anyObject.delegate;
}
return [delegate window];
}
UIViewController* currentVC() {
return currentWindow().visibleViewController;
}
+18
View File
@@ -8,6 +8,12 @@
"game.menu.log_output" = "Log output"; "game.menu.log_output" = "Log output";
"game.menu.custom_controls" = "Custom controls"; "game.menu.custom_controls" = "Custom controls";
// The options button at the top-right corner on iOS 12
"Options" = "Options";
// The play button
"Play" = "Play";
// Version categories // Version categories
"Installed" = "Installed"; "Installed" = "Installed";
"Snapshot" = "Snapshot"; "Snapshot" = "Snapshot";
@@ -17,6 +23,9 @@
"init.migrateDir" = "The PojavLauncher data directory is now %@. All of your existing data has been moved to the new location."; "init.migrateDir" = "The PojavLauncher data directory is now %@. All of your existing data has been moved to the new location.";
"launcher.menu.custom_controls" = "Custom controls";
"launcher.menu.install_jar" = "Install .jar";
"login.error.username.outOfRange" = "Username must be at least 3 characters and maximum 16 characters"; "login.error.username.outOfRange" = "Username must be at least 3 characters and maximum 16 characters";
"login.alert.field.username" = "Username"; "login.alert.field.username" = "Username";
@@ -80,6 +89,8 @@
"preference.section.video" = "Video Settings"; "preference.section.video" = "Video Settings";
"preference.section.footer.video" = "Auto renderer allows Minecraft to decide which renderer to use. Decreasing resolution reduces GPU workload for better performance."; "preference.section.footer.video" = "Auto renderer allows Minecraft to decide which renderer to use. Decreasing resolution reduces GPU workload for better performance.";
"preference.section.control" = "Control customization"; "preference.section.control" = "Control customization";
"preference.section.debug" = "UI Debugging settings";
"preference.section.footer.debug" = "Aside from debugging, these settings may be useful for custom controls. You may need to restart the launcher for changes to take effect.";
//"preference.section.footer.control" = ""; //"preference.section.footer.control" = "";
"preference.section.java" = "Java Tweaks"; "preference.section.java" = "Java Tweaks";
//"preference.section.footer.java" = ""; //"preference.section.footer.java" = "";
@@ -141,3 +152,10 @@
"preference.warn.allocated_memory" = "Due to limitations in the operating system itself, this option may cause instability at this and higher values. Proceed with caution."; "preference.warn.allocated_memory" = "Due to limitations in the operating system itself, this option may cause instability at this and higher values. Proceed with caution.";
"preference.title.custom_env" = "Environment variables"; "preference.title.custom_env" = "Environment variables";
"preference.detail.custom_env" = "This option is under construction."; "preference.detail.custom_env" = "This option is under construction.";
"preference.title.debug_ipad_ui" = "Unlock iPadOS UI";
"preference.detail.debug_ipad_ui" = "Unlock iPad-exlusive UI (alert, keyboard, etc.) if enabled or iPhone UI if disabled.";
"preference.title.debug_show_layout_bounds" = "Show layout bounds";
"preference.detail.debug_show_layout_bounds" = "Show clip bounds, margins";
"preference.title.debug_show_layout_overlap" = "Show layout overlapping";
"preference.detail.debug_show_layout_overlap" = "Overlay every view with a transparent color to reveal overlapping views.";
+2 -2
View File
@@ -124,7 +124,7 @@ void init_logDeviceAndVer(char *argument) {
regLog("[Pre-init] Entitlements availability:"); regLog("[Pre-init] Entitlements availability:");
printEntitlementAvailability(@"com.apple.developer.kernel.extended-virtual-addressing"); printEntitlementAvailability(@"com.apple.developer.kernel.extended-virtual-addressing");
printEntitlementAvailability(@"com.apple.developer.kernel.increased-memory-limit"); printEntitlementAvailability(@"com.apple.developer.kernel.increased-memory-limit");
printEntitlementAvailability(@"com.apple.private.security.no-container"); printEntitlementAvailability(@"com.apple.private.security.no-sandbox");
printEntitlementAvailability(@"dynamic-codesigning"); printEntitlementAvailability(@"dynamic-codesigning");
} }
@@ -341,7 +341,7 @@ int main(int argc, char * argv[]) {
init_migrateToPlist("java_args", "overrideargs.txt"); init_migrateToPlist("java_args", "overrideargs.txt");
// If sandbox is disabled, W^X JIT can be enabled by PojavLauncher itself // If sandbox is disabled, W^X JIT can be enabled by PojavLauncher itself
if (getEntitlementValue(@"com.apple.private.security.no-container")) { if (getEntitlementValue(@"com.apple.private.security.no-sandbox")) {
NSLog(@"[Pre-init] Sandbox is disabled, trying to enable JIT"); NSLog(@"[Pre-init] Sandbox is disabled, trying to enable JIT");
int pid; int pid;
int ret = posix_spawnp(&pid, argv[0], NULL, NULL, argv, environ); int ret = posix_spawnp(&pid, argv[0], NULL, NULL, argv, environ);
-46
View File
@@ -9,52 +9,6 @@
BOOL getEntitlementValue(NSString *key); BOOL getEntitlementValue(NSString *key);
@implementation UIWindow(ext)
// Simulate safe area on iPhones without notch
/*
- (UIEdgeInsets)safeAreaInsets {
return UIEdgeInsetsMake(0, 44, 21, 44);
}
*/
- (UIViewController *)visibleViewController {
UIViewController *current = self.rootViewController;
while (current.presentedViewController) {
if ([current.presentedViewController isKindOfClass:UIAlertController.class] || [current.presentedViewController isKindOfClass:NSClassFromString(@"UIInputWindowController")]) {
break;
}
current = current.presentedViewController;
}
if ([current isKindOfClass:UINavigationController.class]) {
return [(UINavigationController *)self.rootViewController visibleViewController];
} else {
return current;
}
}
@end
// This forces the navigation bar to keep its height (44dp) in landscape
@implementation UINavigationBar(forceFullHeightInLandscape)
- (BOOL)forceFullHeightInLandscape {
return UIScreen.mainScreen.traitCollection.userInterfaceIdiom == UIUserInterfaceIdiomPhone;
}
@end
UIWindow* currentWindow() {
id delegate = UIApplication.sharedApplication.delegate;
if (@available(iOS 13.0, *)) {
delegate = UIApplication.sharedApplication.connectedScenes.anyObject.delegate;
}
return [delegate window];
}
UIViewController* currentVC() {
return currentWindow().visibleViewController;
}
BOOL isJITEnabled() { BOOL isJITEnabled() {
if (getEntitlementValue(@"dynamic-codesigning")) { if (getEntitlementValue(@"dynamic-codesigning")) {
return YES; return YES;
+1 -1
View File
@@ -25,7 +25,7 @@ The [PojavLauncher Website](https://pojav.ml) has extensive documentation on how
Note: This is experimental, although game works smoothly, you should not set Render distance too much. Note: This is experimental, although game works smoothly, you should not set Render distance too much.
1. Setup the sideload app 1. Setup the sideload app
- For iOS 14.0-15.5beta4 on compatible devices, [TrollStore](https://github.com/opa334/TrollStore) is recommended to keep PojavLauncher permanently signed and have JIT automatically enabled. - For iOS 14.0-15.5beta4 on compatible devices, [TrollStore](https://github.com/opa334/TrollStore) is recommended to keep PojavLauncher permanently signed and have JIT enabled by itself.
- Otherwise, install [AltStore](https://altstore.io). Others will also work. - Otherwise, install [AltStore](https://altstore.io). Others will also work.
2. Download an IPA build of PojavLauncher in the Actions tab. 2. Download an IPA build of PojavLauncher in the Actions tab.
3. Open the downloaded IPA in the sideload app to install. 3. Open the downloaded IPA in the sideload app to install.
+1 -1
View File
@@ -18,7 +18,7 @@
<true/> <true/>
<!-- Disable sandbox so that PojavLauncher can enable JIT by itself --> <!-- Disable sandbox so that PojavLauncher can enable JIT by itself -->
<key>com.apple.private.security.no-container</key> <key>com.apple.private.security.no-sandbox</key>
<true/> <true/>
<!-- The following entitlements are required if sandbox is disabled --> <!-- The following entitlements are required if sandbox is disabled -->