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.graphics.*;
import android.util.*; import android.util.*;
import androidx.core.content.res.ResourcesCompat;
import net.kdt.pojavlaunch.R;
public class MineButton extends androidx.appcompat.widget.AppCompatButton public class MineButton extends androidx.appcompat.widget.AppCompatButton
{ {
@ -17,7 +21,7 @@ public class MineButton extends androidx.appcompat.widget.AppCompatButton
} }
public void init() { 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; package net.kdt.pojavlaunch;
import static net.kdt.pojavlaunch.Architecture.ARCH_X86;
import android.app.*; import android.app.*;
import android.content.*; import android.content.*;
import android.content.pm.PackageManager; import android.content.pm.PackageManager;
@ -57,9 +59,9 @@ public class BaseMainActivity extends LoggableActivity {
private static boolean triggeredLeftMouseButton = false; private static boolean triggeredLeftMouseButton = false;
private final Handler theHandler = new Handler() { private final Handler theHandler = new Handler() {
public void handleMessage(Message msg) { public void handleMessage(Message msg) {
if (!LauncherPreferences.PREF_DISABLE_GESTURES) {
switch (msg.what) { switch (msg.what) {
case MSG_LEFT_MOUSE_BUTTON_CHECK: { case MSG_LEFT_MOUSE_BUTTON_CHECK:
if(LauncherPreferences.PREF_DISABLE_GESTURES) break;
int x = CallbackBridge.mouseX; int x = CallbackBridge.mouseX;
int y = CallbackBridge.mouseY; int y = CallbackBridge.mouseY;
if (CallbackBridge.isGrabbing() && if (CallbackBridge.isGrabbing() &&
@ -68,11 +70,11 @@ public class BaseMainActivity extends LoggableActivity {
triggeredLeftMouseButton = true; triggeredLeftMouseButton = true;
sendMouseButton(LWJGLGLFWKeycode.GLFW_MOUSE_BUTTON_LEFT, true); sendMouseButton(LWJGLGLFWKeycode.GLFW_MOUSE_BUTTON_LEFT, true);
} }
} break; break;
case MSG_DROP_ITEM_BUTTON_CHECK: { case MSG_DROP_ITEM_BUTTON_CHECK:
sendKeyPress(LWJGLGLFWKeycode.GLFW_KEY_Q, 0, true); sendKeyPress(LWJGLGLFWKeycode.GLFW_KEY_Q, 0, true);
} break; break;
}
} }
} }
}; };
@ -313,7 +315,7 @@ public class BaseMainActivity extends LoggableActivity {
}); });
minecraftGLView.setFocusable(true);
glTouchListener = new OnTouchListener(){ glTouchListener = new OnTouchListener(){
private boolean isTouchInHotbar = false; private boolean isTouchInHotbar = false;
/* /*
@ -323,7 +325,7 @@ public class BaseMainActivity extends LoggableActivity {
private boolean shouldBeDown = false; private boolean shouldBeDown = false;
/* /*
* When the android system has fingers really near to each other, it tends to * 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. * This variable is here to mitigate the issue.
*/ */
private int lastPointerCount = 0; 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 @Override
public boolean dispatchKeyEvent(KeyEvent event) { public boolean dispatchKeyEvent(KeyEvent event) {
/* /*
@ -763,7 +759,7 @@ public class BaseMainActivity extends LoggableActivity {
} }
private void checkVulkanZinkIsSupported() { private void checkVulkanZinkIsSupported() {
if (Tools.CURRENT_ARCHITECTURE.equals("x86") if (Tools.DEVICE_ARCHITECTURE == ARCH_X86
|| Build.VERSION.SDK_INT < 25 || Build.VERSION.SDK_INT < 25
|| !getPackageManager().hasSystemFeature(PackageManager.FEATURE_VULKAN_HARDWARE_LEVEL) || !getPackageManager().hasSystemFeature(PackageManager.FEATURE_VULKAN_HARDWARE_LEVEL)
|| !getPackageManager().hasSystemFeature(PackageManager.FEATURE_VULKAN_HARDWARE_VERSION)) { || !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) { protected void setRightOverride(boolean val) {
this.rightOverride = 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) { public static void sendKeyPress(int keyCode, char keyChar, int scancode, int modifiers, boolean status) {
CallbackBridge.sendKeycode(keyCode, keyChar, scancode, modifiers, 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) { public static void sendKeyPress(int keyCode) {
sendKeyPress(keyCode, CallbackBridge.getCurrentMods(), true); 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){ for(int keycode : button.getProperties().keycodes){
switch (keycode) { switch (keycode) {
case ControlData.SPECIALBTN_KEYBOARD: case ControlData.SPECIALBTN_KEYBOARD:
switchKeyboardState(); touchCharInput.switchKeyboardState();
break; break;
case ControlData.SPECIALBTN_TOGGLECTRL: case ControlData.SPECIALBTN_TOGGLECTRL:
@ -194,7 +194,7 @@ public class MainActivity extends BaseMainActivity {
if (requestCode == 1 && resultCode == Activity.RESULT_OK) { if (requestCode == 1 && resultCode == Activity.RESULT_OK) {
// Reload PREF_DEFAULTCTRL_PATH // Reload PREF_DEFAULTCTRL_PATH
LauncherPreferences.loadPreferences(); LauncherPreferences.loadPreferences(getApplicationContext());
try { try {
mControlLayout.loadLayout(LauncherPreferences.PREF_DEFAULTCTRL_PATH); mControlLayout.loadLayout(LauncherPreferences.PREF_DEFAULTCTRL_PATH);
} catch (IOException e) { } catch (IOException e) {

View File

@ -12,7 +12,8 @@ public class MinecraftGLView extends TextureView
public MinecraftGLView(Context context, AttributeSet attributeSet) { public MinecraftGLView(Context context, AttributeSet attributeSet) {
super(context, 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.content.res.*;
import android.os.*; import android.os.*;
import androidx.core.app.*; import androidx.core.app.*;
import androidx.preference.*;
import android.util.*; import android.util.*;
import java.io.*; import java.io.*;
import java.text.*; import java.text.*;
@ -60,23 +60,17 @@ public class PojavApplication extends Application
Tools.DIR_ACCOUNT_NEW = Tools.DIR_DATA + "/accounts"; Tools.DIR_ACCOUNT_NEW = Tools.DIR_DATA + "/accounts";
// Tools.FILE_ACCOUNT_JSON = getFilesDir().getAbsolutePath() + "/account_profiles.json"; // Tools.FILE_ACCOUNT_JSON = getFilesDir().getAbsolutePath() + "/account_profiles.json";
File nativeLibDir = new File(getApplicationInfo().nativeLibraryDir);
Tools.CURRENT_ARCHITECTURE = nativeLibDir.getName(); Tools.DEVICE_ARCHITECTURE = Architecture.getDeviceArchitecture();
switch (Tools.CURRENT_ARCHITECTURE) { //Force x86 lib directory for Asus x86 based zenfones
case "arm": Tools.CURRENT_ARCHITECTURE = "arm/aarch32"; break; if(Architecture.isx86Device() && Architecture.is32BitsDevice()){
case "arm64": Tools.CURRENT_ARCHITECTURE = "arm64/aarch64"; break; String originalJNIDirectory = getApplicationInfo().nativeLibraryDir;
case "x86": Tools.CURRENT_ARCHITECTURE = "x86/i386"; break; getApplicationInfo().nativeLibraryDir = originalJNIDirectory.substring(0,
case "x86_64": Tools.CURRENT_ARCHITECTURE = "x86_64/amd64"; break; originalJNIDirectory.lastIndexOf("/"))
.concat("/x86");
} }
// 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);
} catch (Throwable th) { } catch (Throwable th) {
Intent ferrorIntent = new Intent(this, FatalErrorActivity.class); Intent ferrorIntent = new Intent(this, FatalErrorActivity.class);
ferrorIntent.putExtra("throwable", th); ferrorIntent.putExtra("throwable", th);

View File

@ -1,5 +1,7 @@
package net.kdt.pojavlaunch; package net.kdt.pojavlaunch;
import static net.kdt.pojavlaunch.Architecture.archAsString;
import android.Manifest; import android.Manifest;
import android.app.Activity; import android.app.Activity;
import android.app.Dialog; import android.app.Dialog;
@ -110,7 +112,7 @@ public class PojavLoginActivity extends BaseActivity
LinearLayout startScr = new LinearLayout(PojavLoginActivity.this); LinearLayout startScr = new LinearLayout(PojavLoginActivity.this);
LayoutInflater.from(PojavLoginActivity.this).inflate(R.layout.start_screen,startScr); LayoutInflater.from(PojavLoginActivity.this).inflate(R.layout.start_screen,startScr);
PojavLoginActivity.this.setContentView(startScr); PojavLoginActivity.this.setContentView(startScr);
FontChanger.changeFonts(startScr);
progress = (ProgressBar) findViewById(R.id.startscreenProgress); progress = (ProgressBar) findViewById(R.id.startscreenProgress);
if(isStarting) progress.setVisibility(View.VISIBLE); if(isStarting) progress.setVisibility(View.VISIBLE);
startupTextView = (TextView) findViewById(R.id.startscreen_text); startupTextView = (TextView) findViewById(R.id.startscreen_text);
@ -344,7 +346,7 @@ public class PojavLoginActivity extends BaseActivity
mLockSelectJRE.wait(); mLockSelectJRE.wait();
} }
} }
LauncherPreferences.loadPreferences(); LauncherPreferences.loadPreferences(getApplicationContext());
} }
catch(Throwable e){ catch(Throwable e){
Tools.showError(this, e); Tools.showError(this, e);
@ -387,7 +389,7 @@ public class PojavLoginActivity extends BaseActivity
if(rt_version == null) return false; 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 if(!rt_version.equals(current_rt_version)) { //If we already have an integrated one installed, check if it's up-to-date
try { 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));})); (resid, vararg) -> runOnUiThread(()->{if(startupTextView!=null)startupTextView.setText(getString(resid,vararg));}));
MultiRTUtils.postPrepare(PojavLoginActivity.this,"Internal"); MultiRTUtils.postPrepare(PojavLoginActivity.this,"Internal");
return true; 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 DIR_DATA = "/data/data/" + BuildConfig.APPLICATION_ID;
public static String MULTIRT_HOME = DIR_DATA+"/runtimes"; public static String MULTIRT_HOME = DIR_DATA+"/runtimes";
public static String LOCAL_RENDERER = null; public static String LOCAL_RENDERER = null;
public static String CURRENT_ARCHITECTURE; public static int DEVICE_ARCHITECTURE;
// New since 3.3.1 // New since 3.3.1
public static String DIR_ACCOUNT_NEW; public static String DIR_ACCOUNT_NEW;
@ -156,64 +156,6 @@ public final class Tools {
javaArgList.add(cacioClasspath.toString()); 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) { public static String[] getMinecraftArgs(MinecraftAccount profile, JMinecraftVersionList.Version versionInfo, String strGameDir) {
String username = profile.username; String username = profile.username;
String versionName = versionInfo.id; String versionName = versionInfo.id;
@ -226,7 +168,7 @@ public final class Tools {
File gameDir = new File(strGameDir); File gameDir = new File(strGameDir);
gameDir.mkdirs(); 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_access_token", profile.accessToken);
varArgMap.put("auth_player_name", username); varArgMap.put("auth_player_name", username);
varArgMap.put("auth_uuid", profile.profileId); varArgMap.put("auth_uuid", profile.profileId);
@ -873,4 +815,17 @@ public final class Tools {
} }
} }
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 //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(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); mapTable.put(v, null);
return true; return true;
} }
@ -275,9 +275,8 @@ public class ControlLayout extends FrameLayout
} }
} }
//Release the last key //Release last keys
ev.setAction(MotionEvent.ACTION_POINTER_UP); if (lastControlButton != null) lastControlButton.sendKeyPresses(ev,false);
if (lastControlButton != null) lastControlButton.onTouchEvent(ev);
mapTable.put(v, null); mapTable.put(v, null);
//Look for another SWIPEABLE button //Look for another SWIPEABLE button
@ -289,8 +288,7 @@ public class ControlLayout extends FrameLayout
//Press the new key //Press the new key
if(!button.equals(lastControlButton)){ if(!button.equals(lastControlButton)){
ev.setAction(MotionEvent.ACTION_POINTER_DOWN); button.sendKeyPresses(ev,true);
button.onTouchEvent(ev);
mapTable.put(v, button); mapTable.put(v, button);
} }

View File

@ -1,8 +1,13 @@
package net.kdt.pojavlaunch.customcontrols; package net.kdt.pojavlaunch.customcontrols;
import static android.content.Context.INPUT_METHOD_SERVICE;
import android.content.Context; import android.content.Context;
import android.content.res.Configuration;
import android.util.AttributeSet; import android.util.AttributeSet;
import android.view.KeyEvent; import android.view.KeyEvent;
import android.view.inputmethod.InputMethodManager;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
@ -87,6 +92,27 @@ public class TouchCharInput extends androidx.appcompat.widget.AppCompatEditText
super.setSelection(5); 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 * Clear the EditText from any leftover inputs
* It does not affect the in-game input * It does not affect the in-game input

View File

@ -44,9 +44,7 @@ public class CustomSeekBarPreference extends SeekBarPreference {
public void setMin(int min) { 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 //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); super.setMin(min);
if (min != mMin) { if (min != mMin) mMin = min;
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) { public void setSuffix(String suffix) {
this.suffix = 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; package net.kdt.pojavlaunch.prefs;
import android.graphics.Color;
import android.os.*; import android.os.*;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.preference.*; import androidx.preference.*;
import net.kdt.pojavlaunch.R; import net.kdt.pojavlaunch.R;
import net.kdt.pojavlaunch.Tools; import net.kdt.pojavlaunch.fragments.LauncherFragment;
import android.content.*; 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; import static net.kdt.pojavlaunch.prefs.LauncherPreferences.PREF_NOTCH_SIZE;
public class LauncherPreferenceFragment extends PreferenceFragmentCompat implements SharedPreferences.OnSharedPreferenceChangeListener 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 @Override
public void onCreatePreferences(Bundle b, String str) { public void onCreatePreferences(Bundle b, String str) {
addPreferencesFromResource(R.xml.pref_main); 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. //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); findPreference("ignoreNotch").setVisible(Build.VERSION.SDK_INT >= Build.VERSION_CODES.P && PREF_NOTCH_SIZE != 0);
CustomSeekBarPreference seek2 = (CustomSeekBarPreference) findPreference("timeLongPressTrigger"); CustomSeekBarPreference seek2 = findPreference("timeLongPressTrigger");
seek2.setMin(100); seek2.setRange(100, 1000);
seek2.setMax(1000);
seek2.setValue(LauncherPreferences.PREF_LONGPRESS_TRIGGER); seek2.setValue(LauncherPreferences.PREF_LONGPRESS_TRIGGER);
seek2.setSuffix(" ms"); seek2.setSuffix(" ms");
CustomSeekBarPreference seek3 = (CustomSeekBarPreference) findPreference("buttonscale"); CustomSeekBarPreference seek3 = findPreference("buttonscale");
seek3.setMin(80); seek3.setRange(80, 250);
seek3.setMax(250);
seek3.setValue((int) LauncherPreferences.PREF_BUTTONSIZE); seek3.setValue((int) LauncherPreferences.PREF_BUTTONSIZE);
seek3.setSuffix(" %"); seek3.setSuffix(" %");
CustomSeekBarPreference seek4 = (CustomSeekBarPreference) findPreference("mousescale"); CustomSeekBarPreference seek4 = findPreference("mousescale");
seek4.setMin(25); seek4.setRange(25, 300);
seek4.setMax(300);
seek4.setValue((int) LauncherPreferences.PREF_MOUSESCALE); seek4.setValue((int) LauncherPreferences.PREF_MOUSESCALE);
seek4.setSuffix(" %"); seek4.setSuffix(" %");
CustomSeekBarPreference seek5 = (CustomSeekBarPreference) findPreference("resolutionRatio"); CustomSeekBarPreference seek5 = findPreference("resolutionRatio");
seek5.setMin(25); seek5.setMin(25);
seek5.setSuffix(" %"); seek5.setSuffix(" %");
CustomSeekBarPreference seek6 = (CustomSeekBarPreference) findPreference("mousespeed"); CustomSeekBarPreference seek6 = findPreference("mousespeed");
seek6.setMin(25); seek6.setRange(25, 300);
seek6.setMax(300);
seek6.setValue((int)(LauncherPreferences.PREF_MOUSESPEED*100f)); seek6.setValue((int)(LauncherPreferences.PREF_MOUSESPEED*100f));
seek6.setSuffix(" %"); 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); 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.setValue(LauncherPreferences.PREF_RAM_ALLOCATION);
seek7.setSuffix(" MB"); seek7.setSuffix(" MB");
@ -84,6 +99,6 @@ public class LauncherPreferenceFragment extends PreferenceFragmentCompat impleme
@Override @Override
public void onSharedPreferenceChanged(SharedPreferences p, String s) { 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 android.content.*;
import net.kdt.pojavlaunch.*; import net.kdt.pojavlaunch.*;
import net.kdt.pojavlaunch.multirt.MultiRTUtils; import net.kdt.pojavlaunch.multirt.MultiRTUtils;
import net.kdt.pojavlaunch.utils.JREUtils;
public class LauncherPreferences public class LauncherPreferences
{ {
@ -13,45 +14,39 @@ public class LauncherPreferences
public static boolean PREF_VERTYPE_SNAPSHOT = false; public static boolean PREF_VERTYPE_SNAPSHOT = false;
public static boolean PREF_VERTYPE_OLDALPHA = false; public static boolean PREF_VERTYPE_OLDALPHA = false;
public static boolean PREF_VERTYPE_OLDBETA = 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_HIDE_SIDEBAR = false;
public static boolean PREF_IGNORE_NOTCH = false; public static boolean PREF_IGNORE_NOTCH = false;
public static int PREF_NOTCH_SIZE = 0; public static int PREF_NOTCH_SIZE = 0;
public static float PREF_BUTTONSIZE = 100f; public static float PREF_BUTTONSIZE = 100f;
public static float PREF_MOUSESCALE = 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_DEFAULTCTRL_PATH = Tools.CTRLDEF_FILE;
public static String PREF_CUSTOM_JAVA_ARGS; 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_LANGUAGE = "default";
public static String PREF_VERSION_REPOS = "https://launchermeta.mojang.com/mc/game/version_manifest_v2.json"; 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_CHECK_LIBRARY_SHA = true;
public static boolean PREF_DISABLE_GESTURES = false; public static boolean PREF_DISABLE_GESTURES = false;
public static float PREF_MOUSESPEED = 1f; 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 String PREF_DEFAULT_RUNTIME;
public static void loadPreferences() { public static void loadPreferences(Context ctx) {
PREF_RENDERER = DEFAULT_PREF.getString("renderer", "opengles2"); PREF_RENDERER = DEFAULT_PREF.getString("renderer", "opengles2");
PREF_BUTTONSIZE = DEFAULT_PREF.getInt("buttonscale", 100); PREF_BUTTONSIZE = DEFAULT_PREF.getInt("buttonscale", 100);
PREF_MOUSESCALE = DEFAULT_PREF.getInt("mousescale", 100); PREF_MOUSESCALE = DEFAULT_PREF.getInt("mousescale", 100);
PREF_MOUSESPEED = ((float)DEFAULT_PREF.getInt("mousespeed",100))/100f; 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_HIDE_SIDEBAR = DEFAULT_PREF.getBoolean("hideSidebar", false);
PREF_IGNORE_NOTCH = DEFAULT_PREF.getBoolean("ignoreNotch", false); PREF_IGNORE_NOTCH = DEFAULT_PREF.getBoolean("ignoreNotch", false);
PREF_VERTYPE_RELEASE = DEFAULT_PREF.getBoolean("vertype_release", true); PREF_VERTYPE_RELEASE = DEFAULT_PREF.getBoolean("vertype_release", true);
PREF_VERTYPE_SNAPSHOT = DEFAULT_PREF.getBoolean("vertype_snapshot", false); PREF_VERTYPE_SNAPSHOT = DEFAULT_PREF.getBoolean("vertype_snapshot", false);
PREF_VERTYPE_OLDALPHA = DEFAULT_PREF.getBoolean("vertype_oldalpha", false); PREF_VERTYPE_OLDALPHA = DEFAULT_PREF.getBoolean("vertype_oldalpha", false);
PREF_VERTYPE_OLDBETA = DEFAULT_PREF.getBoolean("vertype_oldbeta", 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_DEFAULTCTRL_PATH = DEFAULT_PREF.getString("defaultCtrl", Tools.CTRLDEF_FILE);
PREF_LANGUAGE = DEFAULT_PREF.getString("language", "default"); PREF_LANGUAGE = DEFAULT_PREF.getString("language", "default");
PREF_CHECK_LIBRARY_SHA = DEFAULT_PREF.getBoolean("checkLibraries",true); PREF_CHECK_LIBRARY_SHA = DEFAULT_PREF.getBoolean("checkLibraries",true);
PREF_DISABLE_GESTURES = DEFAULT_PREF.getBoolean("disableGestures",false); PREF_DISABLE_GESTURES = DEFAULT_PREF.getBoolean("disableGestures",false);
PREF_RAM_ALLOCATION = DEFAULT_PREF.getInt("allocation",300); PREF_RAM_ALLOCATION = DEFAULT_PREF.getInt("allocation", findBestRAMAllocation(ctx));
// Get double of max Android heap to set default heap size
int androidHeap = (int) (Runtime.getRuntime().maxMemory() / 1024l / 512l);
int doubleAndroidHeap = androidHeap * 2;
PREF_CUSTOM_JAVA_ARGS = DEFAULT_PREF.getString("javaArgs", ""); PREF_CUSTOM_JAVA_ARGS = DEFAULT_PREF.getString("javaArgs", "");
/* /*
if (PREF_CUSTOM_JAVA_ARGS.isEmpty()) { if (PREF_CUSTOM_JAVA_ARGS.isEmpty()) {
@ -85,7 +80,7 @@ public class LauncherPreferences
PREF_RENDERER = "opengles" + PREF_RENDERER; PREF_RENDERER = "opengles" + PREF_RENDERER;
} }
String argLwjglLibname = "-Dorg.lwjgl.opengl.libname="; 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)) { if (arg.startsWith(argLwjglLibname)) {
// purge arg // purge arg
DEFAULT_PREF.edit().putString("javaArgs", DEFAULT_PREF.edit().putString("javaArgs",
@ -103,4 +98,24 @@ public class LauncherPreferences
LauncherPreferences.DEFAULT_PREF.edit().putString("defaultRuntime",LauncherPreferences.PREF_DEFAULT_RUNTIME).apply(); 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(""); mActivity.mCrashView.setLastCrash("");
try { try {
/*
List<String> jvmArgs = ManagementFactory.getRuntimeMXBean().getInputArguments();
jvmArgs.add("-Xms128M");
jvmArgs.add("-Xmx1G");
*/
Intent mainIntent = new Intent(mActivity, MainActivity.class /* MainActivity.class */); Intent mainIntent = new Intent(mActivity, MainActivity.class /* MainActivity.class */);
// mainIntent.addFlags(Intent.FLAG_ACTIVITY_LAUNCH_ADJACENT); // mainIntent.addFlags(Intent.FLAG_ACTIVITY_LAUNCH_ADJACENT);
mainIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_DOCUMENT); mainIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_DOCUMENT);
mainIntent.addFlags(Intent.FLAG_ACTIVITY_MULTIPLE_TASK); 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) { catch (Throwable e) {
Tools.showError(mActivity, e); Tools.showError(mActivity, e);
} }
/*
FloatingIntent maini = new FloatingIntent(PojavLauncherActivity.this, MainActivity.class);
maini.startFloatingActivity();
*/
} }
mActivity.mTask = null; mActivity.mTask = null;

