From 9a5cee04c6b9a90c23de14087aca1696ce79fbd4 Mon Sep 17 00:00:00 2001 From: Duy Tran Khanh Date: Thu, 18 Aug 2022 08:09:46 +0700 Subject: [PATCH 01/37] wip auto renderer --- .../net/kdt/pojavlaunch/PojavLauncher.java | 1 - Natives/JavaLauncher.m | 29 ++++--------- Natives/LauncherMenuViewController.m | 7 +++- Natives/LauncherPreferences.m | 2 +- Natives/LauncherPreferencesViewController.m | 7 ++-- Natives/egl_bridge.m | 42 ++++++++++++------- Natives/glfw_keycodes.h | 2 + Natives/utils.h | 4 ++ 8 files changed, 53 insertions(+), 41 deletions(-) diff --git a/JavaApp/src/main/java/net/kdt/pojavlaunch/PojavLauncher.java b/JavaApp/src/main/java/net/kdt/pojavlaunch/PojavLauncher.java index b9fee726..b3457649 100644 --- a/JavaApp/src/main/java/net/kdt/pojavlaunch/PojavLauncher.java +++ b/JavaApp/src/main/java/net/kdt/pojavlaunch/PojavLauncher.java @@ -70,7 +70,6 @@ public class PojavLauncher { } } - System.setProperty("org.lwjgl.opengl.libname", System.getenv("POJAV_RENDERER")); System.setProperty("org.lwjgl.vulkan.libname", "libMoltenVK.dylib"); Tools.mGLFWWindowWidth = Integer.parseInt(size[0]); diff --git a/Natives/JavaLauncher.m b/Natives/JavaLauncher.m index 028b9739..525d2d5b 100644 --- a/Natives/JavaLauncher.m +++ b/Natives/JavaLauncher.m @@ -24,25 +24,16 @@ static char args_path[2048]; extern char **environ; -static const char* const_progname = "java"; -static const char* const_launcher = "openjdk"; -static const char** const_jargs = NULL; -static const char** const_appclasspath = NULL; -static const jboolean const_javaw = JNI_FALSE; -static const jboolean const_cpwildcard = JNI_TRUE; -static const jint const_ergo_class = 0; // DEFAULT_POLICY - static int margc = -1; static char* margv[1000]; const char *javaHome; -const char *renderer; const char *allocmem; const char *multidir; char *homeDir; -NSString *renderer_pre; +NSString *renderer; NSString *allocmem_pre; NSString *multidir_pre; @@ -152,7 +143,7 @@ int launchJVM(NSString *username, id launchTarget, int width, int height, int mi setPreference(@"java_home", javaHome_pre); NSLog(@"[JavaLauncher] JAVA_HOME environment variable was not set. Default to %@ for future use.\n", javaHome_pre); } */ else { - if (![NSFileManager.defaultManager fileExistsAtPath:javaHome_pre]) { + if (![fm fileExistsAtPath:javaHome_pre]) { javaHome_pre = environmentFailsafes(minVersion); setPreference(@"java_home", javaHome_pre); NSLog(@"[JavaLauncher] Failed to locate %@. Restored default value for JAVA_HOME.", javaHome_pre); @@ -168,17 +159,15 @@ int launchJVM(NSString *username, id launchTarget, int width, int height, int mi javaHome = javaHome_pre.UTF8String; setenv("JAVA_HOME", javaHome, 1); - renderer_pre = getPreference(@"renderer"); - renderer = renderer_pre.UTF8String; - if (renderer_pre.length == 0) { - renderer_pre = @"libgl4es_114.dylib"; - setPreference(@"renderer", renderer_pre); - renderer = [renderer_pre cStringUsingEncoding:NSUTF8StringEncoding]; - regLog("[JavaLauncher] RENDERER environment variable was not set. Defaulting to %s for future use.\n", renderer); + renderer = getPreference(@"renderer"); + if (renderer.length == 0) { + renderer = @"auto"; + setPreference(@"renderer", renderer); + NSLog(@"[JavaLauncher] RENDERER environment variable was not set. Defaulting to %@ for future use.\n", renderer); } else { - regLog("[JavaLauncher] Restored preference: RENDERER is set to %s\n", renderer); + NSLog(@"[JavaLauncher] Restored preference: RENDERER is set to %@\n", renderer); } - setenv("POJAV_RENDERER", renderer, 1); + setenv("POJAV_RENDERER", renderer.UTF8String, 1); allocmem_pre = [getPreference(@"allocated_memory") stringValue]; allocmem = [allocmem_pre cStringUsingEncoding:NSUTF8StringEncoding]; diff --git a/Natives/LauncherMenuViewController.m b/Natives/LauncherMenuViewController.m index 0a3c15f9..5fa2958b 100644 --- a/Natives/LauncherMenuViewController.m +++ b/Natives/LauncherMenuViewController.m @@ -2,6 +2,7 @@ #import "AccountListViewController.h" #import "LauncherMenuViewController.h" #import "LauncherPreferencesViewController.h" +#import "LauncherPreferencesViewController2.h" #import "LauncherViewController.h" #import "UIButton+AFNetworking.h" #import "UIImageView+AFNetworking.h" @@ -20,10 +21,12 @@ // View controllers are put into an array to keep its state self.options = @[ [[LauncherViewController alloc] init], - [[LauncherPreferencesViewController alloc] init] + [[LauncherPreferencesViewController alloc] init], + [[LauncherPreferencesViewController2 alloc] init] ]; self.options[0].title = @"PojavLauncher"; self.options[1].title = @"Preferences"; + self.options[2].title = @"Preferences (v2)"; //@[@"News", @"Development Console", @"Crash logs"]; self.tableView.separatorStyle = UITableViewCellSeparatorStyleNone; @@ -88,7 +91,7 @@ selected.navigationItem.leftItemsSupplementBackButton = true; } - // This button is placed temporarily while migrating to the new UI + // This button is placed temporarily while migrating to the new UI (or just keep here?) self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:@"❌" style:UIBarButtonItemStyleDone target:self.splitViewController action:@selector(dismissViewController)]; } diff --git a/Natives/LauncherPreferences.m b/Natives/LauncherPreferences.m index de7122cc..1253411e 100644 --- a/Natives/LauncherPreferences.m +++ b/Natives/LauncherPreferences.m @@ -110,7 +110,7 @@ void loadPreferences() { setDefaultValueForPref(prefDict, @"debug_logging", CONFIG_TYPE); setDefaultValueForPref(prefDict, @"arccapes_enable", @YES); setDefaultValueForPref(envPrefDict, @"java_home", @""); - setDefaultValueForPref(envPrefDict, @"renderer", @"libgl4es_114.dylib"); + setDefaultValueForPref(envPrefDict, @"renderer", @"auto"); setDefaultValueForPref(warnPrefDict, @"option_warn", @YES); setDefaultValueForPref(warnPrefDict, @"local_warn", @YES); setDefaultValueForPref(warnPrefDict, @"mem_warn", @YES); diff --git a/Natives/LauncherPreferencesViewController.m b/Natives/LauncherPreferencesViewController.m index 812c1f6f..6eaf8afc 100644 --- a/Natives/LauncherPreferencesViewController.m +++ b/Natives/LauncherPreferencesViewController.m @@ -114,9 +114,10 @@ int tempIndex; CGFloat currY = 8.0; rendererDict = @{ - @"gl4es 1.1.4 - exports OpenGL 2.1": @"libgl4es_114.dylib", - @"tinygl4angle (1.17+) - exports OpenGL 3.2 (Core Profile, limited)": @"libtinygl4angle.dylib", - @"Zink (Mesa 21.0) - exports OpenGL 4.1": @"libOSMesaOverride.dylib" + @"Auto: gl4es or tinygl4angle": @"auto", + @"gl4es 1.1.4 - exports OpenGL 2.1": @ RENDERER_NAME_GL4ES, + @"tinygl4angle (1.17+) - exports OpenGL 3.2 (Core Profile, limited)": @ RENDERER_NAME_MTL_ANGLE, + @"Zink (Mesa 21.0) - exports OpenGL 4.1": @ RENDERER_NAME_VK_ZINK }; scrollView = [[UIScrollView alloc] initWithFrame:self.view.frame]; diff --git a/Natives/egl_bridge.m b/Natives/egl_bridge.m index c2699e6e..efaac1f5 100644 --- a/Natives/egl_bridge.m +++ b/Natives/egl_bridge.m @@ -225,12 +225,15 @@ jboolean pojavInit_OpenGL() { if (config_renderer) return JNI_TRUE; NSString *renderer = @(getenv("POJAV_RENDERER")); + BOOL isAuto = [renderer isEqualToString:@"auto"]; if ([renderer isEqualToString:@"libOSMesa.8.dylib"]) { config_renderer = RENDERER_VIRGL; setenv("GALLIUM_DRIVER", "virpipe", 1); loadSymbolsVirGL(); - } else if ([renderer hasPrefix:@"libgl4es"] || [renderer hasPrefix:@"libtinygl4angle"]) { + } else if (isAuto || [renderer isEqualToString:@ RENDERER_NAME_GL4ES] || [renderer isEqualToString:@ RENDERER_NAME_MTL_ANGLE]) { config_renderer = RENDERER_MTL_ANGLE; + setenv("POJAV_RENDERER", RENDERER_NAME_MTL_ANGLE, 1); + setenv("POJAV_RENDERER_AUTO", "1", 1); loadSymbols(); } else if ([renderer hasPrefix:@"libOSMesa"]) { config_renderer = RENDERER_VK_ZINK; @@ -251,6 +254,11 @@ jboolean pojavInit_OpenGL() { void *renderer_handle = dlopen(getenv("POJAV_RENDERER"), RTLD_GLOBAL); debugLog("%s=%p, error=%s", getenv("POJAV_RENDERER"), renderer_handle, dlerror()); + // Set back to gl4es + if (isAuto) { + setenv("POJAV_RENDERER", RENDERER_NAME_GL4ES, 1); + } + debugLog("EGLBridge: Initializing"); // printf("EGLBridge: ANativeWindow pointer = %p\n", potatoBridge.androidWindow); //(*env)->ThrowNew(env,(*env)->FindClass(env,"java/lang/Exception"),"Trace exception"); @@ -351,19 +359,25 @@ jboolean pojavInit_OpenGL() { } void pojavSetWindowHint(int hint, int value) { - if (hint != GLFW_CLIENT_API) return; - switch (value) { - case GLFW_NO_API: - config_renderer = RENDERER_VULKAN; - /* Nothing to do: initialization is handled in Java-side */ - // pojavInit_Vulkan(); - break; - case GLFW_OPENGL_API: - pojavInit_OpenGL(); - break; - default: - NSLog(@"GLFW: Unimplemented API 0x%x", value); - abort(); + if (hint == GLFW_CLIENT_API) { + switch (value) { + case GLFW_NO_API: + config_renderer = RENDERER_VULKAN; + /* Nothing to do: initialization is handled in Java-side */ + // pojavInit_Vulkan(); + break; + case GLFW_OPENGL_API: + pojavInit_OpenGL(); + break; + default: + NSLog(@"GLFW: Unimplemented API 0x%x", value); + abort(); + } + } else if (getenv("POJAV_RENDERER_AUTO") && hint == GLFW_CONTEXT_VERSION_MAJOR && value >= 3) { + jclass System = env + setenv("POJAV_RENDERER", RENDERER_NAME_MTL_ANGLE, 1); + NSLog(@"----- Set RENDERER to tinygl4angle -----"); + // setProperty org.lwjgl.opengl.libname } } diff --git a/Natives/glfw_keycodes.h b/Natives/glfw_keycodes.h index ef1151fc..6e88a875 100644 --- a/Natives/glfw_keycodes.h +++ b/Natives/glfw_keycodes.h @@ -35,6 +35,8 @@ #define GLFW_NO_API 0 #define GLFW_OPENGL_API 0x30001 +#define GLFW_CONTEXT_VERSION_MAJOR 0x00022002 + /*! @defgroup hat_state Joystick hat states * @brief Joystick hat states. * diff --git a/Natives/utils.h b/Natives/utils.h index 4d385fb4..08c6da1a 100644 --- a/Natives/utils.h +++ b/Natives/utils.h @@ -28,6 +28,10 @@ #define GLFW_FOCUSED 0x00020001 #define GLFW_VISIBLE 0x00020004 +#define RENDERER_NAME_GL4ES "libgl4es_114.dylib" +#define RENDERER_NAME_MTL_ANGLE "libtinygl4angle.dylib" +#define RENDERER_NAME_VK_ZINK "libOSMesaOverride.dylib" + #define SPECIALBTN_KEYBOARD -1 #define SPECIALBTN_TOGGLECTRL -2 #define SPECIALBTN_MOUSEPRI -3 From be39a72e389549855f91b78ca0ce9506ffe9a286 Mon Sep 17 00:00:00 2001 From: Duy Tran Khanh Date: Thu, 18 Aug 2022 08:13:26 +0700 Subject: [PATCH 02/37] WIP: re-write the preferences UI --- Natives/CMakeLists.txt | 3 + Natives/LauncherPreferencesViewController2.h | 10 ++ Natives/LauncherPreferencesViewController2.m | 164 +++++++++++++++++++ Natives/external/TOInsetGroupedTableView | 1 + 4 files changed, 178 insertions(+) create mode 100644 Natives/LauncherPreferencesViewController2.h create mode 100644 Natives/LauncherPreferencesViewController2.m create mode 160000 Natives/external/TOInsetGroupedTableView diff --git a/Natives/CMakeLists.txt b/Natives/CMakeLists.txt index b979d75d..a8937bcd 100644 --- a/Natives/CMakeLists.txt +++ b/Natives/CMakeLists.txt @@ -15,6 +15,7 @@ include_directories( "external/AFNetworking/AFNetworking" "external/AFNetworking/UIKit+AFNetworking" "external/DBNumberedSlider/Classes" + "external/TOInsetGroupedTableView/TOInsetGroupedTableView" "external/fishhook" "external/mesa" ) @@ -100,6 +101,7 @@ add_executable(PojavLauncher customcontrols/CustomControlsUtils.m external/DBNumberedSlider/Classes/DBNumberedSlider.m + external/TOInsetGroupedTableView/TOInsetGroupedTableView/TOInsetGroupedTableView.m AboutLauncherViewController.m AccountListViewController.m @@ -113,6 +115,7 @@ add_executable(PojavLauncher LauncherMenuViewController.m LauncherPreferences.m LauncherPreferencesViewController.m + LauncherPreferencesViewController2.m LauncherSplitViewController.m LauncherViewController.m LoginViewController.m diff --git a/Natives/LauncherPreferencesViewController2.h b/Natives/LauncherPreferencesViewController2.h new file mode 100644 index 00000000..f983eda1 --- /dev/null +++ b/Natives/LauncherPreferencesViewController2.h @@ -0,0 +1,10 @@ +#import + +#define JRE8_NAME_JB @"Java 8" +#define JRE16_NAME_JB @"Java 16" +#define JRE17_NAME_JB @"Java 17" +#define JRE8_NAME_SB @"Java 8 (sandbox)" + +@interface LauncherPreferencesViewController2 : UITableViewController + +@end diff --git a/Natives/LauncherPreferencesViewController2.m b/Natives/LauncherPreferencesViewController2.m new file mode 100644 index 00000000..bae9a17d --- /dev/null +++ b/Natives/LauncherPreferencesViewController2.m @@ -0,0 +1,164 @@ +#import + +#import "DBNumberedSlider.h" +#import "LauncherPreferences.h" +#import "LauncherPreferencesViewController2.h" +#import "TOInsetGroupedTableView.h" + +#include "utils.h" + +@interface LauncherPreferencesViewController2() {} +@property NSArray* prefSections; +@property NSArray*>* prefContents; +@end + +@implementation LauncherPreferencesViewController2 + +- (void)viewDidLoad +{ + [super viewDidLoad]; + + self.tableView = [[TOInsetGroupedTableView alloc] init]; + self.tableView.allowsSelection = NO; + + self.prefSections = @[@"general", @"video", @"control", @"java"]; + + self.prefContents = @[ + @{ + // General settings + @"game_directory": @{ + @"icon": @"folder", + @"type": @"PickField", + @"pickList": @[@"default", @"TODO"] + } + }, @{ + // Video and renderer settings + @"renderer": @{ + @"icon": @"cpu", + @"type": @"PickField", + @"pickList": @[@"gl4es", @"zink", @"wip"] + }, + @"resolution": @{ + @"icon": @"viewfinder", + @"type": @"Slider" + }, + }, @{ + // Control settings + /* + @"disable_gesture": @{ + @"type": @"Switch" + }, + */ + @"press_duration": @{ + @"icon": @"timer", + @"type": @"Slider", + @"min": @(100), + @"max": @(1000) + }, + @"button_scale": @{ + @"icon": @"aspectratio", + @"type": @"Slider", + @"min": @(50), // 80? + @"max": @(500) + }, + @"mouse_scale": @{ + @"icon": @"arrow.up.left.and.arrow.down.right.circle", + @"type": @"Slider", + @"min": @(25), + @"max": @(300) + }, + @"mouse_speed": @{ + @"icon": @"arrow.left.and.right", + @"type": @"Slider", + @"min": @(25), + @"max": @(300) + }, + @"virtmouse_enable": @{ + @"icon": @"cursorarrow.rays", + @"type": @"Switch" + }, + @"slideable_hotbar": @{ + @"icon": @"slider.horizontal.below.rectangle", + @"type": @"Switch" + } + }, @{ + // Java tweaks + @"java_home": @{ + @"icon": @"cube", + @"type": @"PickField", + @"pickList": @[@"java-8-openjdk", @"java-17-openjdk", @"TODO"] + }, + @"java_args": @{ + @"icon": @"slider.vertical.3", + @"type": @"TextField" + }, + @"ram_unjb_enable": @{ // TODO: name as Auto RAM + @"icon": @"slider.horizontal.3", + @"type": @"Switch", + @"hidden": @(getenv("POJAV_DETECTEDJB") != NULL) + }, + @"allocated_memory": @{ + @"icon": @"memorychip", + @"type": @"Slider", + @"min": @(25), + @"max": @(300) + } + } + ]; +} + +- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { + return self.prefSections.count; +} + +- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section { + return NSLocalizedString(([NSString stringWithFormat:@"preference.section.%@", self.prefSections[section]]), nil); +} + +- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { + return self.prefContents[section].count; +} + +- (UITableViewCell *)tableView:(nonnull UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { + UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"cell"]; + if (cell == nil) { + cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"cell"]; + } + + NSString *key = self.prefContents[indexPath.section].allKeys[indexPath.row]; + NSDictionary *item = self.prefContents[indexPath.section].allValues[indexPath.row]; + NSString *type = item[@"type"]; + if ([type isEqualToString:@"PickField"]) { + cell.accessoryView = [[UITextField alloc] init]; + [(id)(cell.accessoryView) setText:getPreference(key)]; + } else if ([type isEqualToString:@"TextField"]) { + UITextField *view = [[UITextField alloc] init]; + view.autocorrectionType = UITextAutocorrectionTypeNo; + view.autocapitalizationType = UITextAutocapitalizationTypeNone; + view.placeholder = NSLocalizedString(([NSString stringWithFormat:@"preference.placeholder.%@", key]), nil); + view.text = getPreference(key); + view.adjustsFontSizeToFitWidth = YES; + cell.accessoryView = view; + } else if ([type isEqualToString:@"Slider"]) { + DBNumberedSlider *view = [[DBNumberedSlider alloc] init]; + view.minimumValue = [item[@"min"] intValue]; + view.maximumValue = [item[@"max"] intValue]; + view.continuous = YES; + view.value = [getPreference(key) intValue]; + cell.accessoryView = view; + } else if ([type isEqualToString:@"Switch"]) { + cell.accessoryView = [[UISwitch alloc] init]; + [(id)(cell.accessoryView) setOn:[getPreference(key) boolValue] animated:NO]; + } else { + NSAssert(NO, @"Unknown type: %@", type); + } + + if (@available(iOS 13.0, *)) { + cell.imageView.image = [UIImage systemImageNamed:item[@"icon"]]; + } + cell.textLabel.text = NSLocalizedString(([NSString stringWithFormat:@"preference.title.%@", key]), nil); + + return cell; +} + +@end diff --git a/Natives/external/TOInsetGroupedTableView b/Natives/external/TOInsetGroupedTableView new file mode 160000 index 00000000..a17c55ac --- /dev/null +++ b/Natives/external/TOInsetGroupedTableView @@ -0,0 +1 @@ +Subproject commit a17c55acd5faabd7114fb26e908cf1e07b570b1c From 9ab7555faad13e92e5d9fb31ea0c5de67fcdb2a4 Mon Sep 17 00:00:00 2001 From: Eilionoir Tunnicliff Date: Wed, 17 Aug 2022 21:18:37 -0400 Subject: [PATCH 03/37] Update branch (#368) * there wasn't cd .. * Start running compile on M1 mini (#367) * Switch to self-hosted runner * Fix name * Fix runner 2 * Update release * Update release.yml * Update release.yml * Fix M1 runner bruh * Fix M1 runner 2 * Update release.yml * Fix yaml * Update release.yml Co-authored-by: Duy Tran Khanh <40482367+khanhduytran0@users.noreply.github.com> --- .github/workflows/development.yml | 60 ++++---------------------- .github/workflows/release.yml | 71 ++++++------------------------- Makefile | 1 + 3 files changed, 22 insertions(+), 110 deletions(-) diff --git a/.github/workflows/development.yml b/.github/workflows/development.yml index 96694823..179dc93e 100644 --- a/.github/workflows/development.yml +++ b/.github/workflows/development.yml @@ -6,56 +6,20 @@ on: jobs: build: name: Development build - runs-on: macOS-11 + runs-on: MacStadium steps: - - name: Set up cache - uses: actions/cache@v2 - id: procache - with: - path: | - ~/__cache - key: ${{ runner.os }}-procursus - - - name: Set up build environment - uses: maxim-lobanov/setup-xcode@v1 - with: - xcode-version: '13.2.1' - - - name: Set up build environment pt. II + - name: Checkout repository uses: actions/checkout@v2 - - name: Set up build environment pt. III + - name: Checkout repository submodules run: git submodule update --init --recursive - - - name: Set up build environment pt. IV (Install) - if: steps.procache.outputs.cache-hit != 'true' - run: | - wget https://apt.procurs.us/bootstrap_darwin-amd64.tar.zst - sudo gtar --preserve-permissions -xkf ./bootstrap_darwin-amd64.tar.zst -C / - echo '/opt/procursus/sbin:/opt/procursus/bin' >> $GITHUB_PATH - PATH=/opt/procursus/sbin:/opt/procursus/bin:$PATH sudo /opt/procursus/bin/apt-get update - sudo /opt/procursus/bin/apt-get -V dist-upgrade -y || : - sudo /opt/procursus/bin/apt-get -V dist-upgrade -y - sudo /opt/procursus/bin/apt-get install ldid make sed fakeroot -y - - - name: Set up build environment pt. V - run: | - echo '/opt/procursus/sbin:/opt/procursus/bin' >> $GITHUB_PATH - - - name: Set up build environment pt. IV (cache) - if: steps.procache.outputs.cache-hit == 'true' - run: | - sudo mkdir -p ~/__cache/procursus/var/cache/apt/archives/partial ~/__cache/procursus/var/lib/apt/lists/partial - sudo rsync -aP ~/__cache/procursus /opt - sudo /opt/procursus/bin/apt-get update - sudo /opt/procursus/bin/apt-get -V dist-upgrade -y || : - sudo /opt/procursus/bin/apt-get -V dist-upgrade -y - - - name: Build the Debian package - run: gmake -j$(sysctl -n hw.ncpu) dsym - - - name: Build the iOS package + + - name: Build packages + env: + password: ${{ secrets.ELLIE_MINI_SECRET }} run: | + export NOSTDIN=1 SUDOPASS=$password + export JAVA_HOME=$(/usr/libexec/java_home -v 1.8) gmake -j$(sysctl -n hw.ncpu) ipa - name: Upload regular artifact @@ -81,9 +45,3 @@ jobs: with: name: PojavLauncher.dSYM path: artifacts/PojavLauncher.dSYM - - - name: Copy Procursus to Cache Location - run: | - sudo mkdir -p ~/__cache - sudo rsync -aP /opt/procursus ~/__cache - sudo rm -rf ~/__cache/procursus/var/cache/apt/archives/partial ~/__cache/procursus/var/lib/apt/lists/partial ~/__cache/procursus/Library/dpkg/triggers/Lock diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 1d133974..53136b28 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -6,63 +6,21 @@ on: jobs: build: name: Release build - runs-on: macOS-11 + runs-on: MacStadium steps: - - name: Set up cache - uses: actions/cache@v2 - id: procache - with: - path: | - ~/__cache - key: ${{ runner.os }}-procursus - - - name: Set up build environment - uses: maxim-lobanov/setup-xcode@v1 - with: - xcode-version: '13.2.1' - - - name: Set up build environment pt. II + - name: Checkout repository uses: actions/checkout@v2 - - name: Set up build environment pt. III + - name: Checkout repository submodules run: git submodule update --init --recursive - - - name: Set up build environment pt. IV (Install) - if: steps.procache.outputs.cache-hit != 'true' + + - name: Build packages + env: + password: ${{ secrets.ELLIE_MINI_SECRET }} run: | - wget https://apt.procurs.us/bootstrap_darwin-amd64.tar.zst - sudo gtar --preserve-permissions -xkf ./bootstrap_darwin-amd64.tar.zst -C / - echo '/opt/procursus/sbin:/opt/procursus/bin' >> $GITHUB_PATH - PATH=/opt/procursus/sbin:/opt/procursus/bin:$PATH sudo /opt/procursus/bin/apt-get update - sudo /opt/procursus/bin/apt-get -V dist-upgrade -y || : - sudo /opt/procursus/bin/apt-get -V dist-upgrade -y - sudo /opt/procursus/bin/apt-get install ldid make sed fakeroot -y - - - name: Set up build environment pt. V - run: | - echo '/opt/procursus/sbin:/opt/procursus/bin' >> $GITHUB_PATH - - - name: Set up build environment pt. IV (cache) - if: steps.procache.outputs.cache-hit == 'true' - run: | - sudo mkdir -p ~/__cache/procursus/var/cache/apt/archives/partial ~/__cache/procursus/var/lib/apt/lists/partial - sudo rsync -aP ~/__cache/procursus /opt - sudo /opt/procursus/bin/apt-get update - sudo /opt/procursus/bin/apt-get -V dist-upgrade -y - sudo /opt/procursus/bin/apt-get -V dist-upgrade -y - - - name: Build the Debian package - run: gmake -j$(sysctl -n hw.ncpu) dsym RELEASE=1 - - - name: Build the iOS package - run: | - mkdir -p depends - # java-8-openjdk - cd depends - wget https://github.com/PojavLauncherTeam/android-openjdk-build-multiarch/releases/download/jre8-99f3f8b/jre8-zero-aarch64-ios.tar.xz - tar xvf jre8-zero-aarch64-ios.tar.xz - rm jre8-zero-aarch64-ios.tar.xz - cd .. + export RELEASE=1 + export NOSTDIN=1 SUDOPASS=$password + export JAVA_HOME=$(/usr/libexec/java_home -v 1.8) gmake -j$(sysctl -n hw.ncpu) ipa - name: Upload regular artifact @@ -80,7 +38,7 @@ jobs: - name: Upload IPA artifact uses: actions/upload-artifact@v2 with: - name: net.kdt.pojavlauncher-INT.ipa + name: net.kdt.pojavlauncher.ipa path: artifacts/net.kdt.pojavlauncher-*.ipa - name: Upload PojavLauncher.dSYM @@ -88,9 +46,4 @@ jobs: with: name: PojavLauncher.dSYM path: artifacts/PojavLauncher.dSYM - - - name: Copy Procursus to Cache Location - run: | - sudo mkdir -p ~/__cache - sudo rsync -aP /opt/procursus ~/__cache - sudo rm -rf ~/__cache/procursus/var/cache/apt/archives/partial ~/__cache/procursus/var/lib/apt/lists/partial ~/__cache/procursus/Library/dpkg/triggers/Lock + diff --git a/Makefile b/Makefile index 3b7ba82e..49367bbc 100644 --- a/Makefile +++ b/Makefile @@ -331,6 +331,7 @@ ipa: dsym tar xvf *.tar.xz; \ rm *.tar.xz; \ fi; \ + cd ..; \ if [ ! -d "java-17-openjdk" ]; then \ mkdir java-17-openjdk && cd java-17-openjdk; \ wget 'https://github.com/PojavLauncherTeam/android-openjdk-build-multiarch/releases/download/jre17-ca01427/jre17-arm64-20220817-release.tar.xz'; \ From 949e49acf57872dd5128c71a351169f099df9659 Mon Sep 17 00:00:00 2001 From: Eilionoir Tunnicliff Date: Wed, 17 Aug 2022 21:23:22 -0400 Subject: [PATCH 04/37] Add TOInsetGroupedTableView to .gitmodules --- .gitmodules | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.gitmodules b/.gitmodules index 324d8d9e..234ef369 100644 --- a/.gitmodules +++ b/.gitmodules @@ -8,3 +8,6 @@ [submodule "Natives/external/AFNetworking"] path = Natives/external/AFNetworking url = https://github.com/AFNetworking/AFNetworking +[submodule "Natives/external/TOInsetGroupedTableView"] + path = Natives/external/TOInsetGroupedTableView + url = https://github.com/TimOliver/TOInsetGroupedTableView From 5c4b672d22749aa28393fb1552b7f32c985c9f81 Mon Sep 17 00:00:00 2001 From: khanhduytran0 Date: Thu, 18 Aug 2022 08:24:41 +0700 Subject: [PATCH 05/37] Update submodule list --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 29d00b74..c71a98d8 100644 --- a/README.md +++ b/README.md @@ -86,6 +86,7 @@ PojavLauncher is amazing, and surprisingly stable, and it wouldn't be this way w - [fishhook](https://github.com/facebook/fishhook) (jailed environment usage only): [BSD-3 License](https://github.com/facebook/fishhook/blob/main/LICENSE). - [Java Native Access](https://github.com/java-native-access/jna): [Apache 2.0 License](https://github.com/java-native-access/jna/blob/master/LICENSE). - [shaderc](https://github.com/google/shaderc) (used by mods that uses Vulkan for rendering): [Apache 2.0 License](https://github.com/google/shaderc/blob/main/LICENSE). +- [TOInsetGroupedTableView](https://github.com/TimOliver/TOInsetGroupedTableView): [MIT License](https://github.com/TimOliver/TOInsetGroupedTableView/blob/master/LICENSE). ## Special thanks to MacStadium! This project is listed under the MacStadium Open Source Program, which allows all of us developers to keep on moving forward even without physical access to a Mac. From 8cc6ac2d09f1ef9248aea8dc0a84c1ed45f19ed5 Mon Sep 17 00:00:00 2001 From: Eilionoir Tunnicliff Date: Wed, 17 Aug 2022 21:50:56 -0400 Subject: [PATCH 06/37] Disable WIP auto renderer --- Natives/egl_bridge.m | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Natives/egl_bridge.m b/Natives/egl_bridge.m index efaac1f5..f37c0efd 100644 --- a/Natives/egl_bridge.m +++ b/Natives/egl_bridge.m @@ -373,12 +373,12 @@ void pojavSetWindowHint(int hint, int value) { NSLog(@"GLFW: Unimplemented API 0x%x", value); abort(); } - } else if (getenv("POJAV_RENDERER_AUTO") && hint == GLFW_CONTEXT_VERSION_MAJOR && value >= 3) { - jclass System = env + } /*else if (getenv("POJAV_RENDERER_AUTO") && hint == GLFW_CONTEXT_VERSION_MAJOR && value >= 3) { + jclass System = env; setenv("POJAV_RENDERER", RENDERER_NAME_MTL_ANGLE, 1); NSLog(@"----- Set RENDERER to tinygl4angle -----"); // setProperty org.lwjgl.opengl.libname - } + } */ } int32_t stride; From 3352426f322e71b50a83455bcc3c0fba61dc1117 Mon Sep 17 00:00:00 2001 From: Eilionoir Tunnicliff Date: Wed, 17 Aug 2022 23:25:41 -0400 Subject: [PATCH 07/37] Changes - Added a few more preferences to v2 - Added strings to Localizable.strings --- Natives/LauncherPreferencesViewController2.m | 20 +++++++++++++++ Natives/en.lproj/Localizable.strings | 27 ++++++++++++++++++++ 2 files changed, 47 insertions(+) diff --git a/Natives/LauncherPreferencesViewController2.m b/Natives/LauncherPreferencesViewController2.m index bae9a17d..258e29c8 100644 --- a/Natives/LauncherPreferencesViewController2.m +++ b/Natives/LauncherPreferencesViewController2.m @@ -31,6 +31,26 @@ @"type": @"PickField", @"pickList": @[@"default", @"TODO"] } + @"home_symlink": @{ + @"icon": @"link", + @"type": @"Switch" + }, + @"check_sha": @{ + @"icon": @"lock.shield", + @"type": @"Switch" + }, + @"cosmetica": @{ + @"icon": @"eyeglasses", + @"type": @"Switch" + }, + @"reset_warnings": @{ + @"icon": @"exclamationmark.triangle", + @"type": @"Switch" + }, + @"reset_settings": @{ + @"icon": @"trash", + @"type": @"Switch" + }, }, @{ // Video and renderer settings @"renderer": @{ diff --git a/Natives/en.lproj/Localizable.strings b/Natives/en.lproj/Localizable.strings index 6d809d5f..6dde7815 100644 --- a/Natives/en.lproj/Localizable.strings +++ b/Natives/en.lproj/Localizable.strings @@ -59,3 +59,30 @@ "login.msa.progress.acquireXboxProfile" = "(3/5) Acquiring the Xbox profile"; "login.msa.progress.acquireMCToken" = "(4/5) Acquiring the Minecraft token"; "login.msa.progress.checkMCProfile" = "(5/5) Checking the Minecraft profile"; + +"preference.section.general" = "General Settings"; +"preference.section.video" = "Video Settings"; +"preference.section.control" = "Control Settings"; +"preference.section.java" = "Java Runtime Settings"; + +"preference.title.game_directory" = "Minecraft game directory"; +"preference.title.home_symlink" = "Enable compatibility symlink"; +"preference.title.check_sha" = "Enable asset verification when launching"; +"preference.title.cosmetica" = "Enable Cosmetica integration"; +"preference.title.reset_warnings" = "Reset all warnings"; +"preference.title.reset_settings" = "Reset all settings"; +"preference.title.renderer" = "Game renderer"; +"preference.title.resolution" = "Game resolution"; +"preference.title.disable_gesture" = "Disable gestures"; +"preference.title.press_duration" = "Long-press duration"; +"preference.title.button_scale" = "On-screen button scale"; +"preference.title.mouse_scale" = "On-screen mouse scale"; +"preference.title.mouse_speed" = "On-screen mouse speed"; +"preference.title.virtmouse_enable" = "Enable on-screen mouse"; +"preference.title.slideable_hotbar" = "Enable slideable hotbar"; +"preference.title.java_home" = "Java runtime selector"; +"preference.title.java_args" = "Custom java arguments"; +"preference.title.auto_ram" = "Enable custom memory slider"; +"preference.title.allocated_memory" = "Allocated memory"; +// sha check +// home symlink From 2c73d020524748d513e506b2b97d403802d4aba0 Mon Sep 17 00:00:00 2001 From: Eilionoir Tunnicliff Date: Wed, 17 Aug 2022 23:26:28 -0400 Subject: [PATCH 08/37] Fix typo --- Natives/LauncherPreferencesViewController2.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Natives/LauncherPreferencesViewController2.m b/Natives/LauncherPreferencesViewController2.m index 258e29c8..0668f81b 100644 --- a/Natives/LauncherPreferencesViewController2.m +++ b/Natives/LauncherPreferencesViewController2.m @@ -50,7 +50,7 @@ @"reset_settings": @{ @"icon": @"trash", @"type": @"Switch" - }, + } }, @{ // Video and renderer settings @"renderer": @{ From e072261a8c5e71a75bcbd2047f76d593c4130717 Mon Sep 17 00:00:00 2001 From: Eilionoir Tunnicliff Date: Wed, 17 Aug 2022 23:27:16 -0400 Subject: [PATCH 09/37] Fix typo 2 --- Natives/LauncherPreferencesViewController2.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Natives/LauncherPreferencesViewController2.m b/Natives/LauncherPreferencesViewController2.m index 0668f81b..76860ee9 100644 --- a/Natives/LauncherPreferencesViewController2.m +++ b/Natives/LauncherPreferencesViewController2.m @@ -30,7 +30,7 @@ @"icon": @"folder", @"type": @"PickField", @"pickList": @[@"default", @"TODO"] - } + }, @"home_symlink": @{ @"icon": @"link", @"type": @"Switch" From 0bd5b8cd81faf8f382089184b04e999851f0ccad Mon Sep 17 00:00:00 2001 From: Eilionoir Tunnicliff Date: Thu, 18 Aug 2022 02:20:54 -0400 Subject: [PATCH 10/37] Rename ram_unjb_enable to auto_ram --- .gitignore | 1 + Natives/LauncherPreferencesViewController2.m | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index b6e1b109..27bde3d2 100644 --- a/.gitignore +++ b/.gitignore @@ -7,3 +7,4 @@ /Natives/build .DS_Store /pojavlauncher.xcodeproj +/depends diff --git a/Natives/LauncherPreferencesViewController2.m b/Natives/LauncherPreferencesViewController2.m index 76860ee9..6365649b 100644 --- a/Natives/LauncherPreferencesViewController2.m +++ b/Natives/LauncherPreferencesViewController2.m @@ -112,7 +112,7 @@ @"icon": @"slider.vertical.3", @"type": @"TextField" }, - @"ram_unjb_enable": @{ // TODO: name as Auto RAM + @"auto_ram": @{ // TODO: name as Auto RAM @"icon": @"slider.horizontal.3", @"type": @"Switch", @"hidden": @(getenv("POJAV_DETECTEDJB") != NULL) From 0c4c53c95301e0057c06a30f21116c94ccff159d Mon Sep 17 00:00:00 2001 From: Duy Tran Khanh Date: Thu, 18 Aug 2022 19:09:12 +0700 Subject: [PATCH 11/37] Finish auto renderer selection --- .../src/main/java/org/lwjgl/opengl/GL.java | 4 +- Natives/egl_bridge.m | 47 +++++++++++-------- 2 files changed, 30 insertions(+), 21 deletions(-) diff --git a/JavaApp/src/main/java/org/lwjgl/opengl/GL.java b/JavaApp/src/main/java/org/lwjgl/opengl/GL.java index bbcf4d1b..7c91ea73 100644 --- a/JavaApp/src/main/java/org/lwjgl/opengl/GL.java +++ b/JavaApp/src/main/java/org/lwjgl/opengl/GL.java @@ -108,7 +108,9 @@ public final class GL { GL = Library.loadNative(GL.class, "org.lwjgl.opengl", Configuration.OPENGL_LIBRARY_NAME, "libGL.so.1", "libGL.so"); break; case MACOSX: - String override = Configuration.OPENGL_LIBRARY_NAME.get(); + // Configuration does not get updated if the value changes, so we have to use System.getProperty() + String override = System.getProperty("org.lwjgl.opengl.libname"); + //Configuration.OPENGL_LIBRARY_NAME.get(); GL = override != null ? Library.loadNative(GL.class, "org.lwjgl.opengl", override) : MacOSXLibrary.getWithIdentifier("com.apple.opengl"); diff --git a/Natives/egl_bridge.m b/Natives/egl_bridge.m index f37c0efd..76057d28 100644 --- a/Natives/egl_bridge.m +++ b/Natives/egl_bridge.m @@ -91,15 +91,14 @@ pid_t gettid() { return (pid_t) pthread_mach_thread_np(pthread_self()); } - -JNIEXPORT void JNICALL Java_net_kdt_pojavlaunch_utils_JREUtils_setenv(JNIEnv *env, jclass clazz, jstring name, jstring value, jboolean overwrite) { - char const *name_c = (*env)->GetStringUTFChars(env, name, NULL); - char const *value_c = (*env)->GetStringUTFChars(env, value, NULL); - - setenv(name_c, value_c, overwrite); - - (*env)->ReleaseStringUTFChars(env, name, name_c); - (*env)->ReleaseStringUTFChars(env, value, value_c); +void JNI_LWJGL_changeRenderer(const char* value_c) { + JNIEnv *env; + (*runtimeJavaVMPtr)->GetEnv(runtimeJavaVMPtr, (void **)&env, JNI_VERSION_1_4); + jstring key = (*env)->NewStringUTF(env, "org.lwjgl.opengl.libname"); + jstring value = (*env)->NewStringUTF(env, value_c); + jclass clazz = (*env)->FindClass(env, "java/lang/System"); + jmethodID method = (*env)->GetStaticMethodID(env, clazz, "setProperty", "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;"); + (*env)->CallStaticObjectMethod(env, clazz, method, key, value); } void pojavTerminate() { @@ -230,10 +229,12 @@ jboolean pojavInit_OpenGL() { config_renderer = RENDERER_VIRGL; setenv("GALLIUM_DRIVER", "virpipe", 1); loadSymbolsVirGL(); - } else if (isAuto || [renderer isEqualToString:@ RENDERER_NAME_GL4ES] || [renderer isEqualToString:@ RENDERER_NAME_MTL_ANGLE]) { + } else if (isAuto || [renderer isEqualToString:@ RENDERER_NAME_GL4ES]) { + config_renderer = RENDERER_MTL_ANGLE; + setenv("POJAV_RENDERER", RENDERER_NAME_GL4ES, 1); + loadSymbols(); + } else if ([renderer isEqualToString:@ RENDERER_NAME_MTL_ANGLE]) { config_renderer = RENDERER_MTL_ANGLE; - setenv("POJAV_RENDERER", RENDERER_NAME_MTL_ANGLE, 1); - setenv("POJAV_RENDERER_AUTO", "1", 1); loadSymbols(); } else if ([renderer hasPrefix:@"libOSMesa"]) { config_renderer = RENDERER_VK_ZINK; @@ -251,12 +252,17 @@ jboolean pojavInit_OpenGL() { } // Pre-load the renderer library + // FIXME: gl4es has to be pre-loaded if it is going to be used later, + // or glCheckFramebufferStatus will return an error void *renderer_handle = dlopen(getenv("POJAV_RENDERER"), RTLD_GLOBAL); debugLog("%s=%p, error=%s", getenv("POJAV_RENDERER"), renderer_handle, dlerror()); - // Set back to gl4es + // Set back to the previous value + setenv("POJAV_RENDERER", renderer.UTF8String, 1); if (isAuto) { - setenv("POJAV_RENDERER", RENDERER_NAME_GL4ES, 1); + JNI_LWJGL_changeRenderer(RENDERER_NAME_GL4ES); + } else { + JNI_LWJGL_changeRenderer(renderer.UTF8String); } debugLog("EGLBridge: Initializing"); @@ -373,12 +379,13 @@ void pojavSetWindowHint(int hint, int value) { NSLog(@"GLFW: Unimplemented API 0x%x", value); abort(); } - } /*else if (getenv("POJAV_RENDERER_AUTO") && hint == GLFW_CONTEXT_VERSION_MAJOR && value >= 3) { - jclass System = env; - setenv("POJAV_RENDERER", RENDERER_NAME_MTL_ANGLE, 1); - NSLog(@"----- Set RENDERER to tinygl4angle -----"); - // setProperty org.lwjgl.opengl.libname - } */ + } else if (strcmp(getenv("POJAV_RENDERER"), "auto")==0 && hint == GLFW_CONTEXT_VERSION_MAJOR && value >= 3) { + // Free unused gl4es library + void *renderer_handle = dlopen(RENDERER_NAME_GL4ES, RTLD_GLOBAL); + dlclose(renderer_handle); + + JNI_LWJGL_changeRenderer(RENDERER_NAME_MTL_ANGLE); + } } int32_t stride; From 8980b642ead6a3c0718e0f6df3af107069238dd7 Mon Sep 17 00:00:00 2001 From: Duy Tran Khanh Date: Thu, 18 Aug 2022 19:18:04 +0700 Subject: [PATCH 12/37] Update LauncherPreferencesViewController2 New keys: - customSwitchValue (type array of NSString) - warnAlways (type BOOL) - warnCondition (type block) --- Natives/LauncherPreferencesViewController2.m | 22 ++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/Natives/LauncherPreferencesViewController2.m b/Natives/LauncherPreferencesViewController2.m index 6365649b..808494ca 100644 --- a/Natives/LauncherPreferencesViewController2.m +++ b/Natives/LauncherPreferencesViewController2.m @@ -103,25 +103,35 @@ } }, @{ // Java tweaks - @"java_home": @{ + @"java_home": @{ // TODO: name as Use Java 17 for older MC @"icon": @"cube", @"type": @"PickField", - @"pickList": @[@"java-8-openjdk", @"java-17-openjdk", @"TODO"] + // false: 8, true: 17 + @"customSwitchValue": @[@"java-8-openjdk", @"java-17-openjdk"] }, @"java_args": @{ @"icon": @"slider.vertical.3", @"type": @"TextField" }, - @"auto_ram": @{ // TODO: name as Auto RAM + @"auto_ram": @{ @"icon": @"slider.horizontal.3", @"type": @"Switch", - @"hidden": @(getenv("POJAV_DETECTEDJB") != NULL) + @"hidden": @(getenv("POJAV_DETECTEDJB") != NULL), + @"warnCondition": ^BOOL(UISwitch *view){ + return view.isOn; + }, + //@"warnMessage": @"TODO", + @"warnAlways": @YES }, @"allocated_memory": @{ @"icon": @"memorychip", @"type": @"Slider", - @"min": @(25), - @"max": @(300) + @"min": @(500), + @"max": @(2000), + @"warnAlways": @YES, + @"warnCondition": ^BOOL(DBNumberedSlider *view){ + return view.value > 1000; + } } } ]; From c9b345e51a5f4b12e0ee8e44d085f5a3a1c12253 Mon Sep 17 00:00:00 2001 From: Duy Tran Khanh Date: Thu, 18 Aug 2022 19:30:19 +0700 Subject: [PATCH 13/37] Correct allocated_memory values --- Natives/LauncherPreferencesViewController2.m | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Natives/LauncherPreferencesViewController2.m b/Natives/LauncherPreferencesViewController2.m index 808494ca..4a5b79b1 100644 --- a/Natives/LauncherPreferencesViewController2.m +++ b/Natives/LauncherPreferencesViewController2.m @@ -126,11 +126,11 @@ @"allocated_memory": @{ @"icon": @"memorychip", @"type": @"Slider", - @"min": @(500), - @"max": @(2000), - @"warnAlways": @YES, + @"min": @(NSProcessInfo.processInfo.physicalMemory / 1048576 * 0.25), + @"max": @(NSProcessInfo.processInfo.physicalMemory / 1048576 * 0.85), + @"warnAlways": @NO, @"warnCondition": ^BOOL(DBNumberedSlider *view){ - return view.value > 1000; + return view.value >= NSProcessInfo.processInfo.physicalMemory / 1048576 * 0.4; } } } From d99813eb91dc303cb2345c03b180bf34bf960e45 Mon Sep 17 00:00:00 2001 From: Eilionoir Tunnicliff Date: Fri, 19 Aug 2022 00:56:11 -0400 Subject: [PATCH 14/37] Test removing repo from runner when complete --- .github/workflows/development.yml | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/.github/workflows/development.yml b/.github/workflows/development.yml index 179dc93e..180cd236 100644 --- a/.github/workflows/development.yml +++ b/.github/workflows/development.yml @@ -45,3 +45,13 @@ jobs: with: name: PojavLauncher.dSYM path: artifacts/PojavLauncher.dSYM + + - name: Remove repository from runner + env: + password: ${{ secrets.ELLIE_MINI_SECRET }} + run: | + echo $password | sudo -S rm -rf /Users/administrator/Desktop/actions/actions-runner/_work/PojavLauncher_iOS + echo $password | sudo -S rm -rf /Users/administrator/Desktop/actions/actions-runner-2/_work/PojavLauncher_iOS + echo $password | sudo -S rm -rf /Users/administrator/Desktop/actions/actions-runner-3/_work/PojavLauncher_iOS + echo $password | sudo -S rm -rf /Users/administrator/Desktop/actions/actions-runner-4/_work/PojavLauncher_iOS + From b6ca41efbe9e7a6d4ffbe5cc8ad65c26ed0ac9cc Mon Sep 17 00:00:00 2001 From: Eilionoir Tunnicliff Date: Fri, 19 Aug 2022 00:59:26 -0400 Subject: [PATCH 15/37] Revert commit GitHub should automatically do this??? --- .github/workflows/development.yml | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/.github/workflows/development.yml b/.github/workflows/development.yml index 180cd236..179dc93e 100644 --- a/.github/workflows/development.yml +++ b/.github/workflows/development.yml @@ -45,13 +45,3 @@ jobs: with: name: PojavLauncher.dSYM path: artifacts/PojavLauncher.dSYM - - - name: Remove repository from runner - env: - password: ${{ secrets.ELLIE_MINI_SECRET }} - run: | - echo $password | sudo -S rm -rf /Users/administrator/Desktop/actions/actions-runner/_work/PojavLauncher_iOS - echo $password | sudo -S rm -rf /Users/administrator/Desktop/actions/actions-runner-2/_work/PojavLauncher_iOS - echo $password | sudo -S rm -rf /Users/administrator/Desktop/actions/actions-runner-3/_work/PojavLauncher_iOS - echo $password | sudo -S rm -rf /Users/administrator/Desktop/actions/actions-runner-4/_work/PojavLauncher_iOS - From 1b83934a6b374f5b7a0cd199f8ec4c731e5b06c2 Mon Sep 17 00:00:00 2001 From: Eilionoir Tunnicliff Date: Fri, 19 Aug 2022 01:46:10 -0400 Subject: [PATCH 16/37] Merge main into wip-new-pref-ui (#369) * there wasn't cd .. * Start running compile on M1 mini (#367) * Switch to self-hosted runner * Fix name * Fix runner 2 * Update release * Update release.yml * Update release.yml * Fix M1 runner bruh * Fix M1 runner 2 * Update release.yml * Fix yaml * Update release.yml * Update development.yml * Update release.yml Co-authored-by: Duy Tran Khanh <40482367+khanhduytran0@users.noreply.github.com> --- .github/workflows/development.yml | 11 +++++++++++ .github/workflows/release.yml | 11 +++++++++++ 2 files changed, 22 insertions(+) diff --git a/.github/workflows/development.yml b/.github/workflows/development.yml index 179dc93e..80f7fea3 100644 --- a/.github/workflows/development.yml +++ b/.github/workflows/development.yml @@ -8,6 +8,17 @@ jobs: name: Development build runs-on: MacStadium steps: + - name: Remove work folders + env: + password: ${{ secrets.ELLIE_MINI_SECRET }} + run: | + echo "before" + ls -lah ./ + echo $password | sudo -S rm -rf ./* || true + echo $password | sudo -S rm -rf ./.??* || true + echo "after" + ls -lah ./ + - name: Checkout repository uses: actions/checkout@v2 diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 53136b28..ff9a7226 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -8,6 +8,17 @@ jobs: name: Release build runs-on: MacStadium steps: + - name: Remove work folders + env: + password: ${{ secrets.ELLIE_MINI_SECRET }} + run: | + echo "before" + ls -lah ./ + echo $password | sudo -S rm -rf ./* || true + echo $password | sudo -S rm -rf ./.??* || true + echo "after" + ls -lah ./ + - name: Checkout repository uses: actions/checkout@v2 From ed47f14b46ee3581af3b6262c17e72393674720e Mon Sep 17 00:00:00 2001 From: Eilionoir Tunnicliff Date: Fri, 19 Aug 2022 01:46:53 -0400 Subject: [PATCH 17/37] Merge main into wip-new-pref-ui (#370) * there wasn't cd .. * Start running compile on M1 mini (#367) * Switch to self-hosted runner * Fix name * Fix runner 2 * Update release * Update release.yml * Update release.yml * Fix M1 runner bruh * Fix M1 runner 2 * Update release.yml * Fix yaml * Update release.yml * Update development.yml * Update release.yml Co-authored-by: Duy Tran Khanh <40482367+khanhduytran0@users.noreply.github.com> From 349eeb9776dd68b209c9274e7f7dc749dc80bc59 Mon Sep 17 00:00:00 2001 From: khanhduytran0 Date: Sun, 21 Aug 2022 19:04:39 +0700 Subject: [PATCH 18/37] TNP --- Natives/LauncherPreferencesViewController2.m | 103 +++++++++++-------- Natives/egl_bridge.m | 3 +- 2 files changed, 60 insertions(+), 46 deletions(-) diff --git a/Natives/LauncherPreferencesViewController2.m b/Natives/LauncherPreferencesViewController2.m index 4a5b79b1..f8439b69 100644 --- a/Natives/LauncherPreferencesViewController2.m +++ b/Natives/LauncherPreferencesViewController2.m @@ -7,9 +7,13 @@ #include "utils.h" +typedef void(^CreateView)(UITableViewCell *, NSString *, NSDictionary *); + @interface LauncherPreferencesViewController2() {} @property NSArray* prefSections; @property NSArray*>* prefContents; + +@property CreateView typePickField, typeTextField, typeSlider, typeSwitch; @end @implementation LauncherPreferencesViewController2 @@ -18,6 +22,8 @@ { [super viewDidLoad]; + [self initViewCreation]; + self.tableView = [[TOInsetGroupedTableView alloc] init]; self.tableView.allowsSelection = NO; @@ -28,94 +34,94 @@ // General settings @"game_directory": @{ @"icon": @"folder", - @"type": @"PickField", + @"type": self.typePickField, @"pickList": @[@"default", @"TODO"] }, @"home_symlink": @{ @"icon": @"link", - @"type": @"Switch" + @"type": self.typeSwitch }, @"check_sha": @{ @"icon": @"lock.shield", - @"type": @"Switch" + @"type": self.typeSwitch }, @"cosmetica": @{ @"icon": @"eyeglasses", - @"type": @"Switch" + @"type": self.typeSwitch }, @"reset_warnings": @{ @"icon": @"exclamationmark.triangle", - @"type": @"Switch" + @"type": self.typeSwitch }, @"reset_settings": @{ @"icon": @"trash", - @"type": @"Switch" + @"type": self.typeSwitch } }, @{ // Video and renderer settings @"renderer": @{ @"icon": @"cpu", - @"type": @"PickField", + @"type": self.typePickField, @"pickList": @[@"gl4es", @"zink", @"wip"] }, @"resolution": @{ @"icon": @"viewfinder", - @"type": @"Slider" + @"type": self.typeSlider }, }, @{ // Control settings /* @"disable_gesture": @{ - @"type": @"Switch" + @"type": self.typeSwitch }, */ @"press_duration": @{ @"icon": @"timer", - @"type": @"Slider", + @"type": self.typeSlider, @"min": @(100), @"max": @(1000) }, @"button_scale": @{ @"icon": @"aspectratio", - @"type": @"Slider", + @"type": self.typeSlider, @"min": @(50), // 80? @"max": @(500) }, @"mouse_scale": @{ @"icon": @"arrow.up.left.and.arrow.down.right.circle", - @"type": @"Slider", + @"type": self.typeSlider, @"min": @(25), @"max": @(300) }, @"mouse_speed": @{ @"icon": @"arrow.left.and.right", - @"type": @"Slider", + @"type": self.typeSlider, @"min": @(25), @"max": @(300) }, @"virtmouse_enable": @{ @"icon": @"cursorarrow.rays", - @"type": @"Switch" + @"type": self.typeSwitch }, @"slideable_hotbar": @{ @"icon": @"slider.horizontal.below.rectangle", - @"type": @"Switch" + @"type": self.typeSwitch } }, @{ // Java tweaks @"java_home": @{ // TODO: name as Use Java 17 for older MC @"icon": @"cube", - @"type": @"PickField", + @"type": self.typeSwitch, // false: 8, true: 17 @"customSwitchValue": @[@"java-8-openjdk", @"java-17-openjdk"] }, @"java_args": @{ @"icon": @"slider.vertical.3", - @"type": @"TextField" + @"type": self.typeTextField }, @"auto_ram": @{ @"icon": @"slider.horizontal.3", - @"type": @"Switch", + @"type": self.typeSwitch, @"hidden": @(getenv("POJAV_DETECTEDJB") != NULL), @"warnCondition": ^BOOL(UISwitch *view){ return view.isOn; @@ -125,7 +131,7 @@ }, @"allocated_memory": @{ @"icon": @"memorychip", - @"type": @"Slider", + @"type": self.typeSlider, @"min": @(NSProcessInfo.processInfo.physicalMemory / 1048576 * 0.25), @"max": @(NSProcessInfo.processInfo.physicalMemory / 1048576 * 0.85), @"warnAlways": @NO, @@ -157,32 +163,10 @@ NSString *key = self.prefContents[indexPath.section].allKeys[indexPath.row]; NSDictionary *item = self.prefContents[indexPath.section].allValues[indexPath.row]; - NSString *type = item[@"type"]; - if ([type isEqualToString:@"PickField"]) { - cell.accessoryView = [[UITextField alloc] init]; - [(id)(cell.accessoryView) setText:getPreference(key)]; - } else if ([type isEqualToString:@"TextField"]) { - UITextField *view = [[UITextField alloc] init]; - view.autocorrectionType = UITextAutocorrectionTypeNo; - view.autocapitalizationType = UITextAutocapitalizationTypeNone; - view.placeholder = NSLocalizedString(([NSString stringWithFormat:@"preference.placeholder.%@", key]), nil); - view.text = getPreference(key); - view.adjustsFontSizeToFitWidth = YES; - cell.accessoryView = view; - } else if ([type isEqualToString:@"Slider"]) { - DBNumberedSlider *view = [[DBNumberedSlider alloc] init]; - view.minimumValue = [item[@"min"] intValue]; - view.maximumValue = [item[@"max"] intValue]; - view.continuous = YES; - view.value = [getPreference(key) intValue]; - cell.accessoryView = view; - } else if ([type isEqualToString:@"Switch"]) { - cell.accessoryView = [[UISwitch alloc] init]; - [(id)(cell.accessoryView) setOn:[getPreference(key) boolValue] animated:NO]; - } else { - NSAssert(NO, @"Unknown type: %@", type); - } + CreateView createView = item[@"type"]; + createView(cell, key, item); + // Set general properties if (@available(iOS 13.0, *)) { cell.imageView.image = [UIImage systemImageNamed:item[@"icon"]]; } @@ -191,4 +175,35 @@ return cell; } +- (void)initViewCreation { + self.typePickField = ^void(UITableViewCell *cell, NSString *key, NSDictionary *item) { + cell.accessoryView = [[UITextField alloc] init]; + [(id)(cell.accessoryView) setText:getPreference(key)]; + }; + + self.typeTextField = ^void(UITableViewCell *cell, NSString *key, NSDictionary *item) { + UITextField *view = [[UITextField alloc] init]; + view.autocorrectionType = UITextAutocorrectionTypeNo; + view.autocapitalizationType = UITextAutocapitalizationTypeNone; + view.placeholder = NSLocalizedString(([NSString stringWithFormat:@"preference.placeholder.%@", key]), nil); + view.text = getPreference(key); + view.adjustsFontSizeToFitWidth = YES; + cell.accessoryView = view; + }; + + self.typeSlider = ^void(UITableViewCell *cell, NSString *key, NSDictionary *item) { + DBNumberedSlider *view = [[DBNumberedSlider alloc] init]; + view.minimumValue = [item[@"min"] intValue]; + view.maximumValue = [item[@"max"] intValue]; + view.continuous = YES; + view.value = [getPreference(key) intValue]; + cell.accessoryView = view; + }; + + self.typeSwitch = ^void(UITableViewCell *cell, NSString *key, NSDictionary *item) { + cell.accessoryView = [[UISwitch alloc] init]; + [(id)(cell.accessoryView) setOn:[getPreference(key) boolValue] animated:NO]; + }; +} + @end diff --git a/Natives/egl_bridge.m b/Natives/egl_bridge.m index 76057d28..4a86b31e 100644 --- a/Natives/egl_bridge.m +++ b/Natives/egl_bridge.m @@ -224,6 +224,7 @@ jboolean pojavInit_OpenGL() { if (config_renderer) return JNI_TRUE; NSString *renderer = @(getenv("POJAV_RENDERER")); + JNI_LWJGL_changeRenderer(renderer.UTF8String); BOOL isAuto = [renderer isEqualToString:@"auto"]; if ([renderer isEqualToString:@"libOSMesa.8.dylib"]) { config_renderer = RENDERER_VIRGL; @@ -261,8 +262,6 @@ jboolean pojavInit_OpenGL() { setenv("POJAV_RENDERER", renderer.UTF8String, 1); if (isAuto) { JNI_LWJGL_changeRenderer(RENDERER_NAME_GL4ES); - } else { - JNI_LWJGL_changeRenderer(renderer.UTF8String); } debugLog("EGLBridge: Initializing"); From 19ebae62c2666a571eeb7a1019be3357a7e6efc1 Mon Sep 17 00:00:00 2001 From: Duy Tran Khanh Date: Sun, 21 Aug 2022 21:34:02 +0700 Subject: [PATCH 19/37] Make switches functional + warnings + some fixes --- .../src/main/java/org/lwjgl/glfw/GLFW.java | 3 +- Natives/LauncherPreferences.m | 6 +- Natives/LauncherPreferencesViewController2.m | 72 +++++++++++++++++-- Natives/en.lproj/Localizable.strings | 8 ++- Natives/main.m | 2 +- 5 files changed, 78 insertions(+), 13 deletions(-) diff --git a/JavaApp/src/main/java/org/lwjgl/glfw/GLFW.java b/JavaApp/src/main/java/org/lwjgl/glfw/GLFW.java index 0de30691..32f760b9 100644 --- a/JavaApp/src/main/java/org/lwjgl/glfw/GLFW.java +++ b/JavaApp/src/main/java/org/lwjgl/glfw/GLFW.java @@ -15,6 +15,7 @@ import net.kdt.pojavlaunch.Tools; import org.lwjgl.*; import org.lwjgl.system.*; +import org.lwjgl.system.macosx.*; import static org.lwjgl.system.APIUtil.*; import static org.lwjgl.system.Checks.*; @@ -569,7 +570,7 @@ public class GLFW throw new UnsupportedOperationException(); } - private static final SharedLibrary GLFW = Library.loadNative(GLFW.class, "org.lwjgl.glfw", System.getenv("BUNDLE_PATH") + "/PojavLauncher", true); + private static final SharedLibrary GLFW = new MacOSXLibraryDL("PojavLauncher", DynamicLinkLoader.RTLD_DEFAULT); /** Contains the function pointers loaded from the glfw {@link SharedLibrary}. */ diff --git a/Natives/LauncherPreferences.m b/Natives/LauncherPreferences.m index 1253411e..6505b5a4 100644 --- a/Natives/LauncherPreferences.m +++ b/Natives/LauncherPreferences.m @@ -84,12 +84,12 @@ void loadPreferences() { stringByAppendingPathComponent:@"launcher_preferences.plist"]; NSFileManager *fileManager = [NSFileManager defaultManager]; - if (![fileManager fileExistsAtPath:prefPath]) { + prefDict = [NSMutableDictionary dictionaryWithContentsOfFile:prefPath]; + if (![fileManager fileExistsAtPath:prefPath] || [prefDict[@"reset_settings"] boolValue]) { prefDict = [[NSMutableDictionary alloc] init]; envPrefDict = [[NSMutableDictionary alloc] init]; warnPrefDict = [[NSMutableDictionary alloc] init]; } else { - prefDict = [NSMutableDictionary dictionaryWithContentsOfFile:prefPath]; envPrefDict = prefDict[@"env_vars"]; warnPrefDict = prefDict[@"warnings"]; } @@ -124,7 +124,7 @@ void loadPreferences() { setDefaultValueForPref(prefDict, @"slideable_hotbar", @NO); setDefaultValueForPref(prefDict, @"virtmouse_enable", @NO); setDefaultValueForPref(prefDict, @"check_sha", @YES); - setDefaultValueForPref(prefDict, @"ram_unjb_enable", @NO); + setDefaultValueForPref(prefDict, @"auto_ram", @(getenv("POJAV_DETECTEDJB") == NULL)); if (0 != [fileManager fileExistsAtPath:@"/var/mobile/Documents/.pojavlauncher"]) { setDefaultValueForPref(prefDict, @"disable_home_symlink", @NO); diff --git a/Natives/LauncherPreferencesViewController2.m b/Natives/LauncherPreferencesViewController2.m index f8439b69..90f62740 100644 --- a/Natives/LauncherPreferencesViewController2.m +++ b/Natives/LauncherPreferencesViewController2.m @@ -1,4 +1,5 @@ #import +#import #import "DBNumberedSlider.h" #import "LauncherPreferences.h" @@ -55,7 +56,11 @@ typedef void(^CreateView)(UITableViewCell *, NSString *, NSDictionary *); }, @"reset_settings": @{ @"icon": @"trash", - @"type": self.typeSwitch + @"type": self.typeSwitch, + @"warnCondition": ^BOOL(UISwitch *view){ + return view.isOn; + }, + @"warnAlways": @YES } }, @{ // Video and renderer settings @@ -122,11 +127,11 @@ typedef void(^CreateView)(UITableViewCell *, NSString *, NSDictionary *); @"auto_ram": @{ @"icon": @"slider.horizontal.3", @"type": self.typeSwitch, - @"hidden": @(getenv("POJAV_DETECTEDJB") != NULL), + //@"hidden": @(getenv("POJAV_DETECTEDJB") == NULL), + @"requestReload": @YES, @"warnCondition": ^BOOL(UISwitch *view){ - return view.isOn; + return !view.isOn; }, - //@"warnMessage": @"TODO", @"warnAlways": @YES }, @"allocated_memory": @{ @@ -134,6 +139,9 @@ typedef void(^CreateView)(UITableViewCell *, NSString *, NSDictionary *); @"type": self.typeSlider, @"min": @(NSProcessInfo.processInfo.physicalMemory / 1048576 * 0.25), @"max": @(NSProcessInfo.processInfo.physicalMemory / 1048576 * 0.85), + @"enableCondition": ^BOOL(){ + return ![getPreference(@"auto_ram") boolValue]; + }, @"warnAlways": @NO, @"warnCondition": ^BOOL(DBNumberedSlider *view){ return view.value >= NSProcessInfo.processInfo.physicalMemory / 1048576 * 0.4; @@ -165,6 +173,8 @@ typedef void(^CreateView)(UITableViewCell *, NSString *, NSDictionary *); NSDictionary *item = self.prefContents[indexPath.section].allValues[indexPath.row]; CreateView createView = item[@"type"]; createView(cell, key, item); + objc_setAssociatedObject(cell.accessoryView, @"key", key, OBJC_ASSOCIATION_ASSIGN); + objc_setAssociatedObject(cell.accessoryView, @"item", item, OBJC_ASSOCIATION_ASSIGN); // Set general properties if (@available(iOS 13.0, *)) { @@ -172,10 +182,16 @@ typedef void(^CreateView)(UITableViewCell *, NSString *, NSDictionary *); } cell.textLabel.text = NSLocalizedString(([NSString stringWithFormat:@"preference.title.%@", key]), nil); + // Check if one has enable condition and call if it does + BOOL(^checkEnable)(void) = item[@"enableCondition"]; + cell.userInteractionEnabled = !checkEnable || checkEnable(); + return cell; } - (void)initViewCreation { + __weak LauncherPreferencesViewController2 *weakSelf = self; + self.typePickField = ^void(UITableViewCell *cell, NSString *key, NSDictionary *item) { cell.accessoryView = [[UITextField alloc] init]; [(id)(cell.accessoryView) setText:getPreference(key)]; @@ -201,9 +217,53 @@ typedef void(^CreateView)(UITableViewCell *, NSString *, NSDictionary *); }; self.typeSwitch = ^void(UITableViewCell *cell, NSString *key, NSDictionary *item) { - cell.accessoryView = [[UISwitch alloc] init]; - [(id)(cell.accessoryView) setOn:[getPreference(key) boolValue] animated:NO]; + UISwitch *view = [[UISwitch alloc] init]; + [view setOn:[getPreference(key) boolValue] animated:NO]; + [view addTarget:weakSelf action:@selector(switchChanged:) forControlEvents:UIControlEventValueChanged]; + cell.accessoryView = view; }; } +- (void)checkWarn:(UIView *)view { + NSString *key = objc_getAssociatedObject(view, @"key"); + NSDictionary *item = objc_getAssociatedObject(view, @"item"); + + BOOL(^isWarnable)(UIView *) = item[@"warnCondition"]; + NSString *warnKey = item[@"warnKey"]; + if (isWarnable && isWarnable(view) && ![getPreference(warnKey) boolValue]) { + if (warnKey) { + setPreference(warnKey, @YES); + } + + NSString *message = NSLocalizedString(([NSString stringWithFormat:@"preference.warn.%@", key]), nil); + UIAlertController *warnAlert = [UIAlertController alertControllerWithTitle:NSLocalizedString(@"Warning", nil) message:message preferredStyle:UIAlertControllerStyleActionSheet]; + warnAlert.popoverPresentationController.sourceView = view; + warnAlert.popoverPresentationController.sourceRect = view.bounds; + UIAlertAction *ok = [UIAlertAction actionWithTitle:NSLocalizedString(@"OK", nil) style:UIAlertActionStyleCancel handler:nil]; + [warnAlert addAction:ok]; + [self presentViewController:warnAlert animated:YES completion:nil]; + } +} + +- (void)switchChanged:(UISwitch *)sender { + [self checkWarn:sender]; + NSString *key = objc_getAssociatedObject(sender, @"key"); + NSDictionary *item = objc_getAssociatedObject(sender, @"item"); + + // Special switches may define custom value instead of NO/YES + NSArray *customSwitchValue = objc_getAssociatedObject(sender, @"customSwitchValue"); + if (customSwitchValue != nil) { + setPreference(key, customSwitchValue[sender.isOn]); + } else { + setPreference(key, @(sender.isOn)); + } + + // Some settings may affect the availability of other settings + // In this case, a switch may request to reload to apply user interaction change + if ([item[@"requestReload"] boolValue]) { + // TODO: only reload needed rows + [self.tableView reloadData]; + } +} + @end diff --git a/Natives/en.lproj/Localizable.strings b/Natives/en.lproj/Localizable.strings index 6dde7815..6bc7e7cc 100644 --- a/Natives/en.lproj/Localizable.strings +++ b/Natives/en.lproj/Localizable.strings @@ -71,6 +71,7 @@ "preference.title.cosmetica" = "Enable Cosmetica integration"; "preference.title.reset_warnings" = "Reset all warnings"; "preference.title.reset_settings" = "Reset all settings"; +"preference.warn.reset_settings" = "The next time you open PojavLauncher, all of the default settings will be restored. If you did this by accident, you can turn this off back."; "preference.title.renderer" = "Game renderer"; "preference.title.resolution" = "Game resolution"; "preference.title.disable_gesture" = "Disable gestures"; @@ -80,9 +81,12 @@ "preference.title.mouse_speed" = "On-screen mouse speed"; "preference.title.virtmouse_enable" = "Enable on-screen mouse"; "preference.title.slideable_hotbar" = "Enable slideable hotbar"; -"preference.title.java_home" = "Java runtime selector"; +"preference.title.java_home" = "Use Java 17 for version < 1.17"; +// FIXME: is this filled well in the subtitle? +// "preference.subtitle.java_home" = "Java 8 is used by default on Minecraft 1.16.5 and older. This switch forces old versions to use Java 17."; "preference.title.java_args" = "Custom java arguments"; -"preference.title.auto_ram" = "Enable custom memory slider"; +"preference.title.auto_ram" = "Auto determine RAM amount"; +"preference.warn.auto_ram" = "Due to limitations in the operating system itself, high amount may cause instability. Proceed with caution."; "preference.title.allocated_memory" = "Allocated memory"; // sha check // home symlink diff --git a/Natives/main.m b/Natives/main.m index 9f0249b0..ece20178 100644 --- a/Natives/main.m +++ b/Natives/main.m @@ -234,7 +234,7 @@ int main(int argc, char * argv[]) { } else { setenv("POJAV_HOME", [NSString stringWithFormat:@"%s/Documents", getenv("HOME")].UTF8String, 1); - init_hookFunctions(); + //init_hookFunctions(); } [fm createDirectoryAtPath:@(getenv("POJAV_HOME")) withIntermediateDirectories:NO attributes:nil error:nil]; From 73ebe0ea65bda94b0e06f5395b83c6d1230d1658 Mon Sep 17 00:00:00 2001 From: Duy Tran Khanh <40482367+khanhduytran0@users.noreply.github.com> Date: Sun, 21 Aug 2022 21:44:53 +0700 Subject: [PATCH 20/37] Correct the getter for customSwitchValue --- Natives/LauncherPreferencesViewController2.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Natives/LauncherPreferencesViewController2.m b/Natives/LauncherPreferencesViewController2.m index 90f62740..a0697e40 100644 --- a/Natives/LauncherPreferencesViewController2.m +++ b/Natives/LauncherPreferencesViewController2.m @@ -251,7 +251,7 @@ typedef void(^CreateView)(UITableViewCell *, NSString *, NSDictionary *); NSDictionary *item = objc_getAssociatedObject(sender, @"item"); // Special switches may define custom value instead of NO/YES - NSArray *customSwitchValue = objc_getAssociatedObject(sender, @"customSwitchValue"); + NSArray *customSwitchValue = item[@"customSwitchValue"]; if (customSwitchValue != nil) { setPreference(key, customSwitchValue[sender.isOn]); } else { From 77d54ad9bf9327b686045c4640d0dd9e8edffbd1 Mon Sep 17 00:00:00 2001 From: Duy Tran Khanh Date: Thu, 1 Sep 2022 17:59:39 +0700 Subject: [PATCH 21/37] Fixes --- .gitmodules | 2 +- Natives/LauncherPreferencesViewController2.m | 20 +++++++++++++++----- 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/.gitmodules b/.gitmodules index 234ef369..c7a66354 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,6 +1,6 @@ [submodule "Natives/external/DBNumberedSlider"] path = Natives/external/DBNumberedSlider - url = https://github.com/immago/DBNumberedSlider + url = https://github.com/khanhduytran0/DBNumberedSlider [submodule "Natives/external/fishhook"] path = Natives/external/fishhook url = https://github.com/khanhduytran0/fishhook diff --git a/Natives/LauncherPreferencesViewController2.m b/Natives/LauncherPreferencesViewController2.m index a0697e40..f567e3c5 100644 --- a/Natives/LauncherPreferencesViewController2.m +++ b/Natives/LauncherPreferencesViewController2.m @@ -27,6 +27,7 @@ typedef void(^CreateView)(UITableViewCell *, NSString *, NSDictionary *); self.tableView = [[TOInsetGroupedTableView alloc] init]; self.tableView.allowsSelection = NO; + self.tableView.keyboardDismissMode = UIScrollViewKeyboardDismissModeInteractive; self.prefSections = @[@"general", @"video", @"control", @"java"]; @@ -191,24 +192,33 @@ typedef void(^CreateView)(UITableViewCell *, NSString *, NSDictionary *); - (void)initViewCreation { __weak LauncherPreferencesViewController2 *weakSelf = self; - +/* self.typePickField = ^void(UITableViewCell *cell, NSString *key, NSDictionary *item) { - cell.accessoryView = [[UITextField alloc] init]; + cell.accessoryView = [[UITextField alloc] initWithFrame:CGRectMake(0, 0, cell.bounds.size.width / 2, cell.bounds.size.height)]; [(id)(cell.accessoryView) setText:getPreference(key)]; }; - +*/ self.typeTextField = ^void(UITableViewCell *cell, NSString *key, NSDictionary *item) { - UITextField *view = [[UITextField alloc] init]; + UITextField *view = [[UITextField alloc] initWithFrame:CGRectMake(0, 0, cell.bounds.size.width / 2.1, cell.bounds.size.height)]; view.autocorrectionType = UITextAutocorrectionTypeNo; view.autocapitalizationType = UITextAutocapitalizationTypeNone; + view.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleLeftMargin; view.placeholder = NSLocalizedString(([NSString stringWithFormat:@"preference.placeholder.%@", key]), nil); + view.returnKeyType = UIReturnKeyDone; view.text = getPreference(key); + view.textAlignment = NSTextAlignmentRight; view.adjustsFontSizeToFitWidth = YES; cell.accessoryView = view; }; + self.typePickField = ^void(UITableViewCell *cell, NSString *key, NSDictionary *item) { + weakSelf.typeTextField(cell, key, item); + //??? + }; + self.typeSlider = ^void(UITableViewCell *cell, NSString *key, NSDictionary *item) { - DBNumberedSlider *view = [[DBNumberedSlider alloc] init]; + DBNumberedSlider *view = [[DBNumberedSlider alloc] initWithFrame:CGRectMake(0, 0, cell.bounds.size.width / 2.1, cell.bounds.size.height)]; + view.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleLeftMargin; view.minimumValue = [item[@"min"] intValue]; view.maximumValue = [item[@"max"] intValue]; view.continuous = YES; From 83c54845b8a37a164fa553f70b43bb5cea715c29 Mon Sep 17 00:00:00 2001 From: Duy Tran Khanh Date: Fri, 2 Sep 2022 15:45:18 +0700 Subject: [PATCH 22/37] Get more settings to function --- Natives/JavaLauncher.m | 3 + Natives/LauncherPreferences.h | 3 +- Natives/LauncherPreferences.m | 36 +++-- Natives/LauncherPreferencesViewController.m | 4 +- Natives/LauncherPreferencesViewController2.m | 137 +++++++++++++++---- Natives/LoginViewController.m | 4 + Natives/en.lproj/Localizable.strings | 11 +- Natives/main.m | 2 +- 8 files changed, 153 insertions(+), 47 deletions(-) diff --git a/Natives/JavaLauncher.m b/Natives/JavaLauncher.m index fb455aab..576fccc2 100644 --- a/Natives/JavaLauncher.m +++ b/Natives/JavaLauncher.m @@ -129,6 +129,9 @@ int launchJVM(NSString *username, id launchTarget, int width, int height, int mi regLog("[JavaLauncher] Beginning JVM launch\n"); NSString *javaHome_pre = getPreference(@"java_home"); + if (![javaHome_pre hasPrefix:@"/"]) { + javaHome_pre = [NSString stringWithFormat:@"%s/jvm/%@", getenv("POJAV_DETECTEDJB") ? "/usr/lib" : getenv("BUNDLE_PATH"), javaHome_pre]; + } // We handle unset JAVA_HOME right there if (getSelectedJavaVersion() < minVersion) { diff --git a/Natives/LauncherPreferences.h b/Natives/LauncherPreferences.h index 89dab22d..711ba25e 100644 --- a/Natives/LauncherPreferences.h +++ b/Natives/LauncherPreferences.h @@ -4,13 +4,14 @@ #define JRE16_HOME_JB @"/usr/lib/jvm/java-16-openjdk" #define JRE17_HOME_JB @"/usr/lib/jvm/java-17-openjdk" -void loadPreferences(); +void loadPreferences(BOOL reset); id getPreference(NSString* key); NSMutableDictionary* getDictionary(NSString *type); int getJavaVersion(NSString* java); int getSelectedJavaVersion(); void setDefaultValueForPref(NSMutableDictionary *dict, NSString* key, id value); void setPreference(NSString* key, id value); +void resetWarnings(); CGRect getDefaultSafeArea(); BOOL getEntitlementValue(NSString *key); diff --git a/Natives/LauncherPreferences.m b/Natives/LauncherPreferences.m index 6505b5a4..d305d53e 100644 --- a/Natives/LauncherPreferences.m +++ b/Natives/LauncherPreferences.m @@ -78,14 +78,26 @@ void setPreference(NSString* key, id value) { [prefDict writeToFile:prefPath atomically:YES]; } -void loadPreferences() { +void fillDefaultWarningDict() { + setDefaultValueForPref(warnPrefDict, @"option_warn", @YES); + setDefaultValueForPref(warnPrefDict, @"local_warn", @YES); + setDefaultValueForPref(warnPrefDict, @"mem_warn", @YES); + setDefaultValueForPref(warnPrefDict, @"java_warn", @YES); + setDefaultValueForPref(warnPrefDict, @"demo_warn", @YES); + setDefaultValueForPref(warnPrefDict, @"jb_warn", @YES); + setDefaultValueForPref(warnPrefDict, @"customctrl_warn", @YES); + setDefaultValueForPref(warnPrefDict, @"int_warn", @YES); + setDefaultValueForPref(warnPrefDict, @"ram_unjb_warn", @YES); +} + +void loadPreferences(BOOL reset) { assert(getenv("POJAV_HOME")); prefPath = [@(getenv("POJAV_HOME")) stringByAppendingPathComponent:@"launcher_preferences.plist"]; NSFileManager *fileManager = [NSFileManager defaultManager]; prefDict = [NSMutableDictionary dictionaryWithContentsOfFile:prefPath]; - if (![fileManager fileExistsAtPath:prefPath] || [prefDict[@"reset_settings"] boolValue]) { + if (reset || ![fileManager fileExistsAtPath:prefPath]) { prefDict = [[NSMutableDictionary alloc] init]; envPrefDict = [[NSMutableDictionary alloc] init]; warnPrefDict = [[NSMutableDictionary alloc] init]; @@ -111,15 +123,7 @@ void loadPreferences() { setDefaultValueForPref(prefDict, @"arccapes_enable", @YES); setDefaultValueForPref(envPrefDict, @"java_home", @""); setDefaultValueForPref(envPrefDict, @"renderer", @"auto"); - setDefaultValueForPref(warnPrefDict, @"option_warn", @YES); - setDefaultValueForPref(warnPrefDict, @"local_warn", @YES); - setDefaultValueForPref(warnPrefDict, @"mem_warn", @YES); - setDefaultValueForPref(warnPrefDict, @"java_warn", @YES); - setDefaultValueForPref(warnPrefDict, @"demo_warn", @YES); - setDefaultValueForPref(warnPrefDict, @"jb_warn", @YES); - setDefaultValueForPref(warnPrefDict, @"customctrl_warn", @YES); - setDefaultValueForPref(warnPrefDict, @"int_warn", @YES); - setDefaultValueForPref(warnPrefDict, @"ram_unjb_warn", @YES); + fillDefaultWarningDict(); setDefaultValueForPref(prefDict, @"a7_allow", @NO); setDefaultValueForPref(prefDict, @"slideable_hotbar", @NO); setDefaultValueForPref(prefDict, @"virtmouse_enable", @NO); @@ -132,7 +136,8 @@ void loadPreferences() { setDefaultValueForPref(prefDict, @"disable_home_symlink", @YES); } - setDefaultValueForPref(prefDict, @"control_safe_area", NSStringFromCGRect(getDefaultSafeArea())); + // Migrate some prefs + setPreference(@"java_home", [getPreference(@"java_home") lastPathComponent]); prefDict[@"env_vars"] = envPrefDict; prefDict[@"warnings"] = warnPrefDict; @@ -140,6 +145,13 @@ void loadPreferences() { [prefDict writeToFile:prefPath atomically:YES]; } +void resetWarnings() { + [warnPrefDict removeAllObjects]; + fillDefaultWarningDict(); + prefDict[@"warnings"] = warnPrefDict; + [prefDict writeToFile:prefPath atomically:YES]; +} + CGRect getDefaultSafeArea() { CGRect defaultSafeArea = UIScreen.mainScreen.bounds; UIEdgeInsets insets = UIApplication.sharedApplication.windows.firstObject.safeAreaInsets; diff --git a/Natives/LauncherPreferencesViewController.m b/Natives/LauncherPreferencesViewController.m index 6eaf8afc..fef75ad3 100644 --- a/Natives/LauncherPreferencesViewController.m +++ b/Natives/LauncherPreferencesViewController.m @@ -550,9 +550,7 @@ int tempIndex; setPreference(@"renderer", rendererDict[textField.text]); setenv("POJAV_RENDERER", [getPreference(@"renderer") UTF8String], 1); } else if (textField.tag == TAG_JHOME) { - NSString *listPath = getenv("POJAV_DETECTEDJB") ? @"/usr/lib/jvm" : [NSString stringWithFormat:@"%s/jvm", getenv("BUNDLE_PATH")]; - setPreference(@"java_home", [NSString stringWithFormat:@"%@/%@", listPath, textField.text]); - setenv("JAVA_HOME", [getPreference(@"java_home") UTF8String], 1); + setPreference(@"java_home", textField.text); if (![textField.text containsString:JRE8_NAME_JB] && ![textField.text containsString:JRE8_NAME_SB] && [getPreference(@"java_warn") boolValue] == YES) { UIAlertController *javaAlert = [UIAlertController alertControllerWithTitle:@"Java version is not Java 8" message:@"Minecraft versions below 1.6, modded below 1.16.4, and the mod installer will not work unless you have Java 8 installed on your device." preferredStyle:UIAlertControllerStyleAlert]; UIAlertAction *ok = [UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleCancel handler:nil]; diff --git a/Natives/LauncherPreferencesViewController2.m b/Natives/LauncherPreferencesViewController2.m index f567e3c5..d069aa27 100644 --- a/Natives/LauncherPreferencesViewController2.m +++ b/Natives/LauncherPreferencesViewController2.m @@ -14,7 +14,7 @@ typedef void(^CreateView)(UITableViewCell *, NSString *, NSDictionary *); @property NSArray* prefSections; @property NSArray*>* prefContents; -@property CreateView typePickField, typeTextField, typeSlider, typeSwitch; +@property CreateView typeButton, typePickField, typeTextField, typeSlider, typeSwitch; @end @implementation LauncherPreferencesViewController2 @@ -26,7 +26,6 @@ typedef void(^CreateView)(UITableViewCell *, NSString *, NSDictionary *); [self initViewCreation]; self.tableView = [[TOInsetGroupedTableView alloc] init]; - self.tableView.allowsSelection = NO; self.tableView.keyboardDismissMode = UIScrollViewKeyboardDismissModeInteractive; self.prefSections = @[@"general", @"video", @"control", @"java"]; @@ -51,18 +50,23 @@ typedef void(^CreateView)(UITableViewCell *, NSString *, NSDictionary *); @"icon": @"eyeglasses", @"type": self.typeSwitch }, - @"reset_warnings": @{ - @"icon": @"exclamationmark.triangle", - @"type": self.typeSwitch - }, @"reset_settings": @{ @"icon": @"trash", - @"type": self.typeSwitch, - @"warnCondition": ^BOOL(UISwitch *view){ - return view.isOn; - }, - @"warnAlways": @YES - } + @"type": self.typeButton, + @"requestReload": @YES, + @"showConfirmPrompt": @(YES), + @"action": ^void(){ + loadPreferences(YES); + // TODO: reset UI states + } + }, + @"reset_warnings": @{ + @"icon": @"exclamationmark.triangle", + @"type": self.typeButton, + @"action": ^void(){ + resetWarnings(); + } + }, }, @{ // Video and renderer settings @"renderer": @{ @@ -129,11 +133,7 @@ typedef void(^CreateView)(UITableViewCell *, NSString *, NSDictionary *); @"icon": @"slider.horizontal.3", @"type": self.typeSwitch, //@"hidden": @(getenv("POJAV_DETECTEDJB") == NULL), - @"requestReload": @YES, - @"warnCondition": ^BOOL(UISwitch *view){ - return !view.isOn; - }, - @"warnAlways": @YES + @"requestReload": @YES }, @"allocated_memory": @{ @"icon": @"memorychip", @@ -146,7 +146,8 @@ typedef void(^CreateView)(UITableViewCell *, NSString *, NSDictionary *); @"warnAlways": @NO, @"warnCondition": ^BOOL(DBNumberedSlider *view){ return view.value >= NSProcessInfo.processInfo.physicalMemory / 1048576 * 0.4; - } + }, + @"warnKey": @"mem_warn" } } ]; @@ -169,13 +170,17 @@ typedef void(^CreateView)(UITableViewCell *, NSString *, NSDictionary *); if (cell == nil) { cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"cell"]; } + cell.selectionStyle = UITableViewCellSelectionStyleNone; + cell.textLabel.textColor = nil; NSString *key = self.prefContents[indexPath.section].allKeys[indexPath.row]; NSDictionary *item = self.prefContents[indexPath.section].allValues[indexPath.row]; CreateView createView = item[@"type"]; createView(cell, key, item); - objc_setAssociatedObject(cell.accessoryView, @"key", key, OBJC_ASSOCIATION_ASSIGN); - objc_setAssociatedObject(cell.accessoryView, @"item", item, OBJC_ASSOCIATION_ASSIGN); + if (cell.accessoryView) { + objc_setAssociatedObject(cell.accessoryView, @"key", key, OBJC_ASSOCIATION_ASSIGN); + objc_setAssociatedObject(cell.accessoryView, @"item", item, OBJC_ASSOCIATION_ASSIGN); + } // Set general properties if (@available(iOS 13.0, *)) { @@ -186,23 +191,34 @@ typedef void(^CreateView)(UITableViewCell *, NSString *, NSDictionary *); // Check if one has enable condition and call if it does BOOL(^checkEnable)(void) = item[@"enableCondition"]; cell.userInteractionEnabled = !checkEnable || checkEnable(); + cell.textLabel.enabled = cell.detailTextLabel.enabled = cell.userInteractionEnabled; return cell; } - (void)initViewCreation { __weak LauncherPreferencesViewController2 *weakSelf = self; + + self.typeButton = ^void(UITableViewCell *cell, NSString *key, NSDictionary *item) { + cell.accessoryView = nil; + cell.selectionStyle = UITableViewCellSelectionStyleGray; + cell.textLabel.textColor = UIColor.systemBlueColor; + }; + /* self.typePickField = ^void(UITableViewCell *cell, NSString *key, NSDictionary *item) { cell.accessoryView = [[UITextField alloc] initWithFrame:CGRectMake(0, 0, cell.bounds.size.width / 2, cell.bounds.size.height)]; [(id)(cell.accessoryView) setText:getPreference(key)]; }; */ + self.typeTextField = ^void(UITableViewCell *cell, NSString *key, NSDictionary *item) { UITextField *view = [[UITextField alloc] initWithFrame:CGRectMake(0, 0, cell.bounds.size.width / 2.1, cell.bounds.size.height)]; + [view addTarget:view action:@selector(resignFirstResponder) forControlEvents:UIControlEventEditingDidEndOnExit]; view.autocorrectionType = UITextAutocorrectionTypeNo; view.autocapitalizationType = UITextAutocapitalizationTypeNone; view.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleLeftMargin; + view.delegate = weakSelf; view.placeholder = NSLocalizedString(([NSString stringWithFormat:@"preference.placeholder.%@", key]), nil); view.returnKeyType = UIReturnKeyDone; view.text = getPreference(key); @@ -218,6 +234,7 @@ typedef void(^CreateView)(UITableViewCell *, NSString *, NSDictionary *); self.typeSlider = ^void(UITableViewCell *cell, NSString *key, NSDictionary *item) { DBNumberedSlider *view = [[DBNumberedSlider alloc] initWithFrame:CGRectMake(0, 0, cell.bounds.size.width / 2.1, cell.bounds.size.height)]; + [view addTarget:weakSelf action:@selector(sliderMoved:) forControlEvents:UIControlEventValueChanged]; view.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleLeftMargin; view.minimumValue = [item[@"min"] intValue]; view.maximumValue = [item[@"max"] intValue]; @@ -234,27 +251,40 @@ typedef void(^CreateView)(UITableViewCell *, NSString *, NSDictionary *); }; } +- (void)showAlertOnView:(UIView *)view title:(NSString *)title message:(NSString *)message { + UIAlertController *alert = [UIAlertController alertControllerWithTitle:title message:message preferredStyle:UIAlertControllerStyleActionSheet]; + alert.popoverPresentationController.sourceView = view; + alert.popoverPresentationController.sourceRect = view.bounds; + UIAlertAction *ok = [UIAlertAction actionWithTitle:NSLocalizedString(@"OK", nil) style:UIAlertActionStyleCancel handler:nil]; + [alert addAction:ok]; + [self presentViewController:alert animated:YES completion:nil]; +} + - (void)checkWarn:(UIView *)view { NSString *key = objc_getAssociatedObject(view, @"key"); NSDictionary *item = objc_getAssociatedObject(view, @"item"); BOOL(^isWarnable)(UIView *) = item[@"warnCondition"]; NSString *warnKey = item[@"warnKey"]; - if (isWarnable && isWarnable(view) && ![getPreference(warnKey) boolValue]) { + if (isWarnable && isWarnable(view) && (!warnKey || [getPreference(warnKey) boolValue])) { if (warnKey) { - setPreference(warnKey, @YES); + setPreference(warnKey, @NO); } NSString *message = NSLocalizedString(([NSString stringWithFormat:@"preference.warn.%@", key]), nil); - UIAlertController *warnAlert = [UIAlertController alertControllerWithTitle:NSLocalizedString(@"Warning", nil) message:message preferredStyle:UIAlertControllerStyleActionSheet]; - warnAlert.popoverPresentationController.sourceView = view; - warnAlert.popoverPresentationController.sourceRect = view.bounds; - UIAlertAction *ok = [UIAlertAction actionWithTitle:NSLocalizedString(@"OK", nil) style:UIAlertActionStyleCancel handler:nil]; - [warnAlert addAction:ok]; - [self presentViewController:warnAlert animated:YES completion:nil]; + [self showAlertOnView:view title:NSLocalizedString(@"Warning", nil) message:message]; } } +#pragma mark Control event handlers + +- (void)sliderMoved:(DBNumberedSlider *)sender { + [self checkWarn:sender]; + NSString *key = objc_getAssociatedObject(sender, @"key"); + + setPreference(key, @(sender.value)); +} + - (void)switchChanged:(UISwitch *)sender { [self checkWarn:sender]; NSString *key = objc_getAssociatedObject(sender, @"key"); @@ -276,4 +306,55 @@ typedef void(^CreateView)(UITableViewCell *, NSString *, NSDictionary *); } } +- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { + [tableView deselectRowAtIndexPath:indexPath animated:NO]; + + UITableViewCell *view = [self.tableView cellForRowAtIndexPath:indexPath]; + if (view.selectionStyle == UITableViewCellSelectionStyleNone) { + return; + } + + NSString *key = self.prefContents[indexPath.section].allKeys[indexPath.row]; + NSDictionary *item = self.prefContents[indexPath.section].allValues[indexPath.row]; + + if ([item[@"showConfirmPrompt"] boolValue]) { + NSString *title = NSLocalizedString(@"preference.title.confirm", nil); + NSString *message = NSLocalizedString(([NSString stringWithFormat:@"preference.title.confirm.%@", key]), nil); + UIAlertController *confirmAlert = [UIAlertController alertControllerWithTitle:title message:message preferredStyle:UIAlertControllerStyleActionSheet]; + confirmAlert.popoverPresentationController.sourceView = view; + confirmAlert.popoverPresentationController.sourceRect = view.bounds; + UIAlertAction *ok = [UIAlertAction actionWithTitle:NSLocalizedString(@"OK", nil) style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) { + [self tableView:tableView invokeActionAtIndexPath:indexPath]; + }]; + UIAlertAction *cancel = [UIAlertAction actionWithTitle:NSLocalizedString(@"Cancel", nil) style:UIAlertActionStyleCancel handler:nil]; + [confirmAlert addAction:cancel]; + [confirmAlert addAction:ok]; + [self presentViewController:confirmAlert animated:YES completion:nil]; + } else { + [self tableView:tableView invokeActionAtIndexPath:indexPath]; + } +} + +- (void)tableView:(UITableView *)tableView invokeActionAtIndexPath:(NSIndexPath *)indexPath { + NSString *key = self.prefContents[indexPath.section].allKeys[indexPath.row]; + NSDictionary *item = self.prefContents[indexPath.section].allValues[indexPath.row]; + + void(^invokeAction)(void) = item[@"action"]; + if (invokeAction) { + invokeAction(); + } + + UIView *view = [self.tableView cellForRowAtIndexPath:indexPath]; + NSString *title = NSLocalizedString(([NSString stringWithFormat:@"preference.title.done.%@", key]), nil); + //NSString *message = NSLocalizedString(([NSString stringWithFormat:@"preference.message.done.%@", key]), nil); + [self showAlertOnView:view title:title message:nil]; +} + +- (void)textFieldDidEndEditing:(UITextField *)sender { + [self checkWarn:sender]; + NSString *key = objc_getAssociatedObject(sender, @"key"); + + setPreference(key, sender.text); +} + @end diff --git a/Natives/LoginViewController.m b/Natives/LoginViewController.m index c88cf80b..bda5d3f5 100644 --- a/Natives/LoginViewController.m +++ b/Natives/LoginViewController.m @@ -21,6 +21,8 @@ #define TYPE_MICROSOFT 1 #define TYPE_OFFLINE 2 +extern NSMutableDictionary *prefDict; + #pragma mark - LoginViewController @interface LoginViewController () { } @@ -36,6 +38,8 @@ [super viewDidLoad]; setViewBackgroundColor(self.view); + setDefaultValueForPref(prefDict, @"control_safe_area", NSStringFromCGRect(getDefaultSafeArea())); + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(msaLoginCallback:) name:@"MSALoginCallback" object:nil]; CGRect screenBounds = [[UIScreen mainScreen] bounds]; diff --git a/Natives/en.lproj/Localizable.strings b/Natives/en.lproj/Localizable.strings index b42bb591..62d7865b 100644 --- a/Natives/en.lproj/Localizable.strings +++ b/Natives/en.lproj/Localizable.strings @@ -70,13 +70,20 @@ "preference.section.control" = "Control Settings"; "preference.section.java" = "Java Runtime Settings"; +"preference.title.confirm" = "Are you sure?"; + "preference.title.game_directory" = "Minecraft game directory"; "preference.title.home_symlink" = "Enable compatibility symlink"; "preference.title.check_sha" = "Enable asset verification when launching"; "preference.title.cosmetica" = "Enable Cosmetica integration"; + "preference.title.reset_warnings" = "Reset all warnings"; +"preference.title.done.reset_warnings" = "All warnings have been reset."; + "preference.title.reset_settings" = "Reset all settings"; -"preference.warn.reset_settings" = "The next time you open PojavLauncher, all of the default settings will be restored. If you did this by accident, you can turn this off back."; +"preference.title.confirm.reset_settings" = "This will remove all of your custom preferences, including resolution, button size, and Java arguments."; +"preference.title.done.reset_settings" = "All of the default settings have been restored."; + "preference.title.renderer" = "Game renderer"; "preference.title.resolution" = "Game resolution"; "preference.title.disable_gesture" = "Disable gestures"; @@ -91,7 +98,7 @@ // "preference.subtitle.java_home" = "Java 8 is used by default on Minecraft 1.16.5 and older. This switch forces old versions to use Java 17."; "preference.title.java_args" = "Custom java arguments"; "preference.title.auto_ram" = "Auto determine RAM amount"; -"preference.warn.auto_ram" = "Due to limitations in the operating system itself, high amount may cause instability. Proceed with caution."; "preference.title.allocated_memory" = "Allocated memory"; +"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."; // sha check // home symlink diff --git a/Natives/main.m b/Natives/main.m index bb3e2b2b..722e5308 100644 --- a/Natives/main.m +++ b/Natives/main.m @@ -252,7 +252,7 @@ int main(int argc, char * argv[]) { init_hookFunctions(); - loadPreferences(); + loadPreferences(NO); init_setupResolvConf(); init_setupMultiDir(); init_setupLauncherProfiles(); From 9c5bea91c8ca4aaca172831e5d0416b6770146ca Mon Sep 17 00:00:00 2001 From: khanhduytran0 Date: Fri, 2 Sep 2022 22:15:33 +0700 Subject: [PATCH 23/37] Fix settings ordering; Added picker; Added destructive cell style --- Natives/LauncherPreferencesViewController2.m | 132 ++++++++++++------- 1 file changed, 86 insertions(+), 46 deletions(-) diff --git a/Natives/LauncherPreferencesViewController2.m b/Natives/LauncherPreferencesViewController2.m index d069aa27..4bd3ee3a 100644 --- a/Natives/LauncherPreferencesViewController2.m +++ b/Natives/LauncherPreferencesViewController2.m @@ -10,9 +10,9 @@ typedef void(^CreateView)(UITableViewCell *, NSString *, NSDictionary *); -@interface LauncherPreferencesViewController2() {} +@interface LauncherPreferencesViewController2() {} @property NSArray* prefSections; -@property NSArray*>* prefContents; +@property NSArray*>* prefContents; @property CreateView typeButton, typePickField, typeTextField, typeSlider, typeSwitch; @end @@ -31,111 +31,114 @@ typedef void(^CreateView)(UITableViewCell *, NSString *, NSDictionary *); self.prefSections = @[@"general", @"video", @"control", @"java"]; self.prefContents = @[ - @{ + @[ // General settings - @"game_directory": @{ + @{@"key": @"game_directory", @"icon": @"folder", @"type": self.typePickField, @"pickList": @[@"default", @"TODO"] }, - @"home_symlink": @{ + @{@"key": @"home_symlink", @"icon": @"link", @"type": self.typeSwitch }, - @"check_sha": @{ + @{@"key": @"check_sha", @"icon": @"lock.shield", @"type": self.typeSwitch }, - @"cosmetica": @{ + @{@"key": @"cosmetica", @"icon": @"eyeglasses", @"type": self.typeSwitch }, - @"reset_settings": @{ - @"icon": @"trash", - @"type": self.typeButton, - @"requestReload": @YES, - @"showConfirmPrompt": @(YES), - @"action": ^void(){ - loadPreferences(YES); - // TODO: reset UI states - } - }, - @"reset_warnings": @{ + @{@"key": @"reset_warnings", @"icon": @"exclamationmark.triangle", @"type": self.typeButton, @"action": ^void(){ resetWarnings(); } }, - }, @{ + @{@"key": @"reset_settings", + @"icon": @"trash", + @"type": self.typeButton, + @"requestReload": @YES, + @"showConfirmPrompt": @YES, + @"destructive": @YES, + @"action": ^void(){ + loadPreferences(YES); + // TODO: reset UI states + } + }, + ], @[ // Video and renderer settings - @"renderer": @{ + @{@"key": @"renderer", @"icon": @"cpu", @"type": self.typePickField, @"pickList": @[@"gl4es", @"zink", @"wip"] }, - @"resolution": @{ + @{@"key": @"resolution", @"icon": @"viewfinder", - @"type": self.typeSlider + @"type": self.typeSlider, + @"min": @(25), + @"max": @(150) }, - }, @{ + ], @[ // Control settings /* @"disable_gesture": @{ @"type": self.typeSwitch }, */ - @"press_duration": @{ + @{@"key": @"press_duration", @"icon": @"timer", @"type": self.typeSlider, @"min": @(100), @"max": @(1000) }, - @"button_scale": @{ + @{@"key": @"button_scale", @"icon": @"aspectratio", @"type": self.typeSlider, @"min": @(50), // 80? @"max": @(500) }, - @"mouse_scale": @{ + @{@"key": @"mouse_scale", @"icon": @"arrow.up.left.and.arrow.down.right.circle", @"type": self.typeSlider, @"min": @(25), @"max": @(300) }, - @"mouse_speed": @{ + @{@"key": @"mouse_speed", @"icon": @"arrow.left.and.right", @"type": self.typeSlider, @"min": @(25), @"max": @(300) }, - @"virtmouse_enable": @{ + @{@"key": @"virtmouse_enable", @"icon": @"cursorarrow.rays", @"type": self.typeSwitch }, - @"slideable_hotbar": @{ + @{@"key": @"slideable_hotbar", @"icon": @"slider.horizontal.below.rectangle", @"type": self.typeSwitch } - }, @{ + ], @[ // Java tweaks - @"java_home": @{ // TODO: name as Use Java 17 for older MC + @{@"key": @"java_home", // TODO: name as Use Java 17 for older MC @"icon": @"cube", @"type": self.typeSwitch, // false: 8, true: 17 @"customSwitchValue": @[@"java-8-openjdk", @"java-17-openjdk"] }, - @"java_args": @{ + @{@"key": @"java_args", @"icon": @"slider.vertical.3", @"type": self.typeTextField }, - @"auto_ram": @{ + @{@"key": @"auto_ram", @"icon": @"slider.horizontal.3", @"type": self.typeSwitch, //@"hidden": @(getenv("POJAV_DETECTEDJB") == NULL), @"requestReload": @YES }, - @"allocated_memory": @{ + @{@"key": @"allocated_memory", @"icon": @"memorychip", @"type": self.typeSlider, @"min": @(NSProcessInfo.processInfo.physicalMemory / 1048576 * 0.25), @@ -149,7 +152,7 @@ typedef void(^CreateView)(UITableViewCell *, NSString *, NSDictionary *); }, @"warnKey": @"mem_warn" } - } + ] ]; } @@ -173,8 +176,8 @@ typedef void(^CreateView)(UITableViewCell *, NSString *, NSDictionary *); cell.selectionStyle = UITableViewCellSelectionStyleNone; cell.textLabel.textColor = nil; - NSString *key = self.prefContents[indexPath.section].allKeys[indexPath.row]; - NSDictionary *item = self.prefContents[indexPath.section].allValues[indexPath.row]; + NSDictionary *item = self.prefContents[indexPath.section][indexPath.row]; + NSString *key = item[@"key"]; CreateView createView = item[@"type"]; createView(cell, key, item); if (cell.accessoryView) { @@ -184,6 +187,8 @@ typedef void(^CreateView)(UITableViewCell *, NSString *, NSDictionary *); // Set general properties if (@available(iOS 13.0, *)) { + BOOL destructive = [item[@"destructive"] boolValue]; + cell.imageView.tintColor = destructive ? UIColor.systemRedColor : nil; cell.imageView.image = [UIImage systemImageNamed:item[@"icon"]]; } cell.textLabel.text = NSLocalizedString(([NSString stringWithFormat:@"preference.title.%@", key]), nil); @@ -200,9 +205,10 @@ typedef void(^CreateView)(UITableViewCell *, NSString *, NSDictionary *); __weak LauncherPreferencesViewController2 *weakSelf = self; self.typeButton = ^void(UITableViewCell *cell, NSString *key, NSDictionary *item) { + BOOL destructive = [item[@"destructive"] boolValue]; cell.accessoryView = nil; cell.selectionStyle = UITableViewCellSelectionStyleGray; - cell.textLabel.textColor = UIColor.systemBlueColor; + cell.textLabel.textColor = destructive ? UIColor.systemRedColor : UIColor.systemBlueColor; }; /* @@ -229,7 +235,18 @@ typedef void(^CreateView)(UITableViewCell *, NSString *, NSDictionary *); self.typePickField = ^void(UITableViewCell *cell, NSString *key, NSDictionary *item) { weakSelf.typeTextField(cell, key, item); - //??? + UITextField *view = (UITextField *)cell.accessoryView; + UIPickerView *picker = [[UIPickerView alloc] init]; + objc_setAssociatedObject(picker, @"item", item, OBJC_ASSOCIATION_ASSIGN); + picker.delegate = weakSelf; + picker.dataSource = weakSelf; + [picker reloadAllComponents]; + UIToolbar *toolbar = [[UIToolbar alloc] initWithFrame:CGRectMake(0.0, 0.0, weakSelf.view.frame.size.width, 44.0)]; + UIBarButtonItem *flexibleSpace = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil]; + UIBarButtonItem *doneButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone target:view action:@selector(resignFirstResponder)]; + toolbar.items = @[flexibleSpace, doneButton]; + view.inputAccessoryView = toolbar; + view.inputView = picker; }; self.typeSlider = ^void(UITableViewCell *cell, NSString *key, NSDictionary *item) { @@ -261,8 +278,8 @@ typedef void(^CreateView)(UITableViewCell *, NSString *, NSDictionary *); } - (void)checkWarn:(UIView *)view { - NSString *key = objc_getAssociatedObject(view, @"key"); NSDictionary *item = objc_getAssociatedObject(view, @"item"); + NSString *key = item[@"key"]; BOOL(^isWarnable)(UIView *) = item[@"warnCondition"]; NSString *warnKey = item[@"warnKey"]; @@ -276,19 +293,40 @@ typedef void(^CreateView)(UITableViewCell *, NSString *, NSDictionary *); } } +#pragma mark - UIPickerView + +- (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component { + +} + +- (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)thePickerView { + return 1; +} + +- (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component { + NSDictionary *item = objc_getAssociatedObject(pickerView, @"item"); + return [item[@"pickList"] count]; +} + +- (NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component { + NSDictionary *item = objc_getAssociatedObject(pickerView, @"item"); + return item[@"pickList"][row]; +} + #pragma mark Control event handlers - (void)sliderMoved:(DBNumberedSlider *)sender { [self checkWarn:sender]; NSString *key = objc_getAssociatedObject(sender, @"key"); + sender.value = (int)sender.value; setPreference(key, @(sender.value)); } - (void)switchChanged:(UISwitch *)sender { [self checkWarn:sender]; - NSString *key = objc_getAssociatedObject(sender, @"key"); NSDictionary *item = objc_getAssociatedObject(sender, @"item"); + NSString *key = item[@"key"]; // Special switches may define custom value instead of NO/YES NSArray *customSwitchValue = item[@"customSwitchValue"]; @@ -311,19 +349,21 @@ typedef void(^CreateView)(UITableViewCell *, NSString *, NSDictionary *); UITableViewCell *view = [self.tableView cellForRowAtIndexPath:indexPath]; if (view.selectionStyle == UITableViewCellSelectionStyleNone) { + // Ignore if selection style is none return; } - NSString *key = self.prefContents[indexPath.section].allKeys[indexPath.row]; - NSDictionary *item = self.prefContents[indexPath.section].allValues[indexPath.row]; + NSDictionary *item = self.prefContents[indexPath.section][indexPath.row]; + NSString *key = item[@"key"]; if ([item[@"showConfirmPrompt"] boolValue]) { + BOOL destructive = [item[@"destructive"] boolValue]; NSString *title = NSLocalizedString(@"preference.title.confirm", nil); NSString *message = NSLocalizedString(([NSString stringWithFormat:@"preference.title.confirm.%@", key]), nil); UIAlertController *confirmAlert = [UIAlertController alertControllerWithTitle:title message:message preferredStyle:UIAlertControllerStyleActionSheet]; confirmAlert.popoverPresentationController.sourceView = view; confirmAlert.popoverPresentationController.sourceRect = view.bounds; - UIAlertAction *ok = [UIAlertAction actionWithTitle:NSLocalizedString(@"OK", nil) style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) { + UIAlertAction *ok = [UIAlertAction actionWithTitle:NSLocalizedString(@"OK", nil) style:destructive?UIAlertActionStyleDestructive:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) { [self tableView:tableView invokeActionAtIndexPath:indexPath]; }]; UIAlertAction *cancel = [UIAlertAction actionWithTitle:NSLocalizedString(@"Cancel", nil) style:UIAlertActionStyleCancel handler:nil]; @@ -336,8 +376,8 @@ typedef void(^CreateView)(UITableViewCell *, NSString *, NSDictionary *); } - (void)tableView:(UITableView *)tableView invokeActionAtIndexPath:(NSIndexPath *)indexPath { - NSString *key = self.prefContents[indexPath.section].allKeys[indexPath.row]; - NSDictionary *item = self.prefContents[indexPath.section].allValues[indexPath.row]; + NSDictionary *item = self.prefContents[indexPath.section][indexPath.row]; + NSString *key = item[@"key"]; void(^invokeAction)(void) = item[@"action"]; if (invokeAction) { From 2a64640c195cffca86422b1b08a6b60227fbf18b Mon Sep 17 00:00:00 2001 From: Duy Tran Khanh Date: Sat, 3 Sep 2022 21:36:40 +0700 Subject: [PATCH 24/37] Make pickerview functional; Rewrite instance manager --- Natives/CMakeLists.txt | 1 + Natives/LauncherPrefGameDirViewController.h | 6 + Natives/LauncherPrefGameDirViewController.m | 227 +++++++++++++++++++ Natives/LauncherPreferencesViewController2.m | 73 +++++- Natives/en.lproj/Localizable.strings | 6 + Natives/utils.h | 2 +- 6 files changed, 302 insertions(+), 13 deletions(-) create mode 100644 Natives/LauncherPrefGameDirViewController.h create mode 100644 Natives/LauncherPrefGameDirViewController.m diff --git a/Natives/CMakeLists.txt b/Natives/CMakeLists.txt index 6cdc08bd..36c6428c 100644 --- a/Natives/CMakeLists.txt +++ b/Natives/CMakeLists.txt @@ -118,6 +118,7 @@ add_executable(PojavLauncher LauncherPreferences.m LauncherPreferencesViewController.m LauncherPreferencesViewController2.m + LauncherPrefGameDirViewController.m LauncherSplitViewController.m LauncherViewController.m LoginViewController.m diff --git a/Natives/LauncherPrefGameDirViewController.h b/Natives/LauncherPrefGameDirViewController.h new file mode 100644 index 00000000..9ef15fc1 --- /dev/null +++ b/Natives/LauncherPrefGameDirViewController.h @@ -0,0 +1,6 @@ +#import + +@interface LauncherPrefGameDirViewController : UITableViewController + +@end + diff --git a/Natives/LauncherPrefGameDirViewController.m b/Natives/LauncherPrefGameDirViewController.m new file mode 100644 index 00000000..7173ccd2 --- /dev/null +++ b/Natives/LauncherPrefGameDirViewController.m @@ -0,0 +1,227 @@ +#import "LauncherPreferences.h" +#import "LauncherPrefGameDirViewController.h" +#import "TOInsetGroupedTableView.h" +#import "ios_uikit_bridge.h" + +@interface LauncherPrefGameDirViewController () +@property NSMutableArray *array; +@end + +@implementation LauncherPrefGameDirViewController + +- (void)viewDidLoad +{ + [super viewDidLoad]; + [self setTitle:NSLocalizedString(@"preference.title.game_directory", nil)]; + + self.array = [[NSMutableArray alloc] init]; + [self.array addObject:@"default"]; + + self.tableView = [[TOInsetGroupedTableView alloc] init]; + self.tableView.keyboardDismissMode = UIScrollViewKeyboardDismissModeInteractive; + self.tableView.sectionFooterHeight = 50; + + NSString *path = [NSString stringWithFormat:@"%s/instances", getenv("POJAV_HOME")]; + + NSFileManager *fm = NSFileManager.defaultManager; + NSArray *files = [fm contentsOfDirectoryAtPath:path error:nil]; + BOOL isDir; + for (NSString *file in files) { + [fm fileExistsAtPath:path isDirectory:(&isDir)]; + if (isDir && ![file isEqualToString:@"default"]) { + [self.array addObject:file]; + } + } +} + +- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section +{ + return self.array.count; +} + +- (UITableViewCell *)tableView:(nonnull UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath +{ + UITextField *view; + UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"cell"]; + if (cell == nil) { + cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"cell"]; + + if (indexPath.row == 0) { + cell.textLabel.text = self.array[indexPath.row]; + } else { + view = [[UITextField alloc] initWithFrame:CGRectMake(20, 10, cell.bounds.size.width/2, cell.bounds.size.height-20)]; + [view addTarget:view action:@selector(resignFirstResponder) forControlEvents:UIControlEventEditingDidEndOnExit]; + view.autocorrectionType = UITextAutocorrectionTypeNo; + view.autocapitalizationType = UITextAutocapitalizationTypeNone; + view.autoresizingMask = UIViewAutoresizingFlexibleWidth; + view.delegate = self; + view.returnKeyType = UIReturnKeyDone; + [cell.contentView addSubview:view]; + } + } + if (indexPath.row > 0) { + view = cell.contentView.subviews.lastObject; + view.placeholder = self.array[indexPath.row]; + view.text = self.array[indexPath.row]; + } + + if ([getPreference(@"game_directory") isEqualToString:self.array[indexPath.row]]) { + cell.accessoryType = UITableViewCellAccessoryCheckmark; + } else { + cell.accessoryType = UITableViewCellAccessoryNone; + } + + // TODO: display size in the detail label + return cell; +} + +- (UIView *)tableView:(UITableView *)tableView +viewForFooterInSection:(NSInteger)section +{ + UITextField *view = [[UITextField alloc] init]; + [view addTarget:view action:@selector(resignFirstResponder) forControlEvents:UIControlEventEditingDidEndOnExit]; + view.autocorrectionType = UITextAutocorrectionTypeNo; + view.autocapitalizationType = UITextAutocapitalizationTypeNone; + view.delegate = self; + view.placeholder = @"add game directory"; + view.returnKeyType = UIReturnKeyDone; + return view; +} + +- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { + setPreference(@"game_directory", self.array[indexPath.row]); + [tableView deselectRowAtIndexPath:indexPath animated:NO]; + for (int i = 0; i < self.array.count; i++) { + UITableViewCell *cell = [self.tableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:i inSection:0]]; + if (i == indexPath.row) { + cell.accessoryType = UITableViewCellAccessoryCheckmark; + } else { + cell.accessoryType = UITableViewCellAccessoryNone; + } + } +} + +- (UIContextMenuConfiguration *)tableView:(UITableView *)tableView contextMenuConfigurationForRowAtIndexPath:(NSIndexPath *)indexPath point:(CGPoint)point API_AVAILABLE(ios(13.0)) +{ + // You can't delete or rename the default instance, though there will be a reset action (TODO) + if (indexPath.row == 0) { + return nil; + } + + if (@available(iOS 13.0, *)) { + UIAction *delete = [UIAction actionWithTitle:@"Delete" image:[UIImage systemImageNamed:@"trash"] identifier:@"deleteAction" handler:^(__kindof UIAction * _Nonnull action) { + [self actionDeleteAtIndexPath:indexPath]; + }]; + delete.attributes = UIMenuElementAttributesDestructive; + + UIAction *rename = [UIAction actionWithTitle:@"Rename" image:[UIImage systemImageNamed:@"pencil"] identifier:@"editAction" handler:^(__kindof UIAction * _Nonnull action) { + UITableViewCell *view = [self.tableView cellForRowAtIndexPath:indexPath]; + [view.contentView.subviews.lastObject becomeFirstResponder]; + }]; + + return [UIContextMenuConfiguration configurationWithIdentifier:nil previewProvider:nil actionProvider:^UIMenu * _Nullable(NSArray * _Nonnull suggestedActions) { + return [UIMenu menuWithTitle:self.array[indexPath.row] children:@[delete, rename]]; + }]; + } + return nil; +} + +- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath +{ + if (editingStyle == UITableViewCellEditingStyleDelete) { + [self actionDeleteAtIndexPath:indexPath]; + } +} + +- (UITableViewCellEditingStyle)tableView:(UITableView *)tableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath +{ + if (indexPath.row == 0) { + // TODO: Reset action? + return UITableViewCellEditingStyleNone; + } else { + return UITableViewCellEditingStyleDelete; + } +} + +- (void)actionDeleteAtIndexPath:(NSIndexPath *)indexPath +{ + UITableViewCell *view = [self.tableView cellForRowAtIndexPath:indexPath]; + NSString *title = NSLocalizedString(@"preference.title.confirm", nil); + NSString *message = [NSString stringWithFormat:NSLocalizedString(@"preference.title.confirm.delete_game_directory", nil), self.array[indexPath.row]]; + UIAlertController *confirmAlert = [UIAlertController alertControllerWithTitle:title message:message preferredStyle:UIAlertControllerStyleActionSheet]; + confirmAlert.popoverPresentationController.sourceView = view; + confirmAlert.popoverPresentationController.sourceRect = view.bounds; + UIAlertAction *ok = [UIAlertAction actionWithTitle:NSLocalizedString(@"OK", nil) style:UIAlertActionStyleDestructive handler:^(UIAlertAction * _Nonnull action) { + NSString *directory = [NSString stringWithFormat:@"%s/instances/%@", getenv("POJAV_HOME"), self.array[indexPath.row]]; + NSError *error; + if([[NSFileManager defaultManager] removeItemAtPath:directory error:&error]) { + if ([getPreference(@"game_directory") isEqualToString:self.array[indexPath.row]]) { + setPreference(@"game_directory", self.array[0]); + [self.tableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0]].accessoryType = UITableViewCellAccessoryCheckmark; + } + [self.array removeObjectAtIndex:indexPath.row]; + [self.tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationFade]; + } else { + showDialog(self, NSLocalizedString(@"Error", nil), error.localizedDescription); + } + }]; + UIAlertAction *cancel = [UIAlertAction actionWithTitle:NSLocalizedString(@"Cancel", nil) style:UIAlertActionStyleCancel handler:nil]; + [confirmAlert addAction:cancel]; + [confirmAlert addAction:ok]; + [self presentViewController:confirmAlert animated:YES completion:nil]; +} + +#pragma mark UITextField + +- (void)textFieldDidEndEditing:(UITextField *)sender { + BOOL isFooterView = sender.superview == self.tableView; + if (!sender.hasText || [sender.text isEqualToString:sender.placeholder]) { + if (isFooterView) { + return; + } + sender.text = sender.placeholder; + return; + } + + NSError *error; + + NSString *dest = [NSString stringWithFormat:@"%s/instances/%@", getenv("POJAV_HOME"), sender.text]; + if (isFooterView) { + [[NSFileManager defaultManager] createDirectoryAtPath:dest withIntermediateDirectories:NO attributes:nil error:&error]; + } else { + NSString *source = [NSString stringWithFormat:@"%s/instances/%@", getenv("POJAV_HOME"), sender.placeholder]; + [NSFileManager.defaultManager moveItemAtPath:source toPath:dest error:&error]; + } + + if (error == nil) { + setPreference(@"game_directory", sender.text); + if (isFooterView) { + NSIndexPath *indexPath = [NSIndexPath indexPathForRow:self.array.count inSection:0]; + [self.array addObject:sender.text]; + [self.tableView beginUpdates]; + [self.tableView insertRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationAutomatic]; + [self.tableView endUpdates]; + [self tableView:self.tableView didSelectRowAtIndexPath:indexPath]; + // Clear text + sender.text = @""; + } else { + int index = [self.array indexOfObject:sender.placeholder]; + self.array[index] = sender.placeholder = sender.text; + } + } else { + // Restore to the previous name if we encounter an error + if (!isFooterView) { + sender.text = sender.placeholder; + } + showDialog(self, NSLocalizedString(@"Error", nil), error.localizedDescription); + } +} + +- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string { + CGRect frame = textField.frame; + frame.size.width = MAX(50, textField.intrinsicContentSize.width + 10); + textField.frame = frame; + return YES; +} + +@end diff --git a/Natives/LauncherPreferencesViewController2.m b/Natives/LauncherPreferencesViewController2.m index 4bd3ee3a..7bf41bdc 100644 --- a/Natives/LauncherPreferencesViewController2.m +++ b/Natives/LauncherPreferencesViewController2.m @@ -4,6 +4,7 @@ #import "DBNumberedSlider.h" #import "LauncherPreferences.h" #import "LauncherPreferencesViewController2.h" +#import "LauncherPrefGameDirViewController.h" #import "TOInsetGroupedTableView.h" #include "utils.h" @@ -14,7 +15,7 @@ typedef void(^CreateView)(UITableViewCell *, NSString *, NSDictionary *); @property NSArray* prefSections; @property NSArray*>* prefContents; -@property CreateView typeButton, typePickField, typeTextField, typeSlider, typeSwitch; +@property CreateView typeButton, typeChildPane, typePickField, typeTextField, typeSlider, typeSwitch; @end @implementation LauncherPreferencesViewController2 @@ -35,8 +36,8 @@ typedef void(^CreateView)(UITableViewCell *, NSString *, NSDictionary *); // General settings @{@"key": @"game_directory", @"icon": @"folder", - @"type": self.typePickField, - @"pickList": @[@"default", @"TODO"] + @"type": self.typeChildPane, + @"class": LauncherPrefGameDirViewController.class, }, @{@"key": @"home_symlink", @"icon": @"link", @@ -73,7 +74,18 @@ typedef void(^CreateView)(UITableViewCell *, NSString *, NSDictionary *); @{@"key": @"renderer", @"icon": @"cpu", @"type": self.typePickField, - @"pickList": @[@"gl4es", @"zink", @"wip"] + @"pickKeys": @[ + @"auto", + @ RENDERER_NAME_GL4ES, + @ RENDERER_NAME_MTL_ANGLE, + @ RENDERER_NAME_VK_ZINK + ], + @"pickList": @[ + NSLocalizedString(@"preference.title.renderer.auto", nil), + NSLocalizedString(@"preference.title.renderer.gl4es", nil), + NSLocalizedString(@"preference.title.renderer.tinygl4angle", nil), + NSLocalizedString(@"preference.title.renderer.zink", nil) + ] }, @{@"key": @"resolution", @"icon": @"viewfinder", @@ -171,10 +183,14 @@ typedef void(^CreateView)(UITableViewCell *, NSString *, NSDictionary *); - (UITableViewCell *)tableView:(nonnull UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"cell"]; if (cell == nil) { - cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"cell"]; + cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:@"cell"]; } + // Reset cell properties, as it could be reused + cell.accessoryType = UITableViewCellAccessoryNone; + cell.accessoryView = nil; cell.selectionStyle = UITableViewCellSelectionStyleNone; cell.textLabel.textColor = nil; + cell.detailTextLabel.text = nil; NSDictionary *item = self.prefContents[indexPath.section][indexPath.row]; NSString *key = item[@"key"]; @@ -206,11 +222,16 @@ typedef void(^CreateView)(UITableViewCell *, NSString *, NSDictionary *); self.typeButton = ^void(UITableViewCell *cell, NSString *key, NSDictionary *item) { BOOL destructive = [item[@"destructive"] boolValue]; - cell.accessoryView = nil; cell.selectionStyle = UITableViewCellSelectionStyleGray; cell.textLabel.textColor = destructive ? UIColor.systemRedColor : UIColor.systemBlueColor; }; + self.typeChildPane = ^void(UITableViewCell *cell, NSString *key, NSDictionary *item) { + cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator; + cell.selectionStyle = UITableViewCellSelectionStyleGray; + cell.detailTextLabel.text = getPreference(key); + }; + /* self.typePickField = ^void(UITableViewCell *cell, NSString *key, NSDictionary *item) { cell.accessoryView = [[UITextField alloc] initWithFrame:CGRectMake(0, 0, cell.bounds.size.width / 2, cell.bounds.size.height)]; @@ -238,9 +259,11 @@ typedef void(^CreateView)(UITableViewCell *, NSString *, NSDictionary *); UITextField *view = (UITextField *)cell.accessoryView; UIPickerView *picker = [[UIPickerView alloc] init]; objc_setAssociatedObject(picker, @"item", item, OBJC_ASSOCIATION_ASSIGN); + objc_setAssociatedObject(picker, @"view", cell.accessoryView, OBJC_ASSOCIATION_ASSIGN); picker.delegate = weakSelf; picker.dataSource = weakSelf; [picker reloadAllComponents]; + [picker selectRow:[item[@"pickKeys"] indexOfObject:getPreference(key)] inComponent:0 animated:NO]; UIToolbar *toolbar = [[UIToolbar alloc] initWithFrame:CGRectMake(0.0, 0.0, weakSelf.view.frame.size.width, 44.0)]; UIBarButtonItem *flexibleSpace = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil]; UIBarButtonItem *doneButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone target:view action:@selector(resignFirstResponder)]; @@ -296,7 +319,18 @@ typedef void(^CreateView)(UITableViewCell *, NSString *, NSDictionary *); #pragma mark - UIPickerView - (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component { - + NSDictionary *item = objc_getAssociatedObject(pickerView, @"item"); + UITextField *view = objc_getAssociatedObject(pickerView, @"view"); + + // If there is key, use it + if (item[@"pickKeys"] != nil) { + view.text = item[@"pickKeys"][row]; + } else { + view.text = item[@"pickList"][row]; + } + + // Save the preference + [self textFieldDidEndEditing:view]; } - (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)thePickerView { @@ -347,12 +381,25 @@ typedef void(^CreateView)(UITableViewCell *, NSString *, NSDictionary *); - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { [tableView deselectRowAtIndexPath:indexPath animated:NO]; - UITableViewCell *view = [self.tableView cellForRowAtIndexPath:indexPath]; - if (view.selectionStyle == UITableViewCellSelectionStyleNone) { - // Ignore if selection style is none - return; - } + NSDictionary *item = self.prefContents[indexPath.section][indexPath.row]; + if (item[@"type"] == self.typeButton) { + [self tableView:tableView invokeActionWithPromptAtIndexPath:indexPath]; + } else if (item[@"type"] == self.typeChildPane) { + [self tableView:tableView openChildPaneAtIndexPath:indexPath]; + } +} + +#pragma mark External UITableView functions + +- (void)tableView:(UITableView *)tableView openChildPaneAtIndexPath:(NSIndexPath *)indexPath { + NSDictionary *item = self.prefContents[indexPath.section][indexPath.row]; + UIViewController *vc = [[item[@"class"] alloc] init]; + [self.navigationController pushViewController:vc animated:YES]; +} + +- (void)tableView:(UITableView *)tableView invokeActionWithPromptAtIndexPath:(NSIndexPath *)indexPath { + UITableViewCell *view = [self.tableView cellForRowAtIndexPath:indexPath]; NSDictionary *item = self.prefContents[indexPath.section][indexPath.row]; NSString *key = item[@"key"]; @@ -390,6 +437,8 @@ typedef void(^CreateView)(UITableViewCell *, NSString *, NSDictionary *); [self showAlertOnView:view title:title message:nil]; } +#pragma mark UITextField + - (void)textFieldDidEndEditing:(UITextField *)sender { [self checkWarn:sender]; NSString *key = objc_getAssociatedObject(sender, @"key"); diff --git a/Natives/en.lproj/Localizable.strings b/Natives/en.lproj/Localizable.strings index 62d7865b..85d468ef 100644 --- a/Natives/en.lproj/Localizable.strings +++ b/Natives/en.lproj/Localizable.strings @@ -73,6 +73,7 @@ "preference.title.confirm" = "Are you sure?"; "preference.title.game_directory" = "Minecraft game directory"; +"preference.title.confirm.delete_game_directory" = "The instance %@ will be deleted forever and cannot be restored."; "preference.title.home_symlink" = "Enable compatibility symlink"; "preference.title.check_sha" = "Enable asset verification when launching"; "preference.title.cosmetica" = "Enable Cosmetica integration"; @@ -85,6 +86,11 @@ "preference.title.done.reset_settings" = "All of the default settings have been restored."; "preference.title.renderer" = "Game renderer"; +"preference.title.renderer.auto" = "Auto: gl4es or tinygl4angle"; +"preference.title.renderer.gl4es" = "gl4es 1.1.4 - exports OpenGL 2.1"; +"preference.title.renderer.tinygl4angle" = "tinygl4angle (1.17+) - exports OpenGL 3.2 (Core Profile, limited)"; +"preference.title.renderer.zink" = "Zink (Mesa 21.0) - exports OpenGL 4.1"; + "preference.title.resolution" = "Game resolution"; "preference.title.disable_gesture" = "Disable gestures"; "preference.title.press_duration" = "Long-press duration"; diff --git a/Natives/utils.h b/Natives/utils.h index dd3e136a..43b77d28 100644 --- a/Natives/utils.h +++ b/Natives/utils.h @@ -30,7 +30,7 @@ #define RENDERER_NAME_GL4ES "libgl4es_114.dylib" #define RENDERER_NAME_MTL_ANGLE "libtinygl4angle.dylib" -#define RENDERER_NAME_VK_ZINK "libOSMesaOverride.dylib" +#define RENDERER_NAME_VK_ZINK "libOSMesa.8.dylib" #define SPECIALBTN_KEYBOARD -1 #define SPECIALBTN_TOGGLECTRL -2 From b6813c22e6230ea3c8b3f72cc448a30c41955c3f Mon Sep 17 00:00:00 2001 From: khanhduytran0 Date: Sat, 3 Sep 2022 22:24:05 +0700 Subject: [PATCH 25/37] Get stuff to sync --- Natives/LauncherPrefGameDirViewController.m | 20 +++++++++++++++----- Natives/LauncherPreferencesViewController2.m | 16 ++++++++++++++++ Natives/LauncherViewController.m | 9 ++++++--- 3 files changed, 37 insertions(+), 8 deletions(-) diff --git a/Natives/LauncherPrefGameDirViewController.m b/Natives/LauncherPrefGameDirViewController.m index 7173ccd2..01f977f6 100644 --- a/Natives/LauncherPrefGameDirViewController.m +++ b/Natives/LauncherPrefGameDirViewController.m @@ -34,6 +34,14 @@ } } +- (void)changeSelectionTo:(NSString *)name { + setPreference(@"game_directory", name); + NSString *multidirPath = [NSString stringWithFormat:@"%s/instances/%@", getenv("POJAV_HOME"), name]; + NSString *lasmPath = [NSString stringWithFormat:@"%s/Library/Application Support/minecraft", getenv("POJAV_HOME")]; + [NSFileManager.defaultManager removeItemAtPath:lasmPath error:nil]; + [NSFileManager.defaultManager createSymbolicLinkAtPath:lasmPath withDestinationPath:multidirPath error:nil]; +} + - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { return self.array.count; @@ -89,7 +97,7 @@ viewForFooterInSection:(NSInteger)section } - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { - setPreference(@"game_directory", self.array[indexPath.row]); + [self changeSelectionTo:self.array[indexPath.row]]; [tableView deselectRowAtIndexPath:indexPath animated:NO]; for (int i = 0; i < self.array.count; i++) { UITableViewCell *cell = [self.tableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:i inSection:0]]; @@ -154,9 +162,9 @@ viewForFooterInSection:(NSInteger)section UIAlertAction *ok = [UIAlertAction actionWithTitle:NSLocalizedString(@"OK", nil) style:UIAlertActionStyleDestructive handler:^(UIAlertAction * _Nonnull action) { NSString *directory = [NSString stringWithFormat:@"%s/instances/%@", getenv("POJAV_HOME"), self.array[indexPath.row]]; NSError *error; - if([[NSFileManager defaultManager] removeItemAtPath:directory error:&error]) { + if([NSFileManager.defaultManager removeItemAtPath:directory error:&error]) { if ([getPreference(@"game_directory") isEqualToString:self.array[indexPath.row]]) { - setPreference(@"game_directory", self.array[0]); + [self changeSelectionTo:self.array[0]]; [self.tableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0]].accessoryType = UITableViewCellAccessoryCheckmark; } [self.array removeObjectAtIndex:indexPath.row]; @@ -187,14 +195,14 @@ viewForFooterInSection:(NSInteger)section NSString *dest = [NSString stringWithFormat:@"%s/instances/%@", getenv("POJAV_HOME"), sender.text]; if (isFooterView) { - [[NSFileManager defaultManager] createDirectoryAtPath:dest withIntermediateDirectories:NO attributes:nil error:&error]; + [NSFileManager.defaultManager createDirectoryAtPath:dest withIntermediateDirectories:NO attributes:nil error:&error]; } else { NSString *source = [NSString stringWithFormat:@"%s/instances/%@", getenv("POJAV_HOME"), sender.placeholder]; [NSFileManager.defaultManager moveItemAtPath:source toPath:dest error:&error]; } if (error == nil) { - setPreference(@"game_directory", sender.text); + [self changeSelectionTo:sender.text]; if (isFooterView) { NSIndexPath *indexPath = [NSIndexPath indexPathForRow:self.array.count inSection:0]; [self.array addObject:sender.text]; @@ -207,6 +215,8 @@ viewForFooterInSection:(NSInteger)section } else { int index = [self.array indexOfObject:sender.placeholder]; self.array[index] = sender.placeholder = sender.text; + NSIndexPath *indexPath = [NSIndexPath indexPathForRow:index inSection:0]; + [self tableView:self.tableView didSelectRowAtIndexPath:indexPath]; } } else { // Restore to the previous name if we encounter an error diff --git a/Natives/LauncherPreferencesViewController2.m b/Natives/LauncherPreferencesViewController2.m index 7bf41bdc..eadf5dd5 100644 --- a/Natives/LauncherPreferencesViewController2.m +++ b/Natives/LauncherPreferencesViewController2.m @@ -168,6 +168,22 @@ typedef void(^CreateView)(UITableViewCell *, NSString *, NSDictionary *); ]; } +- (void)viewWillAppear:(BOOL)animated { + [super viewWillAppear:animated]; + + // Scan for child pane cells and reload them + // FIXME: any cheaper operations? + NSMutableArray *indexPaths = [[NSMutableArray alloc] init]; + for (int section = 0; section < self.prefContents.count; section++) { + for (int row = 0; row < self.prefContents[section].count; row++) { + if (self.prefContents[section][row][@"type"] == self.typeChildPane) { + [indexPaths addObject:[NSIndexPath indexPathForRow:row inSection:section]]; + } + } + } + [self.tableView reloadRowsAtIndexPaths:indexPaths withRowAnimation:UITableViewRowAnimationNone]; +} + - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { return self.prefSections.count; } diff --git a/Natives/LauncherViewController.m b/Natives/LauncherViewController.m index a7eaae2a..21afc4ca 100644 --- a/Natives/LauncherViewController.m +++ b/Natives/LauncherViewController.m @@ -54,8 +54,6 @@ int versionSelectedAt = 0; self.versionList = [[NSMutableArray alloc] init]; - int selectedVersionType = [getPreference(@"selected_version_type") intValue]; - [self reloadVersionList:selectedVersionType]; versionPickerView = [[UIPickerView alloc] init]; versionPickerView.delegate = self; versionPickerView.dataSource = self; @@ -68,7 +66,7 @@ int versionSelectedAt = 0; NSLocalizedString(@"Old-beta", nil), NSLocalizedString(@"Old-alpha", nil) ]]; - versionTypeControl.selectedSegmentIndex = selectedVersionType; + versionTypeControl.selectedSegmentIndex = [getPreference(@"selected_version_type") intValue]; [versionTypeControl addTarget:self action:@selector(changeVersionType:) forControlEvents:UIControlEventValueChanged]; UIBarButtonItem *versionTypeItem = [[UIBarButtonItem alloc] initWithCustomView:versionTypeControl]; UIBarButtonItem *versionFlexibleSpace = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:self action:nil]; @@ -114,6 +112,11 @@ int versionSelectedAt = 0; [scrollView addSubview:self.progressText]; } +- (void)viewWillAppear:(BOOL)animated { + [super viewWillAppear:animated]; + [self reloadVersionList:[getPreference(@"selected_version_type") intValue]]; +} + - (BOOL)isVersionInstalled:(NSString *)versionId { NSString *localPath = [NSString stringWithFormat:@"%s/versions/%@", getenv("POJAV_GAME_DIR"), versionId]; From 1fd2336e3eff041035f73480a731b7a2e5abb2d8 Mon Sep 17 00:00:00 2001 From: Eilionoir Tunnicliff Date: Sat, 3 Sep 2022 17:46:19 -0700 Subject: [PATCH 26/37] Fix type build error (#376) --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index a6a36696..0eabd5b4 100644 --- a/Makefile +++ b/Makefile @@ -71,7 +71,7 @@ POJAV_JRE17_DIR ?= $(SOURCEDIR)/depends/java-17-openjdk endif # Function to use later for checking dependencies -DEPCHECK = $(shell type $(1) >/dev/null 2>&1 && echo 1) +DEPCHECK = $(shell $(1) >/dev/null 2>&1 && echo 1) # Function to modify Info.plist files INFOPLIST = \ From f27808464b15c6e86bc70c18c1afc2e872a0a434 Mon Sep 17 00:00:00 2001 From: khanhduytran0 Date: Sun, 4 Sep 2022 09:47:46 +0700 Subject: [PATCH 27/37] Allow control settings to be changed ingame --- Natives/LauncherMenuViewController.m | 4 +- Natives/LauncherPrefGameDirViewController.m | 5 +- Natives/LauncherPreferences.m | 4 +- Natives/LauncherPreferencesViewController2.m | 53 ++++++-- Natives/SurfaceViewController.m | 120 ++++++++++++------- Natives/egl_bridge.m | 8 +- Natives/en.lproj/Localizable.strings | 27 +++-- Natives/input/ControllerInput.m | 2 +- Natives/input_bridge_v3.m | 10 +- Natives/utils.h | 1 + Natives/utils.m | 8 +- 11 files changed, 165 insertions(+), 77 deletions(-) diff --git a/Natives/LauncherMenuViewController.m b/Natives/LauncherMenuViewController.m index 5fa2958b..c78c405d 100644 --- a/Natives/LauncherMenuViewController.m +++ b/Natives/LauncherMenuViewController.m @@ -26,7 +26,7 @@ ]; self.options[0].title = @"PojavLauncher"; self.options[1].title = @"Preferences"; - self.options[2].title = @"Preferences (v2)"; + self.options[2].title = NSLocalizedString(@"Settings", nil); //@[@"News", @"Development Console", @"Crash logs"]; self.tableView.separatorStyle = UITableViewCellSeparatorStyleNone; @@ -91,7 +91,7 @@ selected.navigationItem.leftItemsSupplementBackButton = true; } - // This button is placed temporarily while migrating to the new UI (or just keep here?) + // Put a close button, as iOS does not have a dedicated back button self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:@"❌" style:UIBarButtonItemStyleDone target:self.splitViewController action:@selector(dismissViewController)]; } diff --git a/Natives/LauncherPrefGameDirViewController.m b/Natives/LauncherPrefGameDirViewController.m index 01f977f6..04ee7397 100644 --- a/Natives/LauncherPrefGameDirViewController.m +++ b/Natives/LauncherPrefGameDirViewController.m @@ -57,7 +57,7 @@ if (indexPath.row == 0) { cell.textLabel.text = self.array[indexPath.row]; } else { - view = [[UITextField alloc] initWithFrame:CGRectMake(20, 10, cell.bounds.size.width/2, cell.bounds.size.height-20)]; + view = [[UITextField alloc] initWithFrame:CGRectMake(20, 10, (cell.bounds.size.width-40)/2, cell.bounds.size.height-20)]; [view addTarget:view action:@selector(resignFirstResponder) forControlEvents:UIControlEventEditingDidEndOnExit]; view.autocorrectionType = UITextAutocorrectionTypeNo; view.autocapitalizationType = UITextAutocapitalizationTypeNone; @@ -91,7 +91,7 @@ viewForFooterInSection:(NSInteger)section view.autocorrectionType = UITextAutocorrectionTypeNo; view.autocapitalizationType = UITextAutocapitalizationTypeNone; view.delegate = self; - view.placeholder = @"add game directory"; + view.placeholder = NSLocalizedString(@"preference.multidir.add_directory", nil); view.returnKeyType = UIReturnKeyDone; return view; } @@ -228,6 +228,7 @@ viewForFooterInSection:(NSInteger)section } - (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string { + [textField invalidateIntrinsicContentSize]; CGRect frame = textField.frame; frame.size.width = MAX(50, textField.intrinsicContentSize.width + 10); textField.frame = frame; diff --git a/Natives/LauncherPreferences.m b/Natives/LauncherPreferences.m index d305d53e..0745acde 100644 --- a/Natives/LauncherPreferences.m +++ b/Natives/LauncherPreferences.m @@ -113,7 +113,9 @@ void loadPreferences(BOOL reset) { setDefaultValueForPref(prefDict, @"button_scale", @(100)); setDefaultValueForPref(prefDict, @"selected_version", @"1.7.10"); setDefaultValueForPref(prefDict, @"selected_version_type", @(0)); - setDefaultValueForPref(envPrefDict, @"time_longPressTrigger", @(400)); + setDefaultValueForPref(envPrefDict, @"press_duration", @(400)); + setDefaultValueForPref(envPrefDict, @"mouse_scale", @(100)); + setDefaultValueForPref(envPrefDict, @"mouse_speed", @(100)); setDefaultValueForPref(envPrefDict, @"default_ctrl", @"default.json"); setDefaultValueForPref(envPrefDict, @"game_directory", @"default"); setDefaultValueForPref(envPrefDict, @"java_args", @""); diff --git a/Natives/LauncherPreferencesViewController2.m b/Natives/LauncherPreferencesViewController2.m index eadf5dd5..1531ae40 100644 --- a/Natives/LauncherPreferencesViewController2.m +++ b/Natives/LauncherPreferencesViewController2.m @@ -28,6 +28,11 @@ typedef void(^CreateView)(UITableViewCell *, NSString *, NSDictionary *); self.tableView = [[TOInsetGroupedTableView alloc] init]; self.tableView.keyboardDismissMode = UIScrollViewKeyboardDismissModeInteractive; + self.tableView.sectionHeaderHeight = 50; + + BOOL(^whenNotInGame)() = ^BOOL(){ + return self.navigationController != nil; + }; self.prefSections = @[@"general", @"video", @"control", @"java"]; @@ -37,23 +42,28 @@ typedef void(^CreateView)(UITableViewCell *, NSString *, NSDictionary *); @{@"key": @"game_directory", @"icon": @"folder", @"type": self.typeChildPane, + @"enableCondition": whenNotInGame, @"class": LauncherPrefGameDirViewController.class, }, @{@"key": @"home_symlink", @"icon": @"link", - @"type": self.typeSwitch + @"type": self.typeSwitch, + @"enableCondition": whenNotInGame }, @{@"key": @"check_sha", @"icon": @"lock.shield", - @"type": self.typeSwitch + @"type": self.typeSwitch, + @"enableCondition": whenNotInGame }, @{@"key": @"cosmetica", @"icon": @"eyeglasses", - @"type": self.typeSwitch + @"type": self.typeSwitch, + @"enableCondition": whenNotInGame }, @{@"key": @"reset_warnings", @"icon": @"exclamationmark.triangle", @"type": self.typeButton, + @"enableCondition": whenNotInGame, @"action": ^void(){ resetWarnings(); } @@ -61,12 +71,13 @@ typedef void(^CreateView)(UITableViewCell *, NSString *, NSDictionary *); @{@"key": @"reset_settings", @"icon": @"trash", @"type": self.typeButton, + @"enableCondition": whenNotInGame, @"requestReload": @YES, @"showConfirmPrompt": @YES, @"destructive": @YES, @"action": ^void(){ loadPreferences(YES); - // TODO: reset UI states + [self.tableView reloadData]; } }, ], @[ @@ -74,6 +85,7 @@ typedef void(^CreateView)(UITableViewCell *, NSString *, NSDictionary *); @{@"key": @"renderer", @"icon": @"cpu", @"type": self.typePickField, + @"enableCondition": whenNotInGame, @"pickKeys": @[ @"auto", @ RENDERER_NAME_GL4ES, @@ -90,6 +102,7 @@ typedef void(^CreateView)(UITableViewCell *, NSString *, NSDictionary *); @{@"key": @"resolution", @"icon": @"viewfinder", @"type": self.typeSlider, + @"enableCondition": whenNotInGame, @"min": @(25), @"max": @(150) }, @@ -137,16 +150,19 @@ typedef void(^CreateView)(UITableViewCell *, NSString *, NSDictionary *); @{@"key": @"java_home", // TODO: name as Use Java 17 for older MC @"icon": @"cube", @"type": self.typeSwitch, + @"enableCondition": whenNotInGame, // false: 8, true: 17 @"customSwitchValue": @[@"java-8-openjdk", @"java-17-openjdk"] }, @{@"key": @"java_args", @"icon": @"slider.vertical.3", - @"type": self.typeTextField + @"type": self.typeTextField, + @"enableCondition": whenNotInGame }, @{@"key": @"auto_ram", @"icon": @"slider.horizontal.3", @"type": self.typeSwitch, + @"enableCondition": whenNotInGame, //@"hidden": @(getenv("POJAV_DETECTEDJB") == NULL), @"requestReload": @YES }, @@ -156,7 +172,7 @@ typedef void(^CreateView)(UITableViewCell *, NSString *, NSDictionary *); @"min": @(NSProcessInfo.processInfo.physicalMemory / 1048576 * 0.25), @"max": @(NSProcessInfo.processInfo.physicalMemory / 1048576 * 0.85), @"enableCondition": ^BOOL(){ - return ![getPreference(@"auto_ram") boolValue]; + return ![getPreference(@"auto_ram") boolValue] && whenNotInGame(); }, @"warnAlways": @NO, @"warnCondition": ^BOOL(DBNumberedSlider *view){ @@ -184,10 +200,27 @@ typedef void(^CreateView)(UITableViewCell *, NSString *, NSDictionary *); [self.tableView reloadRowsAtIndexPaths:indexPaths withRowAnimation:UITableViewRowAnimationNone]; } +- (void)dismissViewController { + [self.presentingViewController performSelector:@selector(updatePreferenceChanges)]; + [self dismissViewControllerAnimated:YES completion:nil]; +} + - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { return self.prefSections.count; } +- (UIView *)tableView:(UITableView *)tableView +viewForHeaderInSection:(NSInteger)section { + if (section != 0 || self.navigationController != nil) { + return nil; + } + + UIButton *doneButton = [UIButton buttonWithType:UIButtonTypeSystem]; + [doneButton setTitle:NSLocalizedString(@"Done", nil) forState:UIControlStateNormal]; + [doneButton addTarget:self action:@selector(dismissViewController) forControlEvents:UIControlEventTouchUpInside]; + return doneButton; +} + - (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section { return NSLocalizedString(([NSString stringWithFormat:@"preference.section.%@", self.prefSections[section]]), nil); } @@ -229,6 +262,7 @@ typedef void(^CreateView)(UITableViewCell *, NSString *, NSDictionary *); BOOL(^checkEnable)(void) = item[@"enableCondition"]; cell.userInteractionEnabled = !checkEnable || checkEnable(); cell.textLabel.enabled = cell.detailTextLabel.enabled = cell.userInteractionEnabled; + [(id)cell.accessoryView setEnabled:cell.userInteractionEnabled]; return cell; } @@ -301,7 +335,12 @@ typedef void(^CreateView)(UITableViewCell *, NSString *, NSDictionary *); self.typeSwitch = ^void(UITableViewCell *cell, NSString *key, NSDictionary *item) { UISwitch *view = [[UISwitch alloc] init]; - [view setOn:[getPreference(key) boolValue] animated:NO]; + NSArray *customSwitchValue = item[@"customSwitchValue"]; + if (customSwitchValue == nil) { + [view setOn:[getPreference(key) boolValue] animated:NO]; + } else { + [view setOn:[getPreference(key) isEqualToString:customSwitchValue[1]] animated:NO]; + } [view addTarget:weakSelf action:@selector(switchChanged:) forControlEvents:UIControlEventValueChanged]; cell.accessoryView = view; }; diff --git a/Natives/SurfaceViewController.m b/Natives/SurfaceViewController.m index 71752e1e..0e5d6880 100644 --- a/Natives/SurfaceViewController.m +++ b/Natives/SurfaceViewController.m @@ -12,6 +12,7 @@ #import "JavaLauncher.h" #import "LauncherPreferences.h" +#import "LauncherPreferencesViewController2.h" #import "MinecraftResourceUtils.h" #import "SurfaceViewController.h" @@ -193,6 +194,7 @@ BOOL slideableHotbar; @property id mouseConnectCallback, mouseDisconnectCallback; @property id controllerConnectCallback, controllerDisconnectCallback; +@property CGFloat mouseSpeed; @property CGRect clickRange; @property BOOL shouldTriggerClick; @@ -219,7 +221,6 @@ BOOL slideableHotbar; CGFloat screenScale = [[UIScreen mainScreen] scale]; resolutionScale = ((NSNumber *)getPreference(@"resolution")).floatValue / 100.0; - slideableHotbar = [getPreference(@"slideable_hotbar") boolValue]; savedWidth = roundf(screenBounds.size.width * screenScale); savedHeight = roundf(screenBounds.size.height * screenScale); @@ -249,7 +250,7 @@ BOOL slideableHotbar; [menuSwipeView addSubview:menuSwipeLineView]; [self.rootView addSubview:menuSwipeView]; - self.menuArray = @[@"game.menu.forceClose" /*, @"game.menu.logOutput" */]; + self.menuArray = @[@"game.menu.force_close", @"Settings" /*, @"game.menu.log_output" */]; self.menuView = [[UITableView alloc] initWithFrame:CGRectMake(self.view.frame.size.width + 30.0, 0, self.view.frame.size.width * 0.3 - 36.0 * 0.7, self.view.frame.size.height)]; @@ -272,9 +273,6 @@ self.view.frame.size.width * 0.3 - 36.0 * 0.7, self.view.frame.size.height)]; [self.rootView addSubview:self.surfaceView]; [self.rootView addSubview:self.ctrlView]; - - CGFloat buttonScale = [getPreference(@"button_scale") floatValue] / 100.0; - UITapGestureRecognizer *tapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(surfaceOnClick:)]; tapGesture.allowedTouchTypes = @[@(UITouchTypeDirect)]; @@ -304,7 +302,6 @@ self.view.frame.size.width * 0.3 - 36.0 * 0.7, self.view.frame.size.height)]; longpressGesture.allowedTouchTypes = @[@(UITouchTypeDirect)]; longpressGesture.cancelsTouchesInView = NO; longpressGesture.delegate = self; - longpressGesture.minimumPressDuration = [getPreference(@"time_longPressTrigger") floatValue] / 1000; [self.surfaceView addGestureRecognizer:longpressGesture]; self.scrollPanGesture = [[UIPanGestureRecognizer alloc] @@ -349,35 +346,6 @@ self.view.frame.size.width * 0.3 - 36.0 * 0.7, self.view.frame.size.height)]; self.swipeableButtons = [[NSMutableArray alloc] init]; - self.cc_dictionary = parseJSONFromFile(controlFilePath); - if (self.cc_dictionary[@"error"] != nil) { - showDialog(self, @"Error", [NSString stringWithFormat:@"Could not open %@: %@", controlFilePath, [self.cc_dictionary[@"error"] localizedDescription]]); - } else { - CGFloat currentScale = [self.cc_dictionary[@"scaledAt"] floatValue]; - CGFloat savedScale = [getPreference(@"button_scale") floatValue]; - loadControlObject(self.ctrlView, self.cc_dictionary, ^void(ControlButton* button) { - BOOL isSwipeable = [button.properties[@"isSwipeable"] boolValue]; - - button.canBeHidden = YES; - for (int i = 0; i < 4; i++) { - int keycodeInt = [button.properties[@"keycodes"][i] intValue]; - button.canBeHidden &= keycodeInt != SPECIALBTN_TOGGLECTRL; - } - - [button addTarget:self action:@selector(executebtn_down:) forControlEvents:UIControlEventTouchDown]; - [button addTarget:self action:@selector(executebtn_up:) forControlEvents:UIControlEventTouchUpInside | UIControlEventTouchUpOutside]; - - if (isSwipeable) { - UIPanGestureRecognizer *panRecognizerButton = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(executebtn_swipe:)]; - panRecognizerButton.delegate = self; - [button addGestureRecognizer:panRecognizerButton]; - [self.swipeableButtons addObject:button]; - } - }); - - self.cc_dictionary[@"scaledAt"] = @(savedScale); - } - [KeyboardInput initKeycodeTable]; if (@available(iOS 14.0, tvOS 14.0, *)) { self.mouseConnectCallback = [[NSNotificationCenter defaultCenter] addObserverForName:GCMouseDidConnectNotification object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *note) { @@ -432,10 +400,33 @@ self.view.frame.size.width * 0.3 - 36.0 * 0.7, self.view.frame.size.height)]; */ // [self setPreferredFramesPerSecond:1000]; + [self updatePreferenceChanges]; [self executebtn_special_togglebtn:0]; [self launchMinecraft]; } +- (void)updatePreferenceChanges { + self.mouseSpeed = [getPreference(@"mouse_speed") floatValue] / 100.0; + slideableHotbar = [getPreference(@"slideable_hotbar") boolValue]; + + virtualMouseEnabled = [getPreference(@"virtmouse_enable") boolValue]; + if (!isGrabbing) { + self.mousePointerView.hidden = !virtualMouseEnabled; + } + + CGRect screenBounds = [[UIScreen mainScreen] bounds]; + CGFloat mouseScale = [getPreference(@"mouse_scale") floatValue] / 100.0; + virtualMouseFrame = CGRectMake(screenBounds.size.width / 2, screenBounds.size.height / 2, 18.0 * mouseScale, 27 * mouseScale); + self.mousePointerView.frame = virtualMouseFrame; + + // May break anytime lol, current: edge, tap, doubleTap, hover, longPress, scrollPan + UILongPressGestureRecognizer *longpressGesture = self.surfaceView.gestureRecognizers[4]; + longpressGesture.minimumPressDuration = [getPreference(@"press_duration") floatValue] / 1000.0; + + self.ctrlView.frame = CGRectFromString(getPreference(@"control_safe_area")); + [self loadCustomControls]; +} + - (void)launchMinecraft { dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ [MinecraftResourceUtils downloadClientJson:getPreference(@"selected_version") progress:nil callback:nil success:^(NSMutableDictionary *json) { @@ -450,6 +441,44 @@ self.view.frame.size.width * 0.3 - 36.0 * 0.7, self.view.frame.size.height)]; }); } +- (void)loadCustomControls { + [self.ctrlView.subviews makeObjectsPerformSelector:@selector(removeFromSuperview)]; + [self.swipeableButtons removeAllObjects]; + [self.cc_dictionary removeAllObjects]; + + NSString *controlFilePath = [NSString stringWithFormat:@"%s/controlmap/%@", getenv("POJAV_HOME"), (NSString *)getPreference(@"default_ctrl")]; + + self.cc_dictionary = parseJSONFromFile(controlFilePath); + if (self.cc_dictionary[@"error"] != nil) { + showDialog(self, NSLocalizedString(@"Error", nil), [NSString stringWithFormat:@"Could not open %@: %@", controlFilePath, [self.cc_dictionary[@"error"] localizedDescription]]); + return; + } + + CGFloat currentScale = [self.cc_dictionary[@"scaledAt"] floatValue]; + CGFloat savedScale = [getPreference(@"button_scale") floatValue]; + loadControlObject(self.ctrlView, self.cc_dictionary, ^void(ControlButton* button) { + BOOL isSwipeable = [button.properties[@"isSwipeable"] boolValue]; + + button.canBeHidden = YES; + for (int i = 0; i < 4; i++) { + int keycodeInt = [button.properties[@"keycodes"][i] intValue]; + button.canBeHidden &= keycodeInt != SPECIALBTN_TOGGLECTRL; + } + + [button addTarget:self action:@selector(executebtn_down:) forControlEvents:UIControlEventTouchDown]; + [button addTarget:self action:@selector(executebtn_up:) forControlEvents:UIControlEventTouchUpInside | UIControlEventTouchUpOutside]; + + if (isSwipeable) { + UIPanGestureRecognizer *panRecognizerButton = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(executebtn_swipe:)]; + panRecognizerButton.delegate = self; + [button addGestureRecognizer:panRecognizerButton]; + [self.swipeableButtons addObject:button]; + } + }); + + self.cc_dictionary[@"scaledAt"] = @(savedScale); +} + - (UIRectEdge)preferredScreenEdgesDeferringSystemGestures { return UIRectEdgeBottom | UIRectEdgeRight; } @@ -458,7 +487,6 @@ self.view.frame.size.width * 0.3 - 36.0 * 0.7, self.view.frame.size.height)]; return NO; } - #pragma mark - Menu functions CGPoint lastCenterPoint; @@ -515,7 +543,7 @@ CGPoint lastCenterPoint; - (void)actionForceClose { UIAlertController* alert = [UIAlertController alertControllerWithTitle:nil - message:NSLocalizedString(@"game.menu.confirm.forceClose", nil) + message:NSLocalizedString(@"game.menu.confirm.force_close", nil) preferredStyle:UIAlertControllerStyleAlert]; UIAlertAction* cancelAction = [UIAlertAction actionWithTitle:NSLocalizedString(@"Cancel", nil) style:UIAlertActionStyleDefault handler:nil]; @@ -531,7 +559,12 @@ CGPoint lastCenterPoint; }]; [alert addAction:okAction]; - [currentVC() presentViewController:alert animated:YES completion:nil]; + [self presentViewController:alert animated:YES completion:nil]; +} + +- (void)actionOpenPreferences { + LauncherPreferencesViewController2 *vc = [[LauncherPreferencesViewController2 alloc] init]; + [self presentViewController:vc animated:YES completion:nil]; } - (void)actionToggleLogOutput { @@ -567,6 +600,9 @@ CGPoint lastCenterPoint; [self actionForceClose]; break; case 1: + [self actionOpenPreferences]; + break; + case 2: [self actionToggleLogOutput]; break; } @@ -587,12 +623,12 @@ CGPoint lastCenterPoint; screenScale *= resolutionScale; if (virtualMouseEnabled) { if (event == ACTION_MOVE) { - virtualMouseFrame.origin.x += location.x - lastVirtualMousePoint.x; - virtualMouseFrame.origin.y += location.y - lastVirtualMousePoint.y; + virtualMouseFrame.origin.x += (location.x - lastVirtualMousePoint.x) * self.mouseSpeed; + virtualMouseFrame.origin.y += (location.y - lastVirtualMousePoint.y) * self.mouseSpeed; } else if (event == ACTION_MOVE_MOTION) { event = ACTION_MOVE; - virtualMouseFrame.origin.x += location.x; - virtualMouseFrame.origin.y += location.y; + virtualMouseFrame.origin.x += location.x * self.mouseSpeed; + virtualMouseFrame.origin.y += location.y * self.mouseSpeed; } virtualMouseFrame.origin.x = clamp(virtualMouseFrame.origin.x, 0, self.view.frame.size.width); virtualMouseFrame.origin.y = clamp(virtualMouseFrame.origin.y, 0, self.view.frame.size.height); diff --git a/Natives/egl_bridge.m b/Natives/egl_bridge.m index 4a86b31e..48c7e4bf 100644 --- a/Natives/egl_bridge.m +++ b/Natives/egl_bridge.m @@ -306,8 +306,8 @@ jboolean pojavInit_OpenGL() { eglBindAPI_p(EGL_OPENGL_ES_API); } - potatoBridge.eglSurface = eglCreateWindowSurface_p(potatoBridge.eglDisplay, config, (__bridge EGLNativeWindowType) ((SurfaceViewController *)currentVC()).surfaceView.layer, NULL); - //NSLog(@"Layer %@", ((SurfaceViewController *)currentVC()).surfaceView.layer); + potatoBridge.eglSurface = eglCreateWindowSurface_p(potatoBridge.eglDisplay, config, (__bridge EGLNativeWindowType) ((SurfaceViewController *)currentWindow().rootViewController).surfaceView.layer, NULL); + //NSLog(@"Layer %@", ((SurfaceViewController *)currentWindow().rootViewController).surfaceView.layer); if (!potatoBridge.eglSurface) { debugLog("EGLBridge: Error eglCreateWindowSurface failed: 0x%x", eglGetError_p()); @@ -412,7 +412,7 @@ void pojavSwapBuffers() { case RENDERER_VK_ZINK: { glFinish_p(); dispatch_async(dispatch_get_main_queue(), ^{ - [((SurfaceViewController *)currentVC()).surfaceView displayLayer]; + [((SurfaceViewController *)currentWindow().rootViewController).surfaceView displayLayer]; }); } break; } @@ -492,7 +492,7 @@ void pojavMakeCurrent(void* window) { void* pojavCreateContext(void* contextSrc) { if (config_renderer == RENDERER_VULKAN) { - return (__bridge void *)(((SurfaceViewController *)currentVC()).surfaceView.layer); + return (__bridge void *)(((SurfaceViewController *)currentWindow().rootViewController).surfaceView.layer); } if (config_renderer == RENDERER_MTL_ANGLE) { diff --git a/Natives/en.lproj/Localizable.strings b/Natives/en.lproj/Localizable.strings index 85d468ef..31c30f2f 100644 --- a/Natives/en.lproj/Localizable.strings +++ b/Natives/en.lproj/Localizable.strings @@ -3,10 +3,10 @@ StringLocalization */ -"game.menu.forceClose" = "Force close"; -"game.menu.confirm.forceClose" = "Are you sure you want to force close?"; -"game.menu.logOutput" = "Log output"; -"game.menu.customControls" = "Custom controls"; +"game.menu.force_close" = "Force close"; +"game.menu.confirm.force_close" = "Are you sure you want to force close?"; +"game.menu.log_output" = "Log output"; +"game.menu.custom_controls" = "Custom controls"; "Installed" = "Installed"; "Snapshot" = "Snapshot"; @@ -65,6 +65,8 @@ "login.msa.progress.acquireMCToken" = "(4/5) Acquiring the Minecraft token"; "login.msa.progress.checkMCProfile" = "(5/5) Checking the Minecraft profile"; +"Settings" = "Settings"; + "preference.section.general" = "General Settings"; "preference.section.video" = "Video Settings"; "preference.section.control" = "Control Settings"; @@ -74,6 +76,8 @@ "preference.title.game_directory" = "Minecraft game directory"; "preference.title.confirm.delete_game_directory" = "The instance %@ will be deleted forever and cannot be restored."; +"preference.multidir.add_directory" = "add game directory"; + "preference.title.home_symlink" = "Enable compatibility symlink"; "preference.title.check_sha" = "Enable asset verification when launching"; "preference.title.cosmetica" = "Enable Cosmetica integration"; @@ -91,20 +95,21 @@ "preference.title.renderer.tinygl4angle" = "tinygl4angle (1.17+) - exports OpenGL 3.2 (Core Profile, limited)"; "preference.title.renderer.zink" = "Zink (Mesa 21.0) - exports OpenGL 4.1"; -"preference.title.resolution" = "Game resolution"; +"preference.title.resolution" = "Game resolution (%)"; "preference.title.disable_gesture" = "Disable gestures"; -"preference.title.press_duration" = "Long-press duration"; -"preference.title.button_scale" = "On-screen button scale"; -"preference.title.mouse_scale" = "On-screen mouse scale"; -"preference.title.mouse_speed" = "On-screen mouse speed"; +"preference.title.press_duration" = "Long-press duration (ms)"; +"preference.title.button_scale" = "On-screen button scale (%)"; +"preference.title.mouse_scale" = "On-screen mouse scale (%)"; +"preference.title.mouse_speed" = "On-screen mouse speed (%)"; "preference.title.virtmouse_enable" = "Enable on-screen mouse"; "preference.title.slideable_hotbar" = "Enable slideable hotbar"; -"preference.title.java_home" = "Use Java 17 for version < 1.17"; +"preference.title.java_home" = "Use Java 17 for Minecraft < 1.17"; // FIXME: is this filled well in the subtitle? // "preference.subtitle.java_home" = "Java 8 is used by default on Minecraft 1.16.5 and older. This switch forces old versions to use Java 17."; "preference.title.java_args" = "Custom java arguments"; +"preference.placeholder.java_args" = "Specify arguments..."; "preference.title.auto_ram" = "Auto determine RAM amount"; -"preference.title.allocated_memory" = "Allocated memory"; +"preference.title.allocated_memory" = "Allocated memory (MB)"; "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."; // sha check // home symlink diff --git a/Natives/input/ControllerInput.m b/Natives/input/ControllerInput.m index b4728bb4..6bc4ca4e 100644 --- a/Natives/input/ControllerInput.m +++ b/Natives/input/ControllerInput.m @@ -169,7 +169,7 @@ BOOL leftShiftHeld; return; } - UIImageView *pointerView = [(id)currentVC() mousePointerView]; + UIImageView *pointerView = [(id)currentWindow().rootViewController mousePointerView]; virtualMouseFrame.origin.x += xValue; virtualMouseFrame.origin.y += yValue; pointerView.frame = virtualMouseFrame; diff --git a/Natives/input_bridge_v3.m b/Natives/input_bridge_v3.m index d6dc7244..6b8f8264 100644 --- a/Natives/input_bridge_v3.m +++ b/Natives/input_bridge_v3.m @@ -270,16 +270,16 @@ JNIEXPORT void JNICALL Java_org_lwjgl_glfw_CallbackBridge_nativeSetGrabbing(JNIE } dispatch_async(dispatch_get_main_queue(), ^{ - UIView *surfaceView = ((SurfaceViewController *)currentVC()).surfaceView; + UIView *surfaceView = ((SurfaceViewController *)currentWindow().rootViewController).surfaceView; if (isGrabbing == JNI_TRUE) { CGFloat screenScale = [[UIScreen mainScreen] scale] * resolutionScale; callback_SurfaceViewController_onTouch(ACTION_DOWN, lastVirtualMousePoint.x * screenScale, lastVirtualMousePoint.y * screenScale); - ((SurfaceViewController *)currentVC()).mousePointerView.frame = virtualMouseFrame; + ((SurfaceViewController *)currentWindow().rootViewController).mousePointerView.frame = virtualMouseFrame; } - ((SurfaceViewController *)currentVC()).scrollPanGesture.enabled = !isGrabbing; - ((SurfaceViewController *)currentVC()).mousePointerView.hidden = isGrabbing || !virtualMouseEnabled; + ((SurfaceViewController *)currentWindow().rootViewController).scrollPanGesture.enabled = !isGrabbing; + ((SurfaceViewController *)currentWindow().rootViewController).mousePointerView.hidden = isGrabbing || !virtualMouseEnabled; if(@available(iOS 14.0, *)) { - [(SurfaceViewController *)currentVC() setNeedsUpdateOfPrefersPointerLocked]; + [(SurfaceViewController *)currentWindow().rootViewController setNeedsUpdateOfPrefersPointerLocked]; } }); } diff --git a/Natives/utils.h b/Natives/utils.h index 43b77d28..2266300b 100644 --- a/Natives/utils.h +++ b/Natives/utils.h @@ -63,6 +63,7 @@ BOOL isControlModifiable; void init_hookFunctions(); void init_setupMultiDir(); +UIWindow* currentWindow(); UIViewController* currentVC(); NSMutableDictionary* parseJSONFromFile(NSString *path); diff --git a/Natives/utils.m b/Natives/utils.m index b83df79a..20097f6e 100644 --- a/Natives/utils.m +++ b/Natives/utils.m @@ -43,12 +43,16 @@ BOOL getEntitlementValue(NSString *key); } @end -UIViewController* currentVC() { +UIWindow* currentWindow() { id delegate = UIApplication.sharedApplication.delegate; if (@available(iOS 13.0, *)) { delegate = UIApplication.sharedApplication.connectedScenes.anyObject.delegate; } - return [delegate window].visibleViewController; + return [delegate window]; +} + +UIViewController* currentVC() { + return currentWindow().visibleViewController; } BOOL isJITEnabled() { From 92813e5d6cb8f6eb9e6433a2ee070872633e3d45 Mon Sep 17 00:00:00 2001 From: Duy Tran Khanh Date: Sun, 4 Sep 2022 11:51:02 +0700 Subject: [PATCH 28/37] Add Debug logging option, section footers --- Natives/LauncherPreferencesViewController2.m | 12 +++++++++++- Natives/en.lproj/Localizable.strings | 7 ++++++- 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/Natives/LauncherPreferencesViewController2.m b/Natives/LauncherPreferencesViewController2.m index 1531ae40..8919fffb 100644 --- a/Natives/LauncherPreferencesViewController2.m +++ b/Natives/LauncherPreferencesViewController2.m @@ -48,7 +48,9 @@ typedef void(^CreateView)(UITableViewCell *, NSString *, NSDictionary *); @{@"key": @"home_symlink", @"icon": @"link", @"type": self.typeSwitch, - @"enableCondition": whenNotInGame + @"enableCondition": ^BOOL(){ + return getenv("POJAV_DETECTEDJB") != NULL && whenNotInGame(); + } }, @{@"key": @"check_sha", @"icon": @"lock.shield", @@ -60,6 +62,10 @@ typedef void(^CreateView)(UITableViewCell *, NSString *, NSDictionary *); @"type": self.typeSwitch, @"enableCondition": whenNotInGame }, + @{@"key": @"debug_logging", + @"icon": @"doc.badge.gearshape", + @"type": self.typeSwitch + }, @{@"key": @"reset_warnings", @"icon": @"exclamationmark.triangle", @"type": self.typeButton, @@ -225,6 +231,10 @@ viewForHeaderInSection:(NSInteger)section { return NSLocalizedString(([NSString stringWithFormat:@"preference.section.%@", self.prefSections[section]]), nil); } +- (NSString *)tableView:(UITableView *)tableView titleForFooterInSection:(NSInteger)section { + return NSLocalizedString(([NSString stringWithFormat:@"preference.section.footer.%@", self.prefSections[section]]), nil); +} + - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { return self.prefContents[section].count; } diff --git a/Natives/en.lproj/Localizable.strings b/Natives/en.lproj/Localizable.strings index 31c30f2f..75e90923 100644 --- a/Natives/en.lproj/Localizable.strings +++ b/Natives/en.lproj/Localizable.strings @@ -68,9 +68,13 @@ "Settings" = "Settings"; "preference.section.general" = "General Settings"; +"preference.section.footer.general" = "* Compatibility symlink option is planned to be removed in a future release."; "preference.section.video" = "Video Settings"; +"preference.section.footer.video" = "Auto renderer allows Minecraft to request which renderer to use. Reducing resolution reduces GPU workload for better performance."; "preference.section.control" = "Control Settings"; +"preference.section.footer.control" = "Long-press duration involves how long to perform left mouse button press and drop item from the hotbar. Mouse settings affect only for the virtual mouse. Slideable hotbar may help you to switch between hotbar slots better if there is a home indicator."; "preference.section.java" = "Java Runtime Settings"; +"preference.section.footer.java" = "Java 8 is used by default for Minecraft < 1.17. You can use Java 17 for these versions, but compatibility with modded is not guaranteed."; "preference.title.confirm" = "Are you sure?"; @@ -78,9 +82,10 @@ "preference.title.confirm.delete_game_directory" = "The instance %@ will be deleted forever and cannot be restored."; "preference.multidir.add_directory" = "add game directory"; -"preference.title.home_symlink" = "Enable compatibility symlink"; +"preference.title.home_symlink" = "Enable compatibility symlink *"; "preference.title.check_sha" = "Enable asset verification when launching"; "preference.title.cosmetica" = "Enable Cosmetica integration"; +"preference.title.debug_logging" = "Debug logging"; "preference.title.reset_warnings" = "Reset all warnings"; "preference.title.done.reset_warnings" = "All warnings have been reset."; From 022a8cae6fd8810da1bb8d2f7f71545ec879527b Mon Sep 17 00:00:00 2001 From: Duy Tran Khanh Date: Sun, 4 Sep 2022 13:28:47 +0700 Subject: [PATCH 29/37] Remove v1 pref UI --- Natives/CMakeLists.txt | 1 - Natives/LauncherMenuViewController.m | 5 +- Natives/LauncherPreferencesViewController.h | 10 - Natives/LauncherPreferencesViewController.m | 1022 ------------------ Natives/LauncherPreferencesViewController2.m | 9 +- Natives/LauncherViewController.m | 1 - Natives/main.m | 1 - 7 files changed, 2 insertions(+), 1047 deletions(-) delete mode 100644 Natives/LauncherPreferencesViewController.h delete mode 100644 Natives/LauncherPreferencesViewController.m diff --git a/Natives/CMakeLists.txt b/Natives/CMakeLists.txt index d6cb2cbb..c78d0180 100644 --- a/Natives/CMakeLists.txt +++ b/Natives/CMakeLists.txt @@ -117,7 +117,6 @@ add_executable(PojavLauncher LauncherFAQViewController.m LauncherMenuViewController.m LauncherPreferences.m - LauncherPreferencesViewController.m LauncherPreferencesViewController2.m LauncherPrefGameDirViewController.m LauncherSplitViewController.m diff --git a/Natives/LauncherMenuViewController.m b/Natives/LauncherMenuViewController.m index c78c405d..00dda033 100644 --- a/Natives/LauncherMenuViewController.m +++ b/Natives/LauncherMenuViewController.m @@ -1,7 +1,6 @@ #import "authenticator/BaseAuthenticator.h" #import "AccountListViewController.h" #import "LauncherMenuViewController.h" -#import "LauncherPreferencesViewController.h" #import "LauncherPreferencesViewController2.h" #import "LauncherViewController.h" #import "UIButton+AFNetworking.h" @@ -21,12 +20,10 @@ // View controllers are put into an array to keep its state self.options = @[ [[LauncherViewController alloc] init], - [[LauncherPreferencesViewController alloc] init], [[LauncherPreferencesViewController2 alloc] init] ]; self.options[0].title = @"PojavLauncher"; - self.options[1].title = @"Preferences"; - self.options[2].title = NSLocalizedString(@"Settings", nil); + self.options[1].title = NSLocalizedString(@"Settings", nil); //@[@"News", @"Development Console", @"Crash logs"]; self.tableView.separatorStyle = UITableViewCellSeparatorStyleNone; diff --git a/Natives/LauncherPreferencesViewController.h b/Natives/LauncherPreferencesViewController.h deleted file mode 100644 index 08d7e687..00000000 --- a/Natives/LauncherPreferencesViewController.h +++ /dev/null @@ -1,10 +0,0 @@ -#import - -#define JRE8_NAME_JB @"Java 8" -#define JRE16_NAME_JB @"Java 16" -#define JRE17_NAME_JB @"Java 17" -#define JRE8_NAME_SB @"Java 8 (sandbox)" - -@interface LauncherPreferencesViewController : UIViewController - -@end diff --git a/Natives/LauncherPreferencesViewController.m b/Natives/LauncherPreferencesViewController.m deleted file mode 100644 index 0b417b17..00000000 --- a/Natives/LauncherPreferencesViewController.m +++ /dev/null @@ -1,1022 +0,0 @@ -#import "DBNumberedSlider.h" -#import "LauncherPreferences.h" -#import "LauncherPreferencesViewController.h" -#import "LauncherViewController.h" - -#include "utils.h" - -#define BTNSCALE 0 -#define RESOLUTION 1 -#define ALLOCMEM 2 -#define JARGS 3 -#define REND 4 -#define JHOME 5 -#define GDIRECTORY 6 - -#define RESETWARN 8 -#define TYPESEL 9 -#define DEBUGLOG 10 -#define MKGDIR 11 -#define RMGDIR 12 -#define SLIDEHOTBAR 13 -#define SAFEAREA 14 -#define HOMESYM 15 -#define RELAUNCH 16 -#define ERASEPREF 17 -#define ARCCAPES 18 -#define VIRTMOUSE 19 -#define CHECKSHA 20 -#define UNJBRAM 21 - -#define TAG_BTNSCALE 98 -#define TAG_RESOLUTION 99 -#define TAG_ALLOCMEM 100 -#define TAG_JARGS 101 - -#define TAG_REND 102 -#define TAG_PICKER_REND 142 -#define TAG_DONE_REND 152 - -#define TAG_JHOME 103 -#define TAG_PICKER_JHOME 143 -#define TAG_DONE_JHOME 153 - -#define TAG_GDIR 104 -#define TAG_PICKER_GDIR 144 -#define TAG_DONE_GDIR 154 - -#define TAG_RESETWARN 106 - -#define TAG_SWITCH_VRELEASE 107 -#define TAG_SWITCH_VSNAPSHOT 108 -#define TAG_SWITCH_VOLDBETA 109 -#define TAG_SWITCH_VOLDALPHA 110 - -#define TAG_DEBUGLOG 111 -#define TAG_SLIDEHOTBAR 112 - -#define TAG_SAFEAREA 113 - -#define TAG_HOMESYM 114 - -#define TAG_RELAUNCH 115 - -#define TAG_ERASEPREF 116 - -#define TAG_ARCCAPES 117 - -#define TAG_VIRTMOUSE 118 - -#define TAG_CHECKSHA 119 - -#define TAG_UNJBRAM 120 - -@interface LauncherPreferencesViewController () { -} - -// - (void)method - -@end - -@implementation LauncherPreferencesViewController - -UITextField *jargsTextField; -UITextField *rendTextField; -UITextField *jhomeTextField; -UITextField *gdirTextField; -UITextField *activeField; -NSArray* rendererList; -NSMutableArray* gdirList; -NSArray* jhomeList; -UIPickerView* rendPickerView; -UIPickerView* gdirPickerView; -UIPickerView* jhomePickerView; -UISwitch *slideHotbarSwitch; -UIBlurEffect *blur; -UIVisualEffectView *blurView; -UIScrollView *scrollView; - -NSDictionary *rendererDict; -NSArray *menuDict; - -int tempIndex; - -- (void)viewDidLoad -{ - [super viewDidLoad]; - setViewBackgroundColor(self.view); - - CGRect screenBounds = [[UIScreen mainScreen] bounds]; - CGFloat screenScale = [[UIScreen mainScreen] scale]; - - int width = (int) roundf(screenBounds.size.width); - int height = (int) roundf(screenBounds.size.height) - self.navigationController.navigationBar.frame.size.height; - CGFloat currY = 8.0; - - rendererDict = @{ - @"Auto: gl4es or tinygl4angle": @"auto", - @"gl4es 1.1.4 - exports OpenGL 2.1": @ RENDERER_NAME_GL4ES, - @"tinygl4angle (1.17+) - exports OpenGL 3.2 (Core Profile, limited)": @ RENDERER_NAME_MTL_ANGLE, - @"Zink (Mesa 21.0) - exports OpenGL 4.1": @ RENDERER_NAME_VK_ZINK - }; - - scrollView = [[UIScrollView alloc] initWithFrame:self.view.frame]; - scrollView.keyboardDismissMode = UIScrollViewKeyboardDismissModeInteractive; - [self.view addSubview:scrollView]; - scrollView.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth; - - UITableView *tableView = [[UITableView alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.size.width + 20, 0)]; - [scrollView addSubview:tableView]; - - [self registerForKeyboardNotifications]; - - blur = [UIBlurEffect effectWithStyle:UIBlurEffectStyleRegular]; - blurView = [[UIVisualEffectView alloc] initWithEffect:blur]; - - UILabel *btnsizeTextView = [[UILabel alloc] initWithFrame:CGRectMake(16.0, currY, 0.0, 30.0)]; - btnsizeTextView.text = @"Button scale (%)"; - btnsizeTextView.numberOfLines = 0; - btnsizeTextView.textAlignment = NSTextAlignmentCenter; - [btnsizeTextView sizeToFit]; - CGRect tempRect = btnsizeTextView.frame; - tempRect.size.height = 30.0; - btnsizeTextView.frame = tempRect; - [tableView addSubview:btnsizeTextView]; - - DBNumberedSlider *buttonSizeSlider = [[DBNumberedSlider alloc] initWithFrame:CGRectMake(20.0 + btnsizeTextView.frame.size.width, currY, self.view.frame.size.width - btnsizeTextView.frame.size.width - 28.0, btnsizeTextView.frame.size.height)]; - buttonSizeSlider.tag = TAG_BTNSCALE; - [buttonSizeSlider addTarget:self action:@selector(sliderMoved:) forControlEvents:UIControlEventTouchUpInside | UIControlEventTouchUpOutside]; - [buttonSizeSlider setBackgroundColor:[UIColor clearColor]]; - buttonSizeSlider.minimumValue = 50.0; - buttonSizeSlider.maximumValue = 500.0; - buttonSizeSlider.continuous = YES; - buttonSizeSlider.value = [getPreference(@"button_scale") floatValue]; - [tableView addSubview:buttonSizeSlider]; - - UILabel *resolutionTextView = [[UILabel alloc] initWithFrame:CGRectMake(16.0, currY+=43.0, 0.0, 30.0)]; - resolutionTextView.text = @"Resolution (%)"; - resolutionTextView.numberOfLines = 0; - resolutionTextView.textAlignment = NSTextAlignmentCenter; - [resolutionTextView sizeToFit]; - tempRect = resolutionTextView.frame; - tempRect.size.height = 30.0; - resolutionTextView.frame = tempRect; - [tableView addSubview:resolutionTextView]; - - DBNumberedSlider *resolutionSlider = [[DBNumberedSlider alloc] initWithFrame:CGRectMake(20.0 + btnsizeTextView.frame.size.width, currY, self.view.frame.size.width - btnsizeTextView.frame.size.width - 28.0, resolutionTextView.frame.size.height)]; - resolutionSlider.tag = TAG_RESOLUTION; - [resolutionSlider addTarget:self action:@selector(sliderMoved:) forControlEvents:UIControlEventTouchUpInside | UIControlEventTouchUpOutside]; - [resolutionSlider setBackgroundColor:[UIColor clearColor]]; - resolutionSlider.minimumValue = 25; - resolutionSlider.maximumValue = 150; - resolutionSlider.continuous = YES; - resolutionSlider.value = [getPreference(@"resolution") intValue]; - [tableView addSubview:resolutionSlider]; - - - if(getenv("POJAV_DETECTEDJB") || [getPreference(@"ram_unjb_enable") boolValue] == YES) { - // You cannot bypass jetsam memory limits unjailbroken - // Use with caution on unjailbroken devices - UILabel *memTextView = [[UILabel alloc] initWithFrame:CGRectMake(16.0, currY+=45.0, 0.0, 30.0)]; - memTextView.text = @"Allocated RAM"; - memTextView.numberOfLines = 0; - memTextView.textAlignment = NSTextAlignmentCenter; - [memTextView sizeToFit]; - tempRect = memTextView.frame; - tempRect.size.height = 30.0; - memTextView.frame = tempRect; - [tableView addSubview:memTextView]; - - DBNumberedSlider *memSlider = [[DBNumberedSlider alloc] initWithFrame:CGRectMake(20.0 + btnsizeTextView.frame.size.width, currY, self.view.frame.size.width - btnsizeTextView.frame.size.width - 28.0, resolutionTextView.frame.size.height)]; - memSlider.tag = TAG_ALLOCMEM; - [memSlider addTarget:self action:@selector(sliderMoved:) forControlEvents:UIControlEventTouchUpInside | UIControlEventTouchUpOutside]; - [memSlider setBackgroundColor:[UIColor clearColor]]; - memSlider.minimumValue = roundf(([[NSProcessInfo processInfo] physicalMemory] / 1048576) * 0.25); - memSlider.maximumValue = roundf(([[NSProcessInfo processInfo] physicalMemory] / 1048576) * 0.85); - memSlider.fontSize = 10; - memSlider.continuous = YES; - memSlider.value = [getPreference(@"allocated_memory") intValue]; - [tableView addSubview:memSlider]; - } - UILabel *jargsTextView = [[UILabel alloc] initWithFrame:CGRectMake(16.0, currY+=47.0, 0.0, 0.0)]; - jargsTextView.text = @"Java arguments "; - jargsTextView.numberOfLines = 0; - [jargsTextView sizeToFit]; - [tableView addSubview:jargsTextView]; - - jargsTextField = [[UITextField alloc] initWithFrame:CGRectMake(buttonSizeSlider.frame.origin.x + 3, currY, width - jargsTextView.bounds.size.width - 28.0, 30)]; - [jargsTextField addTarget:jargsTextField action:@selector(resignFirstResponder) forControlEvents:UIControlEventEditingDidEndOnExit]; - [jargsTextField setReturnKeyType:UIReturnKeyDone]; - jargsTextField.tag = TAG_JARGS; - jargsTextField.delegate = self; - jargsTextField.placeholder = @"Specify arguments..."; - jargsTextField.text = (NSString *) getPreference(@"java_args"); - jargsTextField.autocorrectionType = UITextAutocorrectionTypeNo; - jargsTextField.contentVerticalAlignment = UIControlContentVerticalAlignmentTop; - jargsTextField.contentHorizontalAlignment = UIControlContentHorizontalAlignmentLeft; - [tableView addSubview:jargsTextField]; - - UILabel *rendTextView = [[UILabel alloc] initWithFrame:CGRectMake(16.0, currY+=44.0, 0.0, 0.0)]; - rendTextView.text = @"Renderer"; - rendTextView.numberOfLines = 0; - [rendTextView sizeToFit]; - [tableView addSubview:rendTextView]; - - rendTextField = [[UITextField alloc] initWithFrame:CGRectMake(buttonSizeSlider.frame.origin.x + 3, currY, width - jargsTextView.bounds.size.width - 28.0, 30)]; - [rendTextField addTarget:rendTextField action:@selector(resignFirstResponder) forControlEvents:UIControlEventEditingDidEndOnExit]; - rendTextField.tag = TAG_REND; - rendTextField.autocorrectionType = UITextAutocorrectionTypeNo; - rendTextField.delegate = self; - rendTextField.placeholder = @"Override renderer..."; - //rendTextField.text = self.rendererDict[getPreference(@"renderer")]; - tempIndex = [rendererDict.allValues indexOfObject:getPreference(@"renderer")]; - rendTextField.text = rendererDict.allKeys[tempIndex]; - - rendTextField.contentVerticalAlignment = UIControlContentVerticalAlignmentTop; - rendTextField.contentHorizontalAlignment = UIControlContentHorizontalAlignmentLeft; - [tableView addSubview:rendTextField]; - - //[rendererList addObject:virglrenderer]; - - rendPickerView = [[UIPickerView alloc] init]; - rendPickerView.delegate = self; - rendPickerView.dataSource = self; - rendPickerView.tag = TAG_PICKER_REND; - [rendPickerView reloadAllComponents]; - [rendPickerView selectRow:tempIndex inComponent:0 animated:NO]; - UIToolbar *rendPickerToolbar = [[UIToolbar alloc] initWithFrame:CGRectMake(0.0, 0.0, self.view.frame.size.width, 44.0)]; - UIBarButtonItem *rendFlexibleSpace = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:self action:nil]; - UIBarButtonItem *rendDoneButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone target:self action:@selector(closeKeyboard:)]; - rendDoneButton.tag = TAG_DONE_REND; - rendPickerToolbar.items = @[rendFlexibleSpace, rendDoneButton]; - - rendTextField.inputAccessoryView = rendPickerToolbar; - rendTextField.inputView = rendPickerView; - - UILabel *jhomeTextView = [[UILabel alloc] initWithFrame:CGRectMake(16.0, currY+=44.0, 0.0, 0.0)]; - jhomeTextView.text = @"Java version"; - jhomeTextView.numberOfLines = 0; - [jhomeTextView sizeToFit]; - [tableView addSubview:jhomeTextView]; - - jhomeTextField = [[UITextField alloc] initWithFrame:CGRectMake(buttonSizeSlider.frame.origin.x + 3, currY, width - jargsTextView.bounds.size.width - 28.0, 30)]; - [jhomeTextField addTarget:jhomeTextField action:@selector(resignFirstResponder) forControlEvents:UIControlEventEditingDidEndOnExit]; - jhomeTextField.tag = TAG_JHOME; - jhomeTextField.autocorrectionType = UITextAutocorrectionTypeNo; - jhomeTextField.delegate = self; - jhomeTextField.placeholder = @"Override Java path..."; - - jhomeTextField.text = [getPreference(@"java_home") lastPathComponent]; - - jhomeTextField.contentVerticalAlignment = UIControlContentVerticalAlignmentTop; - jhomeTextField.contentHorizontalAlignment = UIControlContentHorizontalAlignmentLeft; - [tableView addSubview:jhomeTextField]; - - NSString *listPath = getenv("POJAV_DETECTEDJB") ? @"/usr/lib/jvm" : [NSString stringWithFormat:@"%s/jvm", getenv("BUNDLE_PATH")]; - jhomeList = [NSFileManager.defaultManager contentsOfDirectoryAtPath:listPath error:nil]; - - jhomePickerView = [[UIPickerView alloc] init]; - jhomePickerView.delegate = self; - jhomePickerView.dataSource = self; - jhomePickerView.tag = TAG_PICKER_JHOME; - [jhomePickerView reloadAllComponents]; - for (int i = 0; i < jhomeList.count; i++) { - if ([jhomeTextField.text isEqualToString:jhomeList[i]]) { - [jhomePickerView selectRow:i inComponent:0 animated:NO]; - break; - } - } - UIToolbar *jhomePickerToolbar = [[UIToolbar alloc] initWithFrame:CGRectMake(0.0, 0.0, self.view.frame.size.width, 44.0)]; - UIBarButtonItem *jhomeFlexibleSpace = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:self action:nil]; - UIBarButtonItem *jhomeDoneButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone target:self action:@selector(closeKeyboard:)]; - jhomeDoneButton.tag = TAG_DONE_JHOME; - jhomePickerToolbar.items = @[jhomeFlexibleSpace, jhomeDoneButton]; - - jhomeTextField.inputAccessoryView = jhomePickerToolbar; - jhomeTextField.inputView = jhomePickerView; - - UILabel *gdirTextView = [[UILabel alloc] initWithFrame:CGRectMake(16.0, currY+=44.0, 0.0, 0.0)]; - gdirTextView.text = @"Game directory"; - gdirTextView.numberOfLines = 0; - [gdirTextView sizeToFit]; - [tableView addSubview:gdirTextView]; - - gdirTextField = [[UITextField alloc] initWithFrame:CGRectMake(buttonSizeSlider.frame.origin.x + 3, currY, width - jargsTextView.bounds.size.width - 28.0, 30)]; - [gdirTextField addTarget:jhomeTextField action:@selector(resignFirstResponder) forControlEvents:UIControlEventEditingDidEndOnExit]; - gdirTextField.tag = TAG_GDIR; - gdirTextField.delegate = self; - gdirTextField.placeholder = @"Custom game directory..."; - gdirTextField.text = (NSString *) getPreference(@"game_directory"); - gdirTextField.contentVerticalAlignment = UIControlContentVerticalAlignmentTop; - gdirTextField.contentHorizontalAlignment = UIControlContentHorizontalAlignmentLeft; - [tableView addSubview:gdirTextField]; - - gdirPickerView = [[UIPickerView alloc] init]; - gdirPickerView.delegate = self; - gdirPickerView.dataSource = self; - gdirPickerView.tag = TAG_PICKER_GDIR; - [self instanceDirCont]; - UIToolbar *gdirPickerToolbar = [[UIToolbar alloc] initWithFrame:CGRectMake(0.0, 0.0, self.view.frame.size.width, 44.0)]; - UIBarButtonItem *gdirFlexibleSpace = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:self action:nil]; - UIBarButtonItem *gdirDoneButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone target:self action:@selector(closeKeyboard:)]; - UIBarButtonItem *gdirCreateButton = [[UIBarButtonItem alloc] initWithTitle:@"Create new" style:UIBarButtonItemStyleDone target:self action:@selector(createDir:)]; - UIBarButtonItem *gdirDeleteButton = [[UIBarButtonItem alloc] initWithTitle:@"Delete" style:UIBarButtonItemStyleDone target:self action:@selector(removeDir:)]; - gdirDoneButton.tag = TAG_DONE_GDIR; - gdirPickerToolbar.items = @[gdirCreateButton, gdirDeleteButton, gdirFlexibleSpace, gdirDoneButton]; - - gdirTextField.inputAccessoryView = gdirPickerToolbar; - gdirTextField.inputView = gdirPickerView; - - UILabel *slideHotbarTextView = [[UILabel alloc] initWithFrame:CGRectMake(16.0, currY+=44.0, 0.0, 0.0)]; - slideHotbarTextView.text = @"Slideable hotbar"; - slideHotbarTextView.numberOfLines = 0; - [slideHotbarTextView sizeToFit]; - [tableView addSubview:slideHotbarTextView]; - - slideHotbarSwitch = [[UISwitch alloc] initWithFrame:CGRectMake(width - 62.0, currY - 5.0, 50.0, 30)]; - slideHotbarSwitch.tag = TAG_SLIDEHOTBAR; - [slideHotbarSwitch setOn:[getPreference(@"slideable_hotbar") boolValue] animated:NO]; - [slideHotbarSwitch addTarget:self action:@selector(switchChanged:) forControlEvents:UIControlEventValueChanged]; - [tableView addSubview:slideHotbarSwitch]; - - UILabel *resetWarnTextView = [[UILabel alloc] initWithFrame:CGRectMake(16.0, currY+=44.0, 0.0, 0.0)]; - resetWarnTextView.text = @"Reset launcher warnings"; - resetWarnTextView.numberOfLines = 0; - [resetWarnTextView sizeToFit]; - [tableView addSubview:resetWarnTextView]; - - UISwitch *resetWarnSwitch = [[UISwitch alloc] initWithFrame:CGRectMake(width - 62.0, currY - 5.0, 50.0, 30)]; - resetWarnSwitch.tag = TAG_RESETWARN; - [resetWarnSwitch setOn:NO animated:NO]; - [resetWarnSwitch addTarget:self action:@selector(switchChanged:) forControlEvents:UIControlEventValueChanged]; - [tableView addSubview:resetWarnSwitch]; - - UILabel *checkSHATextView = [[UILabel alloc] initWithFrame:CGRectMake(16.0, currY+=44.0, 0.0, 0.0)]; - checkSHATextView.text = @"Check game files before launching"; - checkSHATextView.numberOfLines = 0; - [checkSHATextView sizeToFit]; - [tableView addSubview:checkSHATextView]; - - UISwitch *checkSHASwitch = [[UISwitch alloc] initWithFrame:CGRectMake(width - 62.0, currY - 5.0, 50.0, 30)]; - checkSHASwitch.tag = TAG_CHECKSHA; - [checkSHASwitch setOn:[getPreference(@"check_sha") boolValue] animated:NO]; - [checkSHASwitch addTarget:self action:@selector(switchChanged:) forControlEvents:UIControlEventValueChanged]; - [tableView addSubview:checkSHASwitch]; - - UILabel *debugLogTextView = [[UILabel alloc] initWithFrame:CGRectMake(16.0, currY+=44.0, 0.0, 0.0)]; - debugLogTextView.text = @"Enable debug logging"; - debugLogTextView.numberOfLines = 0; - [debugLogTextView sizeToFit]; - [tableView addSubview:debugLogTextView]; - - UISwitch *debugLogSwitch = [[UISwitch alloc] initWithFrame:CGRectMake(width - 62.0, currY - 5.0, 50.0, 30)]; - debugLogSwitch.tag = TAG_DEBUGLOG; - [debugLogSwitch setOn:[getPreference(@"debug_logging") boolValue] animated:NO]; - [debugLogSwitch addTarget:self action:@selector(switchChanged:) forControlEvents:UIControlEventValueChanged]; - [tableView addSubview:debugLogSwitch]; - - if(getenv("POJAV_DETECTEDJB")) { - // Used for legacy iOS users who are used to - // the old home directory for the game - // TODO: Remove for everyone - UILabel *homesymTextView = [[UILabel alloc] initWithFrame:CGRectMake(16.0, currY+=44.0, 0.0, 0.0)]; - homesymTextView.text = @"Disable home symlink"; - homesymTextView.numberOfLines = 0; - [homesymTextView sizeToFit]; - [tableView addSubview:homesymTextView]; - - UISwitch *homesymSwitch = [[UISwitch alloc] initWithFrame:CGRectMake(width - 62.0, currY - 5.0, 50.0, 30)]; - homesymSwitch.tag = TAG_HOMESYM; - [homesymSwitch setOn:[getPreference(@"disable_home_symlink") boolValue] animated:NO]; - [homesymSwitch addTarget:self action:@selector(switchChanged:) forControlEvents:UIControlEventValueChanged]; - [tableView addSubview:homesymSwitch]; - } - - UILabel *relaunchTextView = [[UILabel alloc] initWithFrame:CGRectMake(16.0, currY+=44.0, 0.0, 0.0)]; - relaunchTextView.text = @"Restart before launching game"; - relaunchTextView.numberOfLines = 0; - [relaunchTextView sizeToFit]; - [tableView addSubview:relaunchTextView]; - - UISwitch *relaunchSwitch = [[UISwitch alloc] initWithFrame:CGRectMake(width - 62.0, currY - 5.0, 50.0, 30)]; - relaunchSwitch.tag = TAG_RELAUNCH; - [relaunchSwitch setOn:[getPreference(@"restart_before_launch") boolValue] animated:NO]; - [relaunchSwitch addTarget:self action:@selector(switchChanged:) forControlEvents:UIControlEventValueChanged]; - [tableView addSubview:relaunchSwitch]; - - UILabel *arcCapesTextView = [[UILabel alloc] initWithFrame:CGRectMake(16.0, currY+=44.0, 0.0, 0.0)]; - arcCapesTextView.text = @"Enable Cosmetica capes"; - arcCapesTextView.numberOfLines = 0; - [arcCapesTextView sizeToFit]; - [tableView addSubview:arcCapesTextView]; - - UISwitch *arcCapesSwitch = [[UISwitch alloc] initWithFrame:CGRectMake(width - 62.0, currY - 5.0, 50.0, 30)]; - arcCapesSwitch.tag = TAG_ARCCAPES; - [arcCapesSwitch setOn:[getPreference(@"arccapes_enable") boolValue] animated:NO]; - [arcCapesSwitch addTarget:self action:@selector(switchChanged:) forControlEvents:UIControlEventValueChanged]; - [tableView addSubview:arcCapesSwitch]; - - UILabel *virtMouseTextView = [[UILabel alloc] initWithFrame:CGRectMake(16.0, currY+=44.0, 0.0, 0.0)]; - virtMouseTextView.text = @"Enable virtual mouse"; - virtMouseTextView.numberOfLines = 0; - [virtMouseTextView sizeToFit]; - [tableView addSubview:virtMouseTextView]; - - UISwitch *virtMouseSwitch = [[UISwitch alloc] initWithFrame:CGRectMake(width - 62.0, currY - 5.0, 50.0, 30)]; - virtMouseSwitch.tag = TAG_VIRTMOUSE; - [virtMouseSwitch setOn:[getPreference(@"virtmouse_enable") boolValue] animated:NO]; - [virtMouseSwitch addTarget:self action:@selector(switchChanged:) forControlEvents:UIControlEventValueChanged]; - [tableView addSubview:virtMouseSwitch]; - - UILabel *erasePrefTextView = [[UILabel alloc] initWithFrame:CGRectMake(16.0, currY+=44.0, 0.0, 0.0)]; - erasePrefTextView.text = @"Reset all settings"; - erasePrefTextView.numberOfLines = 0; - [erasePrefTextView sizeToFit]; - [tableView addSubview:erasePrefTextView]; - - UISwitch *erasePrefSwitch = [[UISwitch alloc] initWithFrame:CGRectMake(width - 62.0, currY - 5.0, 50.0, 30)]; - erasePrefSwitch.tag = TAG_ERASEPREF; - [erasePrefSwitch setOn:NO animated:NO]; - [erasePrefSwitch addTarget:self action:@selector(switchChanged:) forControlEvents:UIControlEventValueChanged]; - [tableView addSubview:erasePrefSwitch]; - - if(!getenv("POJAV_DETECTEDJB")) { - UILabel *enableRAMTextView = [[UILabel alloc] initWithFrame:CGRectMake(16.0, currY+=44.0, 0.0, 0.0)]; - enableRAMTextView.text = @"Enable RAM slider"; - enableRAMTextView.numberOfLines = 0; - [enableRAMTextView sizeToFit]; - [tableView addSubview:enableRAMTextView]; - - UISwitch *enableRAMSwitch = [[UISwitch alloc] initWithFrame:CGRectMake(width - 62.0, currY - 5.0, 50.0, 30)]; - enableRAMSwitch.tag = TAG_UNJBRAM; - [enableRAMSwitch setOn:[getPreference(@"ram_unjb_enable") boolValue] animated:NO]; - [enableRAMSwitch addTarget:self action:@selector(switchChanged:) forControlEvents:UIControlEventValueChanged]; - [tableView addSubview:enableRAMSwitch]; - } - - CGRect frame = tableView.frame; - frame.size.height = currY+=44; - tableView.frame = frame; - scrollView.contentSize = CGSizeMake(scrollView.frame.size.width, tableView.frame.size.height); - - if (@available(iOS 14.0, *)) { - // use UIMenu - UIBarButtonItem *help = [[UIBarButtonItem alloc] initWithImage:[[UIImage systemImageNamed:@"questionmark.circle"] imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate] style:UIBarButtonItemStyleDone target:self action:@selector(helpMenu)]; - UIBarButtonItem *close = [[UIBarButtonItem alloc] initWithImage:[[UIImage systemImageNamed:@"xmark.circle"] imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate] style:UIBarButtonItemStyleDone target:self action:@selector(exitAppAlert)]; - self.navigationItem.rightBarButtonItems = @[help, close]; - UIAction *buttonScale = [UIAction actionWithTitle:@"Button scale" image:[[UIImage systemImageNamed:@"aspectratio"] imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate] identifier:nil handler:^(__kindof UIAction * _Nonnull action) {[self helpAlertOpt:BTNSCALE];}]; - UIAction *resolution = [UIAction actionWithTitle:@"Resolution" image:[[UIImage systemImageNamed:@"viewfinder"] imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate] identifier:nil handler:^(__kindof UIAction * _Nonnull action) {[self helpAlertOpt:RESOLUTION];}]; - UIAction *allocRAM = [UIAction actionWithTitle:@"Allocated RAM" image:[[UIImage systemImageNamed:@"memorychip"] imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate] identifier:nil handler:^(__kindof UIAction * _Nonnull action) {[self helpAlertOpt:ALLOCMEM];}]; - UIAction *jargs = [UIAction actionWithTitle:@"Java arguments" image:[[UIImage systemImageNamed:@"character.cursor.ibeam"] imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate] identifier:nil handler:^(__kindof UIAction * _Nonnull action) {[self helpAlertOpt:JARGS];}]; - UIAction *renderer = [UIAction actionWithTitle:@"Renderer" image:[[UIImage systemImageNamed:@"cpu"] imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate] identifier:nil handler:^(__kindof UIAction * _Nonnull action) {[self helpAlertOpt:REND];}]; - UIAction *jversion = [UIAction actionWithTitle:@"Java version" image:[[UIImage systemImageNamed:@"cube"] imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate] identifier:nil handler:^(__kindof UIAction * _Nonnull action) {[self helpAlertOpt:JHOME];}]; - UIAction *gamedir = [UIAction actionWithTitle:@"Game directory" image:[[UIImage systemImageNamed:@"folder"] imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate] identifier:nil handler:^(__kindof UIAction * _Nonnull action) {[self helpAlertOpt:GDIRECTORY];}]; - UIAction *hotbar = [UIAction actionWithTitle:@"Slideable hotbar" image:[[UIImage systemImageNamed:@"slider.horizontal.below.rectangle"] imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate] identifier:nil handler:^(__kindof UIAction * _Nonnull action) {[self helpAlertOpt:SLIDEHOTBAR];}]; - UIAction *resetwarn = [UIAction actionWithTitle:@"Reset warnings" image:[[UIImage systemImageNamed:@"exclamationmark.triangle"] imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate] identifier:nil handler:^(__kindof UIAction * _Nonnull action) {[self helpAlertOpt:RESETWARN];}]; - UIAction *shacheck = [UIAction actionWithTitle:@"Check game files before launching" image:[[UIImage systemImageNamed:@"shield.lefthalf.fill"] imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate] identifier:nil handler:^(__kindof UIAction * _Nonnull action) {[self helpAlertOpt:CHECKSHA];}]; - UIAction *safearea = [UIAction actionWithTitle:@"Safe area" image:[[UIImage systemImageNamed:@"crop"] imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate] identifier:nil handler:^(__kindof UIAction * _Nonnull action) {[self helpAlertOpt:SAFEAREA];}]; - UIAction *debugLog = [UIAction actionWithTitle:@"Debug logging" image:[[UIImage systemImageNamed:@"doc.badge.gearshape"] imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate] identifier:nil handler:^(__kindof UIAction * _Nonnull action) {[self helpAlertOpt:DEBUGLOG];}]; - UIAction *restart = [UIAction actionWithTitle:@"Restart before launching game" image:[[UIImage systemImageNamed:@"arrowtriangle.left.circle"] imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate] identifier:nil handler:^(__kindof UIAction * _Nonnull action) {[self helpAlertOpt:RELAUNCH];}]; - UIAction *symlink = [UIAction actionWithTitle:@"Home symlink" image:[[UIImage systemImageNamed:@"link"] imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate] identifier:nil handler:^(__kindof UIAction * _Nonnull action) {[self helpAlertOpt:HOMESYM];}]; - UIAction *cosmetica = [UIAction actionWithTitle:@"Enable Cosmetica capes" image:[[UIImage systemImageNamed:@"square.and.arrow.down"] imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate] identifier:nil handler:^(__kindof UIAction * _Nonnull action) {[self helpAlertOpt:ARCCAPES];}]; - UIAction *virtmouse = [UIAction actionWithTitle:@"Enable virtual mouse" image:[[UIImage systemImageNamed:@"cursorarrow.rays"] imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate] identifier:nil handler:^(__kindof UIAction * _Nonnull action) {[self helpAlertOpt:VIRTMOUSE];}]; - UIAction *resetprefs = [UIAction actionWithTitle:@"Reset preferences" image:[[UIImage systemImageNamed:@"trash"] imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate] identifier:nil handler:^(__kindof UIAction * _Nonnull action) {[self helpAlertOpt:ERASEPREF];}]; - UIAction *enableRAM = [UIAction actionWithTitle:@"Enable RAM slider" image:[[UIImage systemImageNamed:@"slider.horizontal.3"] imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate] identifier:nil handler:^(__kindof UIAction * _Nonnull action) {[self helpAlertOpt:UNJBRAM];}]; - - if(getenv("POJAV_DETECTEDJB")) { - menuDict = @[buttonScale, resolution, allocRAM, jargs, renderer, jversion, gamedir, hotbar, resetwarn, shacheck, safearea, debugLog, restart, symlink, cosmetica, virtmouse, resetprefs]; - } else if(!getenv("POJAV_DETECTEDJB") && [getPreference(@"disable_home_symlink") boolValue] == YES) { - menuDict = @[buttonScale, resolution, allocRAM, jargs, renderer, jversion, gamedir, hotbar, resetwarn, shacheck, safearea, debugLog, restart, symlink, cosmetica, virtmouse, resetprefs, enableRAM]; - } else { - menuDict = @[buttonScale, resolution, jargs, renderer, jversion, gamedir, hotbar, resetwarn, shacheck, safearea, debugLog, restart, symlink, cosmetica, virtmouse, resetprefs, enableRAM]; - } - - UIMenu *menu = [UIMenu menuWithTitle:@"" image:nil identifier:nil options:UIMenuOptionsDisplayInline children:menuDict]; - self.navigationItem.rightBarButtonItem.action = nil; - self.navigationItem.rightBarButtonItem.primaryAction = nil; - self.navigationItem.rightBarButtonItem.menu = menu; - } else { - UIBarButtonItem *help = [[UIBarButtonItem alloc] initWithTitle:@"Help" style:UIBarButtonItemStyleDone target:self action:@selector(helpMenu)]; - UIBarButtonItem *close = [[UIBarButtonItem alloc] initWithTitle:@"Close App" style:UIBarButtonItemStyleDone target:self action:@selector(exitApp)]; - self.navigationItem.rightBarButtonItems = @[help, close]; - } -} - -- (void)registerForKeyboardNotifications -{ - [[NSNotificationCenter defaultCenter] addObserver:self - selector:@selector(keyboardWasShown:) - name:UIKeyboardDidShowNotification object:nil]; - - [[NSNotificationCenter defaultCenter] addObserver:self - selector:@selector(keyboardWillBeHidden:) - name:UIKeyboardWillHideNotification object:nil]; - -} - -- (void)keyboardWasShown:(NSNotification*)aNotification -{ - NSDictionary* info = [aNotification userInfo]; - CGSize kbSize = [[info objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue].size; - - UIEdgeInsets contentInsets = UIEdgeInsetsMake(0.0, 0.0, kbSize.height, 0.0); - scrollView.contentInset = contentInsets; - scrollView.scrollIndicatorInsets = contentInsets; - CGRect aRect = self.view.frame; - aRect.size.height -= kbSize.height; - if (!CGRectContainsPoint(aRect, activeField.frame.origin) ) { - CGPoint scrollPoint = CGPointMake(0.0, activeField.frame.origin.y-kbSize.height); - [scrollView setContentOffset:scrollPoint animated:YES]; - } -} - -- (void)keyboardWillBeHidden:(NSNotification*)aNotification -{ - UIEdgeInsets contentInsets = UIEdgeInsetsZero; - scrollView.contentInset = contentInsets; - scrollView.scrollIndicatorInsets = contentInsets; -} - -- (void)textFieldDidBeginEditing:(UITextField *)textField -{ - activeField = textField; -} - -- (void)textFieldDidEndEditing:(UITextField *)textField { - activeField = nil; - if (textField.tag == TAG_JARGS) { - setPreference(@"java_args", textField.text); - } else if (textField.tag == TAG_REND) { - setPreference(@"renderer", rendererDict[textField.text]); - setenv("POJAV_RENDERER", [getPreference(@"renderer") UTF8String], 1); - } else if (textField.tag == TAG_JHOME) { - setPreference(@"java_home", textField.text); - if (![textField.text containsString:JRE8_NAME_JB] && ![textField.text containsString:JRE8_NAME_SB] && [getPreference(@"java_warn") boolValue] == YES) { - UIAlertController *javaAlert = [UIAlertController alertControllerWithTitle:@"Java version is not Java 8" message:@"Minecraft versions below 1.6, modded below 1.16.4, and the mod installer will not work unless you have Java 8 installed on your device." preferredStyle:UIAlertControllerStyleAlert]; - UIAlertAction *ok = [UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleCancel handler:nil]; - [self presentViewController:javaAlert animated:YES completion:nil]; - [javaAlert addAction:ok]; - setPreference(@"java_warn", @NO); - } - } else if (textField.tag == TAG_GDIR) { - setPreference(@"game_directory", textField.text); - init_setupMultiDir(); - } -} - -- (void)exitAppAlert { - UIAlertController *closeAlert = [UIAlertController alertControllerWithTitle:@"Close PojavLauncher?" message:@"" preferredStyle:UIAlertControllerStyleAlert]; - UIAlertAction *close = [UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {[self exitApp];}]; - UIAlertAction *cancel = [UIAlertAction actionWithTitle:@"Cancel" style:UIAlertActionStyleDefault handler:nil]; - [closeAlert addAction:cancel]; - [closeAlert addAction:close]; - [self presentViewController:closeAlert animated:YES completion:nil]; - -} - -- (void)exitApp { - [blurView setFrame:[[self view] bounds]]; - [blurView setAlpha:0]; - [self.view addSubview:blurView]; - - [UIView animateWithDuration:0.5 delay:0 options:UIViewAnimationOptionCurveEaseOut animations:^{ - [blurView setAlpha:1]; - } completion:^(BOOL finished) { - exit(0); - }]; -} - --(void)instanceDirCont { - NSFileManager *fm = [NSFileManager defaultManager]; - NSArray* files = [fm contentsOfDirectoryAtPath:[NSString stringWithFormat:@"%s/instances", getenv("POJAV_HOME")] error:nil]; - if (gdirList == nil) { - gdirList = [NSMutableArray arrayWithCapacity:10]; - } else { - [gdirList removeAllObjects]; - } - BOOL updateTempIndex = YES; - tempIndex = 0; - for(NSString *file in files) { - NSString *path = [[NSString stringWithFormat:@"%s/instances", getenv("POJAV_HOME")] stringByAppendingPathComponent:file]; - BOOL isDir = NO; - [fm fileExistsAtPath:path isDirectory:(&isDir)]; - if(isDir) { - [gdirList addObject:file]; - if ([file isEqualToString:gdirTextField.text]) { - updateTempIndex = NO; - } - if (updateTempIndex) { - ++tempIndex; - } - } - } - [gdirPickerView reloadAllComponents]; - [gdirPickerView selectRow:tempIndex inComponent:0 animated:NO]; -} - -- (void)createDir:(UIBarButtonItem *)sender { - int type = MKGDIR; - UIAlertController *manageDirAC = [UIAlertController alertControllerWithTitle:@"Create a new game directory" message:@"" preferredStyle:UIAlertControllerStyleAlert]; - [manageDirAC addTextFieldWithConfigurationHandler:^(UITextField * _Nonnull textField) { - textField.placeholder = @"Name of new directory"; - textField.secureTextEntry = NO; - }]; - UIAlertAction *confirm = [UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) { - NSString *directory = [NSString stringWithFormat:@"%s/instances/%@", getenv("POJAV_HOME"), [[manageDirAC textFields][0] text]]; - NSError *error; - BOOL isDir = NO; - if([[NSFileManager defaultManager] createDirectoryAtPath:directory withIntermediateDirectories:NO attributes:nil error:&error]) { - [self instanceDirCont]; - gdirTextField.text = [[manageDirAC textFields][0] text]; - [gdirTextField endEditing:YES]; - } - [self manageDirResult:(UIButton *)sender error:error directory:[[manageDirAC textFields][0] text] type:type]; - }]; - [manageDirAC addAction:confirm]; - UIAlertAction *cancel = [UIAlertAction actionWithTitle:@"Cancel" style:UIAlertActionStyleCancel handler:nil]; - [manageDirAC addAction:cancel]; - [self presentViewController:manageDirAC animated:YES completion:nil]; -} -- (void)removeDir:(UIBarButtonItem *)sender { - int type = RMGDIR; - if(![gdirTextField.text isEqualToString:@"default"]) { - UIAlertController *manageDirAC = [UIAlertController alertControllerWithTitle:@"Are you sure you want to delete this?" message:[NSString stringWithFormat:@"The instance %@ will be deleted forever and cannot be restored.", gdirTextField.text] preferredStyle:UIAlertControllerStyleActionSheet]; - UIAlertAction *confirm = [UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) { - NSString *directory = [NSString stringWithFormat:@"%s/instances/%@", getenv("POJAV_HOME"), gdirTextField.text]; - NSLog(@"%@", directory); - NSError *error; - BOOL isDir = NO; - if([[NSFileManager defaultManager] removeItemAtPath:directory error:&error]) { - [self instanceDirCont]; - gdirTextField.text = @"default"; - [gdirTextField endEditing:YES]; - } - [self manageDirResult:(UIButton *)sender error:error directory:gdirTextField.text type:type]; - }]; - [manageDirAC addAction:confirm]; - UIAlertAction *cancel = [UIAlertAction actionWithTitle:@"Cancel" style:UIAlertActionStyleCancel handler:nil]; - [manageDirAC addAction:cancel]; - [self presentViewController:manageDirAC animated:YES completion:nil]; - } else if([gdirTextField.text isEqualToString:@"default"]){ - UIAlertController *gdirAlert = [UIAlertController alertControllerWithTitle:@"You cannot delete the default game directory." message:@"" preferredStyle:UIAlertControllerStyleActionSheet]; - [self setPopoverProperties:gdirAlert.popoverPresentationController sender:(UIButton *)sender]; - UIAlertAction *ok = [UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleCancel handler:nil]; - [gdirAlert addAction:ok]; - [self presentViewController:gdirAlert animated:YES completion:nil]; - } -} - -- (void)manageDirResult:(UIButton *)sender error:(NSError *)error directory:(NSString *)dirName type:(int)type { - NSString *title; - NSString *message; - if (error == nil) { - if(type == MKGDIR) { - title = @"Successfully changed directory."; - } else if (type == RMGDIR) { - title = @"Successfully removed directory."; - } - } else { - title = @"An error occurred."; - message = error.localizedDescription; - } - - UIAlertController *gdirAlert = [UIAlertController alertControllerWithTitle:title message:message preferredStyle:UIAlertControllerStyleActionSheet]; - [self setPopoverProperties:gdirAlert.popoverPresentationController sender:sender]; - UIAlertAction *ok = [UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleCancel handler:nil]; - [gdirAlert addAction:ok]; - [self presentViewController:gdirAlert animated:YES completion:nil]; -} - -- (void)helpMenu { - if (@available(iOS 14.0, *)) { - // UIMenu - } else { - UIAlertController *helpAlert = [UIAlertController alertControllerWithTitle:@"Needing help with these preferences?" message:nil preferredStyle:UIAlertControllerStyleActionSheet]; - UIAlertAction *btnscale = [UIAlertAction actionWithTitle:@"Button scale" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {[self helpAlertOpt:BTNSCALE];}]; - [helpAlert addAction:btnscale]; - UIAlertAction *resolution = [UIAlertAction actionWithTitle:@"Resolution" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {[self helpAlertOpt:RESOLUTION];}]; - [helpAlert addAction:resolution]; - if(getenv("POJAV_DETECTEDJB") || [getPreference(@"disable_home_symlink") boolValue] == YES) { - UIAlertAction *allocmem = [UIAlertAction actionWithTitle:@"Allocated RAM" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {[self helpAlertOpt:ALLOCMEM];}]; - [helpAlert addAction:allocmem]; - } - UIAlertAction *jargs = [UIAlertAction actionWithTitle:@"Java arguments" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {[self helpAlertOpt:JARGS];}]; - [helpAlert addAction:jargs]; - UIAlertAction *renderer = [UIAlertAction actionWithTitle:@"Renderer" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {[self helpAlertOpt:REND];}]; - [helpAlert addAction:renderer]; - if(getenv("POJAV_DETECTEDJB")) { - UIAlertAction *jhome = [UIAlertAction actionWithTitle:@"Java version" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {[self helpAlertOpt:JHOME];}]; - [helpAlert addAction:jhome]; - } - UIAlertAction *gdirectory = [UIAlertAction actionWithTitle:@"Game directory" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {[self helpAlertOpt:GDIRECTORY];}]; - [helpAlert addAction:gdirectory]; - UIAlertAction *slidehotbar = [UIAlertAction actionWithTitle:@"Slideable hotbar" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {[self helpAlertOpt:SLIDEHOTBAR];}]; - [helpAlert addAction:slidehotbar]; - UIAlertAction *resetwarn = [UIAlertAction actionWithTitle:@"Reset warnings" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {[self helpAlertOpt:RESETWARN];}]; - [helpAlert addAction:resetwarn]; - UIAlertAction *checksha = [UIAlertAction actionWithTitle:@"Check game files before launching" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {[self helpAlertOpt:VIRTMOUSE];}]; - [helpAlert addAction:checksha]; - UIAlertAction *safearea = [UIAlertAction actionWithTitle:@"Safe area" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {[self helpAlertOpt:SAFEAREA];}]; - [helpAlert addAction:safearea]; - UIAlertAction *debuglog = [UIAlertAction actionWithTitle:@"Debug logging" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {[self helpAlertOpt:DEBUGLOG];}]; - [helpAlert addAction:debuglog]; - UIAlertAction *relaunch = [UIAlertAction actionWithTitle:@"Restart before launching game" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {[self helpAlertOpt:RELAUNCH];}]; - [helpAlert addAction:relaunch]; - if(getenv("POJAV_DETECTEDJB")) { - UIAlertAction *homesym = [UIAlertAction actionWithTitle:@"Home symlink" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {[self helpAlertOpt:HOMESYM];}]; - [helpAlert addAction:homesym]; - } - UIAlertAction *arccapes = [UIAlertAction actionWithTitle:@"Enable Cosmetica capes" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {[self helpAlertOpt:ARCCAPES];}]; - [helpAlert addAction:arccapes]; - UIAlertAction *virtmouse = [UIAlertAction actionWithTitle:@"Enable virtual mouse" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {[self helpAlertOpt:VIRTMOUSE];}]; - [helpAlert addAction:virtmouse]; - UIAlertAction *erasepref = [UIAlertAction actionWithTitle:@"Reset preferences" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {[self helpAlertOpt:ERASEPREF];}]; - [helpAlert addAction:erasepref]; - if(!getenv("POJAV_DETECTEDJB")) { - UIAlertAction *enableRAM = [UIAlertAction actionWithTitle:@"Enable RAM slider" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {[self helpAlertOpt:UNJBRAM];}]; - [helpAlert addAction:enableRAM]; - } - UIAlertAction *cancel = [UIAlertAction actionWithTitle:@"Cancel" style:UIAlertActionStyleCancel handler:nil]; - [helpAlert addAction:cancel]; - [self setPopoverProperties:helpAlert.popoverPresentationController sender:(UIButton *)self.navigationItem.rightBarButtonItem]; - [self presentViewController:helpAlert animated:YES completion:nil]; - } -} - -- (void)helpAlertOpt:(int)setting { - NSString *title; - NSString *message; - if(setting == BTNSCALE) { - title = @"Button scale"; - message = @"This option allows you to tweak the button scale of the on-screen controls. The numbered slider extends from 50 to 500."; - } else if(setting == RESOLUTION) { - title = @"Resolution"; - message = @"This option allows you to downscale the resolution of the game. Reducing resolution reduces GPU workload for better performance. The minimum resolution scale is 25%."; - } else if(setting == ALLOCMEM) { - title = @"Allocated RAM"; - if(getenv("POJAV_DETECTEDJB")) { - message = @"This option allows you to change the amount of memory used by the game. The minimum is 25% (default) and the maximum is 85%. To be safe, any value over 40% will require a tool like jetsamctl to prevent memory crashes."; - } else if (!(getenv("POJAV_DETECTEDJB") && ![getPreference(@"ram_unjb_enable") boolValue] == NO)){ - message = @"This option allows you to change the amount of memory used by the game. This option is disabled by default on unjailbroken devices due to potential instability of the launcher."; - } else { - message = @"This option allows you to change the amount of memory used by the game. The minimum is 25% (default) and the maximum is 85%. Use this at your own risk while unjailbroken, as it can cause instability or break launching the game entirely."; - } - } else if(setting == JARGS) { - title = @"Java arguments"; - message = @"This option allows you to edit arguments that can be passed to Minecraft. Not all arguments work with PojavLauncher, so be aware."; - } else if(setting == REND) { - title = @"Renderer"; - message = @"This option allows you to change the renderer in use. Choosing tinygl4angle will allow 1.17+ to be played, but will also not work with older versions."; - } else if(setting == JHOME) { - title = @"Java version"; - if(getenv("POJAV_DETECTEDJB")) { - message = @"This option allows you to change the Java executable directory. Choosing Java 16 or Java 17 may allow you to play 1.17, however older versions and most versions of modded Minecraft, as well as the mod installer, will not work."; - } else { - message = @"This option is disabled when running PojavLauncher unjailbroken."; - } - } else if(setting == GDIRECTORY) { - title = @"Game directory"; - message = @"This option allows you to change where your Minecraft settings and saves are stored in a MultiMC like fashion. Useful for when you want to have multiple mod loaders installed but do not want to delete/move mods around to switch."; - } else if(setting == SLIDEHOTBAR) { - title = @"Slideable hotbar"; - message = @"This option allows you to use a finger to slide between hotbar slots."; - } else if(setting == SAFEAREA) { - title = @"Safe area"; - message = @"This option moves the game surface area into a safe area instead of fullscreen. This option is only available for iPhones with notch."; - } else if(setting == RESETWARN) { - title = @"Reset warnings"; - message = @"This option re-enables all warnings to be shown again."; - } else if(setting == TYPESEL) { - title = @"Type switches"; - message = @"These switches allow to to change where or not releases, snapshots, old betas, and old alphas will show up in the version selection menu."; - } else if(setting == CHECKSHA) { - title = @"Check game files before launching"; - message = @"When this option is enabled, every file is validated with SHA1, therefore local modifications will be overwritten."; - } else if(setting == DEBUGLOG) { - title = @"Enable debug logging"; - message = @"This option logs internal settings and actions to latestlog.txt. This helps the developers find issues easier, but Minecraft may run slower as the logs will be written to more often."; - } else if(setting == HOMESYM) { - title = @"Disable home symlink"; - if(getenv("POJAV_DETECTEDJB")) { - message = @"This option disables the home symlink to /var/mobile/Documents/.pojavlauncher from the new game directory. This is used for legacy add-ons to continue working, and as a transition from the old 1.2 directory structure."; - } else { - message = @"This option is disabled when running PojavLauncher unjailbroken."; - } - } else if(setting == RELAUNCH) { - title = @"Restart before launching game"; - message = @"This option allows the launcher to restart itself before launching the game, therefore all changes are applied such as JVM Arguments and Java version. The restart mechanism doesn't always work, so a toggle is here for now."; - } else if (setting == ERASEPREF) { - title = @"Reset preferences"; - message = @"This option resets the launcher preferences to their initial state."; - } else if (setting == ARCCAPES) { - title = @"Enable Cosmetica capes"; - message = @"This option allows you to switch from the OptiFine cape service to Cosmetica. See more about Cosmetica on our website."; - } else if (setting == VIRTMOUSE) { - title = @"Enable virtual mouse"; - message = @"This option allows you to enable or disable the virtual mouse pointer at launch of the game."; - } else if (setting == UNJBRAM){ - title = @"Enable RAM slider"; - message = @"This option allows you to enable or disable the Allocated RAM slider when unjailbroken. See \"Allocated RAM\" for more information."; - } else { - title = @"Error"; - message = [NSString stringWithFormat:@"The setting %d hasn't been specified with a description.", setting]; - } - UIAlertController *helpAlertOpt = [UIAlertController alertControllerWithTitle:title message:message preferredStyle:UIAlertControllerStyleActionSheet]; - UIAlertAction *ok = [UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleCancel handler:nil]; - [self setPopoverProperties:helpAlertOpt.popoverPresentationController sender:(UIButton *)self.navigationItem.rightBarButtonItem]; - [helpAlertOpt addAction:ok]; - [self presentViewController:helpAlertOpt animated:YES completion:nil]; -} - -- (void)sliderMoved:(DBNumberedSlider *)sender { - float memVal; - switch (sender.tag) { - case TAG_BTNSCALE: - setPreference(@"button_scale", @((int)sender.value)); - break; - case TAG_RESOLUTION: - setPreference(@"resolution", @((int)sender.value)); - break; - case TAG_ALLOCMEM: - memVal = roundf(([[NSProcessInfo processInfo] physicalMemory] / 1048576) * 0.40); - if(sender.value >= memVal && [getPreference(@"mem_warn") boolValue] == YES) { - NSString *title = @"High memory value selected."; - NSString *message; - if(getenv("POJAV_DETECTEDJB")) { - message = @"Due to limitations in the operating system itself, you will need to use a tool like overb0ard to prevent jetsam crashes."; - } else { - message = @"Due to limitations in the operating system itself, this option may cause instability at this and higher values. Proceed with caution."; - } - UIAlertController *memAlert = [UIAlertController alertControllerWithTitle:title message:message preferredStyle:UIAlertControllerStyleActionSheet]; - [self setPopoverProperties:memAlert.popoverPresentationController sender:(UIButton *)sender]; - UIAlertAction *ok = [UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleCancel handler:nil]; - [self presentViewController:memAlert animated:YES completion:nil]; - [memAlert addAction:ok]; - setPreference(@"mem_warn", @NO); - } - setPreference(@"allocated_memory", @((int)sender.value)); - break; - default: - NSLog(@"what does slider %ld for? implement me!", sender.tag); - break; - } -} - -- (void)switchChanged:(UISwitch *)sender { - switch (sender.tag) { - case TAG_RESETWARN: - setPreference(@"mem_warn", @YES); - setPreference(@"option_warn", @YES); - setPreference(@"local_warn", @YES); - setPreference(@"java_warn", @YES); - setPreference(@"jb_warn", @YES); - setPreference(@"customctrl_warn", @YES); - setPreference(@"int_warn", @YES); - setPreference(@"ram_unjb_warn", @YES); - { - UIAlertController *resetWarn = [UIAlertController alertControllerWithTitle:@"Warnings reset." message:@"Restart to show warnings again." preferredStyle:UIAlertControllerStyleActionSheet]; - [self setPopoverProperties:resetWarn.popoverPresentationController sender:(UIButton *)sender]; - UIAlertAction *ok = [UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleCancel handler:nil]; - [self presentViewController:resetWarn animated:YES completion:nil]; - [resetWarn addAction:ok]; - } - break; - case TAG_SLIDEHOTBAR: - setPreference(@"slideable_hotbar", @(sender.isOn)); - break; - case TAG_CHECKSHA: - setPreference(@"check_sha", @(sender.isOn)); - break; - case TAG_DEBUGLOG: - setPreference(@"debug_logging", @(sender.isOn)); - break; - case TAG_HOMESYM: - setPreference(@"disable_home_symlink", @(sender.isOn)); - if([getPreference(@"disable_home_symlink") boolValue] == YES){ - NSString *message = [NSString stringWithFormat:@"This will remove the link at /var/mobile/Documents/.pojavlauncher. The new directory is %s.", getenv("POJAV_HOME")]; - UIAlertController *homesymWarn = [UIAlertController alertControllerWithTitle:@"Are you sure?" message:message preferredStyle:UIAlertControllerStyleActionSheet]; - [self setPopoverProperties:homesymWarn.popoverPresentationController sender:(UIButton *)sender]; - UIAlertAction *ok = [UIAlertAction actionWithTitle:@"Continue" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {[[NSFileManager defaultManager] removeItemAtPath:@"/var/mobile/Documents/.pojavlauncher" error:nil];}]; - UIAlertAction *cancel = [UIAlertAction actionWithTitle:@"Cancel" style:UIAlertActionStyleCancel handler:nil]; - [self presentViewController:homesymWarn animated:YES completion:nil]; - [homesymWarn addAction:cancel]; - [homesymWarn addAction:ok]; - } else { - NSString *message = [NSString stringWithFormat:@"This will create a link to %s at /var/mobile/Documents/.pojavlauncher. This option will be removed in a future release.", getenv("POJAV_HOME")]; - UIAlertController *homesymWarn = [UIAlertController alertControllerWithTitle:@"Are you sure?" message:message preferredStyle:UIAlertControllerStyleActionSheet]; - [self setPopoverProperties:homesymWarn.popoverPresentationController sender:(UIButton *)sender]; - UIAlertAction *ok = [UIAlertAction actionWithTitle:@"Continue" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {symlink("/usr/share/pojavlauncher", "/var/mobile/Documents/.pojavlauncher");}]; - UIAlertAction *cancel = [UIAlertAction actionWithTitle:@"Cancel" style:UIAlertActionStyleCancel handler:nil]; - [self presentViewController:homesymWarn animated:YES completion:nil]; - [homesymWarn addAction:cancel]; - [homesymWarn addAction:ok]; - } - break; - case TAG_RELAUNCH: - setPreference(@"restart_before_launch", @(sender.isOn)); - break; - case TAG_ERASEPREF: - { - NSString *prefFile = [NSString stringWithFormat:@"%s/launcher_preferences.plist", getenv("POJAV_HOME")]; - UIAlertController *eraseprefWarn = [UIAlertController alertControllerWithTitle:@"Are you sure?" message:@"This will remove all of your custom preferences, including resolution, button size, and Java arguments." preferredStyle:UIAlertControllerStyleActionSheet]; - [self setPopoverProperties:eraseprefWarn.popoverPresentationController sender:(UIButton *)sender]; - UIAlertAction *ok = [UIAlertAction actionWithTitle:@"Continue" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) { - [[NSFileManager defaultManager] removeItemAtPath:prefFile error:nil]; - UIAlertController *eraseprefPost = [UIAlertController alertControllerWithTitle:@"Preferences reset" message:@"The next time you open PojavLauncher, all of the default settings will be restored." preferredStyle:UIAlertControllerStyleActionSheet]; - [self setPopoverProperties:eraseprefWarn.popoverPresentationController sender:(UIButton *)sender]; - UIAlertAction *cancel = [UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleCancel handler:nil]; - [self presentViewController:eraseprefPost animated:YES completion:nil]; - [eraseprefPost addAction:cancel]; - }]; - UIAlertAction *cancel = [UIAlertAction actionWithTitle:@"Cancel" style:UIAlertActionStyleCancel handler:nil]; - [self presentViewController:eraseprefWarn animated:YES completion:nil]; - [eraseprefWarn addAction:cancel]; - [eraseprefWarn addAction:ok]; - } - break; - case TAG_ARCCAPES: - setPreference(@"arccapes_enable", @(sender.isOn)); - break; - case TAG_VIRTMOUSE: - setPreference(@"virtmouse_enable", @(sender.isOn)); - break; - case TAG_UNJBRAM: - { - setPreference(@"ram_unjb_enable", @(sender.isOn)); - UIAlertController *enableRAMPost = [UIAlertController alertControllerWithTitle:@"RAM slider option has been changed" message:@"You will need to restart the launcher for changes to take effect." preferredStyle:UIAlertControllerStyleActionSheet]; - [self setPopoverProperties:enableRAMPost.popoverPresentationController sender:(UIButton *)sender]; - UIAlertAction *ok = [UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleCancel handler:nil]; - [self presentViewController:enableRAMPost animated:YES completion:nil]; - [enableRAMPost addAction:ok]; - } - break; - default: - NSLog(@"what does switch %ld for? implement me!", sender.tag); - break; - } -} - -- (void)setPopoverProperties:(UIPopoverPresentationController *)controller sender:(UIButton *)sender { - if (controller != nil) { - controller.sourceView = sender; - controller.sourceRect = sender.bounds; - } -} - -#pragma mark - UIPopoverPresentationControllerDelegate -- (UIModalPresentationStyle)adaptivePresentationStyleForPresentationController:(UIPresentationController *)controller traitCollection:(UITraitCollection *)traitCollection { - return UIModalPresentationNone; -} - -#pragma mark - UIPickerView -- (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component { - if(pickerView.tag == TAG_PICKER_REND) { - rendTextField.text = [self pickerView:pickerView titleForRow:row forComponent:component]; - } else if(pickerView.tag == TAG_PICKER_JHOME) { - jhomeTextField.text = [self pickerView:pickerView titleForRow:row forComponent:component]; - } else if(pickerView.tag == TAG_PICKER_GDIR) { - gdirTextField.text = [self pickerView:pickerView titleForRow:row forComponent:component]; - setPreference(@"game_directory", gdirTextField.text); - init_setupMultiDir(); - } -} - -- (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)thePickerView { - return 1; -} - -- (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component { - if(pickerView.tag == TAG_PICKER_REND) { - return rendererDict.allKeys.count; - } else if(pickerView.tag == TAG_PICKER_JHOME) { - return jhomeList.count; - } else if(pickerView.tag == TAG_PICKER_GDIR) { - return gdirList.count; - } else { - return 0; - } -} - -- (NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component { - NSObject *object; - if(pickerView.tag == TAG_PICKER_REND) { - object = [rendererDict.allKeys objectAtIndex:row]; - } else if(pickerView.tag == TAG_PICKER_JHOME) { - object = [jhomeList objectAtIndex:row]; - } else if(pickerView.tag == TAG_PICKER_GDIR) { - object = [gdirList objectAtIndex:row]; - } - return (NSString*) object; -} - -- (void)closeKeyboard:(UIBarButtonItem *)doneButton { - if (doneButton.tag == TAG_DONE_REND) { - [rendTextField endEditing:YES]; - } else if (doneButton.tag == TAG_DONE_JHOME) { - [jhomeTextField endEditing:YES]; - } else if (doneButton.tag == TAG_DONE_GDIR) { - [gdirTextField endEditing:YES]; - } -} - -@end diff --git a/Natives/LauncherPreferencesViewController2.m b/Natives/LauncherPreferencesViewController2.m index 8919fffb..5c7b96c3 100644 --- a/Natives/LauncherPreferencesViewController2.m +++ b/Natives/LauncherPreferencesViewController2.m @@ -283,7 +283,7 @@ viewForHeaderInSection:(NSInteger)section { self.typeButton = ^void(UITableViewCell *cell, NSString *key, NSDictionary *item) { BOOL destructive = [item[@"destructive"] boolValue]; cell.selectionStyle = UITableViewCellSelectionStyleGray; - cell.textLabel.textColor = destructive ? UIColor.systemRedColor : UIColor.systemBlueColor; + cell.textLabel.textColor = destructive ? UIColor.systemRedColor : weakSelf.view.tintColor; }; self.typeChildPane = ^void(UITableViewCell *cell, NSString *key, NSDictionary *item) { @@ -292,13 +292,6 @@ viewForHeaderInSection:(NSInteger)section { cell.detailTextLabel.text = getPreference(key); }; -/* - self.typePickField = ^void(UITableViewCell *cell, NSString *key, NSDictionary *item) { - cell.accessoryView = [[UITextField alloc] initWithFrame:CGRectMake(0, 0, cell.bounds.size.width / 2, cell.bounds.size.height)]; - [(id)(cell.accessoryView) setText:getPreference(key)]; - }; -*/ - self.typeTextField = ^void(UITableViewCell *cell, NSString *key, NSDictionary *item) { UITextField *view = [[UITextField alloc] initWithFrame:CGRectMake(0, 0, cell.bounds.size.width / 2.1, cell.bounds.size.height)]; [view addTarget:view action:@selector(resignFirstResponder) forControlEvents:UIControlEventEditingDidEndOnExit]; diff --git a/Natives/LauncherViewController.m b/Natives/LauncherViewController.m index 21afc4ca..4d5fd2de 100644 --- a/Natives/LauncherViewController.m +++ b/Natives/LauncherViewController.m @@ -2,7 +2,6 @@ #import "CustomControlsViewController.h" #import "JavaGUIViewController.h" #import "LauncherPreferences.h" -#import "LauncherPreferencesViewController.h" #import "LauncherViewController.h" #import "MinecraftResourceUtils.h" #import "ios_uikit_bridge.h" diff --git a/Natives/main.m b/Natives/main.m index e5fc46b1..4be355f0 100644 --- a/Natives/main.m +++ b/Natives/main.m @@ -7,7 +7,6 @@ #import "AppDelegate.h" #import "customcontrols/CustomControlsUtils.h" #import "LauncherPreferences.h" -#import "LauncherPreferencesViewController.h" #include #include From db2d237419a99f7c2fd684b5a05b5d833ce8728c Mon Sep 17 00:00:00 2001 From: Eilionoir Tunnicliff Date: Sun, 4 Sep 2022 04:15:17 -0400 Subject: [PATCH 30/37] Tweak auto ram stuff - Warn unjailbroken - Change to 37% from 40% warning - Rename key to auto_ram_warn --- Natives/LauncherPreferences.m | 4 ++-- Natives/LauncherPreferencesViewController2.m | 12 +++++++++--- Natives/en.lproj/Localizable.strings | 1 + 3 files changed, 12 insertions(+), 5 deletions(-) diff --git a/Natives/LauncherPreferences.m b/Natives/LauncherPreferences.m index 0745acde..c43abd61 100644 --- a/Natives/LauncherPreferences.m +++ b/Natives/LauncherPreferences.m @@ -87,7 +87,7 @@ void fillDefaultWarningDict() { setDefaultValueForPref(warnPrefDict, @"jb_warn", @YES); setDefaultValueForPref(warnPrefDict, @"customctrl_warn", @YES); setDefaultValueForPref(warnPrefDict, @"int_warn", @YES); - setDefaultValueForPref(warnPrefDict, @"ram_unjb_warn", @YES); + setDefaultValueForPref(warnPrefDict, @"auto_ram_warn", @YES); } void loadPreferences(BOOL reset) { @@ -119,7 +119,7 @@ void loadPreferences(BOOL reset) { setDefaultValueForPref(envPrefDict, @"default_ctrl", @"default.json"); setDefaultValueForPref(envPrefDict, @"game_directory", @"default"); setDefaultValueForPref(envPrefDict, @"java_args", @""); - setDefaultValueForPref(envPrefDict, @"allocated_memory", [NSNumber numberWithFloat:roundf(([[NSProcessInfo processInfo] physicalMemory] / 1048576) * 0.30)]); + setDefaultValueForPref(envPrefDict, @"allocated_memory", [NSNumber numberWithFloat:roundf(([[NSProcessInfo processInfo] physicalMemory] / 1048576) * 0.25)]); setDefaultValueForPref(prefDict, @"restart_before_launch", @NO); setDefaultValueForPref(prefDict, @"debug_logging", CONFIG_TYPE); setDefaultValueForPref(prefDict, @"arccapes_enable", @YES); diff --git a/Natives/LauncherPreferencesViewController2.m b/Natives/LauncherPreferencesViewController2.m index 5c7b96c3..76f7b14c 100644 --- a/Natives/LauncherPreferencesViewController2.m +++ b/Natives/LauncherPreferencesViewController2.m @@ -168,8 +168,14 @@ typedef void(^CreateView)(UITableViewCell *, NSString *, NSDictionary *); @{@"key": @"auto_ram", @"icon": @"slider.horizontal.3", @"type": self.typeSwitch, - @"enableCondition": whenNotInGame, - //@"hidden": @(getenv("POJAV_DETECTEDJB") == NULL), + @"enableCondition": ^BOOL(){ + return getenv("POJAV_DETECTEDJB") == NULL && whenNotInGame(); + }, + @"warnAlways": @NO, + @"warnCondition": ^BOOL(){ + return getenv("POJAV_DETECTEDJB") == NULL && whenNotInGame(); + }, + @"warnKey": @"auto_ram_warn", @"requestReload": @YES }, @{@"key": @"allocated_memory", @@ -182,7 +188,7 @@ typedef void(^CreateView)(UITableViewCell *, NSString *, NSDictionary *); }, @"warnAlways": @NO, @"warnCondition": ^BOOL(DBNumberedSlider *view){ - return view.value >= NSProcessInfo.processInfo.physicalMemory / 1048576 * 0.4; + return view.value >= NSProcessInfo.processInfo.physicalMemory / 1048576 * 0.37; }, @"warnKey": @"mem_warn" } diff --git a/Natives/en.lproj/Localizable.strings b/Natives/en.lproj/Localizable.strings index 75e90923..540ee620 100644 --- a/Natives/en.lproj/Localizable.strings +++ b/Natives/en.lproj/Localizable.strings @@ -114,6 +114,7 @@ "preference.title.java_args" = "Custom java arguments"; "preference.placeholder.java_args" = "Specify arguments..."; "preference.title.auto_ram" = "Auto determine RAM amount"; +"preference.warn.auto_ram" = "Disabling this option on an unjailbroken devices can create instability if altered. Proceed with caution."; "preference.title.allocated_memory" = "Allocated memory (MB)"; "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."; // sha check From 4726cf6e3cda9d513a7f2315c2c0fc2b008b174b Mon Sep 17 00:00:00 2001 From: khanhduytran0 Date: Sun, 4 Sep 2022 17:04:35 +0700 Subject: [PATCH 31/37] Update DBNumberedSlider --- Natives/external/DBNumberedSlider | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Natives/external/DBNumberedSlider b/Natives/external/DBNumberedSlider index bc6ea603..4eddc68b 160000 --- a/Natives/external/DBNumberedSlider +++ b/Natives/external/DBNumberedSlider @@ -1 +1 @@ -Subproject commit bc6ea60353efd2e741de81f84aa691441f2d0ca9 +Subproject commit 4eddc68b5f92247f8afc0f6114d1b92b338749f4 From d42d4e963e269ab81eb49a2ab15facde4ccff827 Mon Sep 17 00:00:00 2001 From: Duy Tran Khanh Date: Mon, 5 Sep 2022 19:38:39 +0700 Subject: [PATCH 32/37] Allow changing resolution while in game (1.13+) For now, this only works properly on Minecraft 1.13+. Older version doesn't seem to get the new resolution (will be fixed later) Additional changes: - Make ingame settings background transparent - Set prefersHomeIndicatorAutoHidden to YES --- Natives/LauncherPreferencesViewController2.m | 5 +++- Natives/SurfaceViewController.m | 24 +++++++++++++------- 2 files changed, 20 insertions(+), 9 deletions(-) diff --git a/Natives/LauncherPreferencesViewController2.m b/Natives/LauncherPreferencesViewController2.m index 76f7b14c..916bb043 100644 --- a/Natives/LauncherPreferencesViewController2.m +++ b/Natives/LauncherPreferencesViewController2.m @@ -30,6 +30,10 @@ typedef void(^CreateView)(UITableViewCell *, NSString *, NSDictionary *); self.tableView.keyboardDismissMode = UIScrollViewKeyboardDismissModeInteractive; self.tableView.sectionHeaderHeight = 50; + if (self.navigationController == nil) { + self.tableView.backgroundColor = [UIColor colorWithWhite:0 alpha:0.4]; + } + BOOL(^whenNotInGame)() = ^BOOL(){ return self.navigationController != nil; }; @@ -108,7 +112,6 @@ typedef void(^CreateView)(UITableViewCell *, NSString *, NSDictionary *); @{@"key": @"resolution", @"icon": @"viewfinder", @"type": self.typeSlider, - @"enableCondition": whenNotInGame, @"min": @(25), @"max": @(150) }, diff --git a/Natives/SurfaceViewController.m b/Natives/SurfaceViewController.m index 0e5d6880..1ce10197 100644 --- a/Natives/SurfaceViewController.m +++ b/Natives/SurfaceViewController.m @@ -222,8 +222,8 @@ BOOL slideableHotbar; resolutionScale = ((NSNumber *)getPreference(@"resolution")).floatValue / 100.0; - savedWidth = roundf(screenBounds.size.width * screenScale); - savedHeight = roundf(screenBounds.size.height * screenScale); + savedWidth = roundf(screenBounds.size.width * screenScale * resolutionScale); + savedHeight = roundf(screenBounds.size.height * screenScale * resolutionScale); self.rootView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.size.width + 30.0, self.view.frame.size.height)]; [self.view addSubview:self.rootView]; @@ -410,11 +410,12 @@ self.view.frame.size.width * 0.3 - 36.0 * 0.7, self.view.frame.size.height)]; slideableHotbar = [getPreference(@"slideable_hotbar") boolValue]; virtualMouseEnabled = [getPreference(@"virtmouse_enable") boolValue]; - if (!isGrabbing) { - self.mousePointerView.hidden = !virtualMouseEnabled; - } + self.mousePointerView.hidden = isGrabbing || !virtualMouseEnabled; - CGRect screenBounds = [[UIScreen mainScreen] bounds]; + CGRect screenBounds = UIScreen.mainScreen.bounds; + CGFloat screenScale = UIScreen.mainScreen.scale; + + // Update virtual mouse scale CGFloat mouseScale = [getPreference(@"mouse_scale") floatValue] / 100.0; virtualMouseFrame = CGRectMake(screenBounds.size.width / 2, screenBounds.size.height / 2, 18.0 * mouseScale, 27 * mouseScale); self.mousePointerView.frame = virtualMouseFrame; @@ -425,6 +426,13 @@ self.view.frame.size.width * 0.3 - 36.0 * 0.7, self.view.frame.size.height)]; self.ctrlView.frame = CGRectFromString(getPreference(@"control_safe_area")); [self loadCustomControls]; + + // Update resolution + resolutionScale = [getPreference(@"resolution") floatValue] / 100.0; + self.surfaceView.layer.contentsScale = screenScale * resolutionScale; + savedWidth = roundf(screenBounds.size.width * screenScale * resolutionScale); + savedHeight = roundf(screenBounds.size.height * screenScale * resolutionScale); + CallbackBridge_nativeSendScreenSize(savedWidth, savedHeight); } - (void)launchMinecraft { @@ -434,7 +442,7 @@ self.view.frame.size.width * 0.3 - 36.0 * 0.7, self.view.frame.size.height)]; launchJVM( BaseAuthenticator.current.authData[@"username"], json, - savedWidth * resolutionScale, savedHeight * resolutionScale, + savedWidth, savedHeight, [json[@"javaVersion"][@"majorVersion"] intValue] ); }]; @@ -484,7 +492,7 @@ self.view.frame.size.width * 0.3 - 36.0 * 0.7, self.view.frame.size.height)]; } - (BOOL)prefersHomeIndicatorAutoHidden { - return NO; + return YES; } #pragma mark - Menu functions From b14f23c169d54d46ae57004e7e8f7f2a43a74a4c Mon Sep 17 00:00:00 2001 From: Duy Tran Khanh Date: Tue, 6 Sep 2022 18:10:53 +0700 Subject: [PATCH 33/37] Adjust background transparency and tweaks --- Natives/LauncherPreferencesViewController2.m | 9 +++++---- Natives/en.lproj/Localizable.strings | 2 +- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/Natives/LauncherPreferencesViewController2.m b/Natives/LauncherPreferencesViewController2.m index 916bb043..191c0cca 100644 --- a/Natives/LauncherPreferencesViewController2.m +++ b/Natives/LauncherPreferencesViewController2.m @@ -31,7 +31,7 @@ typedef void(^CreateView)(UITableViewCell *, NSString *, NSDictionary *); self.tableView.sectionHeaderHeight = 50; if (self.navigationController == nil) { - self.tableView.backgroundColor = [UIColor colorWithWhite:0 alpha:0.4]; + self.tableView.alpha = 0.9; } BOOL(^whenNotInGame)() = ^BOOL(){ @@ -156,7 +156,7 @@ typedef void(^CreateView)(UITableViewCell *, NSString *, NSDictionary *); } ], @[ // Java tweaks - @{@"key": @"java_home", // TODO: name as Use Java 17 for older MC + @{@"key": @"java_home", // Use Java 17 for Minecraft < 1.17 @"icon": @"cube", @"type": self.typeSwitch, @"enableCondition": whenNotInGame, @@ -174,7 +174,6 @@ typedef void(^CreateView)(UITableViewCell *, NSString *, NSDictionary *); @"enableCondition": ^BOOL(){ return getenv("POJAV_DETECTEDJB") == NULL && whenNotInGame(); }, - @"warnAlways": @NO, @"warnCondition": ^BOOL(){ return getenv("POJAV_DETECTEDJB") == NULL && whenNotInGame(); }, @@ -189,7 +188,6 @@ typedef void(^CreateView)(UITableViewCell *, NSString *, NSDictionary *); @"enableCondition": ^BOOL(){ return ![getPreference(@"auto_ram") boolValue] && whenNotInGame(); }, - @"warnAlways": @NO, @"warnCondition": ^BOOL(DBNumberedSlider *view){ return view.value >= NSProcessInfo.processInfo.physicalMemory / 1048576 * 0.37; }, @@ -373,6 +371,9 @@ viewForHeaderInSection:(NSInteger)section { BOOL(^isWarnable)(UIView *) = item[@"warnCondition"]; NSString *warnKey = item[@"warnKey"]; + // Display warning if: warn condition is met and either one of these: + // - does not have warnKey, always warn + // - has warnKey and its value is YES, warn once and set it to NO if (isWarnable && isWarnable(view) && (!warnKey || [getPreference(warnKey) boolValue])) { if (warnKey) { setPreference(warnKey, @NO); diff --git a/Natives/en.lproj/Localizable.strings b/Natives/en.lproj/Localizable.strings index 540ee620..ceb1eee0 100644 --- a/Natives/en.lproj/Localizable.strings +++ b/Natives/en.lproj/Localizable.strings @@ -70,7 +70,7 @@ "preference.section.general" = "General Settings"; "preference.section.footer.general" = "* Compatibility symlink option is planned to be removed in a future release."; "preference.section.video" = "Video Settings"; -"preference.section.footer.video" = "Auto renderer allows Minecraft to request which renderer to use. Reducing resolution reduces GPU workload for better performance."; +"preference.section.footer.video" = "Auto renderer allows Minecraft to decide which renderer to use. Reducing resolution reduces GPU workload for better performance."; "preference.section.control" = "Control Settings"; "preference.section.footer.control" = "Long-press duration involves how long to perform left mouse button press and drop item from the hotbar. Mouse settings affect only for the virtual mouse. Slideable hotbar may help you to switch between hotbar slots better if there is a home indicator."; "preference.section.java" = "Java Runtime Settings"; From 8bea48479d6e5f18df01806a1100cc5a63b2e526 Mon Sep 17 00:00:00 2001 From: Duy Tran Khanh Date: Thu, 8 Sep 2022 19:25:09 +0700 Subject: [PATCH 34/37] Add settings details (subtitle) --- Natives/LauncherPreferencesViewController2.m | 44 ++++++++++++++-- Natives/en.lproj/Localizable.strings | 54 +++++++++++++------- 2 files changed, 75 insertions(+), 23 deletions(-) diff --git a/Natives/LauncherPreferencesViewController2.m b/Natives/LauncherPreferencesViewController2.m index 191c0cca..c01c20f2 100644 --- a/Natives/LauncherPreferencesViewController2.m +++ b/Natives/LauncherPreferencesViewController2.m @@ -50,6 +50,7 @@ typedef void(^CreateView)(UITableViewCell *, NSString *, NSDictionary *); @"class": LauncherPrefGameDirViewController.class, }, @{@"key": @"home_symlink", + @"hasDetail": @YES, @"icon": @"link", @"type": self.typeSwitch, @"enableCondition": ^BOOL(){ @@ -57,16 +58,19 @@ typedef void(^CreateView)(UITableViewCell *, NSString *, NSDictionary *); } }, @{@"key": @"check_sha", + @"hasDetail": @YES, @"icon": @"lock.shield", @"type": self.typeSwitch, @"enableCondition": whenNotInGame }, @{@"key": @"cosmetica", + @"hasDetail": @YES, @"icon": @"eyeglasses", @"type": self.typeSwitch, @"enableCondition": whenNotInGame }, @{@"key": @"debug_logging", + @"hasDetail": @YES, @"icon": @"doc.badge.gearshape", @"type": self.typeSwitch }, @@ -110,6 +114,7 @@ typedef void(^CreateView)(UITableViewCell *, NSString *, NSDictionary *); ] }, @{@"key": @"resolution", + @"hasDetail": @YES, @"icon": @"viewfinder", @"type": self.typeSlider, @"min": @(25), @@ -123,40 +128,47 @@ typedef void(^CreateView)(UITableViewCell *, NSString *, NSDictionary *); }, */ @{@"key": @"press_duration", + @"hasDetail": @YES, @"icon": @"timer", @"type": self.typeSlider, @"min": @(100), @"max": @(1000) }, @{@"key": @"button_scale", + @"hasDetail": @YES, @"icon": @"aspectratio", @"type": self.typeSlider, @"min": @(50), // 80? @"max": @(500) }, @{@"key": @"mouse_scale", + @"hasDetail": @YES, @"icon": @"arrow.up.left.and.arrow.down.right.circle", @"type": self.typeSlider, @"min": @(25), @"max": @(300) }, @{@"key": @"mouse_speed", + @"hasDetail": @YES, @"icon": @"arrow.left.and.right", @"type": self.typeSlider, @"min": @(25), @"max": @(300) }, @{@"key": @"virtmouse_enable", + @"hasDetail": @YES, @"icon": @"cursorarrow.rays", @"type": self.typeSwitch }, @{@"key": @"slideable_hotbar", + @"hasDetail": @YES, @"icon": @"slider.horizontal.below.rectangle", @"type": self.typeSwitch } ], @[ // Java tweaks @{@"key": @"java_home", // Use Java 17 for Minecraft < 1.17 + @"hasDetail": @YES, @"icon": @"cube", @"type": self.typeSwitch, @"enableCondition": whenNotInGame, @@ -164,11 +176,13 @@ typedef void(^CreateView)(UITableViewCell *, NSString *, NSDictionary *); @"customSwitchValue": @[@"java-8-openjdk", @"java-17-openjdk"] }, @{@"key": @"java_args", + @"hasDetail": @YES, @"icon": @"slider.vertical.3", @"type": self.typeTextField, @"enableCondition": whenNotInGame }, @{@"key": @"auto_ram", + @"hasDetail": @YES, @"icon": @"slider.horizontal.3", @"type": self.typeSwitch, @"enableCondition": ^BOOL(){ @@ -181,6 +195,7 @@ typedef void(^CreateView)(UITableViewCell *, NSString *, NSDictionary *); @"requestReload": @YES }, @{@"key": @"allocated_memory", + @"hasDetail": @YES, @"icon": @"memorychip", @"type": self.typeSlider, @"min": @(NSProcessInfo.processInfo.physicalMemory / 1048576 * 0.25), @@ -239,7 +254,11 @@ viewForHeaderInSection:(NSInteger)section { } - (NSString *)tableView:(UITableView *)tableView titleForFooterInSection:(NSInteger)section { - return NSLocalizedString(([NSString stringWithFormat:@"preference.section.footer.%@", self.prefSections[section]]), nil); + NSString *footer = NSLocalizedStringWithDefaultValue(([NSString stringWithFormat:@"preference.section.footer.%@", self.prefSections[section]]), @"Localizable", NSBundle.mainBundle, @" ", nil); + if ([footer isEqualToString:@" "]) { + return nil; + } + return footer; } - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { @@ -247,9 +266,24 @@ viewForHeaderInSection:(NSInteger)section { } - (UITableViewCell *)tableView:(nonnull UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { - UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"cell"]; + NSDictionary *item = self.prefContents[indexPath.section][indexPath.row]; + + NSString *cellID; + UITableViewCellStyle cellStyle; + if (item[@"type"] == self.typeChildPane) { + cellID = @"cellValue1"; + cellStyle = UITableViewCellStyleValue1; + } else { + cellID = @"cellSubtitle"; + cellStyle = UITableViewCellStyleSubtitle; + } + + UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellID]; if (cell == nil) { - cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:@"cell"]; + cell = [[UITableViewCell alloc] initWithStyle:cellStyle + reuseIdentifier:cellID]; + cell.detailTextLabel.numberOfLines = 0; + cell.detailTextLabel.lineBreakMode = NSLineBreakByWordWrapping; } // Reset cell properties, as it could be reused cell.accessoryType = UITableViewCellAccessoryNone; @@ -258,7 +292,6 @@ viewForHeaderInSection:(NSInteger)section { cell.textLabel.textColor = nil; cell.detailTextLabel.text = nil; - NSDictionary *item = self.prefContents[indexPath.section][indexPath.row]; NSString *key = item[@"key"]; CreateView createView = item[@"type"]; createView(cell, key, item); @@ -274,6 +307,9 @@ viewForHeaderInSection:(NSInteger)section { cell.imageView.image = [UIImage systemImageNamed:item[@"icon"]]; } cell.textLabel.text = NSLocalizedString(([NSString stringWithFormat:@"preference.title.%@", key]), nil); + if ([item[@"hasDetail"] boolValue]) { + cell.detailTextLabel.text = NSLocalizedString(([NSString stringWithFormat:@"preference.detail.%@", key]), nil); + } // Check if one has enable condition and call if it does BOOL(^checkEnable)(void) = item[@"enableCondition"]; diff --git a/Natives/en.lproj/Localizable.strings b/Natives/en.lproj/Localizable.strings index ceb1eee0..11e6a99c 100644 --- a/Natives/en.lproj/Localizable.strings +++ b/Natives/en.lproj/Localizable.strings @@ -70,11 +70,11 @@ "preference.section.general" = "General Settings"; "preference.section.footer.general" = "* Compatibility symlink option is planned to be removed in a future release."; "preference.section.video" = "Video Settings"; -"preference.section.footer.video" = "Auto renderer allows Minecraft to decide which renderer to use. Reducing resolution reduces GPU workload for better performance."; -"preference.section.control" = "Control Settings"; -"preference.section.footer.control" = "Long-press duration involves how long to perform left mouse button press and drop item from the hotbar. Mouse settings affect only for the virtual mouse. Slideable hotbar may help you to switch between hotbar slots better if there is a home indicator."; -"preference.section.java" = "Java Runtime Settings"; -"preference.section.footer.java" = "Java 8 is used by default for Minecraft < 1.17. You can use Java 17 for these versions, but compatibility with modded is not guaranteed."; +"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.footer.control" = ""; +"preference.section.java" = "Java Tweaks"; +//"preference.section.footer.java" = ""; "preference.title.confirm" = "Are you sure?"; @@ -83,9 +83,13 @@ "preference.multidir.add_directory" = "add game directory"; "preference.title.home_symlink" = "Enable compatibility symlink *"; -"preference.title.check_sha" = "Enable asset verification when launching"; -"preference.title.cosmetica" = "Enable Cosmetica integration"; +"preference.detail.home_symlink" = "Make a symlink at /var/mobile/Documents/.pojavlauncher. Unavailable in sandboxed environment."; +"preference.title.check_sha" = "Check files after downloading"; +"preference.detail.check_sha" = "This option forces launcher to check the file hash if it's available. Prevents broken downloads."; +"preference.title.cosmetica" = "Cosmetica Capes"; +"preference.detail.cosmetica" = "Enable capes from Cosmetica (previously Arc). For more information please visit https://cosmetica.cc. Requires OptiFine"; "preference.title.debug_logging" = "Debug logging"; +"preference.detail.debug_logging" = "Logs internal settings and actions to latestlog.txt. This helps the developers find issues easier, but Minecraft may run slower as the logs will be written to more often."; "preference.title.reset_warnings" = "Reset all warnings"; "preference.title.done.reset_warnings" = "All warnings have been reset."; @@ -94,28 +98,40 @@ "preference.title.confirm.reset_settings" = "This will remove all of your custom preferences, including resolution, button size, and Java arguments."; "preference.title.done.reset_settings" = "All of the default settings have been restored."; -"preference.title.renderer" = "Game renderer"; +"preference.title.renderer" = "Renderer"; "preference.title.renderer.auto" = "Auto: gl4es or tinygl4angle"; "preference.title.renderer.gl4es" = "gl4es 1.1.4 - exports OpenGL 2.1"; "preference.title.renderer.tinygl4angle" = "tinygl4angle (1.17+) - exports OpenGL 3.2 (Core Profile, limited)"; "preference.title.renderer.zink" = "Zink (Mesa 21.0) - exports OpenGL 4.1"; +"preference.detail.renderer" = "Change the OpenGL render engine to use"; -"preference.title.resolution" = "Game resolution (%)"; +"preference.title.resolution" = "Resolution (%)"; +"preference.detail.resolution" = "Allows you to decrease the game resolution."; "preference.title.disable_gesture" = "Disable gestures"; "preference.title.press_duration" = "Long-press duration (ms)"; +"preference.detail.press_duration" = "Change trigger time for long press in destroy block and drop item."; "preference.title.button_scale" = "On-screen button scale (%)"; -"preference.title.mouse_scale" = "On-screen mouse scale (%)"; -"preference.title.mouse_speed" = "On-screen mouse speed (%)"; -"preference.title.virtmouse_enable" = "Enable on-screen mouse"; -"preference.title.slideable_hotbar" = "Enable slideable hotbar"; +"preference.detail.button_scale" = "Upscale them if buttons are too small, usually needed for iPad users."; +"preference.title.mouse_scale" = "Mouse scaling (%)"; +"preference.detail.mouse_scale" = "Change the size of the virtual mouse"; +"preference.title.mouse_speed" = "Mouse speed (%)"; +"preference.detail.mouse_speed" = "Change the speed of the virtual mouse"; +"preference.title.virtmouse_enable" = "Virtual mouse"; +"preference.detail.virtmouse_enable" = "Enable this option to start with virtual mouse on"; +"preference.title.slideable_hotbar" = "Slideable hotbar"; +"preference.detail.slideable_hotbar" = "Make the hotbar slideable like the mouse wheel"; "preference.title.java_home" = "Use Java 17 for Minecraft < 1.17"; -// FIXME: is this filled well in the subtitle? -// "preference.subtitle.java_home" = "Java 8 is used by default on Minecraft 1.16.5 and older. This switch forces old versions to use Java 17."; -"preference.title.java_args" = "Custom java arguments"; +"preference.detail.java_home" = "Java 8 is used by default for those versions. Enable this option to force use Java 17, however compatibility with modded is not guaranteed."; +"preference.title.java_args" = "JVM Launch arguments"; +"preference.detail.java_args" = "Be careful, this can make the game crash if modified without any prior knowledge."; "preference.placeholder.java_args" = "Specify arguments..."; -"preference.title.auto_ram" = "Auto determine RAM amount"; -"preference.warn.auto_ram" = "Disabling this option on an unjailbroken devices can create instability if altered. Proceed with caution."; -"preference.title.allocated_memory" = "Allocated memory (MB)"; +"preference.title.auto_ram" = "Auto RAM"; +"preference.detail.auto_ram" = "Enables automatic RAM adjuster"; +"preference.warn.auto_ram" = "Disabling this option on an unjailbroken device can create instability if altered. Proceed with caution."; +"preference.title.allocated_memory" = "Memory allocation (MB)"; +"preference.detail.allocated_memory" = "Controls how much memory is given to Minecraft"; "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.detail.custom_env" = "This option is under construction."; // sha check // home symlink From 6ceac73d60abe84716da15b05e07d3627e7f0ecf Mon Sep 17 00:00:00 2001 From: Duy Tran Khanh <40482367+khanhduytran0@users.noreply.github.com> Date: Thu, 8 Sep 2022 21:29:58 +0700 Subject: [PATCH 35/37] Clean some unintended line breaks --- Natives/LauncherPreferencesViewController2.m | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/Natives/LauncherPreferencesViewController2.m b/Natives/LauncherPreferencesViewController2.m index c01c20f2..09ee986b 100644 --- a/Natives/LauncherPreferencesViewController2.m +++ b/Natives/LauncherPreferencesViewController2.m @@ -237,8 +237,7 @@ typedef void(^CreateView)(UITableViewCell *, NSString *, NSDictionary *); return self.prefSections.count; } -- (UIView *)tableView:(UITableView *)tableView -viewForHeaderInSection:(NSInteger)section { +- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section { if (section != 0 || self.navigationController != nil) { return nil; } @@ -280,8 +279,7 @@ viewForHeaderInSection:(NSInteger)section { UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellID]; if (cell == nil) { - cell = [[UITableViewCell alloc] initWithStyle:cellStyle - reuseIdentifier:cellID]; + cell = [[UITableViewCell alloc] initWithStyle:cellStyle reuseIdentifier:cellID]; cell.detailTextLabel.numberOfLines = 0; cell.detailTextLabel.lineBreakMode = NSLineBreakByWordWrapping; } From f521a0c5c15956c6fe60c121eec0020719966451 Mon Sep 17 00:00:00 2001 From: Duy Tran Khanh Date: Fri, 9 Sep 2022 06:00:54 +0700 Subject: [PATCH 36/37] Toggleable settings details --- Natives/LauncherPreferencesViewController2.m | 24 +++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/Natives/LauncherPreferencesViewController2.m b/Natives/LauncherPreferencesViewController2.m index 09ee986b..9f1aeea5 100644 --- a/Natives/LauncherPreferencesViewController2.m +++ b/Natives/LauncherPreferencesViewController2.m @@ -14,6 +14,7 @@ typedef void(^CreateView)(UITableViewCell *, NSString *, NSDictionary *); @interface LauncherPreferencesViewController2() {} @property NSArray* prefSections; @property NSArray*>* prefContents; +@property BOOL prefDetailVisible; @property CreateView typeButton, typeChildPane, typePickField, typeTextField, typeSlider, typeSwitch; @end @@ -26,6 +27,8 @@ typedef void(^CreateView)(UITableViewCell *, NSString *, NSDictionary *); [self initViewCreation]; + self.prefDetailVisible = self.navigationController == nil; + self.tableView = [[TOInsetGroupedTableView alloc] init]; self.tableView.keyboardDismissMode = UIScrollViewKeyboardDismissModeInteractive; self.tableView.sectionHeaderHeight = 50; @@ -210,6 +213,14 @@ typedef void(^CreateView)(UITableViewCell *, NSString *, NSDictionary *); } ] ]; + + UIBarButtonItem *helpButton; + if (@available(iOS 13.0, *)) { + helpButton = [[UIBarButtonItem alloc] initWithImage:[UIImage systemImageNamed:@"questionmark.circle"] style:UIBarButtonItemStyleDone target:self action:@selector(toggleDetailVisibility)]; + } else { + helpButton = [[UIBarButtonItem alloc] initWithTitle:NSLocalizedString(@"Help", nil) style:UIBarButtonItemStyleDone target:self action:@selector(toggleDetailVisibility)]; + } + self.navigationItem.rightBarButtonItems = @[helpButton]; } - (void)viewWillAppear:(BOOL)animated { @@ -233,6 +244,13 @@ typedef void(^CreateView)(UITableViewCell *, NSString *, NSDictionary *); [self dismissViewControllerAnimated:YES completion:nil]; } +- (void)toggleDetailVisibility { + self.prefDetailVisible = !self.prefDetailVisible; + [self.tableView reloadData]; +} + +#pragma mark UITableView + - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { return self.prefSections.count; } @@ -305,8 +323,10 @@ typedef void(^CreateView)(UITableViewCell *, NSString *, NSDictionary *); cell.imageView.image = [UIImage systemImageNamed:item[@"icon"]]; } cell.textLabel.text = NSLocalizedString(([NSString stringWithFormat:@"preference.title.%@", key]), nil); - if ([item[@"hasDetail"] boolValue]) { + if ([item[@"hasDetail"] boolValue] && self.prefDetailVisible) { cell.detailTextLabel.text = NSLocalizedString(([NSString stringWithFormat:@"preference.detail.%@", key]), nil); + } else if (createView != self.typeChildPane) { + cell.detailTextLabel.text = nil; } // Check if one has enable condition and call if it does @@ -318,6 +338,8 @@ typedef void(^CreateView)(UITableViewCell *, NSString *, NSDictionary *); return cell; } +#pragma mark initViewCreation, showAlert, checkWarn + - (void)initViewCreation { __weak LauncherPreferencesViewController2 *weakSelf = self; From 746933e3eb08f9b43e893b8278aa67ec1659f9d5 Mon Sep 17 00:00:00 2001 From: Duy Tran Khanh Date: Fri, 9 Sep 2022 19:03:06 +0700 Subject: [PATCH 37/37] Cleanup Restart before launching code --- Natives/BKSSystemService.h | 9 -------- Natives/LauncherPreferences.m | 1 - Natives/ios_uikit_bridge.m | 42 ++++++++++++----------------------- 3 files changed, 14 insertions(+), 38 deletions(-) delete mode 100644 Natives/BKSSystemService.h diff --git a/Natives/BKSSystemService.h b/Natives/BKSSystemService.h deleted file mode 100644 index b44e4088..00000000 --- a/Natives/BKSSystemService.h +++ /dev/null @@ -1,9 +0,0 @@ -#import - -@interface BKSSystemService : NSObject - -- (unsigned int)createClientPort; -- (void)openApplication:(NSString *)app options:(id)arg2 withResult:(id)arg3 ; -- (void)openURL:(NSURL *)url application:(NSString *)app options:(id)options clientPort:(unsigned int)port withResult:(id)result; - -@end diff --git a/Natives/LauncherPreferences.m b/Natives/LauncherPreferences.m index c43abd61..5636dc8d 100644 --- a/Natives/LauncherPreferences.m +++ b/Natives/LauncherPreferences.m @@ -120,7 +120,6 @@ void loadPreferences(BOOL reset) { setDefaultValueForPref(envPrefDict, @"game_directory", @"default"); setDefaultValueForPref(envPrefDict, @"java_args", @""); setDefaultValueForPref(envPrefDict, @"allocated_memory", [NSNumber numberWithFloat:roundf(([[NSProcessInfo processInfo] physicalMemory] / 1048576) * 0.25)]); - setDefaultValueForPref(prefDict, @"restart_before_launch", @NO); setDefaultValueForPref(prefDict, @"debug_logging", CONFIG_TYPE); setDefaultValueForPref(prefDict, @"arccapes_enable", @YES); setDefaultValueForPref(envPrefDict, @"java_home", @""); diff --git a/Natives/ios_uikit_bridge.m b/Natives/ios_uikit_bridge.m index 0975e9ed..68f2dec5 100644 --- a/Natives/ios_uikit_bridge.m +++ b/Natives/ios_uikit_bridge.m @@ -1,6 +1,5 @@ #import "authenticator/BaseAuthenticator.h" #import "AppDelegate.h" -#import "BKSSystemService.h" #import "SceneDelegate.h" #import "LoginViewController.h" #import "LauncherPreferences.h" @@ -104,37 +103,24 @@ jstring UIKit_accessClipboard(JNIEnv* env, jint action, jstring copySrc) { } void UIKit_launchMinecraftSurfaceVC() { - setPreference(@"internal_launch_on_boot", getPreference(@"restart_before_launch")); + // Leave this pref, might be useful later for launching with Quick Actions/Shortcuts/URL Scheme + //setPreference(@"internal_launch_on_boot", getPreference(@"restart_before_launch")); setPreference(@"internal_selected_account", BaseAuthenticator.current.authData[@"username"]); setPreference(@"internal_useStackQueue", @(isUseStackQueueCall ? YES : NO)); dispatch_async(dispatch_get_main_queue(), ^{ - if ([getPreference(@"restart_before_launch") boolValue]) { - NSURL *url = [NSURL URLWithString:@"pojavlauncher://"]; - BKSSystemService *service = [[NSClassFromString(@"BKSSystemService") alloc] init]; - unsigned int port = [service createClientPort]; - [service openURL:url application:@"net.kdt.pojavlauncher" options:nil clientPort:port withResult:nil]; - - // exiting too fast will cause it to fail (race condition?) - // [FBSystemService][0xbb88] Caller "PojavLauncher:pid" has a sandbox that does not allow opening URL's. - // The request was denied by service delegate (SBMainWorkspace) for reason: Security ("Sandbox check failed for process (PojavLauncher:pid) openURL not allowed"). - // therefore, sleep for 1ms before exit - usleep(1000); - exit(0); - } else { - id delegate = UIApplication.sharedApplication.delegate; - if (@available(iOS 13.0, *)) { - delegate = UIApplication.sharedApplication.connectedScenes.anyObject.delegate; - } - UIWindow *window = [delegate window]; - [UIView animateWithDuration:0.2 animations:^{ - window.alpha = 0; - } completion:^(BOOL b){ - [window resignKeyWindow]; - window.alpha = 1; - window.rootViewController = [[SurfaceViewController alloc] init]; - [window makeKeyAndVisible]; - }]; + id delegate = UIApplication.sharedApplication.delegate; + if (@available(iOS 13.0, *)) { + delegate = UIApplication.sharedApplication.connectedScenes.anyObject.delegate; } + UIWindow *window = [delegate window]; + [UIView animateWithDuration:0.2 animations:^{ + window.alpha = 0; + } completion:^(BOOL b){ + [window resignKeyWindow]; + window.alpha = 1; + window.rootViewController = [[SurfaceViewController alloc] init]; + [window makeKeyAndVisible]; + }]; }); }