diff --git a/app_2009scape/src/main/AndroidManifest.xml b/app_2009scape/src/main/AndroidManifest.xml index 94c3a0f88..e16935c7d 100644 --- a/app_2009scape/src/main/AndroidManifest.xml +++ b/app_2009scape/src/main/AndroidManifest.xml @@ -63,32 +63,13 @@ android:screenOrientation="sensorLandscape" android:name="net.kdt.pojavlaunch.FatalErrorActivity" android:configChanges="keyboardHidden|orientation|screenSize|keyboard|navigation"/> - - - - - - + + { switch (menuItem.getItemId()) { - case R.id.nav_forceclose: dialogForceClose(BaseMainActivity.this); + case R.id.nav_forceclose: + //dialogForceClose(BaseMainActivity.this); break; - case R.id.nav_viewlog: openLogOutput(); + case R.id.nav_viewlog: + //openLogOutput(); break; - case R.id.nav_debug: minecraftGLView.togglepointerDebugging(); + //case R.id.nav_debug: minecraftGLView.togglepointerDebugging(); + // break; + case R.id.nav_customkey: + //dialogSendCustomKey(); break; - case R.id.nav_customkey: dialogSendCustomKey(); + case R.id.nav_mousespd: + //adjustMouseSpeedLive(); break; - case R.id.nav_mousespd: adjustMouseSpeedLive(); - break; - case R.id.nav_customctrl: openCustomControls(); + case R.id.nav_customctrl: + //openCustomControls(); break; } @@ -120,22 +91,20 @@ public class BaseMainActivity extends BaseActivity { touchpad = findViewById(R.id.main_touchpad); + //this.minecraftGLView = findViewById(R.id.main_game_render_view); + //this.drawerLayout.closeDrawers(); - this.minecraftGLView = findViewById(R.id.main_game_render_view); - this.drawerLayout.closeDrawers(); - - minecraftGLView.setSurfaceReadyListener(() -> { + //minecraftGLView.setSurfaceReadyListener(() -> { try { - runCraft(); + //runCraft(); }catch (Throwable e){ Tools.showError(getApplicationContext(), e, true); } - }); - minecraftGLView.start(); + //minecraftGLView.start(); + + } catch(Exception e){ - } catch (Throwable e) { - Tools.showError(this, e, true); } } @@ -165,34 +134,6 @@ public class BaseMainActivity extends BaseActivity { return Build.VERSION.SDK_INT >= 26; } - private void runCraft() throws Throwable { - if(Tools.LOCAL_RENDERER == null) { - Tools.LOCAL_RENDERER = LauncherPreferences.PREF_RENDERER; - } - Logger.getInstance().appendToLog("--------- beggining with launcher debug"); - Logger.getInstance().appendToLog("Info: Launcher version: " + BuildConfig.VERSION_NAME); - if (Tools.LOCAL_RENDERER.equals("vulkan_zink")) { - checkVulkanZinkIsSupported(); - } - checkLWJGL3Installed(); - - JREUtils.jreReleaseList = JREUtils.readJREReleaseProperties(); - JREUtils.checkJavaArchitecture(this, JREUtils.jreReleaseList.get("OS_ARCH")); - checkJavaArgsIsLaunchable(JREUtils.jreReleaseList.get("JAVA_VERSION")); - // appendlnToLog("Info: Custom Java arguments: \"" + LauncherPreferences.PREF_CUSTOM_JAVA_ARGS + "\""); - - Logger.getInstance().appendToLog("Info: Selected Minecraft version: " + mVersionInfo.id + - ((mVersionInfo.inheritsFrom == null || mVersionInfo.inheritsFrom.equals(mVersionInfo.id)) ? - "" : " (" + mVersionInfo.inheritsFrom + ")")); - - JREUtils.redirectAndPrintJRELog(this); - Tools.launchMinecraft(this, mProfile, mProfile.selectedVersion); - } - - private void checkJavaArgsIsLaunchable(String jreVersion) throws Throwable { - Logger.getInstance().appendToLog("Info: Custom Java arguments: \"" + LauncherPreferences.PREF_CUSTOM_JAVA_ARGS + "\""); - } - private void checkLWJGL3Installed() { File lwjgl3dir = new File(Tools.DIR_GAME_HOME, "lwjgl3"); if (!lwjgl3dir.exists() || lwjgl3dir.isFile() || lwjgl3dir.list().length == 0) { @@ -233,42 +174,8 @@ public class BaseMainActivity extends BaseActivity { return s.toString(); } - private void dialogSendCustomKey() { - AlertDialog.Builder dialog = new AlertDialog.Builder(this); - dialog.setTitle(R.string.control_customkey); - dialog.setItems(EfficientAndroidLWJGLKeycode.generateKeyName(), (dInterface, position) -> EfficientAndroidLWJGLKeycode.execKeyIndex(position)); - dialog.show(); - } - boolean isInEditor; - private void openCustomControls() { - if(ingameControlsEditorListener == null) return; - ((MainActivity)this).mControlLayout.setModifiable(true); - navDrawer.getMenu().clear(); - navDrawer.inflateMenu(R.menu.menu_customctrl); - navDrawer.setNavigationItemSelectedListener(ingameControlsEditorListener); - isInEditor = true; - } - - public void leaveCustomControls() { - if(this instanceof MainActivity) { - try { - MainActivity.mControlLayout.hideAllHandleViews(); - MainActivity.mControlLayout.loadLayout((CustomControls)null); - MainActivity.mControlLayout.setModifiable(false); - System.gc(); - MainActivity.mControlLayout.loadLayout(LauncherPreferences.DEFAULT_PREF.getString("defaultCtrl",Tools.CTRLDEF_FILE)); - } catch (IOException e) { - Tools.showError(this,e); - } - //((MainActivity) this).mControlLayout.loadLayout((CustomControls)null); - } - navDrawer.getMenu().clear(); - navDrawer.inflateMenu(R.menu.menu_runopt); - navDrawer.setNavigationItemSelectedListener(gameActionListener); - isInEditor = false; - } private void openLogOutput() { loggerView.setVisibility(View.VISIBLE); mIsResuming = false; @@ -304,20 +211,6 @@ public class BaseMainActivity extends BaseActivity { }).show(); } - @Override - public boolean dispatchKeyEvent(KeyEvent event) { - if (event.getKeyCode() == KeyEvent.KEYCODE_BACK && !touchCharInput.isEnabled()) { - if(event.getAction() != KeyEvent.ACTION_UP) return true; // We eat it anyway - sendKeyPress(LWJGLGLFWKeycode.GLFW_KEY_ESCAPE); - return true; - } - return super.dispatchKeyEvent(event); - } - - public static void switchKeyboardState() { - if(touchCharInput != null) touchCharInput.switchKeyboardState(); - } - int tmpMouseSpeed; public void adjustMouseSpeedLive() { diff --git a/app_2009scape/src/main/java/net/kdt/pojavlaunch/JavaGUILauncherActivity.java b/app_2009scape/src/main/java/net/kdt/pojavlaunch/JavaGUILauncherActivity.java index 934045972..3988065f4 100644 --- a/app_2009scape/src/main/java/net/kdt/pojavlaunch/JavaGUILauncherActivity.java +++ b/app_2009scape/src/main/java/net/kdt/pojavlaunch/JavaGUILauncherActivity.java @@ -29,7 +29,6 @@ public class JavaGUILauncherActivity extends BaseActivity implements View.OnTou String specialChars = "/*!@#$%^&*()\"{}_[+=-_]\'|\\?/<>,."; private LoggerView loggerView; private boolean mouseState = false; - private int mode = 0; private LinearLayout touchPad; private ImageView mousePointer; @@ -72,24 +71,11 @@ public class JavaGUILauncherActivity extends BaseActivity implements View.OnTou @Override public boolean onScale(ScaleGestureDetector detector) { float scaleFactor = detector.getScaleFactor(); - switch(mode){ - case 0: // Pinch to Zoom - if (scaleFactor > 1) { - //Send F4 To Zoom Out - AWTInputBridge.sendKey((char)115,115); - } else { - //116 - AWTInputBridge.sendKey((char)116,116); - } - break; - case 1: // Right click - AWTInputBridge.sendKey((char)122,122); - AWTInputBridge.sendMousePress(AWTInputEvent.BUTTON1_DOWN_MASK); - break; - - + if (scaleFactor > 1) { //Send F4 To Zoom Out + AWTInputBridge.sendKey((char)115,115); + } else { //116 F5 To Zoom In + AWTInputBridge.sendKey((char) 116, 116); } - return true; } @@ -108,13 +94,11 @@ public class JavaGUILauncherActivity extends BaseActivity implements View.OnTou @Override public boolean onDown(MotionEvent event) { - //... return super.onDown(event); } @Override public boolean onSingleTapUp(MotionEvent event) { - //... return true; } @@ -149,7 +133,7 @@ public class JavaGUILauncherActivity extends BaseActivity implements View.OnTou this.touchPad = findViewById(R.id.main_touchpad); touchPad.setFocusable(false); - touchPad.setVisibility(View.GONE); + touchPad.setVisibility(View.VISIBLE); this.mousePointer = findViewById(R.id.main_mouse_pointer); this.mousePointer.post(() -> { @@ -162,17 +146,6 @@ public class JavaGUILauncherActivity extends BaseActivity implements View.OnTou private float prevX, prevY; @Override public boolean onTouch(View v, MotionEvent event) { - mode = 1; - //longTapGestureDetector.onLongPress(event); - // MotionEvent reports input details from the touch screen - // and other input controls. In this case, you are only - // interested in events where the touch position changed. - // int index = event.getActionIndex(); - - //System.out.println("sending pos: "+prevX+","+prevY); - //sendScaledMousePosition(prevX,prevY); - //AWTInputBridge.sendMousePress(AWTInputEvent.NOBUTTON); - int action = event.getActionMasked(); float x = event.getX(); @@ -192,6 +165,9 @@ public class JavaGUILauncherActivity extends BaseActivity implements View.OnTou clearRC(); } else { switch (action) { + case MotionEvent.ACTION_POINTER_DOWN: //Second finger rightclicking + AWTInputBridge.sendKey((char)122,122); + AWTInputBridge.sendMousePress(AWTInputEvent.BUTTON1_DOWN_MASK); case MotionEvent.ACTION_UP: // 1 case MotionEvent.ACTION_CANCEL: // 3 case MotionEvent.ACTION_POINTER_UP: // 6 @@ -212,8 +188,6 @@ public class JavaGUILauncherActivity extends BaseActivity implements View.OnTou } } - scaleGestureDetector.onTouchEvent(event); - // debugText.setText(CallbackBridge.DEBUG_STRING.toString()); CallbackBridge.DEBUG_STRING.setLength(0); @@ -226,15 +200,12 @@ public class JavaGUILauncherActivity extends BaseActivity implements View.OnTou // this.textLogBehindGL = (TextView) findViewById(R.id.main_log_behind_GL); // this.textLogBehindGL.setTypeface(Typeface.MONOSPACE); - final File modFile = (File) getIntent().getExtras().getSerializable("modFile"); final String javaArgs = getIntent().getExtras().getString("javaArgs"); mTextureView = findViewById(R.id.installmod_surfaceview); mTextureView.setOnTouchListener((v, event) -> { - mode = 0; - if(scaleGestureDetector.onTouchEvent(event)){ - } + scaleGestureDetector.onTouchEvent(event); float x = event.getX(); float y = event.getY(); if (gestureDetector.onTouchEvent(event)) { @@ -242,7 +213,6 @@ public class JavaGUILauncherActivity extends BaseActivity implements View.OnTou AWTInputBridge.sendMousePress(AWTInputEvent.BUTTON1_DOWN_MASK); return true; } - switch (event.getActionMasked()) { case MotionEvent.ACTION_UP: // 1 case MotionEvent.ACTION_CANCEL: // 3 @@ -266,12 +236,6 @@ public class JavaGUILauncherActivity extends BaseActivity implements View.OnTou try { final int exit = doCustomInstall(modFile, javaArgs); Logger.getInstance().appendToLog(getString(R.string.toast_optifine_success)); - if (exit != 0) return; - runOnUiThread(() -> { - Toast.makeText(JavaGUILauncherActivity.this, R.string.toast_optifine_success, Toast.LENGTH_SHORT).show(); - MainActivity.fullyExit(); - }); - } catch (Throwable e) { Logger.getInstance().appendToLog("Install failed:"); Logger.getInstance().appendToLog(Log.getStackTraceString(e)); @@ -284,18 +248,6 @@ public class JavaGUILauncherActivity extends BaseActivity implements View.OnTou //scaleUp(mTextureView); } - private void clearRC(){ - rcState = false; - AWTInputBridge.sendKey((char)121,121); - findViewById(R.id.installmod_mouse_sec).setBackground(getResources().getDrawable( R.drawable.control_button )); - } - - private void activateRC(){ - rcState = true; - AWTInputBridge.sendKey((char)122,122); - findViewById(R.id.installmod_mouse_sec).setBackground(getResources().getDrawable( R.drawable.control_button_pressed )); - } - @Override public boolean onTouch(View v, MotionEvent e) { long time = System.currentTimeMillis(); @@ -337,10 +289,11 @@ public class JavaGUILauncherActivity extends BaseActivity implements View.OnTou @Override public boolean dispatchKeyEvent(KeyEvent event) { if(event.getAction() == KeyEvent.ACTION_DOWN){ - //Log.i("key getKeycode", String.valueOf(event.getKeyCode())); - //Log.i("key unicode", String.valueOf((char)event.getUnicodeChar())); - //Log.i("key unicode int", String.valueOf(event.getUnicodeChar())); - + /* + Log.i("key getKeycode", String.valueOf(event.getKeyCode())); + Log.i("key unicode", String.valueOf((char)event.getUnicodeChar())); + Log.i("key unicode int", String.valueOf(event.getUnicodeChar())); + */ if(event.getKeyCode() == 67){ // Backspace AWTInputBridge.sendKey((char)0x08,0x08); @@ -409,7 +362,7 @@ public class JavaGUILauncherActivity extends BaseActivity implements View.OnTou c = '\\'; break; } - System.out.println("I SEE A "+(char)event.getUnicodeChar()); + //System.out.println("I SEE A "+(char)event.getUnicodeChar()); if(c != (char)event.getUnicodeChar()){ System.out.println("REPLACED with "+(char)c); AWTInputBridge.sendKey((char)123,123); @@ -436,6 +389,18 @@ public class JavaGUILauncherActivity extends BaseActivity implements View.OnTou return true; } + private void clearRC(){ + rcState = false; + AWTInputBridge.sendKey((char)121,121); + findViewById(R.id.installmod_mouse_sec).setBackground(getResources().getDrawable( R.drawable.control_button )); + } + + private void activateRC(){ + rcState = true; + AWTInputBridge.sendKey((char)122,122); + findViewById(R.id.installmod_mouse_sec).setBackground(getResources().getDrawable( R.drawable.control_button_pressed )); + } + public void placeMouseAdd(float x, float y) { this.mousePointer.setX(mousePointer.getX() + x); this.mousePointer.setY(mousePointer.getY() + y); @@ -469,9 +434,9 @@ public class JavaGUILauncherActivity extends BaseActivity implements View.OnTou public void toggleVirtualMouse(View v) { isVirtualMouseEnabled = !isVirtualMouseEnabled; - touchPad.setVisibility(isVirtualMouseEnabled ? View.VISIBLE : View.GONE); + touchPad.setVisibility(isVirtualMouseEnabled ? View.GONE : View.VISIBLE); Toast.makeText(this, - isVirtualMouseEnabled ? R.string.control_mouseon : R.string.control_mouseoff, + isVirtualMouseEnabled ? R.string.control_mouseoff : R.string.control_mouseon, Toast.LENGTH_SHORT).show(); } diff --git a/app_2009scape/src/main/java/net/kdt/pojavlaunch/PojavApplication.java b/app_2009scape/src/main/java/net/kdt/pojavlaunch/PojavApplication.java new file mode 100644 index 000000000..8b27f901d --- /dev/null +++ b/app_2009scape/src/main/java/net/kdt/pojavlaunch/PojavApplication.java @@ -0,0 +1,91 @@ +package net.kdt.pojavlaunch; + +import android.app.*; +import android.content.*; +import android.content.pm.*; +import android.content.res.*; +import android.os.*; +import androidx.core.app.*; + +import android.util.*; +import java.io.*; +import java.text.*; +import java.util.*; + +import net.kdt.pojavlaunch.utils.*; + +public class PojavApplication extends Application +{ + public static String CRASH_REPORT_TAG = "PojavCrashReport"; + + @Override + public void onCreate() { + Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler(){ + @Override + public void uncaughtException(Thread thread, Throwable th) { + boolean storagePermAllowed = Build.VERSION.SDK_INT < 23 || ActivityCompat.checkSelfPermission(PojavApplication.this, android.Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED; + File crashFile = new File(storagePermAllowed ? Tools.DIR_GAME_HOME : Tools.DIR_DATA, "latestcrash.txt"); + try { + // Write to file, since some devices may not able to show error + crashFile.getParentFile().mkdirs(); + crashFile.createNewFile(); + PrintStream crashStream = new PrintStream(crashFile); + crashStream.append("PojavLauncher crash report\n"); + crashStream.append(" - Time: " + DateFormat.getDateTimeInstance().format(new Date()) + "\n"); + crashStream.append(" - Device: " + Build.PRODUCT + " " + Build.MODEL + "\n"); + crashStream.append(" - Android version: " + Build.VERSION.RELEASE + "\n"); + crashStream.append(" - Crash stack trace:\n"); + crashStream.append(" - Launcher version: " + BuildConfig.VERSION_NAME + "\n"); + crashStream.append(Log.getStackTraceString(th)); + crashStream.close(); + } catch (Throwable th2) { + Log.e(CRASH_REPORT_TAG, " - Exception attempt saving crash stack trace:", th2); + Log.e(CRASH_REPORT_TAG, " - The crash stack trace was:", th); + } + + FatalErrorActivity.showError(PojavApplication.this, crashFile.getAbsolutePath(), storagePermAllowed, th); + // android.os.Process.killProcess(android.os.Process.myPid()); + + BaseMainActivity.fullyExit(); + } + }); + + try { + super.onCreate(); + Tools.APP_NAME = getResources().getString(R.string.app_short_name); + + Tools.DIR_DATA = getDir("files", MODE_PRIVATE).getParent(); + //Tools.DIR_HOME_JRE = Tools.DIR_DATA + "/jre_runtime".replace("/data/user/0", "/data/data"); + 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"; + + + 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); + startActivity(ferrorIntent); + } + } + + @Override + protected void attachBaseContext(Context base) { + super.attachBaseContext(LocaleUtils.setLocale(base)); + } + + @Override + public void onConfigurationChanged(Configuration newConfig) { + super.onConfigurationChanged(newConfig); + LocaleUtils.setLocale(this); + } +} diff --git a/app_2009scape/src/main/java/net/kdt/pojavlaunch/PojavLoginActivity.java b/app_2009scape/src/main/java/net/kdt/pojavlaunch/PojavLoginActivity.java index 74aa6dba9..da6ab0c47 100644 --- a/app_2009scape/src/main/java/net/kdt/pojavlaunch/PojavLoginActivity.java +++ b/app_2009scape/src/main/java/net/kdt/pojavlaunch/PojavLoginActivity.java @@ -5,14 +5,11 @@ import static net.kdt.pojavlaunch.Tools.getFileName; import android.Manifest; import android.app.Activity; -import android.app.Dialog; import android.app.ProgressDialog; import android.content.Intent; import android.content.SharedPreferences; import android.content.pm.PackageManager; import android.content.res.AssetManager; -import android.graphics.Color; -import android.graphics.drawable.ColorDrawable; import android.net.Uri; import android.os.Build; import android.os.Bundle; @@ -21,8 +18,6 @@ import android.view.LayoutInflater; import android.view.View; import android.widget.CheckBox; import android.widget.EditText; -import android.widget.ImageButton; -import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.ListView; import android.widget.ProgressBar; @@ -35,17 +30,9 @@ import androidx.appcompat.app.AlertDialog; import androidx.core.app.ActivityCompat; import androidx.core.content.ContextCompat; -import net.kdt.pojavlaunch.authenticator.microsoft.MicrosoftAuthTask; -import net.kdt.pojavlaunch.authenticator.microsoft.ui.MicrosoftLoginGUIActivity; -import net.kdt.pojavlaunch.authenticator.mojang.InvalidateTokenTask; -import net.kdt.pojavlaunch.authenticator.mojang.LoginListener; -import net.kdt.pojavlaunch.authenticator.mojang.LoginTask; -import net.kdt.pojavlaunch.authenticator.mojang.RefreshListener; -import net.kdt.pojavlaunch.customcontrols.CustomControls; import net.kdt.pojavlaunch.multirt.MultiRTConfigDialog; import net.kdt.pojavlaunch.multirt.MultiRTUtils; import net.kdt.pojavlaunch.prefs.LauncherPreferences; -import net.kdt.pojavlaunch.value.MinecraftAccount; import org.apache.commons.io.FileUtils; import org.apache.commons.io.IOUtils; @@ -68,7 +55,6 @@ public class PojavLoginActivity extends BaseActivity private CheckBox sRemember, sOffline; private TextView startupTextView; private SharedPreferences firstLaunchPrefs; - private MinecraftAccount mProfile = null; private boolean isSkipInit = false; private boolean isStarting = false; @@ -202,9 +188,7 @@ public class PojavLoginActivity extends BaseActivity super.onResume(); Tools.updateWindowSize(this); - - // Clear current profile - PojavProfile.setCurrentProfile(this, null); + } @@ -259,22 +243,14 @@ public class PojavLoginActivity extends BaseActivity } private void initMain() throws Throwable { mkdirs(Tools.DIR_ACCOUNT_NEW); - PojavMigrator.migrateAccountData(this); mkdirs(Tools.DIR_GAME_HOME); mkdirs(Tools.DIR_GAME_HOME + "/lwjgl3"); mkdirs(Tools.DIR_GAME_HOME + "/config"); - if (!PojavMigrator.migrateGameDir()) { - mkdirs(Tools.DIR_GAME_NEW); - mkdirs(Tools.DIR_GAME_NEW + "/mods"); - mkdirs(Tools.DIR_HOME_VERSION); - mkdirs(Tools.DIR_HOME_LIBRARY); - } mkdirs(Tools.CTRLMAP_PATH); try { - new CustomControls(this).save(Tools.CTRLDEF_FILE); Tools.copyAssetFile(this, "components/security/pro-grade.jar", Tools.DIR_DATA, true); Tools.copyAssetFile(this, "components/security/java_sandbox.policy", Tools.DIR_DATA, true); @@ -323,9 +299,6 @@ public class PojavLoginActivity extends BaseActivity }); t.start(); } - }else if(requestCode == MicrosoftLoginGUIActivity.AUTHENTICATE_MICROSOFT_REQUEST) { - //Log.i("MicroLoginWrap","Got microsoft login result:" + data); - performMicroLogin(data); } } } @@ -362,12 +335,7 @@ public class PojavLoginActivity extends BaseActivity else return file.mkdirs(); } - - public void loginMicrosoft(View view) { - Intent i = new Intent(this,MicrosoftLoginGUIActivity.class); - startActivityForResult(i,MicrosoftLoginGUIActivity.AUTHENTICATE_MICROSOFT_REQUEST); - } - + @Override protected void onNewIntent(Intent intent) { super.onNewIntent(intent); @@ -383,21 +351,6 @@ public class PojavLoginActivity extends BaseActivity if (!error_description.startsWith("The user has denied access to the scope requested by the client application")) { Toast.makeText(this, "Error: " + error + ": " + error_description, Toast.LENGTH_LONG).show(); } - } else { - String code = data.getQueryParameter("code"); - new MicrosoftAuthTask(this, new RefreshListener(){ - @Override - public void onFailed(Throwable e) { - Tools.showError(PojavLoginActivity.this, e); - } - - @Override - public void onSuccess(MinecraftAccount b) { - mProfile = b; - playProfile(false); - } - }).execute("false", code); - // Toast.makeText(this, "Logged in to Microsoft account, but NYI", Toast.LENGTH_LONG).show(); } } } @@ -412,187 +365,19 @@ public class PojavLoginActivity extends BaseActivity return listView.getChildAt(childIndex); } } - - public void loginSavedAcc(View view) { - String[] accountArr = new File(Tools.DIR_ACCOUNT_NEW).list(); - if(accountArr.length == 0){ - showNoAccountDialog(); - return; - } - - final Dialog accountDialog = new Dialog(PojavLoginActivity.this); - - accountDialog.setContentView(R.layout.simple_account_list_holder); - - LinearLayout accountListLayout = accountDialog.findViewById(R.id.accountListLayout); - LayoutInflater inflater = (LayoutInflater) this.getSystemService(LAYOUT_INFLATER_SERVICE); - - for (int accountIndex = 0; accountIndex < accountArr.length; accountIndex++) { - String s = accountArr[accountIndex]; - View child = inflater.inflate(R.layout.simple_account_list_item, accountListLayout,false); - TextView accountName = child.findViewById(R.id.accountitem_text_name); - ImageButton removeButton = child.findViewById(R.id.accountitem_button_remove); - ImageView imageView = child.findViewById(R.id.account_head); - - String accNameStr = s.substring(0, s.length() - 5); - imageView.setImageBitmap(MinecraftAccount.load(accNameStr).getSkinFace()); - - accountName.setText(accNameStr); - - accountListLayout.addView(child); - - accountName.setOnClickListener(new View.OnClickListener() { - final String selectedAccName = accountName.getText().toString(); - @Override - public void onClick(View v) { - try { - RefreshListener authListener = new RefreshListener(){ - @Override - public void onFailed(Throwable e) { - Tools.showError(PojavLoginActivity.this, e); - } - - @Override - public void onSuccess(MinecraftAccount out) { - accountDialog.dismiss(); - mProfile = out; - playProfile(true); - } - }; - - MinecraftAccount acc = MinecraftAccount.load(selectedAccName); - if (acc.isMicrosoft){ - new MicrosoftAuthTask(PojavLoginActivity.this, authListener) - .execute("true", acc.msaRefreshToken); - } else if (acc.accessToken.length() >= 5) { - PojavProfile.updateTokens(PojavLoginActivity.this, selectedAccName, authListener); - } else { - accountDialog.dismiss(); - PojavProfile.launch(PojavLoginActivity.this, selectedAccName); - } - } catch (Exception e) { - Tools.showError(PojavLoginActivity.this, e); - } - } - }); - - final int accountIndex_final = accountIndex; - removeButton.setOnClickListener(new View.OnClickListener() { - final String selectedAccName = accountName.getText().toString(); - @Override - public void onClick(View v) { - AlertDialog.Builder builder2 = new AlertDialog.Builder(PojavLoginActivity.this); - builder2.setTitle(selectedAccName); - builder2.setMessage(R.string.warning_remove_account); - builder2.setPositiveButton(android.R.string.ok, (p1, p2) -> { - new InvalidateTokenTask(PojavLoginActivity.this).execute(selectedAccName); - accountListLayout.removeViewsInLayout(accountIndex_final, 1); - - if (accountListLayout.getChildCount() == 0) { - accountDialog.dismiss(); //No need to keep it, since there is no account - return; - } - //Refreshes the layout with the same settings so it take the missing child into account. - accountListLayout.setLayoutParams(accountListLayout.getLayoutParams()); - - }); - builder2.setNegativeButton(android.R.string.cancel, null); - builder2.show(); - } - }); - - } - accountDialog.getWindow().setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT)); - accountDialog.show(); - } - - private MinecraftAccount loginOffline() { - new File(Tools.DIR_ACCOUNT_OLD).mkdir(); - - String text = edit2.getText().toString(); - if (text.isEmpty()) { - edit2.setError(getString(R.string.global_error_field_empty)); - } else if (text.length() < 3 || text.length() > 16 || !text.matches("\\w+")) { - edit2.setError(getString(R.string.login_error_invalid_username)); - } else if (new File(Tools.DIR_ACCOUNT_NEW + "/" + text + ".json").exists()) { - edit2.setError(getString(R.string.login_error_exist_username)); - } else if (!edit3.getText().toString().isEmpty()) { - edit3.setError(getString(R.string.login_error_offline_password)); - } else { - MinecraftAccount builder = new MinecraftAccount(); - builder.isMicrosoft = false; - builder.username = text; - - return builder; - } - return null; - } - - - public void loginMC(final View v) - { - - if (sOffline.isChecked()) { - mProfile = loginOffline(); - playProfile(false); - } else { - ProgressBar prb = findViewById(R.id.launcherAccProgress); - new LoginTask().setLoginListener(new LoginListener(){ - @Override - public void onBeforeLogin() { - v.setEnabled(false); - prb.setVisibility(View.VISIBLE); - } - - @Override - public void onLoginDone(String[] result) { - if(result[0].equals("ERROR")){ - Tools.dialogOnUiThread(PojavLoginActivity.this, - getResources().getString(R.string.global_error), strArrToString(result)); - } else{ - MinecraftAccount builder = new MinecraftAccount(); - builder.accessToken = result[1]; - builder.clientToken = result[2]; - builder.profileId = result[3]; - builder.username = result[4]; - builder.updateSkinFace(); - mProfile = builder; - } - runOnUiThread(() -> { - v.setEnabled(true); - prb.setVisibility(View.GONE); - playProfile(false); - }); - } - }).execute(edit2.getText().toString(), edit3.getText().toString()); - } - } - private void playProfile(boolean notOnLogin) { - if (mProfile != null) { - try { - String profileName = null; - if (sRemember.isChecked() || notOnLogin) { - profileName = mProfile.save(); - } - - PojavProfile.launch(PojavLoginActivity.this, profileName == null ? mProfile : profileName); - } catch (IOException e) { - Tools.showError(this, e); - } - } } - + public static String strArrToString(String[] strArr) { String[] strArrEdit = strArr.clone(); strArrEdit[0] = ""; - + String str = Arrays.toString(strArrEdit); str = str.substring(1, str.length() - 1).replace(",", "\n"); - + return str; } //We are calling this method to check the permission status diff --git a/app_2009scape/src/main/java/net/kdt/pojavlaunch/Tools.java b/app_2009scape/src/main/java/net/kdt/pojavlaunch/Tools.java index b008e106e..7ea6d7e91 100644 --- a/app_2009scape/src/main/java/net/kdt/pojavlaunch/Tools.java +++ b/app_2009scape/src/main/java/net/kdt/pojavlaunch/Tools.java @@ -10,15 +10,12 @@ import android.util.*; import com.google.gson.*; import java.io.*; -import java.lang.reflect.*; import java.net.HttpURLConnection; import java.net.URL; import java.nio.charset.*; import java.util.*; import java.util.zip.*; -import net.kdt.pojavlaunch.prefs.*; import net.kdt.pojavlaunch.utils.*; -import net.kdt.pojavlaunch.value.*; import org.apache.commons.codec.binary.Hex; import org.lwjgl.glfw.*; @@ -89,68 +86,6 @@ public final class Tools { CTRLMAP_PATH = DIR_GAME_HOME + "/controlmap"; CTRLDEF_FILE = DIR_GAME_HOME + "/controlmap/default.json"; } - - - public static void launchMinecraft(final Activity activity, MinecraftAccount profile, String versionName) throws Throwable { - ActivityManager.MemoryInfo mi = new ActivityManager.MemoryInfo(); - ((ActivityManager)activity.getSystemService(Context.ACTIVITY_SERVICE)).getMemoryInfo(mi); - if(LauncherPreferences.PREF_RAM_ALLOCATION > (mi.availMem/1048576L)) { - Object memoryErrorLock = new Object(); - activity.runOnUiThread(() -> { - androidx.appcompat.app.AlertDialog.Builder b = new androidx.appcompat.app.AlertDialog.Builder(activity) - .setMessage(activity.getString(R.string.memory_warning_msg,(mi.availMem/1048576L),LauncherPreferences.PREF_RAM_ALLOCATION)) - .setPositiveButton(android.R.string.ok, (dialogInterface, i) -> {synchronized(memoryErrorLock){memoryErrorLock.notifyAll();}}) - .setOnCancelListener((i) -> {synchronized(memoryErrorLock){memoryErrorLock.notifyAll();}}); - b.show(); - }); - synchronized (memoryErrorLock) { - memoryErrorLock.wait(); - } - } - - JMinecraftVersionList.Version versionInfo = Tools.getVersionInfo(null,versionName); - PerVersionConfig.update(); - PerVersionConfig.VersionConfig pvcConfig = PerVersionConfig.configMap.get(versionName); - - String gamedirPath; - if(pvcConfig != null && pvcConfig.gamePath != null && !pvcConfig.gamePath.isEmpty()) gamedirPath = pvcConfig.gamePath; - else gamedirPath = Tools.DIR_GAME_NEW; - if(pvcConfig != null && pvcConfig.jvmArgs != null && !pvcConfig.jvmArgs.isEmpty()) LauncherPreferences.PREF_CUSTOM_JAVA_ARGS = pvcConfig.jvmArgs; - PojavLoginActivity.disableSplash(gamedirPath); - String[] launchArgs = getMinecraftArgs(profile, versionInfo, gamedirPath); - - // ctx.appendlnToLog("Minecraft Args: " + Arrays.toString(launchArgs)); - - String launchClassPath = generateLaunchClassPath(versionInfo,versionName); - - List javaArgList = new ArrayList(); - - // Only Java 8 supports headful AWT for now - if (JREUtils.jreReleaseList.get("JAVA_VERSION").equals("1.8.0")) { - getCacioJavaArgs(javaArgList, false); - } - -/* - int mcReleaseDate = Integer.parseInt(versionInfo.releaseTime.substring(0, 10).replace("-", "")); - // 13w17a: 20130425 - // 13w18a: 20130502 - if (mcReleaseDate < 20130502 && versionInfo.minimumLauncherVersion < 9){ - ctx.appendlnToLog("AWT-enabled version detected! ("+mcReleaseDate+")"); - getCacioJavaArgs(javaArgList,false); - }else{ - getCacioJavaArgs(javaArgList,false); // true - ctx.appendlnToLog("Headless version detected! ("+mcReleaseDate+")"); - } -*/ - - javaArgList.add("-cp"); - javaArgList.add(getLWJGL3ClassPath() + ":" + launchClassPath); - - javaArgList.add(versionInfo.mainClass); - javaArgList.addAll(Arrays.asList(launchArgs)); - // ctx.appendlnToLog("full args: "+javaArgList.toString()); - JREUtils.launchJavaVM(activity, javaArgList); - } public static void getCacioJavaArgs(List javaArgList, boolean isHeadless) { javaArgList.add("-Djava.awt.headless="+isHeadless); @@ -176,74 +111,6 @@ public final class Tools { javaArgList.add(cacioClasspath.toString()); } - public static String[] getMinecraftArgs(MinecraftAccount profile, JMinecraftVersionList.Version versionInfo, String strGameDir) { - String username = profile.username; - String versionName = versionInfo.id; - if (versionInfo.inheritsFrom != null) { - versionName = versionInfo.inheritsFrom; - } - - String userType = "mojang"; - - File gameDir = new File(strGameDir); - gameDir.mkdirs(); - - Map varArgMap = new ArrayMap<>(); - varArgMap.put("auth_access_token", profile.accessToken); - varArgMap.put("auth_player_name", username); - varArgMap.put("auth_uuid", profile.profileId); - varArgMap.put("assets_root", Tools.ASSETS_PATH); - varArgMap.put("assets_index_name", versionInfo.assets); - varArgMap.put("game_assets", Tools.ASSETS_PATH); - varArgMap.put("game_directory", gameDir.getAbsolutePath()); - varArgMap.put("user_properties", "{}"); - varArgMap.put("user_type", userType); - varArgMap.put("version_name", versionName); - varArgMap.put("version_type", versionInfo.type); - - List minecraftArgs = new ArrayList(); - if (versionInfo.arguments != null) { - // Support Minecraft 1.13+ - for (Object arg : versionInfo.arguments.game) { - if (arg instanceof String) { - minecraftArgs.add((String) arg); - } else { - /* - JMinecraftVersionList.Arguments.ArgValue argv = (JMinecraftVersionList.Arguments.ArgValue) arg; - if (argv.values != null) { - minecraftArgs.add(argv.values[0]); - } else { - - for (JMinecraftVersionList.Arguments.ArgValue.ArgRules rule : arg.rules) { - // rule.action = allow - // TODO implement this - } - - } - */ - } - } - } - minecraftArgs.add("--width"); - minecraftArgs.add(Integer.toString(CallbackBridge.windowWidth)); - minecraftArgs.add("--height"); - minecraftArgs.add(Integer.toString(CallbackBridge.windowHeight)); - minecraftArgs.add("--fullscreenWidth"); - minecraftArgs.add(Integer.toString(CallbackBridge.windowWidth)); - minecraftArgs.add("--fullscreenHeight"); - minecraftArgs.add(Integer.toString(CallbackBridge.windowHeight)); - - String[] argsFromJson = JSONUtils.insertJSONValueList( - splitAndFilterEmpty( - versionInfo.minecraftArguments == null ? - fromStringArray(minecraftArgs.toArray(new String[0])): - versionInfo.minecraftArguments - ), varArgMap - ); - // Tools.dialogOnUiThread(this, "Result args", Arrays.asList(argsFromJson).toString()); - return argsFromJson; - } - public static String fromStringArray(String[] strArr) { StringBuilder builder = new StringBuilder(); for (int i = 0; i < strArr.length; i++) { @@ -289,47 +156,6 @@ public final class Tools { } private static boolean isClientFirst = false; - public static String generateLaunchClassPath(JMinecraftVersionList.Version info,String actualname) { - StringBuilder libStr = new StringBuilder(); //versnDir + "/" + version + "/" + version + ".jar:"; - - String[] classpath = generateLibClasspath(info); - - // Debug: LWJGL 3 override - // File lwjgl2Folder = new File(Tools.MAIN_PATH, "lwjgl2"); - - /* - File lwjgl3Folder = new File(Tools.MAIN_PATH, "lwjgl3"); - if (lwjgl3Folder.exists()) { - for (File file: lwjgl3Folder.listFiles()) { - if (file.getName().endsWith(".jar")) { - libStr.append(file.getAbsolutePath() + ":"); - } - } - } else if (lwjgl2Folder.exists()) { - for (File file: lwjgl2Folder.listFiles()) { - if (file.getName().endsWith(".jar")) { - libStr.append(file.getAbsolutePath() + ":"); - } - } - } - */ - - if (isClientFirst) { - libStr.append(getPatchedFile(actualname)); - } - for (String perJar : classpath) { - if (!new File(perJar).exists()) { - Log.d(APP_NAME, "Ignored non-exists file: " + perJar); - continue; - } - libStr.append((isClientFirst ? ":" : "") + perJar + (!isClientFirst ? ":" : "")); - } - if (!isClientFirst) { - libStr.append(getPatchedFile(actualname)); - } - - return libStr.toString(); - } public static DisplayMetrics getDisplayMetrics(Activity activity) { DisplayMetrics displayMetrics = new DisplayMetrics(); @@ -505,131 +331,6 @@ public final class Tools { Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(url)); act.startActivity(browserIntent); } - - public static String[] generateLibClasspath(JMinecraftVersionList.Version info) { - List libDir = new ArrayList(); - - for (DependentLibrary libItem: info.libraries) { - String[] libInfos = libItem.name.split(":"); - libDir.add(Tools.DIR_HOME_LIBRARY + "/" + Tools.artifactToPath(libInfos[0], libInfos[1], libInfos[2])); - } - return libDir.toArray(new String[0]); - } - - public static JMinecraftVersionList.Version getVersionInfo(BaseLauncherActivity bla, String versionName) { - try { - JMinecraftVersionList.Version customVer = Tools.GLOBAL_GSON.fromJson(read(DIR_HOME_VERSION + "/" + versionName + "/" + versionName + ".json"), JMinecraftVersionList.Version.class); - for (DependentLibrary lib : customVer.libraries) { - if (lib.name.startsWith(LIBNAME_OPTIFINE)) { - customVer.optifineLib = lib; - } - } - if (customVer.inheritsFrom == null || customVer.inheritsFrom.equals(customVer.id)) { - return customVer; - } else { - JMinecraftVersionList.Version inheritsVer = null; - if(bla != null) if (bla.mVersionList != null) { - for (JMinecraftVersionList.Version valueVer : bla.mVersionList.versions) { - if (valueVer.id.equals(customVer.inheritsFrom) && (!new File(DIR_HOME_VERSION + "/" + customVer.inheritsFrom + "/" + customVer.inheritsFrom + ".json").exists()) && (valueVer.url != null)) { - Tools.downloadFile(valueVer.url,DIR_HOME_VERSION + "/" + customVer.inheritsFrom + "/" + customVer.inheritsFrom + ".json"); - } - } - }//If it won't download, just search for it - try{ - inheritsVer = Tools.GLOBAL_GSON.fromJson(read(DIR_HOME_VERSION + "/" + customVer.inheritsFrom + "/" + customVer.inheritsFrom + ".json"), JMinecraftVersionList.Version.class); - }catch(IOException e) { - throw new RuntimeException("Can't find the source version for "+ versionName +" (req version="+customVer.inheritsFrom+")"); - } - inheritsVer.inheritsFrom = inheritsVer.id; - insertSafety(inheritsVer, customVer, - "assetIndex", "assets", "id", - "mainClass", "minecraftArguments", - "optifineLib", "releaseTime", "time", "type" - ); - - List libList = new ArrayList(Arrays.asList(inheritsVer.libraries)); - try { - loop_1: - for (DependentLibrary lib : customVer.libraries) { - String libName = lib.name.substring(0, lib.name.lastIndexOf(":")); - for (int i = 0; i < libList.size(); i++) { - DependentLibrary libAdded = libList.get(i); - String libAddedName = libAdded.name.substring(0, libAdded.name.lastIndexOf(":")); - - if (libAddedName.equals(libName)) { - Log.d(APP_NAME, "Library " + libName + ": Replaced version " + - libName.substring(libName.lastIndexOf(":") + 1) + " with " + - libAddedName.substring(libAddedName.lastIndexOf(":") + 1)); - libList.set(i, lib); - continue loop_1; - } - } - - libList.add(lib); - } - } finally { - inheritsVer.libraries = libList.toArray(new DependentLibrary[0]); - } - - // Inheriting Minecraft 1.13+ with append custom args - if (inheritsVer.arguments != null && customVer.arguments != null) { - List totalArgList = new ArrayList(); - totalArgList.addAll(Arrays.asList(inheritsVer.arguments.game)); - - int nskip = 0; - for (int i = 0; i < customVer.arguments.game.length; i++) { - if (nskip > 0) { - nskip--; - continue; - } - - Object perCustomArg = customVer.arguments.game[i]; - if (perCustomArg instanceof String) { - String perCustomArgStr = (String) perCustomArg; - // Check if there is a duplicate argument on combine - if (perCustomArgStr.startsWith("--") && totalArgList.contains(perCustomArgStr)) { - perCustomArg = customVer.arguments.game[i + 1]; - if (perCustomArg instanceof String) { - perCustomArgStr = (String) perCustomArg; - // If the next is argument value, skip it - if (!perCustomArgStr.startsWith("--")) { - nskip++; - } - } - } else { - totalArgList.add(perCustomArgStr); - } - } else if (!totalArgList.contains(perCustomArg)) { - totalArgList.add(perCustomArg); - } - } - - inheritsVer.arguments.game = totalArgList.toArray(new Object[0]); - } - - return inheritsVer; - } - } catch (Exception e) { - throw new RuntimeException(e); - } - } - - // Prevent NullPointerException - private static void insertSafety(JMinecraftVersionList.Version targetVer, JMinecraftVersionList.Version fromVer, String... keyArr) { - for (String key : keyArr) { - Object value = null; - try { - Field fieldA = fromVer.getClass().getDeclaredField(key); - value = fieldA.get(fromVer); - if (((value instanceof String) && !((String) value).isEmpty()) || value != null) { - Field fieldB = targetVer.getClass().getDeclaredField(key); - fieldB.set(targetVer, value); - } - } catch (Throwable th) { - Log.w(Tools.APP_NAME, "Unable to insert " + key + "=" + value, th); - } - } - } public static String convertStream(InputStream inputStream) throws IOException { return convertStream(inputStream, Charset.forName("UTF-8")); @@ -717,29 +418,6 @@ public final class Tools { File file = new File(nameOutput); DownloadUtils.downloadFile(urlInput, file); } - public abstract static class DownloaderFeedback { - public abstract void updateProgress(int curr, int max); - } - public static void downloadFileMonitored(String urlInput,String nameOutput, DownloaderFeedback monitor) throws IOException { - File nameOutputFile = new File(nameOutput); - if (!nameOutputFile.exists()) { - nameOutputFile.getParentFile().mkdirs(); - } - HttpURLConnection conn = (HttpURLConnection) new URL(urlInput).openConnection(); - InputStream readStr = conn.getInputStream(); - FileOutputStream fos = new FileOutputStream(nameOutputFile); - int cur = 0; - int oval = 0; - int len = conn.getContentLength(); - byte[] buf = new byte[65535]; - while ((cur = readStr.read(buf)) != -1) { - oval += cur; - fos.write(buf, 0, cur); - monitor.updateProgress(oval, len); - } - fos.close(); - conn.disconnect(); - } public static boolean compareSHA1(File f, String sourceSHA) { try { String sha1_dst; @@ -864,7 +542,7 @@ public final class Tools { Cursor cursor = ctx.getContentResolver().query(uri, null, null, null, null); try { if (cursor != null && cursor.moveToFirst()) { - result = cursor.getString(cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME)); + //result = cursor.getString(cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME)); } } finally { cursor.close(); diff --git a/app_2009scape/src/main/java/net/kdt/pojavlaunch/Touchpad.java b/app_2009scape/src/main/java/net/kdt/pojavlaunch/Touchpad.java index bbd5d7fa9..977b9da1a 100644 --- a/app_2009scape/src/main/java/net/kdt/pojavlaunch/Touchpad.java +++ b/app_2009scape/src/main/java/net/kdt/pojavlaunch/Touchpad.java @@ -1,6 +1,5 @@ package net.kdt.pojavlaunch; -import static net.kdt.pojavlaunch.MinecraftGLView.FINGER_SCROLL_THRESHOLD; import static net.kdt.pojavlaunch.Tools.currentDisplayMetrics; import static net.kdt.pojavlaunch.prefs.LauncherPreferences.DEFAULT_PREF; @@ -26,6 +25,7 @@ import org.lwjgl.glfw.CallbackBridge; * Class dealing with the virtual mouse */ public class Touchpad extends FrameLayout { + private static final int FINGER_SCROLL_THRESHOLD = 10; /* Whether the Touchpad should be displayed */ private boolean displayState; diff --git a/app_2009scape/src/main/java/net/kdt/pojavlaunch/multirt/MultiRTConfigDialog.java b/app_2009scape/src/main/java/net/kdt/pojavlaunch/multirt/MultiRTConfigDialog.java new file mode 100644 index 000000000..e00eb8e45 --- /dev/null +++ b/app_2009scape/src/main/java/net/kdt/pojavlaunch/multirt/MultiRTConfigDialog.java @@ -0,0 +1,44 @@ +package net.kdt.pojavlaunch.multirt; + +import android.app.Activity; +import android.app.AlertDialog; +import android.content.Intent; +import android.webkit.MimeTypeMap; + +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; + +import net.kdt.pojavlaunch.BaseLauncherActivity; +import net.kdt.pojavlaunch.R; + +public class MultiRTConfigDialog { + public static final int MULTIRT_PICK_RUNTIME = 2048; + public static final int MULTIRT_PICK_RUNTIME_STARTUP = 2049; + public AlertDialog dialog; + public RecyclerView dialogView; + public void prepare(BaseLauncherActivity ctx) { + AlertDialog.Builder builder = new AlertDialog.Builder(ctx); + builder.setTitle(R.string.multirt_config_title); + dialogView = new RecyclerView(ctx); + LinearLayoutManager linearLayoutManager = new LinearLayoutManager(ctx); + linearLayoutManager.setOrientation(LinearLayoutManager.VERTICAL); + dialogView.setLayoutManager(linearLayoutManager); + dialogView.setAdapter(new RTRecyclerViewAdapter(this)); + builder.setView(dialogView); + builder.setPositiveButton(R.string.multirt_config_add, (dialog, which) -> openRuntimeSelector(ctx,MULTIRT_PICK_RUNTIME)); + builder.setNegativeButton(R.string.mcn_exit_call, (dialog, which) -> dialog.cancel()); + dialog = builder.create(); + } + public void refresh() { + RecyclerView.Adapter adapter = dialogView.getAdapter(); + if(adapter != null)dialogView.getAdapter().notifyDataSetChanged(); + } + public static void openRuntimeSelector(Activity ctx, int code) { + Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT); + intent.addCategory(Intent.CATEGORY_OPENABLE); + String mimeType = MimeTypeMap.getSingleton().getMimeTypeFromExtension("xz"); + if(mimeType == null) mimeType = "*/*"; + intent.setType(mimeType); + ctx.startActivityForResult(intent,code); + } +} diff --git a/app_2009scape/src/main/java/net/kdt/pojavlaunch/multirt/MultiRTUtils.java b/app_2009scape/src/main/java/net/kdt/pojavlaunch/multirt/MultiRTUtils.java new file mode 100644 index 000000000..a5f717ca5 --- /dev/null +++ b/app_2009scape/src/main/java/net/kdt/pojavlaunch/multirt/MultiRTUtils.java @@ -0,0 +1,264 @@ +package net.kdt.pojavlaunch.multirt; + +import android.content.Context; +import android.system.Os; + +import net.kdt.pojavlaunch.R; +import net.kdt.pojavlaunch.Tools; +import net.kdt.pojavlaunch.utils.JREUtils; + +import org.apache.commons.compress.archivers.tar.TarArchiveEntry; +import org.apache.commons.compress.archivers.tar.TarArchiveInputStream; +import org.apache.commons.compress.compressors.xz.XZCompressorInputStream; +import org.apache.commons.io.FileUtils; +import org.apache.commons.io.IOUtils; + +import java.io.BufferedInputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Objects; + +public class MultiRTUtils { + public static HashMap cache = new HashMap<>(); + public static class Runtime { + public Runtime(String name) { + this.name = name; + } + public String name; + public String versionString; + public String arch; + public int javaVersion; + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + Runtime runtime = (Runtime) o; + return name.equals(runtime.name); + } + @Override + public int hashCode() { + return Objects.hash(name); + } + } + public static interface ProgressReporterThingy { + void reportStringProgress(int resid, Object ... stuff); + } + private static final File runtimeFolder = new File(Tools.MULTIRT_HOME); + private static final String JAVA_VERSION_str = "JAVA_VERSION=\""; + private static final String OS_ARCH_str = "OS_ARCH=\""; + public static List getRuntimes() { + if(!runtimeFolder.exists()) runtimeFolder.mkdirs(); + ArrayList ret = new ArrayList<>(); + System.out.println("Fetch runtime list"); + for(File f : runtimeFolder.listFiles()) { + ret.add(read(f.getName())); + } + + return ret; + } + public static String getNearestJREName(int majorVersion) { + List runtimes = getRuntimes(); + int diff_factor = Integer.MAX_VALUE; + String result = null; + for(Runtime r : runtimes) { + if(r.javaVersion >= majorVersion) { // lower - not useful + int currentFactor = r.javaVersion - majorVersion; + if(diff_factor > currentFactor) { + result = r.name; + diff_factor = currentFactor; + } + } + } + return result; + } + public static void installRuntimeNamed(InputStream runtimeInputStream, String name, ProgressReporterThingy thingy) throws IOException { + File dest = new File(runtimeFolder,"/"+name); + File tmp = new File(dest,"temporary"); + if(dest.exists()) FileUtils.deleteDirectory(dest); + dest.mkdirs(); + FileOutputStream fos = new FileOutputStream(tmp); + thingy.reportStringProgress(R.string.multirt_progress_caching); + IOUtils.copy(runtimeInputStream,fos); + fos.close(); + runtimeInputStream.close(); + uncompressTarXZ(tmp,dest,thingy); + tmp.delete(); + read(name); + } + private static void __installRuntimeNamed__NoRM(InputStream runtimeInputStream, File dest, ProgressReporterThingy thingy) throws IOException { + File tmp = new File(dest,"temporary"); + FileOutputStream fos = new FileOutputStream(tmp); + thingy.reportStringProgress(R.string.multirt_progress_caching); + IOUtils.copy(runtimeInputStream,fos); + fos.close(); + runtimeInputStream.close(); + uncompressTarXZ(tmp,dest,thingy); + tmp.delete(); + } + public static void postPrepare(Context ctx, String name) throws IOException { + File dest = new File(runtimeFolder,"/"+name); + if(!dest.exists()) return; + Runtime r = read(name); + String libFolder = "lib"; + if(new File(dest,libFolder+"/"+r.arch).exists()) libFolder = libFolder+"/"+r.arch; + File ftIn = new File(dest, libFolder+ "/libfreetype.so.6"); + File ftOut = new File(dest, libFolder + "/libfreetype.so"); + if (ftIn.exists() && (!ftOut.exists() || ftIn.length() != ftOut.length())) { + ftIn.renameTo(ftOut); + } + + // Refresh libraries + copyDummyNativeLib(ctx,"libawt_xawt.so",dest,libFolder); + } + private static void copyDummyNativeLib(Context ctx, String name, File dest, String libFolder) throws IOException { + + File fileLib = new File(dest, "/"+libFolder + "/" + name); + fileLib.delete(); + FileInputStream is = new FileInputStream(new File(ctx.getApplicationInfo().nativeLibraryDir, name)); + FileOutputStream os = new FileOutputStream(fileLib); + IOUtils.copy(is, os); + is.close(); + os.close(); + } + public static Runtime installRuntimeNamedBinpack(InputStream universalFileInputStream, InputStream platformBinsInputStream, String name, String binpackVersion, ProgressReporterThingy thingy) throws IOException { + File dest = new File(runtimeFolder,"/"+name); + if(dest.exists()) FileUtils.deleteDirectory(dest); + dest.mkdirs(); + __installRuntimeNamed__NoRM(universalFileInputStream,dest,thingy); + __installRuntimeNamed__NoRM(platformBinsInputStream,dest,thingy); + File binpack_verfile = new File(runtimeFolder,"/"+name+"/pojav_version"); + FileOutputStream fos = new FileOutputStream(binpack_verfile); + fos.write(binpackVersion.getBytes()); + fos.close(); + cache.remove(name); // Force reread + return read(name); + } + public static String __internal__readBinpackVersion(String name) { + File binpack_verfile = new File(runtimeFolder,"/"+name+"/pojav_version"); + try { + if (binpack_verfile.exists()) { + return Tools.read(binpack_verfile.getAbsolutePath()); + }else{ + return null; + } + }catch (IOException e) { + e.printStackTrace(); + return null; + } + } + public static void removeRuntimeNamed(String name) throws IOException { + File dest = new File(runtimeFolder,"/"+name); + if(dest.exists()) { + FileUtils.deleteDirectory(dest); + cache.remove(name); + } + } + public static void setRuntimeNamed(Context ctx, String name) throws IOException { + File dest = new File(runtimeFolder,"/"+name); + if((!dest.exists()) || MultiRTUtils.forceReread(name).versionString == null) throw new RuntimeException("Selected runtime is broken!"); + Tools.DIR_HOME_JRE = dest.getAbsolutePath(); + JREUtils.relocateLibPath(ctx); + } + public static Runtime forceReread(String name) { + cache.remove(name); + return read(name); + } + public static Runtime read(String name) { + if(cache.containsKey(name)) return cache.get(name); + Runtime retur; + File release = new File(runtimeFolder,"/"+name+"/release"); + if(!release.exists()) { + return new Runtime(name); + } + try { + String content = Tools.read(release.getAbsolutePath()); + int _JAVA_VERSION_index = content.indexOf(JAVA_VERSION_str); + int _OS_ARCH_index = content.indexOf(OS_ARCH_str); + if(_JAVA_VERSION_index != -1 && _OS_ARCH_index != -1) { + _JAVA_VERSION_index += JAVA_VERSION_str.length(); + _OS_ARCH_index += OS_ARCH_str.length(); + String javaVersion = content.substring(_JAVA_VERSION_index,content.indexOf('"',_JAVA_VERSION_index)); + String[] javaVersionSplit = javaVersion.split("\\."); + int javaVersionInt; + if (javaVersionSplit[0].equals("1")) { + javaVersionInt = Integer.parseInt(javaVersionSplit[1]); + } else { + javaVersionInt = Integer.parseInt(javaVersionSplit[0]); + } + Runtime r = new Runtime(name); + r.arch = content.substring(_OS_ARCH_index,content.indexOf('"',_OS_ARCH_index)); + r.javaVersion = javaVersionInt; + r.versionString = javaVersion; + retur = r; + }else{ + retur = new Runtime(name); + } + }catch(IOException e) { + retur = new Runtime(name); + } + cache.put(name,retur); + return retur; + } + private static void uncompressTarXZ(final File tarFile, final File dest, final ProgressReporterThingy thingy) throws IOException { + dest.mkdirs(); + TarArchiveInputStream tarIn = null; + + tarIn = new TarArchiveInputStream( + new XZCompressorInputStream( + new BufferedInputStream( + new FileInputStream(tarFile) + ) + ) + ); + TarArchiveEntry tarEntry = tarIn.getNextTarEntry(); + // tarIn is a TarArchiveInputStream + while (tarEntry != null) { + /* + * Unpacking very small files in short time cause + * application to ANR or out of memory, so delay + * a little if size is below than 20kb (20480 bytes) + */ + if (tarEntry.getSize() <= 20480) { + try { + // 40 small files per second + Thread.sleep(25); + } catch (InterruptedException ignored) {} + } + final String tarEntryName = tarEntry.getName(); + // publishProgress(null, "Unpacking " + tarEntry.getName()); + thingy.reportStringProgress(R.string.global_unpacking,tarEntryName); + File destPath = new File(dest, tarEntry.getName()); + if (tarEntry.isSymbolicLink()) { + destPath.getParentFile().mkdirs(); + try { + // android.system.Os + // Libcore one support all Android versions + Os.symlink(tarEntry.getName(), tarEntry.getLinkName()); + } catch (Throwable e) { + e.printStackTrace(); + } + + } else if (tarEntry.isDirectory()) { + destPath.mkdirs(); + destPath.setExecutable(true); + } else if (!destPath.exists() || destPath.length() != tarEntry.getSize()) { + destPath.getParentFile().mkdirs(); + destPath.createNewFile(); + + FileOutputStream os = new FileOutputStream(destPath); + IOUtils.copy(tarIn, os); + os.close(); + + } + tarEntry = tarIn.getNextTarEntry(); + } + tarIn.close(); + } +} diff --git a/app_2009scape/src/main/java/net/kdt/pojavlaunch/multirt/RTRecyclerViewAdapter.java b/app_2009scape/src/main/java/net/kdt/pojavlaunch/multirt/RTRecyclerViewAdapter.java new file mode 100644 index 000000000..e268f773a --- /dev/null +++ b/app_2009scape/src/main/java/net/kdt/pojavlaunch/multirt/RTRecyclerViewAdapter.java @@ -0,0 +1,132 @@ +package net.kdt.pojavlaunch.multirt; + +import android.app.ProgressDialog; +import android.content.Context; +import android.content.res.ColorStateList; +import android.graphics.Color; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.Button; +import android.widget.TextView; + +import androidx.annotation.NonNull; +import androidx.appcompat.app.AlertDialog; +import androidx.recyclerview.widget.RecyclerView; + +import net.kdt.pojavlaunch.R; +import net.kdt.pojavlaunch.Tools; +import net.kdt.pojavlaunch.prefs.LauncherPreferences; + +import java.io.IOException; +import java.util.List; + +public class RTRecyclerViewAdapter extends RecyclerView.Adapter { + MultiRTConfigDialog dialog; + public RTRecyclerViewAdapter(MultiRTConfigDialog dialog) { + this.dialog = dialog; + } + @NonNull + @Override + public RTViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { + View recyclableView = LayoutInflater.from(parent.getContext()).inflate(R.layout.multirt_recyclable_view,parent,false); + return new RTViewHolder(recyclableView); + } + + @Override + public void onBindViewHolder(@NonNull RTViewHolder holder, int position) { + final List runtimes = MultiRTUtils.getRuntimes(); + holder.bindRuntime(runtimes.get(position),position); + } + public boolean isDefaultRuntime(MultiRTUtils.Runtime rt) { + return LauncherPreferences.PREF_DEFAULT_RUNTIME.equals(rt.name); + } + public void setDefault(MultiRTUtils.Runtime rt){ + LauncherPreferences.PREF_DEFAULT_RUNTIME = rt.name; + LauncherPreferences.DEFAULT_PREF.edit().putString("defaultRuntime",LauncherPreferences.PREF_DEFAULT_RUNTIME).apply(); + RTRecyclerViewAdapter.this.notifyDataSetChanged(); + } + @Override + public int getItemCount() { + return MultiRTUtils.getRuntimes().size(); + } + public class RTViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener{ + final TextView javaVersionView; + final TextView fullJavaVersionView; + final ColorStateList defaultColors; + final Button setDefaultButton; + final Context ctx; + MultiRTUtils.Runtime currentRuntime; + int currentPosition; + public RTViewHolder(View itemView) { + super(itemView); + javaVersionView = itemView.findViewById(R.id.multirt_view_java_version); + fullJavaVersionView = itemView.findViewById(R.id.multirt_view_java_version_full); + itemView.findViewById(R.id.multirt_view_removebtn).setOnClickListener(this); + setDefaultButton = itemView.findViewById(R.id.multirt_view_setdefaultbtn); + setDefaultButton.setOnClickListener(this); + defaultColors = fullJavaVersionView.getTextColors(); + ctx = itemView.getContext(); + } + public void bindRuntime(MultiRTUtils.Runtime rt, int pos) { + currentRuntime = rt; + currentPosition = pos; + if(rt.versionString != null) { + javaVersionView.setText(ctx.getString(R.string.multirt_java_ver, rt.name, rt.javaVersion)); + fullJavaVersionView.setText(rt.versionString); + fullJavaVersionView.setTextColor(defaultColors); + setDefaultButton.setVisibility(View.VISIBLE); + boolean default_ = isDefaultRuntime(rt); + setDefaultButton.setEnabled(!default_); + setDefaultButton.setText(default_?R.string.multirt_config_setdefault_already:R.string.multirt_config_setdefault); + }else{ + javaVersionView.setText(rt.name); + fullJavaVersionView.setText(R.string.multirt_runtime_corrupt); + fullJavaVersionView.setTextColor(Color.RED); + setDefaultButton.setVisibility(View.GONE); + } + } + + @Override + public void onClick(View v) { + if(v.getId() == R.id.multirt_view_removebtn) { + if (currentRuntime != null) { + if(MultiRTUtils.getRuntimes().size() < 2) { + AlertDialog.Builder bldr = new AlertDialog.Builder(ctx); + bldr.setTitle(R.string.global_error); + bldr.setMessage(R.string.multirt_config_removeerror_last); + bldr.setPositiveButton(android.R.string.ok,(adapter, which)->adapter.dismiss()); + bldr.show(); + return; + } + + final ProgressDialog barrier = new ProgressDialog(ctx); + barrier.setMessage(ctx.getString(R.string.global_waiting)); + barrier.setProgressStyle(ProgressDialog.STYLE_SPINNER); + barrier.setCancelable(false); + barrier.show(); + Thread t = new Thread(() -> { + try { + MultiRTUtils.removeRuntimeNamed(currentRuntime.name); + } catch (IOException e) { + Tools.showError(itemView.getContext(), e); + } + v.post(() -> { + if(isDefaultRuntime(currentRuntime)) setDefault(MultiRTUtils.getRuntimes().get(0)); + barrier.dismiss(); + RTRecyclerViewAdapter.this.notifyDataSetChanged(); + dialog.dialog.show(); + }); + }); + t.start(); + } + }else if(v.getId() == R.id.multirt_view_setdefaultbtn) { + if(currentRuntime != null) { + setDefault(currentRuntime); + RTRecyclerViewAdapter.this.notifyDataSetChanged(); + } + } + } + + } +} diff --git a/app_2009scape/src/main/java/net/kdt/pojavlaunch/multirt/RTSpinnerAdapter.java b/app_2009scape/src/main/java/net/kdt/pojavlaunch/multirt/RTSpinnerAdapter.java new file mode 100644 index 000000000..4a499c371 --- /dev/null +++ b/app_2009scape/src/main/java/net/kdt/pojavlaunch/multirt/RTSpinnerAdapter.java @@ -0,0 +1,103 @@ +package net.kdt.pojavlaunch.multirt; + +import android.content.Context; +import android.database.DataSetObserver; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.SpinnerAdapter; +import android.widget.TextView; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + +import net.kdt.pojavlaunch.R; + +import java.util.List; + +public class RTSpinnerAdapter implements SpinnerAdapter { + final Context ctx; + List runtimes; + public RTSpinnerAdapter(@NonNull Context context, List runtimes) { + this.runtimes = runtimes; + MultiRTUtils.Runtime runtime = new MultiRTUtils.Runtime(""); + runtime.versionString = ""; + this.runtimes.add(runtime); + ctx = context; + } + + @Override + public void registerDataSetObserver(DataSetObserver observer) { + + } + + @Override + public void unregisterDataSetObserver(DataSetObserver observer) { + + } + + @Override + public int getCount() { + return runtimes.size(); + } + + @Override + public Object getItem(int position) { + return runtimes.get(position); + } + + @Override + public long getItemId(int position) { + return runtimes.get(position).name.hashCode(); + } + + @Override + public boolean hasStableIds() { + return true; + } + + @NonNull + @Override + public View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent) { + View v = convertView!=null? + convertView: + LayoutInflater.from(ctx).inflate(R.layout.multirt_recyclable_view,parent,false); + + MultiRTUtils.Runtime rt = runtimes.get(position); + + final TextView javaVersionView = v.findViewById(R.id.multirt_view_java_version); + final TextView fullJavaVersionView = v.findViewById(R.id.multirt_view_java_version_full); + v.findViewById(R.id.multirt_view_removebtn).setVisibility(View.GONE); + v.findViewById(R.id.multirt_view_setdefaultbtn).setVisibility(View.GONE); + + if(rt.versionString != null) { + javaVersionView.setText(ctx.getString(R.string.multirt_java_ver, rt.name, rt.javaVersion)); + fullJavaVersionView.setText(rt.versionString); + }else{ + javaVersionView.setText(rt.name); + fullJavaVersionView.setText(R.string.multirt_runtime_corrupt); + } + return v; + } + + @Override + public int getItemViewType(int position) { + return 0; + } + + @Override + public int getViewTypeCount() { + return 1; + } + + @Override + public boolean isEmpty() { + return runtimes.isEmpty(); + } + + @Override + public View getDropDownView(int position, View convertView, ViewGroup parent) { + return getView(position,convertView,parent); + } + +} diff --git a/app_2009scape/src/main/java/net/kdt/pojavlaunch/prefs/BackButtonPreference.java b/app_2009scape/src/main/java/net/kdt/pojavlaunch/prefs/BackButtonPreference.java index 8621cbe2f..00a8a2e2a 100644 --- a/app_2009scape/src/main/java/net/kdt/pojavlaunch/prefs/BackButtonPreference.java +++ b/app_2009scape/src/main/java/net/kdt/pojavlaunch/prefs/BackButtonPreference.java @@ -6,7 +6,6 @@ import android.util.AttributeSet; import androidx.preference.Preference; import net.kdt.pojavlaunch.R; -import net.kdt.pojavlaunch.extra.ExtraCore; public class BackButtonPreference extends Preference { public BackButtonPreference(Context context, AttributeSet attrs) { @@ -31,6 +30,5 @@ public class BackButtonPreference extends Preference { @Override protected void onClick() { // It is caught by an ExtraListener in the LauncherActivity - ExtraCore.setValue("back_preference", "true"); } } diff --git a/app_2009scape/src/main/java/net/kdt/pojavlaunch/utils/JREUtils.java b/app_2009scape/src/main/java/net/kdt/pojavlaunch/utils/JREUtils.java index e60814fcd..374b7630c 100644 --- a/app_2009scape/src/main/java/net/kdt/pojavlaunch/utils/JREUtils.java +++ b/app_2009scape/src/main/java/net/kdt/pojavlaunch/utils/JREUtils.java @@ -318,9 +318,6 @@ public class JREUtils { if (exitCode != 0) { activity.runOnUiThread(() -> { AlertDialog.Builder dialog = new AlertDialog.Builder(activity); - dialog.setMessage(activity.getString(R.string.mcn_exit_title, exitCode)); - - dialog.setPositiveButton(android.R.string.ok, (p1, p2) -> BaseMainActivity.fullyExit()); dialog.show(); }); } diff --git a/app_2009scape/src/main/java/org/lwjgl/glfw/CallbackBridge.java b/app_2009scape/src/main/java/org/lwjgl/glfw/CallbackBridge.java index 13460241f..d4396e9f4 100644 --- a/app_2009scape/src/main/java/org/lwjgl/glfw/CallbackBridge.java +++ b/app_2009scape/src/main/java/org/lwjgl/glfw/CallbackBridge.java @@ -122,9 +122,6 @@ public class CallbackBridge { public static String accessAndroidClipboard(int type, String copy) { switch (type) { case CLIPBOARD_COPY: - BaseMainActivity.GLOBAL_CLIPBOARD.setPrimaryClip(ClipData.newPlainText("Copy", copy)); - return null; - case CLIPBOARD_PASTE: if (BaseMainActivity.GLOBAL_CLIPBOARD.hasPrimaryClip() && BaseMainActivity.GLOBAL_CLIPBOARD.getPrimaryClipDescription().hasMimeType(ClipDescription.MIMETYPE_TEXT_PLAIN)) { return BaseMainActivity.GLOBAL_CLIPBOARD.getPrimaryClip().getItemAt(0).getText().toString(); diff --git a/app_2009scape/src/main/jni/stdio_is.c b/app_2009scape/src/main/jni/stdio_is.c index f422c3695..7fce8c103 100644 --- a/app_2009scape/src/main/jni/stdio_is.c +++ b/app_2009scape/src/main/jni/stdio_is.c @@ -80,8 +80,6 @@ void custom_exit(int code) { JNIEXPORT void JNICALL Java_net_kdt_pojavlaunch_utils_JREUtils_setupExitTrap(JNIEnv *env, jclass clazz, jobject context) { exitTrap_ctx = (*env)->NewGlobalRef(env,context); (*env)->GetJavaVM(env,&exitTrap_jvm); - exitTrap_exitClass = (*env)->NewGlobalRef(env,(*env)->FindClass(env,"net/kdt/pojavlaunch/ExitActivity")); - exitTrap_staticMethod = (*env)->GetStaticMethodID(env,exitTrap_exitClass,"showExitMessage","(Landroid/content/Context;I)V"); xhook_enable_debug(1); xhook_register(".*\\.so$","exit",custom_exit,&old_exit); xhook_refresh(1); diff --git a/app_2009scape/src/main/res/layout/main_with_customctrl.xml b/app_2009scape/src/main/res/layout/main_with_customctrl.xml index 830440bab..4cf59d6af 100644 --- a/app_2009scape/src/main/res/layout/main_with_customctrl.xml +++ b/app_2009scape/src/main/res/layout/main_with_customctrl.xml @@ -20,10 +20,6 @@ android:layout_width="match_parent" android:layout_height="match_parent"> -