Merge pull request #1839 from Mathias-Boulay/Better_defaults

[MINOR] Better Default update
This commit is contained in:
Boulay Mathias 2021-08-16 17:43:09 +02:00 committed by GitHub
commit d53b4b86bb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
24 changed files with 454 additions and 425 deletions

View File

@ -4,6 +4,10 @@ import android.content.*;
import android.graphics.*;
import android.util.*;
import androidx.core.content.res.ResourcesCompat;
import net.kdt.pojavlaunch.R;
public class MineButton extends androidx.appcompat.widget.AppCompatButton
{
@ -17,7 +21,7 @@ public class MineButton extends androidx.appcompat.widget.AppCompatButton
}
public void init() {
setTypeface(Typeface.createFromAsset(getContext().getAssets(), "font/NotoSans-Bold.ttf"));
setTypeface(ResourcesCompat.getFont(getContext(), R.font.noto_sans_bold));
}
}

View File

@ -0,0 +1,101 @@
package net.kdt.pojavlaunch;
import android.os.Build;
import java.util.Locale;
/**
* This class aims at providing a simple and easy way to deal with the device architecture.
*/
public class Architecture {
public static int UNSUPPORTED_ARCH = -1;
public static int ARCH_ARM64 = 0x1;
public static int ARCH_ARM = 0x2;
public static int ARCH_X86 = 0x4;
public static int ARCH_X86_64 = 0x8;
/**
* Tell us if the device supports 64 bits architecture
* @return If the device supports 64 bits architecture
*/
public static boolean is64BitsDevice(){
return Build.SUPPORTED_64_BIT_ABIS.length != 0;
}
/**
* Tell us if the device supports 32 bits architecture
* Note, that a 64 bits device won't be reported as supporting 32 bits.
* @return If the device supports 32 bits architecture
*/
public static boolean is32BitsDevice(){
return !is64BitsDevice();
}
/**
* Tells the device supported architecture.
* Since mips(/64) has been phased out long ago, is isn't checked here.
*
* @return ARCH_ARM || ARCH_ARM64 || ARCH_X86 || ARCH_86_64
*/
public static int getDeviceArchitecture(){
if(isx86Device()){
return is64BitsDevice() ? ARCH_X86_64 : ARCH_X86;
}
return is64BitsDevice() ? ARCH_ARM64 : ARCH_ARM;
}
/**
* Tell is the device is based on an x86 processor.
* It doesn't tell if the device is 64 or 32 bits.
* @return Whether or not the device is x86 based.
*/
public static boolean isx86Device(){
//We check the whole range of supported ABIs,
//Since asus zenfones can place arm before their native instruction set.
String[] ABI = is64BitsDevice() ? Build.SUPPORTED_64_BIT_ABIS : Build.SUPPORTED_32_BIT_ABIS;
int comparedArch = is64BitsDevice() ? ARCH_X86_64 : ARCH_X86;
for (String str : ABI) {
if (archAsInt(str) == comparedArch) return true;
}
return false;
}
/**
* Tell is the device is based on an arm processor.
* It doesn't tell if the device is 64 or 32 bits.
* @return Whether or not the device is arm based.
*/
public static boolean isArmDevice(){
return !isx86Device();
}
/**
* Convert an architecture from a String to an int.
* @param arch The architecture as a String
* @return The architecture as an int, can be UNSUPPORTED_ARCH if unknown.
*/
public static int archAsInt(String arch){
arch = arch.toLowerCase().trim().replace(" ", "");
if(arch.contains("arm64") || arch.equals("aarch64")) return ARCH_ARM64;
if(arch.contains("arm")) return ARCH_ARM;
if(arch.contains("x86_64") || arch.contains("amd64")) return ARCH_X86_64;
if(arch.contains("x86") || (arch.startsWith("i") && arch.endsWith("86"))) return ARCH_X86;
//Shouldn't happen
return UNSUPPORTED_ARCH;
}
/**
* Convert to a string an architecture.
* @param arch The architecture as an int.
* @return "arm64" || "arm" || "x86_64" || "x86" || "UNSUPPORTED_ARCH"
*/
public static String archAsString(int arch){
if(arch == ARCH_ARM64) return "arm64";
if(arch == ARCH_ARM) return "arm";
if(arch == ARCH_X86_64) return "x86_64";
if(arch == ARCH_X86) return "x86";
return "UNSUPPORTED_ARCH";
}
}

View File

@ -1,21 +0,0 @@
package net.kdt.pojavlaunch;
public class ArchitectureCheck
{
public static String getArch() {
String arch = System.getProperty("os.arch");
String archConverted = null;
if (arch.equals("aarch64") ||
arch.endsWith("v8a") ||
arch.startsWith("arm64")) {
archConverted = "arm64";
} else if (arch.startsWith("arm") || arch.endsWith("v7a")) {
archConverted = "arm32";
} else if (arch.startsWith("x86") || arch.startsWith("amd")) {
archConverted = "x86";
}
return archConverted;
}
}

View File