View File

@ -1,16 +1,17 @@
package net.kdt.pojavlaunch.utils; 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.app.*;
import android.content.*; import android.content.*;
import android.opengl.EGL14; import android.os.Build;
import android.opengl.EGLExt;
import android.opengl.GLES10;
import android.system.*; import android.system.*;
import android.util.*; import android.util.*;
import android.widget.Toast; import android.widget.Toast;
import androidx.annotation.Nullable;
import com.oracle.dalvik.*; import com.oracle.dalvik.*;
import java.io.*; import java.io.*;
import java.util.*; import java.util.*;
@ -23,27 +24,24 @@ import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.egl.EGLContext; import javax.microedition.khronos.egl.EGLContext;
import javax.microedition.khronos.egl.EGLDisplay; import javax.microedition.khronos.egl.EGLDisplay;
public class JREUtils public class JREUtils {
{
private JREUtils() {} private JREUtils() {}
public static String JRE_ARCHITECTURE;
public static String LD_LIBRARY_PATH; public static String LD_LIBRARY_PATH;
private static String nativeLibDir; private static String nativeLibDir;
public static void checkJavaArchitecture(LoggableActivity act, String jreArch) throws Exception { /**
String[] argName = Tools.CURRENT_ARCHITECTURE.split("/"); * Checks if the java architecture is correct for the device architecture.
act.appendlnToLog("Architecture: " + Tools.CURRENT_ARCHITECTURE); * @param act An Activity with logging capabilities
if (!(jreArch.contains(argName[0]) || jreArch.contains(argName[1]))) { * @param jreArch The java architecture to compare as a String.
// x86 check workaround */
if (jreArch.startsWith("i") && jreArch.endsWith("86") && Tools.CURRENT_ARCHITECTURE.contains("x86") && !Tools.CURRENT_ARCHITECTURE.contains("64")) { public static void checkJavaArchitecture(LoggableActivity act, String jreArch) {
return; 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) { public static String findInLdLibPath(String libName) {
@ -160,12 +158,10 @@ public class JREUtils
} }
public static void relocateLibPath(final Context ctx) throws IOException { public static void relocateLibPath(final Context ctx) throws IOException {
if (JRE_ARCHITECTURE == null) { String JRE_ARCHITECTURE = readJREReleaseProperties().get("OS_ARCH");
JRE_ARCHITECTURE = readJREReleaseProperties().get("OS_ARCH"); if (Architecture.archAsInt(JRE_ARCHITECTURE) == ARCH_X86){
if (JRE_ARCHITECTURE.startsWith("i") && JRE_ARCHITECTURE.endsWith("86") && Tools.CURRENT_ARCHITECTURE.contains("x86") && !Tools.CURRENT_ARCHITECTURE.contains("64")) {
JRE_ARCHITECTURE = "i386/i486/i586"; JRE_ARCHITECTURE = "i386/i486/i586";
} }
}
nativeLibDir = ctx.getApplicationInfo().nativeLibraryDir; 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(); StringBuilder ldLibraryPath = new StringBuilder();
ldLibraryPath.append( ldLibraryPath.append(
Tools.DIR_HOME_JRE + "/" + Tools.DIRNAME_HOME_JRE + "/jli:" + 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_VENDOR", "Android");
envMap.put("REGAL_GL_RENDERER", "Regal"); envMap.put("REGAL_GL_RENDERER", "Regal");
envMap.put("REGAL_GL_VERSION", "4.5"); envMap.put("REGAL_GL_VERSION", "4.5");
if(Tools.LOCAL_RENDERER != null) { if(LOCAL_RENDERER != null) {
envMap.put("POJAV_RENDERER", Tools.LOCAL_RENDERER); envMap.put("POJAV_RENDERER", LOCAL_RENDERER);
} }
envMap.put("AWTSTUB_WIDTH", Integer.toString(CallbackBridge.windowWidth > 0 ? CallbackBridge.windowWidth : CallbackBridge.physicalWidth)); 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)); envMap.put("AWTSTUB_HEIGHT", Integer.toString(CallbackBridge.windowHeight > 0 ? CallbackBridge.windowHeight : CallbackBridge.physicalHeight));
@ -232,15 +228,15 @@ public class JREUtils
} }
reader.close(); reader.close();
} }
if(!envMap.containsKey("LIBGL_ES") && Tools.LOCAL_RENDERER != null) { if(!envMap.containsKey("LIBGL_ES") && LOCAL_RENDERER != null) {
int glesMajor = getDetectedVersion(); int glesMajor = getDetectedVersion();
Log.i("glesDetect","GLES version detected: "+glesMajor); Log.i("glesDetect","GLES version detected: "+glesMajor);
if (glesMajor < 3) { if (glesMajor < 3) {
//fallback to 2 since it's the minimum for the entire app //fallback to 2 since it's the minimum for the entire app
envMap.put("LIBGL_ES","2"); envMap.put("LIBGL_ES","2");
} else if (Tools.LOCAL_RENDERER.startsWith("opengles")) { } else if (LOCAL_RENDERER.startsWith("opengles")) {
envMap.put("LIBGL_ES", Tools.LOCAL_RENDERER.replace("opengles", "").replace("_5", "")); envMap.put("LIBGL_ES", LOCAL_RENDERER.replace("opengles", "").replace("_5", ""));
} else { } else {
// TODO if can: other backends such as Vulkan. // TODO if can: other backends such as Vulkan.
// Sure, they should provide GLES 3 support. // Sure, they should provide GLES 3 support.
@ -261,55 +257,25 @@ public class JREUtils
// return ldLibraryPath; // 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); JREUtils.relocateLibPath(ctx);
// ctx.appendlnToLog("LD_LIBRARY_PATH = " + JREUtils.LD_LIBRARY_PATH); final String graphicsLib = loadGraphicsLibrary();
final String graphicsLib; List<String> userArgs = getJavaArgs(ctx,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;
}
List<String> javaArgList = new ArrayList<String>(); //Remove arguments that can interfere with the good working of the launcher
javaArgList.add(Tools.DIR_HOME_JRE + "/bin/java"); purgeArg(userArgs,"-Xms");
Tools.getJavaArgs(ctx, javaArgList,graphicsLib); purgeArg(userArgs,"-Xmx");
purgeArg(javaArgList,"-Xms"); purgeArg(userArgs,"-d32");
purgeArg(javaArgList,"-Xmx"); purgeArg(userArgs,"-d64");
/*if(Tools.CURRENT_ARCHITECTURE.contains("32") && ((mi.availMem / 1048576L)-50) > 300) {
javaArgList.add("-Xms300M"); //Add automatically generated args
javaArgList.add("-Xmx300M"); userArgs.add("-Xms" + LauncherPreferences.PREF_RAM_ALLOCATION + "M");
}else {*/ userArgs.add("-Xmx" + LauncherPreferences.PREF_RAM_ALLOCATION + "M");
javaArgList.add("-Xms" + LauncherPreferences.PREF_RAM_ALLOCATION + "M");
javaArgList.add("-Xmx" + LauncherPreferences.PREF_RAM_ALLOCATION + "M"); userArgs.addAll(JVMArgs);
//}
ctx.runOnUiThread(new Runnable() { ctx.runOnUiThread(() -> Toast.makeText(ctx, ctx.getString(R.string.autoram_info_msg,LauncherPreferences.PREF_RAM_ALLOCATION), Toast.LENGTH_SHORT).show());
public void run() { System.out.println(JVMArgs);
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);
// For debugging only! // For debugging only!
/* /*
@ -325,27 +291,135 @@ public class JREUtils
setupExitTrap(ctx.getApplication()); setupExitTrap(ctx.getApplication());
chdir(Tools.DIR_GAME_NEW); 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); ctx.appendlnToLog("Java Exit code: " + exitCode);
if (exitCode != 0) { if (exitCode != 0) {
ctx.runOnUiThread(new Runnable(){ ctx.runOnUiThread(() -> {
@Override
public void run() {
AlertDialog.Builder dialog = new AlertDialog.Builder(ctx); AlertDialog.Builder dialog = new AlertDialog.Builder(ctx);
dialog.setMessage(ctx.getString(R.string.mcn_exit_title, exitCode)); dialog.setMessage(ctx.getString(R.string.mcn_exit_title, exitCode));
dialog.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener(){
@Override dialog.setPositiveButton(android.R.string.ok, (p1, p2) -> BaseMainActivity.fullyExit());
public void onClick(DialogInterface p1, int p2){
BaseMainActivity.fullyExit();
}
});
dialog.show(); dialog.show();
}
}); });
} }
return exitCode; 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) { private static void purgeArg(List<String> argList, String argStart) {
for(int i = 0; i < argList.size(); i++) { for(int i = 0; i < argList.size(); i++) {
final String arg = argList.get(i); final String arg = argList.get(i);

View File

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

View File

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

View File

@ -32,13 +32,6 @@
android:summary="@string/mcl_disable_gestures_subtitle" android:summary="@string/mcl_disable_gestures_subtitle"
android:title="@string/mcl_disable_gestures" /> 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 <androidx.preference.SwitchPreferenceCompat
android:defaultValue="false" android:defaultValue="false"
android:key="hideSidebar" android:key="hideSidebar"
@ -53,7 +46,7 @@
app2:showSeekBarValue="true" app2:showSeekBarValue="true"
app2:selectable="false"/> app2:selectable="false"/>
<androidx.preference.SwitchPreferenceCompat <androidx.preference.SwitchPreferenceCompat
android:defaultValue="true" android:defaultValue="false"
android:key="ignoreNotch" android:key="ignoreNotch"
android:summary="@string/mcl_setting_subtitle_ignore_notch" android:summary="@string/mcl_setting_subtitle_ignore_notch"
android:title="@string/mcl_setting_title_ignore_notch" android:title="@string/mcl_setting_title_ignore_notch"