@ -1,5 +1,7 @@
package net.kdt.pojavlaunch;
import static net.kdt.pojavlaunch.Architecture.ARCH_X86;
import android.app.*;
import android.content.*;
import android.content.pm.PackageManager;
@ -57,22 +59,22 @@ public class BaseMainActivity extends LoggableActivity {
private static boolean triggeredLeftMouseButton = false;
private final Handler theHandler = new Handler() {
public void handleMessage(Message msg) {
if (!LauncherPreferences.PREF_DISABLE_GESTURES) {
switch (msg.what) {
case MSG_LEFT_MOUSE_BUTTON_CHECK: {
int x = CallbackBridge.mouseX;
int y = CallbackBridge.mouseY;
if (CallbackBridge.isGrabbing() &&
Math.abs(initialX - x) < fingerStillThreshold &&
Math.abs(initialY - y) < fingerStillThreshold) {
triggeredLeftMouseButton = true;
sendMouseButton(LWJGLGLFWKeycode.GLFW_MOUSE_BUTTON_LEFT, true);
}
} break;
case MSG_DROP_ITEM_BUTTON_CHECK: {
sendKeyPress(LWJGLGLFWKeycode.GLFW_KEY_Q, 0, true);
} break;
}
switch (msg.what) {
case MSG_LEFT_MOUSE_BUTTON_CHECK:
if(LauncherPreferences.PREF_DISABLE_GESTURES) break;
int x = CallbackBridge.mouseX;
int y = CallbackBridge.mouseY;
if (CallbackBridge.isGrabbing() &&
Math.abs(initialX - x) < fingerStillThreshold &&
Math.abs(initialY - y) < fingerStillThreshold) {
triggeredLeftMouseButton = true;
sendMouseButton(LWJGLGLFWKeycode.GLFW_MOUSE_BUTTON_LEFT, true);
}
break;
case MSG_DROP_ITEM_BUTTON_CHECK:
sendKeyPress(LWJGLGLFWKeycode.GLFW_KEY_Q, 0, true);
break;
}
}
};
@ -313,7 +315,7 @@ public class BaseMainActivity extends LoggableActivity {
});
minecraftGLView.setFocusable(true);
glTouchListener = new OnTouchListener(){
private boolean isTouchInHotbar = false;
/*
@ -323,7 +325,7 @@ public class BaseMainActivity extends LoggableActivity {
private boolean shouldBeDown = false;
/*
* When the android system has fingers really near to each other, it tends to
* either swap or remove a pointer.
* either swap or remove a pointer !
* This variable is here to mitigate the issue.
*/
private int lastPointerCount = 0;
@ -634,12 +636,6 @@ public class BaseMainActivity extends LoggableActivity {
}
boolean isKeyboard(KeyEvent evt) {
System.out.println("Event:" +evt);
return EfficientAndroidLWJGLKeycode.containsKey(evt.getKeyCode());
}
@Override
public boolean dispatchKeyEvent(KeyEvent event) {
/*
@ -763,7 +759,7 @@ public class BaseMainActivity extends LoggableActivity {
}
private void checkVulkanZinkIsSupported() {
if (Tools.CURRENT_ARCHITECTURE.equals("x86")
if (Tools.DEVICE_ARCHITECTURE == ARCH_X86
|| Build.VERSION.SDK_INT < 25
|| !getPackageManager().hasSystemFeature(PackageManager.FEATURE_VULKAN_HARDWARE_LEVEL)
|| !getPackageManager().hasSystemFeature(PackageManager.FEATURE_VULKAN_HARDWARE_VERSION)) {
@ -900,25 +896,6 @@ public class BaseMainActivity extends LoggableActivity {
}
/**
* Toggle on and off the soft keyboard, depending of the state
* The condition is prone to errors if the keyboard is being hidden without the consent
* of the current TouchCharInput
*/
public void switchKeyboardState(){
//If an hard keyboard is present, never trigger the soft one
if(touchCharInput.hasFocus()
|| getResources().getConfiguration().keyboard == Configuration.KEYBOARD_QWERTY){
touchCharInput.clear();
touchCharInput.disable();
}else{
InputMethodManager imm = (InputMethodManager) getSystemService(INPUT_METHOD_SERVICE);
touchCharInput.enable();
touchCharInput.postDelayed(() -> imm.showSoftInput(touchCharInput, InputMethodManager.SHOW_IMPLICIT), 200);
}
}
protected void setRightOverride(boolean val) {
this.rightOverride = val;
}
@ -934,29 +911,6 @@ public class BaseMainActivity extends LoggableActivity {
public static void sendKeyPress(int keyCode, char keyChar, int scancode, int modifiers, boolean status) {
CallbackBridge.sendKeycode(keyCode, keyChar, scancode, modifiers, status);
}
public static boolean doesObjectContainField(Class objectClass, String fieldName) {
for (Field field : objectClass.getFields()) {
if (field.getName().equals(fieldName)) {
return true;
}
}
return false;
}
public void sendKeyPress(char keyChar) {
if(doesObjectContainField(KeyEvent.class,"KEYCODE_" + Character.toUpperCase(keyChar))) {
try {
int keyCode = KeyEvent.class.getField("KEYCODE_" + Character.toUpperCase(keyChar)).getInt(null);
sendKeyPress(EfficientAndroidLWJGLKeycode.getValue(keyCode), keyChar, 0, CallbackBridge.getCurrentMods(), true);
sendKeyPress(EfficientAndroidLWJGLKeycode.getValue(keyCode), keyChar, 0, CallbackBridge.getCurrentMods(), false);
} catch (IllegalAccessException | NoSuchFieldException e) {
}
return;
}
sendKeyPress(0, keyChar, 0, CallbackBridge.getCurrentMods(), true);
sendKeyPress(0, keyChar, 0, CallbackBridge.getCurrentMods(), false);
}
public static void sendKeyPress(int keyCode) {
sendKeyPress(keyCode, CallbackBridge.getCurrentMods(), true);

View File

@ -1,33 +0,0 @@
package net.kdt.pojavlaunch;
import android.graphics.*;
import android.view.*;
import android.widget.*;
import android.content.*;
import com.kdt.mcgui.*;
public class FontChanger
{
private static Typeface fNotoSans, fMinecraftTen;
public static void initFonts(Context ctx) {
fNotoSans = Typeface.createFromAsset(ctx.getAssets(), "font/NotoSans-Bold.ttf");
fMinecraftTen = Typeface.createFromAsset(ctx.getAssets(), "font/minecraft-ten.ttf");
}
public static void changeFonts(ViewGroup viewTree) {
View child;
for(int i = 0; i < viewTree.getChildCount(); ++i) {
child = viewTree.getChildAt(i);
if (child instanceof ViewGroup) {
changeFonts((ViewGroup) child);
} else if (child instanceof TextView) {
changeFont((TextView) child);
}
}
}
public static void changeFont(TextView view) {
view.setTypeface(view instanceof MineButton ? fMinecraftTen : fNotoSans);
}
}

View File

@ -1,43 +0,0 @@
package net.kdt.pojavlaunch;
public class JVersion extends Object
{
private String version;
private JVersion(String version)
{
this.version = version;
}
public static JVersion from(String version)
{
return new JVersion(version);
}
public boolean isVersionCode()
{
return !version.contains(".");
}
public JVersion toVersionCode()
{
if(!isVersionCode()){
version = version.replace(".", "");
return this;
} else throw new RuntimeException("Can't convert version code to itself");
}
public JVersion toVersionName()
{
if(isVersionCode()){
StringBuilder charList = new StringBuilder();
for(int i=0; i<version.length(); i++){
charList.append(version.substring(i, i+1));
if(i != version.length() - 1){
charList.append(".");
}
}
version = charList.toString();
return this;
} else throw new RuntimeException("Can't convert version name to itself");
}
public String getVersion()
{
return version;
}
}

View File

@ -63,7 +63,7 @@ public class MainActivity extends BaseMainActivity {
for(int keycode : button.getProperties().keycodes){
switch (keycode) {
case ControlData.SPECIALBTN_KEYBOARD:
switchKeyboardState();
touchCharInput.switchKeyboardState();
break;
case ControlData.SPECIALBTN_TOGGLECTRL:
@ -194,7 +194,7 @@ public class MainActivity extends BaseMainActivity {
if (requestCode == 1 && resultCode == Activity.RESULT_OK) {
// Reload PREF_DEFAULTCTRL_PATH
LauncherPreferences.loadPreferences();
LauncherPreferences.loadPreferences(getApplicationContext());
try {
mControlLayout.loadLayout(LauncherPreferences.PREF_DEFAULTCTRL_PATH);
} catch (IOException e) {

View File

@ -12,7 +12,8 @@ public class MinecraftGLView extends TextureView
public MinecraftGLView(Context context, AttributeSet attributeSet) {
super(context, attributeSet);
//Fixes freeform and dex mode having transparent glass,
//since it forces android to used the background color of the view/layout behind it.
setOpaque(false);
}
}

View File

@ -6,7 +6,7 @@ import android.content.pm.*;
import android.content.res.*;
import android.os.*;
import androidx.core.app.*;
import androidx.preference.*;
import android.util.*;
import java.io.*;
import java.text.*;
@ -59,24 +59,18 @@ public class PojavApplication extends Application
Tools.DIR_ACCOUNT_OLD = Tools.DIR_DATA + "/Users";
Tools.DIR_ACCOUNT_NEW = Tools.DIR_DATA + "/accounts";
// Tools.FILE_ACCOUNT_JSON = getFilesDir().getAbsolutePath() + "/account_profiles.json";
File nativeLibDir = new File(getApplicationInfo().nativeLibraryDir);
Tools.CURRENT_ARCHITECTURE = nativeLibDir.getName();
switch (Tools.CURRENT_ARCHITECTURE) {
case "arm": Tools.CURRENT_ARCHITECTURE = "arm/aarch32"; break;
case "arm64": Tools.CURRENT_ARCHITECTURE = "arm64/aarch64"; break;
case "x86": Tools.CURRENT_ARCHITECTURE = "x86/i386"; break;
case "x86_64": Tools.CURRENT_ARCHITECTURE = "x86_64/amd64"; break;
}
// Special case for Asus x86 devixes
if (Build.SUPPORTED_ABIS[0].equals("x86")) {
getApplicationInfo().nativeLibraryDir = nativeLibDir.getParent() + "/x86";
Tools.CURRENT_ARCHITECTURE = "x86/i386";
}
FontChanger.initFonts(this);
Tools.DEVICE_ARCHITECTURE = Architecture.getDeviceArchitecture();
//Force x86 lib directory for Asus x86 based zenfones
if(Architecture.isx86Device() && Architecture.is32BitsDevice()){
String originalJNIDirectory = getApplicationInfo().nativeLibraryDir;
getApplicationInfo().nativeLibraryDir = originalJNIDirectory.substring(0,
originalJNIDirectory.lastIndexOf("/"))
.concat("/x86");
}
} catch (Throwable th) {
Intent ferrorIntent = new Intent(this, FatalErrorActivity.class);
ferrorIntent.putExtra("throwable", th);

View File

@ -1,5 +1,7 @@
package net.kdt.pojavlaunch;
import static net.kdt.pojavlaunch.Architecture.archAsString;
import android.Manifest;
import android.app.Activity;
import android.app.Dialog;
@ -110,7 +112,7 @@ public class PojavLoginActivity extends BaseActivity
LinearLayout startScr = new LinearLayout(PojavLoginActivity.this);
LayoutInflater.from(PojavLoginActivity.this).inflate(R.layout.start_screen,startScr);
PojavLoginActivity.this.setContentView(startScr);
FontChanger.changeFonts(startScr);
progress = (ProgressBar) findViewById(R.id.startscreenProgress);
if(isStarting) progress.setVisibility(View.VISIBLE);
startupTextView = (TextView) findViewById(R.id.startscreen_text);
@ -344,7 +346,7 @@ public class PojavLoginActivity extends BaseActivity
mLockSelectJRE.wait();
}
}
LauncherPreferences.loadPreferences();
LauncherPreferences.loadPreferences(getApplicationContext());
}
catch(Throwable e){
Tools.showError(this, e);
@ -387,7 +389,7 @@ public class PojavLoginActivity extends BaseActivity
if(rt_version == null) return false;
if(!rt_version.equals(current_rt_version)) { //If we already have an integrated one installed, check if it's up-to-date
try {
MultiRTUtils.installRuntimeNamedBinpack(am.open("components/jre/universal.tar.xz"), am.open("components/jre/bin-" + Tools.CURRENT_ARCHITECTURE.split("/")[0] + ".tar.xz"), "Internal", rt_version,
MultiRTUtils.installRuntimeNamedBinpack(am.open("components/jre/universal.tar.xz"), am.open("components/jre/bin-" + archAsString(Tools.DEVICE_ARCHITECTURE) + ".tar.xz"), "Internal", rt_version,
(resid, vararg) -> runOnUiThread(()->{if(startupTextView!=null)startupTextView.setText(getString(resid,vararg));}));
MultiRTUtils.postPrepare(PojavLoginActivity.this,"Internal");
return true;

View File

@ -45,7 +45,7 @@ public final class Tools {
public static String DIR_DATA = "/data/data/" + BuildConfig.APPLICATION_ID;
public static String MULTIRT_HOME = DIR_DATA+"/runtimes";
public static String LOCAL_RENDERER = null;
public static String CURRENT_ARCHITECTURE;
public static int DEVICE_ARCHITECTURE;
// New since 3.3.1
public static String DIR_ACCOUNT_NEW;
@ -156,64 +156,6 @@ public final class Tools {
javaArgList.add(cacioClasspath.toString());
}
public static void getJavaArgs(Context ctx, List<String> javaArgList, String renderLib) {
List<String> overrideableArgList = new ArrayList<String>();
overrideableArgList.add("-Djava.home=" + Tools.DIR_HOME_JRE);
overrideableArgList.add("-Djava.io.tmpdir=" + ctx.getCacheDir().getAbsolutePath());
overrideableArgList.add("-Duser.home=" + new File(Tools.DIR_GAME_NEW).getParent());
overrideableArgList.add("-Duser.language=" + System.getProperty("user.language"));
// overrideableArgList.add("-Duser.timezone=GMT");
overrideableArgList.add("-Dos.name=Linux");
overrideableArgList.add("-Dos.version=Android-" + Build.VERSION.RELEASE);
overrideableArgList.add("-Dpojav.path.minecraft=" + DIR_GAME_NEW);
overrideableArgList.add("-Dpojav.path.private.account=" + DIR_ACCOUNT_NEW);
// javaArgList.add("-Dorg.lwjgl.libname=liblwjgl3.so");
// javaArgList.add("-Dorg.lwjgl.system.jemalloc.libname=libjemalloc.so");
overrideableArgList.add("-Dorg.lwjgl.opengl.libname=" + renderLib);
// overrideableArgList.add("-Dorg.lwjgl.opengl.libname=libgl4es_115.so");
// javaArgList.add("-Dorg.lwjgl.opengl.libname=libRegal.so");
// Enable LWJGL3 debug
// overrideableArgList.add("-Dorg.lwjgl.util.Debug=true");
// overrideableArgList.add("-Dorg.lwjgl.util.DebugFunctions=true");
// overrideableArgList.add("-Dorg.lwjgl.util.DebugLoader=true");
// GLFW Stub width height
overrideableArgList.add("-Dglfwstub.windowWidth=" + CallbackBridge.windowWidth);
overrideableArgList.add("-Dglfwstub.windowHeight=" + CallbackBridge.windowHeight);
overrideableArgList.add("-Dglfwstub.initEgl=false");
overrideableArgList.add("-Dnet.minecraft.clientmodname=" + Tools.APP_NAME);
// Disable FML Early Loading Screen to get Forge 1.14+ works
overrideableArgList.add("-Dfml.earlyprogresswindow=false");
// Override args
for (String argOverride : LauncherPreferences.PREF_CUSTOM_JAVA_ARGS.split(" ")) {
for (int i = overrideableArgList.size() - 1; i >= 0; i--) {
String arg = overrideableArgList.get(i);
// Currently, only java property is supported overridable argument, other such as "-X:" are handled by the JVM.
// Althought java properties are also handled by JVM, but duplicate bug from parser may occurs, so replace them.
if (arg.startsWith("-D") && argOverride.startsWith(arg.substring(0, arg.indexOf('=') + 1))) {
// Override the matched argument
overrideableArgList.set(i, argOverride);
break;
} else if (!argOverride.isEmpty() && i == 0) {
// Overridable argument has mismatched, so add the custom argument to overridable argument list
javaArgList.add(argOverride);
}
}
}
javaArgList.addAll(overrideableArgList);
}
public static String[] getMinecraftArgs(MinecraftAccount profile, JMinecraftVersionList.Version versionInfo, String strGameDir) {
String username = profile.username;
String versionName = versionInfo.id;
@ -226,7 +168,7 @@ public final class Tools {
File gameDir = new File(strGameDir);
gameDir.mkdirs();
Map<String, String> varArgMap = new ArrayMap<String, String>();
Map<String, String> varArgMap = new ArrayMap<>();
varArgMap.put("auth_access_token", profile.accessToken);
varArgMap.put("auth_player_name", username);
varArgMap.put("auth_uuid", profile.profileId);
@ -872,5 +814,18 @@ public final class Tools {
Tools.updateWindowSize(ctx);
}
}
public static int getTotalDeviceMemory(Context ctx){
ActivityManager actManager = (ActivityManager) ctx.getSystemService(Context.ACTIVITY_SERVICE);
ActivityManager.MemoryInfo memInfo = new ActivityManager.MemoryInfo();
actManager.getMemoryInfo(memInfo);
return (int) (memInfo.totalMem / 1048576L);
}
public static int getFreeDeviceMemory(Context ctx){
ActivityManager actManager = (ActivityManager) ctx.getSystemService(Context.ACTIVITY_SERVICE);
ActivityManager.MemoryInfo memInfo = new ActivityManager.MemoryInfo();
actManager.getMemoryInfo(memInfo);
return (int) (memInfo.availMem / 1048576L);
}
}

View File

@ -260,7 +260,7 @@ public class ControlLayout extends FrameLayout
//Check if the action is cancelling, reset the lastControl button associated to the view
if(ev.getActionMasked() == MotionEvent.ACTION_UP || ev.getActionMasked() == MotionEvent.ACTION_CANCEL){
if(lastControlButton != null) lastControlButton.onTouchEvent(ev);
if(lastControlButton != null) lastControlButton.sendKeyPresses(ev,false);
mapTable.put(v, null);
return true;
}
@ -275,9 +275,8 @@ public class ControlLayout extends FrameLayout
}
}
//Release the last key
ev.setAction(MotionEvent.ACTION_POINTER_UP);
if (lastControlButton != null) lastControlButton.onTouchEvent(ev);
//Release last keys
if (lastControlButton != null) lastControlButton.sendKeyPresses(ev,false);
mapTable.put(v, null);
//Look for another SWIPEABLE button
@ -289,8 +288,7 @@ public class ControlLayout extends FrameLayout
//Press the new key
if(!button.equals(lastControlButton)){
ev.setAction(MotionEvent.ACTION_POINTER_DOWN);
button.onTouchEvent(ev);
button.sendKeyPresses(ev,true);
mapTable.put(v, button);
}

View File

@ -1,8 +1,13 @@
package net.kdt.pojavlaunch.customcontrols;
import static android.content.Context.INPUT_METHOD_SERVICE;
import android.content.Context;
import android.content.res.Configuration;
import android.util.AttributeSet;
import android.view.KeyEvent;
import android.view.inputmethod.InputMethodManager;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
@ -87,6 +92,27 @@ public class TouchCharInput extends androidx.appcompat.widget.AppCompatEditText
super.setSelection(5);
}
/**
* Toggle on and off the soft keyboard, depending of the state
*
* @return if the keyboard is set to be shown.
*/
public boolean switchKeyboardState(){
//If an hard keyboard is present, never trigger the soft one
if(hasFocus()
|| getResources().getConfiguration().keyboard == Configuration.KEYBOARD_QWERTY){
clear();
disable();
return false;
}else{
InputMethodManager imm = (InputMethodManager) getContext().getSystemService(INPUT_METHOD_SERVICE);
enable();
postDelayed(() -> imm.showSoftInput(this, InputMethodManager.SHOW_IMPLICIT), 200);
return true;
}
}
/**
* Clear the EditText from any leftover inputs
* It does not affect the in-game input

View File

@ -269,7 +269,7 @@ public class ControlButton extends androidx.appcompat.widget.AppCompatButton imp
if(mProperties.isSwipeable && !isPointerOutOfBounds){
//Remove keys
if(!triggerToggle(event)) {
sendKeyPresses(event, false);
sendKeyPresses(event,false);
}
}
isPointerOutOfBounds = true;
@ -282,7 +282,7 @@ public class ControlButton extends androidx.appcompat.widget.AppCompatButton imp
((ControlLayout) getParent()).onTouch(this, event);
//RE-press the button
if(mProperties.isSwipeable && !mProperties.isToggle){
sendKeyPresses(event, true);
sendKeyPresses(event,true);
}
}
isPointerOutOfBounds = false;
@ -291,7 +291,7 @@ public class ControlButton extends androidx.appcompat.widget.AppCompatButton imp
case MotionEvent.ACTION_DOWN: // 0
case MotionEvent.ACTION_POINTER_DOWN: // 5
if(!mProperties.isToggle){
sendKeyPresses(event, true);
sendKeyPresses(event,true);
}
break;
@ -306,7 +306,7 @@ public class ControlButton extends androidx.appcompat.widget.AppCompatButton imp
isPointerOutOfBounds = false;
if(!triggerToggle(event)) {
sendKeyPresses(event, false);
sendKeyPresses(event,false);
}
break;
@ -476,7 +476,7 @@ public class ControlButton extends androidx.appcompat.widget.AppCompatButton imp
if(keycode >= GLFW_KEY_UNKNOWN){
MainActivity.sendKeyPress(keycode, CallbackBridge.getCurrentMods(), isDown);
CallbackBridge.setModifiers(keycode, isDown);
}else {
}else{
super.onTouchEvent(event);
}
}

View File

@ -44,9 +44,7 @@ public class CustomSeekBarPreference extends SeekBarPreference {
public void setMin(int min) {
//Note: since the max (setMax is a final function) is not taken into account properly, setting the min over the max may produce funky results
super.setMin(min);
if (min != mMin) {
mMin = min;
}
if (min != mMin) mMin = min;
}
@ -92,7 +90,21 @@ public class CustomSeekBarPreference extends SeekBarPreference {
}
/**
* Set a suffix to be appended on the TextView associated to the value
* @param suffix The suffix to append as a String
*/
public void setSuffix(String suffix) {
this.suffix = suffix;
}
/**
* Convenience function to set both min and max at the same time.
* @param min The minimum value
* @param max The maximum value
*/
public void setRange(int min, int max){
setMin(min);
setMax(max);
}
}

View File

@ -1,61 +1,76 @@
package net.kdt.pojavlaunch.prefs;
import android.graphics.Color;
import android.os.*;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.preference.*;
import net.kdt.pojavlaunch.R;
import net.kdt.pojavlaunch.Tools;
import net.kdt.pojavlaunch.fragments.LauncherFragment;
import android.content.*;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import static net.kdt.pojavlaunch.Architecture.is32BitsDevice;
import static net.kdt.pojavlaunch.Tools.getTotalDeviceMemory;
import static net.kdt.pojavlaunch.prefs.LauncherPreferences.PREF_NOTCH_SIZE;
public class LauncherPreferenceFragment extends PreferenceFragmentCompat implements SharedPreferences.OnSharedPreferenceChangeListener
{
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
view.setBackgroundColor(Color.parseColor("#44000000"));
super.onViewCreated(view, savedInstanceState);
}
@Override
public void onCreatePreferences(Bundle b, String str) {
addPreferencesFromResource(R.xml.pref_main);
// Disable freeform mode in Android 6.0 and below.
findPreference("freeform").setVisible(Build.VERSION.SDK_INT >= Build.VERSION_CODES.N);
//Disable notch checking behavior on android 8.1 and below.
findPreference("ignoreNotch").setVisible(Build.VERSION.SDK_INT >= Build.VERSION_CODES.P && PREF_NOTCH_SIZE != 0);
CustomSeekBarPreference seek2 = (CustomSeekBarPreference) findPreference("timeLongPressTrigger");
seek2.setMin(100);
seek2.setMax(1000);
CustomSeekBarPreference seek2 = findPreference("timeLongPressTrigger");
seek2.setRange(100, 1000);
seek2.setValue(LauncherPreferences.PREF_LONGPRESS_TRIGGER);
seek2.setSuffix(" ms");
CustomSeekBarPreference seek3 = (CustomSeekBarPreference) findPreference("buttonscale");
seek3.setMin(80);
seek3.setMax(250);
CustomSeekBarPreference seek3 = findPreference("buttonscale");
seek3.setRange(80, 250);
seek3.setValue((int) LauncherPreferences.PREF_BUTTONSIZE);
seek3.setSuffix(" %");
CustomSeekBarPreference seek4 = (CustomSeekBarPreference) findPreference("mousescale");
seek4.setMin(25);
seek4.setMax(300);
CustomSeekBarPreference seek4 = findPreference("mousescale");
seek4.setRange(25, 300);
seek4.setValue((int) LauncherPreferences.PREF_MOUSESCALE);
seek4.setSuffix(" %");
CustomSeekBarPreference seek5 = (CustomSeekBarPreference) findPreference("resolutionRatio");
CustomSeekBarPreference seek5 = findPreference("resolutionRatio");
seek5.setMin(25);
seek5.setSuffix(" %");
CustomSeekBarPreference seek6 = (CustomSeekBarPreference) findPreference("mousespeed");
seek6.setMin(25);
seek6.setMax(300);
seek6.setValue((int)(LauncherPreferences.PREF_MOUSESPEED*100f));
CustomSeekBarPreference seek6 = findPreference("mousespeed");
seek6.setRange(25, 300);
seek6.setValue((int)(LauncherPreferences.PREF_MOUSESPEED*100f));
seek6.setSuffix(" %");
int freeMem = (int) (Runtime.getRuntime().freeMemory() / 1048576l);
CustomSeekBarPreference seek7 = (CustomSeekBarPreference) findPreference("allocation");
int maxRAM;
int deviceRam = getTotalDeviceMemory(getContext());
CustomSeekBarPreference seek7 = findPreference("allocation");
seek7.setMin(256);
if(Tools.CURRENT_ARCHITECTURE.contains("32")) seek7.setMax(1100);
else seek7.setMax(freeMem > 4096 ? freeMem : 4096);
if(is32BitsDevice()) maxRAM = Math.min(1100, deviceRam);
else maxRAM = deviceRam - (deviceRam < 3064 ? 800 : 1024); //To have a minimum for the device to breathe
seek7.setMax(maxRAM);
seek7.setValue(LauncherPreferences.PREF_RAM_ALLOCATION);
seek7.setSuffix(" MB");
@ -84,6 +99,6 @@ public class LauncherPreferenceFragment extends PreferenceFragmentCompat impleme
@Override
public void onSharedPreferenceChanged(SharedPreferences p, String s) {
LauncherPreferences.loadPreferences();
LauncherPreferences.loadPreferences(getContext());
}
}

View File

@ -3,6 +3,7 @@ package net.kdt.pojavlaunch.prefs;
import android.content.*;
import net.kdt.pojavlaunch.*;
import net.kdt.pojavlaunch.multirt.MultiRTUtils;
import net.kdt.pojavlaunch.utils.JREUtils;
public class LauncherPreferences
{
@ -13,45 +14,39 @@ public class LauncherPreferences
public static boolean PREF_VERTYPE_SNAPSHOT = false;
public static boolean PREF_VERTYPE_OLDALPHA = false;
public static boolean PREF_VERTYPE_OLDBETA = false;
public static boolean PREF_FREEFORM = false;
public static boolean PREF_HIDE_SIDEBAR = false;
public static boolean PREF_IGNORE_NOTCH = false;
public static int PREF_NOTCH_SIZE = 0;
public static float PREF_BUTTONSIZE = 100f;
public static float PREF_MOUSESCALE = 100f;
public static int PREF_LONGPRESS_TRIGGER = 500;
public static int PREF_LONGPRESS_TRIGGER = 300;
public static String PREF_DEFAULTCTRL_PATH = Tools.CTRLDEF_FILE;
public static String PREF_CUSTOM_JAVA_ARGS;
public static String PREF_CUSTOM_OPENGL_LIBNAME = "libgl4es_114.so";
public static String PREF_LANGUAGE = "default";
public static String PREF_VERSION_REPOS = "https://launchermeta.mojang.com/mc/game/version_manifest_v2.json";
public static boolean PREF_CHECK_LIBRARY_SHA = true;
public static boolean PREF_DISABLE_GESTURES = false;
public static float PREF_MOUSESPEED = 1f;
public static int PREF_RAM_ALLOCATION=300;
public static int PREF_RAM_ALLOCATION;
public static String PREF_DEFAULT_RUNTIME;
public static void loadPreferences() {
public static void loadPreferences(Context ctx) {
PREF_RENDERER = DEFAULT_PREF.getString("renderer", "opengles2");
PREF_BUTTONSIZE = DEFAULT_PREF.getInt("buttonscale", 100);
PREF_MOUSESCALE = DEFAULT_PREF.getInt("mousescale", 100);
PREF_MOUSESPEED = ((float)DEFAULT_PREF.getInt("mousespeed",100))/100f;
PREF_FREEFORM = DEFAULT_PREF.getBoolean("freeform", false);
PREF_HIDE_SIDEBAR = DEFAULT_PREF.getBoolean("hideSidebar", false);
PREF_IGNORE_NOTCH = DEFAULT_PREF.getBoolean("ignoreNotch", false);
PREF_VERTYPE_RELEASE = DEFAULT_PREF.getBoolean("vertype_release", true);
PREF_VERTYPE_SNAPSHOT = DEFAULT_PREF.getBoolean("vertype_snapshot", false);
PREF_VERTYPE_OLDALPHA = DEFAULT_PREF.getBoolean("vertype_oldalpha", false);
PREF_VERTYPE_OLDBETA = DEFAULT_PREF.getBoolean("vertype_oldbeta", false);
PREF_LONGPRESS_TRIGGER = DEFAULT_PREF.getInt("timeLongPressTrigger", 500);
PREF_LONGPRESS_TRIGGER = DEFAULT_PREF.getInt("timeLongPressTrigger", 300);
PREF_DEFAULTCTRL_PATH = DEFAULT_PREF.getString("defaultCtrl", Tools.CTRLDEF_FILE);
PREF_LANGUAGE = DEFAULT_PREF.getString("language", "default");
PREF_CHECK_LIBRARY_SHA = DEFAULT_PREF.getBoolean("checkLibraries",true);
PREF_DISABLE_GESTURES = DEFAULT_PREF.getBoolean("disableGestures",false);
PREF_RAM_ALLOCATION = DEFAULT_PREF.getInt("allocation",300);
// Get double of max Android heap to set default heap size
int androidHeap = (int) (Runtime.getRuntime().maxMemory() / 1024l / 512l);
int doubleAndroidHeap = androidHeap * 2;
PREF_RAM_ALLOCATION = DEFAULT_PREF.getInt("allocation", findBestRAMAllocation(ctx));
PREF_CUSTOM_JAVA_ARGS = DEFAULT_PREF.getString("javaArgs", "");
/*
if (PREF_CUSTOM_JAVA_ARGS.isEmpty()) {
@ -85,7 +80,7 @@ public class LauncherPreferences
PREF_RENDERER = "opengles" + PREF_RENDERER;
}
String argLwjglLibname = "-Dorg.lwjgl.opengl.libname=";
for (String arg : PREF_CUSTOM_JAVA_ARGS.split(" ")) {
for (String arg : JREUtils.parseJavaArguments(PREF_CUSTOM_JAVA_ARGS)) {
if (arg.startsWith(argLwjglLibname)) {
// purge arg
DEFAULT_PREF.edit().putString("javaArgs",
@ -103,4 +98,24 @@ public class LauncherPreferences
LauncherPreferences.DEFAULT_PREF.edit().putString("defaultRuntime",LauncherPreferences.PREF_DEFAULT_RUNTIME).apply();
}
}
/**
* This functions aims at finding the best default RAM amount,
* according to the RAM amount of the physical device.
* Put not enough RAM ? Minecraft will lag and crash.
* Put too much RAM ?
* The GC will lag, android won't be able to breathe properly.
* @param ctx Context needed to get the total memory of the device.
* @return The best default value found.
*/
private static int findBestRAMAllocation(Context ctx){
int deviceRam = Tools.getTotalDeviceMemory(ctx);
if (deviceRam < 1024) return 300;
if (deviceRam < 1536) return 450;
if (deviceRam < 2048) return 600;
if (deviceRam < 3064) return 936;
if (deviceRam < 4096) return 1148;
if (deviceRam < 6144) return 1536;
return 2048; //Default RAM allocation for 64 bits
}
}

View File

@ -344,35 +344,15 @@ public class MinecraftDownloaderTask extends AsyncTask<String, String, Throwable
mActivity.mCrashView.setLastCrash("");
try {
/*
List<String> jvmArgs = ManagementFactory.getRuntimeMXBean().getInputArguments();
jvmArgs.add("-Xms128M");
jvmArgs.add("-Xmx1G");
*/
Intent mainIntent = new Intent(mActivity, MainActivity.class /* MainActivity.class */);
// mainIntent.addFlags(Intent.FLAG_ACTIVITY_LAUNCH_ADJACENT);
mainIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_DOCUMENT);
mainIntent.addFlags(Intent.FLAG_ACTIVITY_MULTIPLE_TASK);
if (LauncherPreferences.PREF_FREEFORM) {
DisplayMetrics dm = new DisplayMetrics();
mActivity.getWindowManager().getDefaultDisplay().getMetrics(dm);
ActivityOptions options = (ActivityOptions) ActivityOptions.class.getMethod("makeBasic").invoke(null);
Rect freeformRect = new Rect(0, 0, dm.widthPixels / 2, dm.heightPixels / 2);
options.getClass().getDeclaredMethod("setLaunchBounds", Rect.class).invoke(options, freeformRect);
mActivity.startActivity(mainIntent, options.toBundle());
} else {
mActivity.startActivity(mainIntent);
}
mActivity.startActivity(mainIntent);
}
catch (Throwable e) {
Tools.showError(mActivity, e);
}
/*
FloatingIntent maini = new FloatingIntent(PojavLauncherActivity.this, MainActivity.class);
maini.startFloatingActivity();
*/
}
mActivity.mTask = null;

View File

@ -1,16 +1,17 @@
package net.kdt.pojavlaunch.utils;
import static net.kdt.pojavlaunch.Architecture.ARCH_X86;
import static net.kdt.pojavlaunch.Architecture.archAsString;
import static net.kdt.pojavlaunch.Architecture.is64BitsDevice;
import static net.kdt.pojavlaunch.Tools.LOCAL_RENDERER;
import android.app.*;
import android.content.*;
import android.opengl.EGL14;
import android.opengl.EGLExt;
import android.opengl.GLES10;
import android.os.Build;
import android.system.*;
import android.util.*;
import android.widget.Toast;
import androidx.annotation.Nullable;
import com.oracle.dalvik.*;
import java.io.*;
import java.util.*;
@ -23,27 +24,24 @@ import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.egl.EGLContext;
import javax.microedition.khronos.egl.EGLDisplay;
public class JREUtils
{
public class JREUtils {
private JREUtils() {}
public static String JRE_ARCHITECTURE;
public static String LD_LIBRARY_PATH;
private static String nativeLibDir;
public static void checkJavaArchitecture(LoggableActivity act, String jreArch) throws Exception {
String[] argName = Tools.CURRENT_ARCHITECTURE.split("/");
act.appendlnToLog("Architecture: " + Tools.CURRENT_ARCHITECTURE);
if (!(jreArch.contains(argName[0]) || jreArch.contains(argName[1]))) {
// x86 check workaround
if (jreArch.startsWith("i") && jreArch.endsWith("86") && Tools.CURRENT_ARCHITECTURE.contains("x86") && !Tools.CURRENT_ARCHITECTURE.contains("64")) {
return;
}
/**
* Checks if the java architecture is correct for the device architecture.
* @param act An Activity with logging capabilities
* @param jreArch The java architecture to compare as a String.
*/
public static void checkJavaArchitecture(LoggableActivity act, String jreArch) {
act.appendlnToLog("Architecture: " + archAsString(Tools.DEVICE_ARCHITECTURE));
if(Tools.DEVICE_ARCHITECTURE == Architecture.archAsInt(jreArch)) return;
act.appendlnToLog("Architecture " + archAsString(Tools.DEVICE_ARCHITECTURE) + " is incompatible with Java Runtime " + jreArch);
throw new RuntimeException(act.getString(R.string.mcn_check_fail_incompatiblearch, archAsString(Tools.DEVICE_ARCHITECTURE), jreArch));
act.appendlnToLog("Architecture " + Tools.CURRENT_ARCHITECTURE + " is incompatible with Java Runtime " + jreArch);
throw new RuntimeException(act.getString(R.string.mcn_check_fail_incompatiblearch, Tools.CURRENT_ARCHITECTURE, jreArch));
}
}
public static String findInLdLibPath(String libName) {
@ -160,11 +158,9 @@ public class JREUtils
}
public static void relocateLibPath(final Context ctx) throws IOException {
if (JRE_ARCHITECTURE == null) {
JRE_ARCHITECTURE = readJREReleaseProperties().get("OS_ARCH");
if (JRE_ARCHITECTURE.startsWith("i") && JRE_ARCHITECTURE.endsWith("86") && Tools.CURRENT_ARCHITECTURE.contains("x86") && !Tools.CURRENT_ARCHITECTURE.contains("64")) {
JRE_ARCHITECTURE = "i386/i486/i586";
}
String JRE_ARCHITECTURE = readJREReleaseProperties().get("OS_ARCH");
if (Architecture.archAsInt(JRE_ARCHITECTURE) == ARCH_X86){
JRE_ARCHITECTURE = "i386/i486/i586";
}
nativeLibDir = ctx.getApplicationInfo().nativeLibraryDir;
@ -176,7 +172,7 @@ public class JREUtils
}
}
String libName = Tools.CURRENT_ARCHITECTURE.contains("64") ? "lib64" : "lib";
String libName = is64BitsDevice() ? "lib64" : "lib";
StringBuilder ldLibraryPath = new StringBuilder();
ldLibraryPath.append(
Tools.DIR_HOME_JRE + "/" + Tools.DIRNAME_HOME_JRE + "/jli:" +
@ -215,8 +211,8 @@ public class JREUtils
envMap.put("REGAL_GL_VENDOR", "Android");
envMap.put("REGAL_GL_RENDERER", "Regal");
envMap.put("REGAL_GL_VERSION", "4.5");
if(Tools.LOCAL_RENDERER != null) {
envMap.put("POJAV_RENDERER", Tools.LOCAL_RENDERER);
if(LOCAL_RENDERER != null) {
envMap.put("POJAV_RENDERER", LOCAL_RENDERER);
}
envMap.put("AWTSTUB_WIDTH", Integer.toString(CallbackBridge.windowWidth > 0 ? CallbackBridge.windowWidth : CallbackBridge.physicalWidth));
envMap.put("AWTSTUB_HEIGHT", Integer.toString(CallbackBridge.windowHeight > 0 ? CallbackBridge.windowHeight : CallbackBridge.physicalHeight));
@ -232,15 +228,15 @@ public class JREUtils
}
reader.close();
}
if(!envMap.containsKey("LIBGL_ES") && Tools.LOCAL_RENDERER != null) {
if(!envMap.containsKey("LIBGL_ES") && LOCAL_RENDERER != null) {
int glesMajor = getDetectedVersion();
Log.i("glesDetect","GLES version detected: "+glesMajor);
if (glesMajor < 3) {
//fallback to 2 since it's the minimum for the entire app
envMap.put("LIBGL_ES","2");
} else if (Tools.LOCAL_RENDERER.startsWith("opengles")) {
envMap.put("LIBGL_ES", Tools.LOCAL_RENDERER.replace("opengles", "").replace("_5", ""));
} else if (LOCAL_RENDERER.startsWith("opengles")) {
envMap.put("LIBGL_ES", LOCAL_RENDERER.replace("opengles", "").replace("_5", ""));
} else {
// TODO if can: other backends such as Vulkan.
// Sure, they should provide GLES 3 support.
@ -261,55 +257,25 @@ public class JREUtils
// return ldLibraryPath;
}
public static int launchJavaVM(final LoggableActivity ctx, final List<String> args) throws Throwable {
public static int launchJavaVM(final LoggableActivity ctx,final List<String> JVMArgs) throws Throwable {
JREUtils.relocateLibPath(ctx);
// ctx.appendlnToLog("LD_LIBRARY_PATH = " + JREUtils.LD_LIBRARY_PATH);
final String graphicsLib;
if(Tools.LOCAL_RENDERER != null){
switch (Tools.LOCAL_RENDERER) {
case "opengles2":
graphicsLib = "libgl4es_114.so";
break;
case "opengles2_5":
graphicsLib = "libgl4es_115.so";
break;
case "vulkan_zink":
graphicsLib = "libOSMesa_8.so";
break;
case "opengles3_vgpu":
graphicsLib = "libvgpu.so";
break;
default:
throw new RuntimeException("Undefined renderer: " + Tools.LOCAL_RENDERER);
}
if (!dlopen(graphicsLib) && !dlopen(findInLdLibPath(graphicsLib))) {
System.err.println("Failed to load renderer " + graphicsLib + ". Falling back to GL4ES 1.1.4");
Tools.LOCAL_RENDERER = "opengles2";
dlopen(nativeLibDir + "/libgl4es_114.so");
}
}else{
graphicsLib = null;
}
final String graphicsLib = loadGraphicsLibrary();
List<String> userArgs = getJavaArgs(ctx,graphicsLib);
List<String> javaArgList = new ArrayList<String>();
javaArgList.add(Tools.DIR_HOME_JRE + "/bin/java");
Tools.getJavaArgs(ctx, javaArgList,graphicsLib);
purgeArg(javaArgList,"-Xms");
purgeArg(javaArgList,"-Xmx");
/*if(Tools.CURRENT_ARCHITECTURE.contains("32") && ((mi.availMem / 1048576L)-50) > 300) {
javaArgList.add("-Xms300M");
javaArgList.add("-Xmx300M");
}else {*/
javaArgList.add("-Xms" + LauncherPreferences.PREF_RAM_ALLOCATION + "M");
javaArgList.add("-Xmx" + LauncherPreferences.PREF_RAM_ALLOCATION + "M");
//}
ctx.runOnUiThread(new Runnable() {
public void run() {
Toast.makeText(ctx, ctx.getString(R.string.autoram_info_msg,LauncherPreferences.PREF_RAM_ALLOCATION), Toast.LENGTH_SHORT).show();
}
});
System.out.println(javaArgList);
javaArgList.addAll(args);
//Remove arguments that can interfere with the good working of the launcher
purgeArg(userArgs,"-Xms");
purgeArg(userArgs,"-Xmx");
purgeArg(userArgs,"-d32");
purgeArg(userArgs,"-d64");
//Add automatically generated args
userArgs.add("-Xms" + LauncherPreferences.PREF_RAM_ALLOCATION + "M");
userArgs.add("-Xmx" + LauncherPreferences.PREF_RAM_ALLOCATION + "M");
userArgs.addAll(JVMArgs);
ctx.runOnUiThread(() -> Toast.makeText(ctx, ctx.getString(R.string.autoram_info_msg,LauncherPreferences.PREF_RAM_ALLOCATION), Toast.LENGTH_SHORT).show());
System.out.println(JVMArgs);
// For debugging only!
/*
@ -325,27 +291,135 @@ public class JREUtils
setupExitTrap(ctx.getApplication());
chdir(Tools.DIR_GAME_NEW);
final int exitCode = VMLauncher.launchJVM(javaArgList.toArray(new String[0]));
final int exitCode = VMLauncher.launchJVM(userArgs.toArray(new String[0]));
ctx.appendlnToLog("Java Exit code: " + exitCode);
if (exitCode != 0) {
ctx.runOnUiThread(new Runnable(){
@Override
public void run() {
AlertDialog.Builder dialog = new AlertDialog.Builder(ctx);
dialog.setMessage(ctx.getString(R.string.mcn_exit_title, exitCode));
dialog.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener(){
ctx.runOnUiThread(() -> {
AlertDialog.Builder dialog = new AlertDialog.Builder(ctx);
dialog.setMessage(ctx.getString(R.string.mcn_exit_title, exitCode));
@Override
public void onClick(DialogInterface p1, int p2){
BaseMainActivity.fullyExit();
}
});
dialog.show();
}
});
dialog.setPositiveButton(android.R.string.ok, (p1, p2) -> BaseMainActivity.fullyExit());
dialog.show();
});
}
return exitCode;
}
/**
* Gives an argument list filled with both the user args
* and the auto-generated ones (eg. the window resolution).
* @param ctx The application context
* @param renderLib The name of the renderer used.
* @return A list filled with args.
*/
public static List<String> getJavaArgs(Context ctx, String renderLib) {
List<String> userArguments = parseJavaArguments(LauncherPreferences.PREF_CUSTOM_JAVA_ARGS);
String[] overridableArguments = new String[]{
"-Djava.home=" + Tools.DIR_HOME_JRE,
"-Djava.io.tmpdir=" + ctx.getCacheDir().getAbsolutePath(),
"-Duser.home=" + new File(Tools.DIR_GAME_NEW).getParent(),
"-Duser.language=" + System.getProperty("user.language"),
"-Dos.name=Linux",
"-Dos.version=Android-" + Build.VERSION.RELEASE,
"-Dpojav.path.minecraft=" + Tools.DIR_GAME_NEW,
"-Dpojav.path.private.account=" + Tools.DIR_ACCOUNT_NEW,
"-Dorg.lwjgl.opengl.libname=" + renderLib,
//LWJGL 3 DEBUG FLAGS
//"-Dorg.lwjgl.util.Debug=true",
//"-Dorg.lwjgl.util.DebugFunctions=true",
//"-Dorg.lwjgl.util.DebugLoader=true",
// GLFW Stub width height
"-Dglfwstub.windowWidth=" + CallbackBridge.windowWidth,
"-Dglfwstub.windowHeight=" + CallbackBridge.windowHeight,
"-Dglfwstub.initEgl=false",
"-Dnet.minecraft.clientmodname=" + Tools.APP_NAME,
"-Dfml.earlyprogresswindow=false" //Forge 1.14+ workaround
};
for (String userArgument : userArguments) {
for(int i=0; i < overridableArguments.length; ++i){
String overridableArgument = overridableArguments[i];
//Only java properties are considered overridable for now
if(userArgument.startsWith("-D") && userArgument.startsWith(overridableArgument.substring(0, overridableArgument.indexOf("=")))){
overridableArguments[i] = ""; //Remove the argument since it is overridden
break;
}
}
}
//Add all the arguments
userArguments.addAll(Arrays.asList(overridableArguments));
return userArguments;
}
/**
* Parse and separate java arguments in a user friendly fashion
* It supports multi line and absence of spaces between arguments
* The function also supports auto-removal of improper arguments, although it may miss some.
*
* @param args The un-parsed argument list.
* @return Parsed args as an ArrayList
*/
public static ArrayList<String> parseJavaArguments(String args){
ArrayList<String> parsedArguments = new ArrayList<>(0);
args = args.trim().replace(" ", "");
//For each prefixes, we separate args.
for(String prefix : new String[]{"-XX:-","-XX:+", "-XX:","-"}){
while (true){
int start = args.indexOf(prefix);
if(start == -1) break;
//Get the end of the current argument
int end = args.indexOf("-", start + prefix.length());
if(end == -1) end = args.length();
//Extract it
String parsedSubString = args.substring(start, end);
args = args.replace(parsedSubString, "");
//Check if two args aren't bundled together by mistake
if(parsedSubString.indexOf('=') == parsedSubString.lastIndexOf('='))
parsedArguments.add(parsedSubString);
else Log.w("JAVA ARGS PARSER", "Removed improper arguments: " + parsedSubString);
}
}
return parsedArguments;
}
/**
* Open the render library in accordance to the settings.
* It will fallback if it fails to load the library.
* @return The name of the loaded library
*/
public static String loadGraphicsLibrary(){
String renderLibrary;
switch (LOCAL_RENDERER){
case "opengles2": renderLibrary = "libgl4es_114.so"; break;
case "opengles2_5": renderLibrary = "libgl4es_115.so"; break;
case "vulkan_zink": renderLibrary = "libOSMesa_8.so"; break;
case "opengles3_vgpu" : renderLibrary = "libvgpu.so"; break;
default:
Log.w("RENDER_LIBRARY", "No renderer selected, defaulting to opengles2");
renderLibrary = "libgl4es_114.so";
break;
}
if (!dlopen(renderLibrary) && !dlopen(findInLdLibPath(renderLibrary))) {
Log.e("RENDER_LIBRARY","Failed to load renderer " + renderLibrary + ". Falling back to GL4ES 1.1.4");
LOCAL_RENDERER = "opengles2";
renderLibrary = "libgl4es_114.so";
dlopen(nativeLibDir + "/libgl4es_114.so");
}
return renderLibrary;
}
/**
* Remove the argument from the list, if it exists
* If the argument exists multiple times, they will all be removed.
* @param argList The argument list to purge
* @param argStart The argument to purge from the list.
*/
private static void purgeArg(List<String> argList, String argStart) {
for(int i = 0; i < argList.size(); i++) {
final String arg = argList.get(i);

View File

@ -16,7 +16,7 @@ public class LocaleUtils {
public static Context setLocale(Context context) {
if (LauncherPreferences.DEFAULT_PREF == null) {
LauncherPreferences.DEFAULT_PREF = PreferenceManager.getDefaultSharedPreferences(context);
LauncherPreferences.loadPreferences();
LauncherPreferences.loadPreferences(context);
}
Locale locale;

View File

@ -11,12 +11,14 @@
android:layout_height="wrap_content"
android:text="@string/app_short_name"
android:textAppearance="?android:attr/textAppearanceLarge"
android:fontFamily="@font/noto_sans_bold"
android:textSize="40sp"/>
<TextView
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:text="@string/app_motd"
android:fontFamily="@font/noto_sans_bold"
android:id="@+id/startscreen_text"/>
<ProgressBar

View File

@ -31,13 +31,6 @@
android:key="disableGestures"
android:summary="@string/mcl_disable_gestures_subtitle"
android:title="@string/mcl_disable_gestures" />
<androidx.preference.SwitchPreferenceCompat
android:defaultValue="false"
android:key="freeform"
android:summary="@string/mcl_setting_subtitle_freeform"
android:title="@string/mcl_setting_title_freeform"
app2:icon="@drawable/freeform_opt" />
<androidx.preference.SwitchPreferenceCompat
android:defaultValue="false"
@ -53,7 +46,7 @@
app2:showSeekBarValue="true"
app2:selectable="false"/>
<androidx.preference.SwitchPreferenceCompat
android:defaultValue="true"
android:defaultValue="false"
android:key="ignoreNotch"
android:summary="@string/mcl_setting_subtitle_ignore_notch"
android:title="@string/mcl_setting_title_ignore_notch"