Cleanup, part 2

This commit is contained in:
artdeell 2023-04-30 21:30:11 +03:00
parent 57b37dfc8c
commit 8e669caa2e
63 changed files with 423 additions and 707 deletions

View File

@ -591,7 +591,7 @@ public class AWTInputEvent {
/** /**
* Constant for the Microsoft Windows "Windows" key. * Constant for the Microsoft Windows "Windows" key.
* It is used for both the left and right version of the key. * It is used for both the left and right version of the key.
* @see #getKeyLocation() * see getKeyLocation
* @since 1.5 * @since 1.5
*/ */
public static final int VK_WINDOWS = 0x020C; public static final int VK_WINDOWS = 0x020C;
@ -888,25 +888,25 @@ public class AWTInputEvent {
public static final int MOUSE_WHEEL = 7 + MOUSE_FIRST; public static final int MOUSE_WHEEL = 7 + MOUSE_FIRST;
/** /**
* Indicates no mouse buttons; used by {@link #getButton}. * Indicates no mouse buttons; used by getButton.
* @since 1.4 * @since 1.4
*/ */
public static final int NOBUTTON = 0; public static final int NOBUTTON = 0;
/** /**
* Indicates mouse button #1; used by {@link #getButton}. * Indicates mouse button #1; used by getButton.
* @since 1.4 * @since 1.4
*/ */
public static final int BUTTON1 = 1; public static final int BUTTON1 = 1;
/** /**
* Indicates mouse button #2; used by {@link #getButton}. * Indicates mouse button #2; used by getButton.
* @since 1.4 * @since 1.4
*/ */
public static final int BUTTON2 = 2; public static final int BUTTON2 = 2;
/** /**
* Indicates mouse button #3; used by {@link #getButton}. * Indicates mouse button #3; used by getButton.
* @since 1.4 * @since 1.4
*/ */
public static final int BUTTON3 = 3; public static final int BUTTON3 = 3;

View File

@ -6,11 +6,11 @@ import android.os.Build;
* This class aims at providing a simple and easy way to deal with the device architecture. * This class aims at providing a simple and easy way to deal with the device architecture.
*/ */
public class Architecture { public class Architecture {
public static int UNSUPPORTED_ARCH = -1; public static final int UNSUPPORTED_ARCH = -1;
public static int ARCH_ARM64 = 0x1; public static final int ARCH_ARM64 = 0x1;
public static int ARCH_ARM = 0x2; public static final int ARCH_ARM = 0x2;
public static int ARCH_X86 = 0x4; public static final int ARCH_X86 = 0x4;
public static int ARCH_X86_64 = 0x8; public static final int ARCH_X86_64 = 0x8;
/** /**
* Tell us if the device supports 64 bits architecture * Tell us if the device supports 64 bits architecture
@ -58,14 +58,6 @@ public class Architecture {
return false; 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();
}
/** /**

View File

@ -28,6 +28,7 @@ import java.io.OutputStream;
/** /**
* An activity dedicated to importing control files. * An activity dedicated to importing control files.
*/ */
@SuppressWarnings("IOStreamConstructor")
public class ImportControlActivity extends Activity { public class ImportControlActivity extends Activity {
private Uri mUriData; private Uri mUriData;
@ -75,7 +76,7 @@ public class ImportControlActivity extends Activity {
//Import and verify thread //Import and verify thread
//Kill the app if the file isn't valid. //Kill the app if the file isn't valid.
new Thread(() -> { new Thread(() -> {
importControlFile("TMP_IMPORT_FILE"); importControlFile();
if(verify())mIsFileVerified = true; if(verify())mIsFileVerified = true;
else runOnUiThread(() -> { else runOnUiThread(() -> {
@ -118,23 +119,19 @@ public class ImportControlActivity extends Activity {
/** /**
* Copy a the file from the Intent data with a provided name into the controlmap folder. * Copy a the file from the Intent data with a provided name into the controlmap folder.
* @param fileName The file name to use.
* @return whether the file was successfully imported
*/ */
private boolean importControlFile(String fileName){ private void importControlFile(){
InputStream is; InputStream is;
try { try {
is = getContentResolver().openInputStream(mUriData); is = getContentResolver().openInputStream(mUriData);
OutputStream os = new FileOutputStream(Tools.CTRLMAP_PATH + "/" + fileName + ".json"); OutputStream os = new FileOutputStream(Tools.CTRLMAP_PATH + "/" + "TMP_IMPORT_FILE" + ".json");
IOUtils.copy(is, os); IOUtils.copy(is, os);
os.close(); os.close();
is.close(); is.close();
return true;
} catch (IOException e) { } catch (IOException e) {
e.printStackTrace(); e.printStackTrace();
} }
return false;
} }
/** /**
@ -146,9 +143,7 @@ public class ImportControlActivity extends Activity {
fileName = trimFileName(fileName); fileName = trimFileName(fileName);
if(fileName.isEmpty()) return false; if(fileName.isEmpty()) return false;
if (FileUtils.exists(Tools.CTRLMAP_PATH + "/" + fileName + ".json")) return false; return !FileUtils.exists(Tools.CTRLMAP_PATH + "/" + fileName + ".json");
return true;
} }
/** /**

View File

@ -3,32 +3,41 @@ package net.kdt.pojavlaunch;
import static net.kdt.pojavlaunch.MainActivity.fullyExit; import static net.kdt.pojavlaunch.MainActivity.fullyExit;
import android.annotation.SuppressLint; import android.annotation.SuppressLint;
import android.os.*; import android.os.Bundle;
import android.util.*; import android.util.Log;
import android.view.*; import android.view.GestureDetector;
import android.widget.*; import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.Toast;
import androidx.activity.OnBackPressedCallback; import androidx.activity.OnBackPressedCallback;
import java.io.*; import com.kdt.LoggerView;
import java.nio.ByteBuffer;
import java.util.*;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import net.kdt.pojavlaunch.customcontrols.keyboard.AwtCharSender; import net.kdt.pojavlaunch.customcontrols.keyboard.AwtCharSender;
import net.kdt.pojavlaunch.customcontrols.keyboard.TouchCharInput; import net.kdt.pojavlaunch.customcontrols.keyboard.TouchCharInput;
import net.kdt.pojavlaunch.multirt.MultiRTUtils; import net.kdt.pojavlaunch.multirt.MultiRTUtils;
import net.kdt.pojavlaunch.multirt.Runtime; import net.kdt.pojavlaunch.prefs.LauncherPreferences;
import net.kdt.pojavlaunch.prefs.*; import net.kdt.pojavlaunch.utils.JREUtils;
import net.kdt.pojavlaunch.utils.*; import net.kdt.pojavlaunch.utils.MathUtils;
import org.lwjgl.glfw.*;
import com.kdt.LoggerView; import org.lwjgl.glfw.CallbackBridge;
import java.io.File;
import java.io.InputStream;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
public class JavaGUILauncherActivity extends BaseActivity implements View.OnTouchListener { public class JavaGUILauncherActivity extends BaseActivity implements View.OnTouchListener {
private static final int MSG_LEFT_MOUSE_BUTTON_CHECK = 1028;
private AWTCanvasView mTextureView; private AWTCanvasView mTextureView;
private LoggerView mLoggerView; private LoggerView mLoggerView;
private TouchCharInput mTouchCharInput; private TouchCharInput mTouchCharInput;
@ -128,7 +137,7 @@ public class JavaGUILauncherActivity extends BaseActivity implements View.OnTouc
try { try {
placeMouseAt(CallbackBridge.physicalWidth / 2, CallbackBridge.physicalHeight / 2); placeMouseAt(CallbackBridge.physicalWidth / 2f, CallbackBridge.physicalHeight / 2f);
final File modFile = (File) getIntent().getExtras().getSerializable("modFile"); final File modFile = (File) getIntent().getExtras().getSerializable("modFile");
final String javaArgs = getIntent().getExtras().getString("javaArgs"); final String javaArgs = getIntent().getExtras().getString("javaArgs");
@ -188,6 +197,7 @@ public class JavaGUILauncherActivity extends BaseActivity implements View.OnTouc
@SuppressLint("ClickableViewAccessibility")
@Override @Override
public boolean onTouch(View v, MotionEvent e) { public boolean onTouch(View v, MotionEvent e) {
boolean isDown; boolean isDown;
@ -231,16 +241,12 @@ public class JavaGUILauncherActivity extends BaseActivity implements View.OnTouc
return true; return true;
} }
public void placeMouseAdd(float x, float y) {
mMousePointerImageView.setX(mMousePointerImageView.getX() + x);
mMousePointerImageView.setY(mMousePointerImageView.getY() + y);
}
public void placeMouseAt(float x, float y) { public void placeMouseAt(float x, float y) {
mMousePointerImageView.setX(x); mMousePointerImageView.setX(x);
mMousePointerImageView.setY(y); mMousePointerImageView.setY(y);
} }
@SuppressWarnings("SuspiciousNameCombination")
void sendScaledMousePosition(float x, float y){ void sendScaledMousePosition(float x, float y){
// Clamp positions to the borders of the usable view, then scale them // Clamp positions to the borders of the usable view, then scale them
x = androidx.core.math.MathUtils.clamp(x, mTextureView.getX(), mTextureView.getX() + mTextureView.getWidth()); x = androidx.core.math.MathUtils.clamp(x, mTextureView.getX(), mTextureView.getX() + mTextureView.getWidth());
@ -260,14 +266,6 @@ public class JavaGUILauncherActivity extends BaseActivity implements View.OnTouc
mLoggerView.setVisibility(View.VISIBLE); mLoggerView.setVisibility(View.VISIBLE);
} }
public void closeLogOutput(View view) {
if (mSkipDetectMod) {
mLoggerView.setVisibility(View.GONE);
} else {
forceClose(null);
}
}
public void toggleVirtualMouse(View v) { public void toggleVirtualMouse(View v) {
mIsVirtualMouseEnabled = !mIsVirtualMouseEnabled; mIsVirtualMouseEnabled = !mIsVirtualMouseEnabled;
mTouchPad.setVisibility(mIsVirtualMouseEnabled ? View.VISIBLE : View.GONE); mTouchPad.setVisibility(mIsVirtualMouseEnabled ? View.VISIBLE : View.GONE);
@ -279,7 +277,7 @@ public class JavaGUILauncherActivity extends BaseActivity implements View.OnTouc
public int launchJavaRuntime(File modFile, String javaArgs) { public int launchJavaRuntime(File modFile, String javaArgs) {
JREUtils.redirectAndPrintJRELog(); JREUtils.redirectAndPrintJRELog();
try { try {
List<String> javaArgList = new ArrayList<String>(); List<String> javaArgList = new ArrayList<>();
// Enable Caciocavallo // Enable Caciocavallo
Tools.getCacioJavaArgs(javaArgList,MultiRTUtils.getSelectedRuntime().javaVersion == 8); Tools.getCacioJavaArgs(javaArgList,MultiRTUtils.getSelectedRuntime().javaVersion == 8);
@ -311,7 +309,7 @@ public class JavaGUILauncherActivity extends BaseActivity implements View.OnTouc
private int doCustomInstall(File modFile, String javaArgs) throws IOException { private int doCustomInstall(File modFile, String javaArgs) {
mSkipDetectMod = true; mSkipDetectMod = true;
return launchJavaRuntime(modFile, javaArgs); return launchJavaRuntime(modFile, javaArgs);
} }

View File

@ -230,6 +230,7 @@ public class LauncherActivity extends BaseActivity {
LauncherPreferences.computeNotchSize(this); LauncherPreferences.computeNotchSize(this);
} }
@SuppressWarnings("SameParameterValue")
private Fragment getVisibleFragment(String tag){ private Fragment getVisibleFragment(String tag){
Fragment fragment = getSupportFragmentManager().findFragmentByTag(tag); Fragment fragment = getSupportFragmentManager().findFragmentByTag(tag);
if(fragment != null && fragment.isVisible()) { if(fragment != null && fragment.isVisible()) {
@ -238,6 +239,7 @@ public class LauncherActivity extends BaseActivity {
return null; return null;
} }
@SuppressWarnings("unused")
private Fragment getVisibleFragment(int id){ private Fragment getVisibleFragment(int id){
Fragment fragment = getSupportFragmentManager().findFragmentById(id); Fragment fragment = getSupportFragmentManager().findFragmentById(id);
if(fragment != null && fragment.isVisible()) { if(fragment != null && fragment.isVisible()) {

View File

@ -12,7 +12,7 @@ import java.lang.ref.WeakReference;
*/ */
@Keep @Keep
public class Logger { public class Logger {
private static Logger sLoggerSingleton = null; private static volatile Logger sLoggerSingleton = null;
/* Instance variables */ /* Instance variables */
private final File mLogFile; private final File mLogFile;
@ -21,11 +21,7 @@ public class Logger {
/* No public construction */ /* No public construction */
private Logger(){ private Logger(){
this("latestlog.txt"); mLogFile = new File(Tools.DIR_GAME_HOME, "latestlog.txt");
}
private Logger(String fileName){
mLogFile = new File(Tools.DIR_GAME_HOME, fileName);
// Make a new instance of the log file // Make a new instance of the log file
// Default PrintStream constructor will overwrite the file for us // Default PrintStream constructor will overwrite the file for us
try { try {
@ -66,11 +62,6 @@ public class Logger {
}catch (IOException e){ e.printStackTrace();} }catch (IOException e){ e.printStackTrace();}
} }
/** Disables the printing */
public void shutdown(){
mLogStream.close();
}
/** /**
* Perform various checks to see if the log is safe to print * Perform various checks to see if the log is safe to print
* Subclasses may want to override this behavior * Subclasses may want to override this behavior

View File

@ -174,10 +174,10 @@ public class LwjglGlfwKeycode {
/** If this bit is set one or more Super keys were held down. */ /** If this bit is set one or more Super keys were held down. */
public static final int GLFW_MOD_SUPER = 0x8; public static final int GLFW_MOD_SUPER = 0x8;
/** If this bit is set the Caps Lock key is enabled and the {@link #GLFW_LOCK_KEY_MODS LOCK_KEY_MODS} input mode is set. */ /** If this bit is set the Caps Lock key is enabled and the LOCK_KEY_MODS input mode is set. */
public static final int GLFW_MOD_CAPS_LOCK = 0x10; public static final int GLFW_MOD_CAPS_LOCK = 0x10;
/** If this bit is set the Num Lock key is enabled and the {@link #GLFW_LOCK_KEY_MODS LOCK_KEY_MODS} input mode is set. */ /** If this bit is set the Num Lock key is enabled and the LOCK_KEY_MODS input mode is set. */
public static final int GLFW_MOD_NUM_LOCK = 0x20; public static final int GLFW_MOD_NUM_LOCK = 0x20;

View File

@ -51,8 +51,6 @@ public class MainActivity extends BaseActivity implements ControlButtonMenuListe
volatile public static boolean isInputStackCall; volatile public static boolean isInputStackCall;
public float scaleFactor = 1;
public static TouchCharInput touchCharInput; public static TouchCharInput touchCharInput;
private MinecraftGLSurface minecraftGLView; private MinecraftGLSurface minecraftGLView;
private static Touchpad touchpad; private static Touchpad touchpad;
@ -81,7 +79,7 @@ public class MainActivity extends BaseActivity implements ControlButtonMenuListe
mProfile = PojavProfile.getCurrentProfileContent(this, null); mProfile = PojavProfile.getCurrentProfileContent(this, null);
if(LauncherProfiles.mainProfileJson == null) LauncherProfiles.update(); if(LauncherProfiles.mainProfileJson == null) LauncherProfiles.update();
minecraftProfile = LauncherProfiles.mainProfileJson.profiles.get(LauncherPreferences.DEFAULT_PREF.getString(LauncherPreferences.PREF_KEY_CURRENT_PROFILE,"")); minecraftProfile = LauncherProfiles.mainProfileJson.profiles.get(LauncherPreferences.DEFAULT_PREF.getString(LauncherPreferences.PREF_KEY_CURRENT_PROFILE,""));
MCOptionUtils.load(Tools.getGameDirPath(minecraftProfile)); MCOptionUtils.load(Tools.getGameDirPath(minecraftProfile).getAbsolutePath());
GameService.startService(this); GameService.startService(this);
initLayout(R.layout.activity_basemain); initLayout(R.layout.activity_basemain);
CallbackBridge.addGrabListener(touchpad); CallbackBridge.addGrabListener(touchpad);
@ -155,8 +153,8 @@ public class MainActivity extends BaseActivity implements ControlButtonMenuListe
CallbackBridge.nativeSetUseInputStackQueue(isInputStackCall); CallbackBridge.nativeSetUseInputStackQueue(isInputStackCall);
Tools.getDisplayMetrics(this); Tools.getDisplayMetrics(this);
windowWidth = Tools.getDisplayFriendlyRes(currentDisplayMetrics.widthPixels, scaleFactor); windowWidth = Tools.getDisplayFriendlyRes(currentDisplayMetrics.widthPixels, 1f);
windowHeight = Tools.getDisplayFriendlyRes(currentDisplayMetrics.heightPixels, scaleFactor); windowHeight = Tools.getDisplayFriendlyRes(currentDisplayMetrics.heightPixels, 1f);
// Menu // Menu

View File

@ -54,6 +54,7 @@ public class MinecraftGLSurface extends View implements GrabListener{
private final TapDetector mDoubleTapDetector = new TapDetector(2, TapDetector.DETECTION_METHOD_DOWN); private final TapDetector mDoubleTapDetector = new TapDetector(2, TapDetector.DETECTION_METHOD_DOWN);
/* MC GUI scale, listened by MCOptionUtils */ /* MC GUI scale, listened by MCOptionUtils */
private int mGuiScale; private int mGuiScale;
@SuppressWarnings("FieldCanBeLocal") // it can't, otherwise the weak reference will disappear
private final MCOptionUtils.MCOptionListener mGuiScaleListener = () -> mGuiScale = getMcScale(); private final MCOptionUtils.MCOptionListener mGuiScaleListener = () -> mGuiScale = getMcScale();
/* Surface ready listener, used by the activity to launch minecraft */ /* Surface ready listener, used by the activity to launch minecraft */
SurfaceReadyListener mSurfaceReadyListener = null; SurfaceReadyListener mSurfaceReadyListener = null;

View File

@ -22,8 +22,8 @@ import net.kdt.pojavlaunch.tasks.AsyncAssetManager;
import net.kdt.pojavlaunch.utils.*; import net.kdt.pojavlaunch.utils.*;
public class PojavApplication extends Application { public class PojavApplication extends Application {
public static String CRASH_REPORT_TAG = "PojavCrashReport"; public static final String CRASH_REPORT_TAG = "PojavCrashReport";
public static ExecutorService sExecutorService = new ThreadPoolExecutor(4, 4, 500, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<>()); public static final ExecutorService sExecutorService = new ThreadPoolExecutor(4, 4, 500, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<>());
@Override @Override
public void onCreate() { public void onCreate() {
@ -74,7 +74,7 @@ public class PojavApplication extends Application {
originalJNIDirectory.lastIndexOf("/")) originalJNIDirectory.lastIndexOf("/"))
.concat("/x86"); .concat("/x86");
} }
AsyncAssetManager.unpackRuntime(getAssets(), false); AsyncAssetManager.unpackRuntime(getAssets());
} catch (Throwable throwable) { } catch (Throwable throwable) {
Intent ferrorIntent = new Intent(this, FatalErrorActivity.class); Intent ferrorIntent = new Intent(this, FatalErrorActivity.class);
ferrorIntent.putExtra("throwable", throwable); ferrorIntent.putExtra("throwable", throwable);

View File

@ -1,44 +1,38 @@
package net.kdt.pojavlaunch; package net.kdt.pojavlaunch;
import android.app.*;
import android.content.*;
import android.content.res.Configuration;
import android.database.Cursor;
import android.net.*;
import android.os.*;
import android.provider.OpenableColumns;
import android.util.*;
import com.google.gson.*;
import java.io.*;
import java.lang.reflect.*;
import java.nio.charset.*;
import java.util.*;
import net.kdt.pojavlaunch.extra.ExtraConstants;
import net.kdt.pojavlaunch.extra.ExtraCore;
import net.kdt.pojavlaunch.multirt.MultiRTUtils;
import net.kdt.pojavlaunch.plugins.FFmpegPlugin;
import net.kdt.pojavlaunch.prefs.*;
import net.kdt.pojavlaunch.utils.*;
import net.kdt.pojavlaunch.value.*;
import net.kdt.pojavlaunch.value.launcherprofiles.LauncherProfiles;
import net.kdt.pojavlaunch.value.launcherprofiles.MinecraftProfile;
import org.apache.commons.codec.binary.Hex;
import org.apache.commons.io.IOUtils;
import org.lwjgl.glfw.*;
import android.view.*;
import android.webkit.MimeTypeMap;
import android.widget.EditText;
import android.widget.Toast;
import static android.os.Build.VERSION.SDK_INT; import static android.os.Build.VERSION.SDK_INT;
import static android.os.Build.VERSION_CODES.P; import static android.os.Build.VERSION_CODES.P;
import static net.kdt.pojavlaunch.PojavApplication.sExecutorService; import static net.kdt.pojavlaunch.PojavApplication.sExecutorService;
import static net.kdt.pojavlaunch.prefs.LauncherPreferences.PREF_IGNORE_NOTCH; import static net.kdt.pojavlaunch.prefs.LauncherPreferences.PREF_IGNORE_NOTCH;
import static net.kdt.pojavlaunch.prefs.LauncherPreferences.PREF_NOTCH_SIZE; import static net.kdt.pojavlaunch.prefs.LauncherPreferences.PREF_NOTCH_SIZE;
import android.app.Activity;
import android.app.ActivityManager;
import android.app.AlertDialog;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.ProgressDialog;
import android.content.ClipData;
import android.content.ClipboardManager;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.res.Configuration;
import android.database.Cursor;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.Environment;
import android.provider.OpenableColumns;
import android.util.ArrayMap;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.View;
import android.view.WindowManager;
import android.webkit.MimeTypeMap;
import android.widget.EditText;
import android.widget.Toast;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.core.app.NotificationManagerCompat; import androidx.core.app.NotificationManagerCompat;
@ -46,9 +40,42 @@ import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentActivity; import androidx.fragment.app.FragmentActivity;
import androidx.fragment.app.FragmentTransaction; import androidx.fragment.app.FragmentTransaction;
public final class Tools { import com.google.gson.Gson;
public static final boolean ENABLE_DEV_FEATURES = BuildConfig.DEBUG; import com.google.gson.GsonBuilder;
import net.kdt.pojavlaunch.multirt.MultiRTUtils;
import net.kdt.pojavlaunch.plugins.FFmpegPlugin;
import net.kdt.pojavlaunch.prefs.LauncherPreferences;
import net.kdt.pojavlaunch.utils.DownloadUtils;
import net.kdt.pojavlaunch.utils.JREUtils;
import net.kdt.pojavlaunch.utils.JSONUtils;
import net.kdt.pojavlaunch.utils.OldVersionsUtils;
import net.kdt.pojavlaunch.value.DependentLibrary;
import net.kdt.pojavlaunch.value.MinecraftAccount;
import net.kdt.pojavlaunch.value.launcherprofiles.LauncherProfiles;
import net.kdt.pojavlaunch.value.launcherprofiles.MinecraftProfile;
import org.apache.commons.codec.binary.Hex;
import org.apache.commons.io.IOUtils;
import org.lwjgl.glfw.CallbackBridge;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.lang.reflect.Field;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
@SuppressWarnings("IOStreamConstructor")
public final class Tools {
public static String APP_NAME = "null"; public static String APP_NAME = "null";
public static final Gson GLOBAL_GSON = new GsonBuilder().setPrettyPrinting().create(); public static final Gson GLOBAL_GSON = new GsonBuilder().setPrettyPrinting().create();
@ -60,14 +87,13 @@ public final class Tools {
public static String MULTIRT_HOME; public static String MULTIRT_HOME;
public static String LOCAL_RENDERER = null; public static String LOCAL_RENDERER = null;
public static int DEVICE_ARCHITECTURE; public static int DEVICE_ARCHITECTURE;
public static String LAUNCHERPROFILES_RTPREFIX = "pojav://"; public static final String LAUNCHERPROFILES_RTPREFIX = "pojav://";
// New since 3.3.1 // New since 3.3.1
public static String DIR_ACCOUNT_NEW; public static String DIR_ACCOUNT_NEW;
public static String DIR_ACCOUNT_OLD; public static String DIR_ACCOUNT_OLD;
public static String DIR_GAME_HOME = Environment.getExternalStorageDirectory().getAbsolutePath() + "/games/PojavLauncher"; public static String DIR_GAME_HOME = Environment.getExternalStorageDirectory().getAbsolutePath() + "/games/PojavLauncher";
public static String DIR_GAME_NEW; public static String DIR_GAME_NEW;
public static String DIR_GAME_OLD = Environment.getExternalStorageDirectory().getAbsolutePath() + "/games/.minecraft";
// New since 3.0.0 // New since 3.0.0
public static String DIR_HOME_JRE; public static String DIR_HOME_JRE;
@ -83,8 +109,6 @@ public final class Tools {
public static String OBSOLETE_RESOURCES_PATH; public static String OBSOLETE_RESOURCES_PATH;
public static String CTRLMAP_PATH; public static String CTRLMAP_PATH;
public static String CTRLDEF_FILE; public static String CTRLDEF_FILE;
public static final String LIBNAME_OPTIFINE = "optifine:OptiFine";
public static final int RUN_MOD_INSTALLER = 2050; public static final int RUN_MOD_INSTALLER = 2050;
@ -130,13 +154,12 @@ public final class Tools {
public static void launchMinecraft(final Activity activity, MinecraftAccount minecraftAccount, public static void launchMinecraft(final Activity activity, MinecraftAccount minecraftAccount,
MinecraftProfile minecraftProfile, String versionId) throws Throwable { MinecraftProfile minecraftProfile, String versionId) throws Throwable {
ActivityManager.MemoryInfo mi = new ActivityManager.MemoryInfo(); int freeDeviceMemory = getFreeDeviceMemory(activity);
((ActivityManager)activity.getSystemService(Context.ACTIVITY_SERVICE)).getMemoryInfo(mi); if(LauncherPreferences.PREF_RAM_ALLOCATION > freeDeviceMemory) {
if(LauncherPreferences.PREF_RAM_ALLOCATION > (mi.availMem/1048576L)) {
Object memoryErrorLock = new Object(); Object memoryErrorLock = new Object();
activity.runOnUiThread(() -> { activity.runOnUiThread(() -> {
androidx.appcompat.app.AlertDialog.Builder b = new androidx.appcompat.app.AlertDialog.Builder(activity) 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)) .setMessage(activity.getString(R.string.memory_warning_msg, freeDeviceMemory ,LauncherPreferences.PREF_RAM_ALLOCATION))
.setPositiveButton(android.R.string.ok, (dialogInterface, i) -> {synchronized(memoryErrorLock){memoryErrorLock.notifyAll();}}) .setPositiveButton(android.R.string.ok, (dialogInterface, i) -> {synchronized(memoryErrorLock){memoryErrorLock.notifyAll();}})
.setOnCancelListener((i) -> {synchronized(memoryErrorLock){memoryErrorLock.notifyAll();}}); .setOnCancelListener((i) -> {synchronized(memoryErrorLock){memoryErrorLock.notifyAll();}});
b.show(); b.show();
@ -147,12 +170,12 @@ public final class Tools {
} }
JMinecraftVersionList.Version versionInfo = Tools.getVersionInfo(versionId); JMinecraftVersionList.Version versionInfo = Tools.getVersionInfo(versionId);
LauncherProfiles.update(); LauncherProfiles.update();
String gamedirPath = Tools.getGameDirPath(minecraftProfile); File gamedir = Tools.getGameDirPath(minecraftProfile);
// Pre-process specific files // Pre-process specific files
disableSplash(gamedirPath); disableSplash(gamedir);
String[] launchArgs = getMinecraftClientArgs(minecraftAccount, versionInfo, gamedirPath); String[] launchArgs = getMinecraftClientArgs(minecraftAccount, versionInfo, gamedir);
// Select the appropriate openGL version // Select the appropriate openGL version
OldVersionsUtils.selectOpenGlVersion(versionInfo); OldVersionsUtils.selectOpenGlVersion(versionInfo);
@ -160,7 +183,7 @@ public final class Tools {
String launchClassPath = generateLaunchClassPath(versionInfo, versionId); String launchClassPath = generateLaunchClassPath(versionInfo, versionId);
List<String> javaArgList = new ArrayList<String>(); List<String> javaArgList = new ArrayList<>();
getCacioJavaArgs(javaArgList, MultiRTUtils.getSelectedRuntime().javaVersion == 8); getCacioJavaArgs(javaArgList, MultiRTUtils.getSelectedRuntime().javaVersion == 8);
@ -171,7 +194,7 @@ public final class Tools {
} }
javaArgList.add("-Dlog4j.configurationFile=" + configFile); javaArgList.add("-Dlog4j.configurationFile=" + configFile);
} }
javaArgList.addAll(Arrays.asList(getMinecraftJVMArgs(versionId, gamedirPath))); javaArgList.addAll(Arrays.asList(getMinecraftJVMArgs(versionId, gamedir)));
javaArgList.add("-cp"); javaArgList.add("-cp");
javaArgList.add(getLWJGL3ClassPath() + ":" + launchClassPath); javaArgList.add(getLWJGL3ClassPath() + ":" + launchClassPath);
@ -181,17 +204,17 @@ public final class Tools {
FFmpegPlugin.discover(activity); FFmpegPlugin.discover(activity);
String args = LauncherPreferences.PREF_CUSTOM_JAVA_ARGS; String args = LauncherPreferences.PREF_CUSTOM_JAVA_ARGS;
if(Tools.isValidString(minecraftProfile.javaArgs)) args = minecraftProfile.javaArgs; if(Tools.isValidString(minecraftProfile.javaArgs)) args = minecraftProfile.javaArgs;
JREUtils.launchJavaVM(activity, gamedirPath, javaArgList, args); JREUtils.launchJavaVM(activity, gamedir, javaArgList, args);
} }
public static String getGameDirPath(@NonNull MinecraftProfile minecraftProfile){ public static File getGameDirPath(@NonNull MinecraftProfile minecraftProfile){
if(minecraftProfile.gameDir != null){ if(minecraftProfile.gameDir != null){
if(minecraftProfile.gameDir.startsWith(Tools.LAUNCHERPROFILES_RTPREFIX)) if(minecraftProfile.gameDir.startsWith(Tools.LAUNCHERPROFILES_RTPREFIX))
return minecraftProfile.gameDir.replace(Tools.LAUNCHERPROFILES_RTPREFIX,Tools.DIR_GAME_HOME+"/"); return new File(minecraftProfile.gameDir.replace(Tools.LAUNCHERPROFILES_RTPREFIX,Tools.DIR_GAME_HOME+"/"));
else else
return Tools.DIR_GAME_HOME + '/' + minecraftProfile.gameDir; return new File(Tools.DIR_GAME_HOME,minecraftProfile.gameDir);
} }
return Tools.DIR_GAME_NEW; return new File(Tools.DIR_GAME_NEW);
} }
public static void buildNotificationChannel(Context context){ public static void buildNotificationChannel(Context context){
@ -202,26 +225,24 @@ public final class Tools {
NotificationManagerCompat manager = NotificationManagerCompat.from(context); NotificationManagerCompat manager = NotificationManagerCompat.from(context);
manager.createNotificationChannel(channel); manager.createNotificationChannel(channel);
} }
public static void disableSplash(File dir) {
private static boolean mkdirs(String path) { File configDir = new File(dir, "config");
File file = new File(path); if(configDir.exists() || configDir.mkdirs()) {
return file.mkdirs(); File forgeSplashFile = new File(dir, "config/splash.properties");
} String forgeSplashContent = "enabled=true";
try {
public static void disableSplash(String dir) { if (forgeSplashFile.exists()) {
mkdirs(dir + "/config"); forgeSplashContent = Tools.read(forgeSplashFile.getAbsolutePath());
File forgeSplashFile = new File(dir, "config/splash.properties"); }
String forgeSplashContent = "enabled=true"; if (forgeSplashContent.contains("enabled=true")) {
try { Tools.write(forgeSplashFile.getAbsolutePath(),
if (forgeSplashFile.exists()) { forgeSplashContent.replace("enabled=true", "enabled=false"));
forgeSplashContent = Tools.read(forgeSplashFile.getAbsolutePath()); }
} catch (IOException e) {
Log.w(Tools.APP_NAME, "Could not disable Forge 1.12.2 and below splash screen!", e);
} }
if (forgeSplashContent.contains("enabled=true")) { } else {
Tools.write(forgeSplashFile.getAbsolutePath(), Log.w(Tools.APP_NAME, "Failed to create the configuration directory");
forgeSplashContent.replace("enabled=true", "enabled=false"));
}
} catch (IOException e) {
Log.w(Tools.APP_NAME, "Could not disable Forge 1.12.2 and below splash screen!", e);
} }
} }
@ -261,19 +282,20 @@ public final class Tools {
} }
StringBuilder cacioClasspath = new StringBuilder(); StringBuilder cacioClasspath = new StringBuilder();
cacioClasspath.append("-Xbootclasspath/" + (isJava8 ? "p" : "a")); cacioClasspath.append("-Xbootclasspath/").append(isJava8 ? "p" : "a");
File cacioDir = new File(DIR_GAME_HOME + "/caciocavallo" + (isJava8 ? "" : "17")); File cacioDir = new File(DIR_GAME_HOME + "/caciocavallo" + (isJava8 ? "" : "17"));
if (cacioDir.exists() && cacioDir.isDirectory()) { File[] cacioFiles = cacioDir.listFiles();
for (File file : cacioDir.listFiles()) { if (cacioFiles != null) {
for (File file : cacioFiles) {
if (file.getName().endsWith(".jar")) { if (file.getName().endsWith(".jar")) {
cacioClasspath.append(":" + file.getAbsolutePath()); cacioClasspath.append(":").append(file.getAbsolutePath());
} }
} }
} }
javaArgList.add(cacioClasspath.toString()); javaArgList.add(cacioClasspath.toString());
} }
public static String[] getMinecraftJVMArgs(String versionName, String strGameDir) { public static String[] getMinecraftJVMArgs(String versionName, File gameDir) {
JMinecraftVersionList.Version versionInfo = Tools.getVersionInfo(versionName, true); JMinecraftVersionList.Version versionInfo = Tools.getVersionInfo(versionName, true);
// Parse Forge 1.17+ additional JVM Arguments // Parse Forge 1.17+ additional JVM Arguments
if (versionInfo.inheritsFrom == null || versionInfo.arguments == null || versionInfo.arguments.jvm == null) { if (versionInfo.inheritsFrom == null || versionInfo.arguments == null || versionInfo.arguments.jvm == null) {
@ -282,39 +304,22 @@ public final class Tools {
Map<String, String> varArgMap = new ArrayMap<>(); Map<String, String> varArgMap = new ArrayMap<>();
varArgMap.put("classpath_separator", ":"); varArgMap.put("classpath_separator", ":");
varArgMap.put("library_directory", strGameDir + "/libraries"); varArgMap.put("library_directory", new File(gameDir, "libraries").getAbsolutePath());
varArgMap.put("version_name", versionInfo.id); varArgMap.put("version_name", versionInfo.id);
varArgMap.put("natives_directory", Tools.NATIVE_LIB_DIR); varArgMap.put("natives_directory", Tools.NATIVE_LIB_DIR);
List<String> minecraftArgs = new ArrayList<String>(); List<String> minecraftArgs = new ArrayList<>();
if (versionInfo.arguments != null) { if (versionInfo.arguments != null) {
for (Object arg : versionInfo.arguments.jvm) { for (Object arg : versionInfo.arguments.jvm) {
if (arg instanceof String) { if (arg instanceof String) {
minecraftArgs.add((String) arg); minecraftArgs.add((String) arg);
} else { } //TODO: implement (?maybe?)
/*
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
}
}
*/
}
} }
} }
return JSONUtils.insertJSONValueList(minecraftArgs.toArray(new String[0]), varArgMap);
String[] argsFromJson = JSONUtils.insertJSONValueList(minecraftArgs.toArray(new String[0]), varArgMap);
// Tools.dialogOnUiThread(this, "Result args", Arrays.asList(argsFromJson).toString());
return argsFromJson;
} }
public static String[] getMinecraftClientArgs(MinecraftAccount profile, JMinecraftVersionList.Version versionInfo, String strGameDir) { public static String[] getMinecraftClientArgs(MinecraftAccount profile, JMinecraftVersionList.Version versionInfo, File gameDir) {
String username = profile.username; String username = profile.username;
String versionName = versionInfo.id; String versionName = versionInfo.id;
if (versionInfo.inheritsFrom != null) { if (versionInfo.inheritsFrom != null) {
@ -323,9 +328,6 @@ public final class Tools {
String userType = "mojang"; String userType = "mojang";
File gameDir = new File(strGameDir);
gameDir.mkdirs();
Map<String, String> varArgMap = new ArrayMap<>(); Map<String, String> varArgMap = new ArrayMap<>();
varArgMap.put("auth_session", profile.accessToken); // For legacy versions of MC varArgMap.put("auth_session", profile.accessToken); // For legacy versions of MC
varArgMap.put("auth_access_token", profile.accessToken); varArgMap.put("auth_access_token", profile.accessToken);
@ -341,39 +343,23 @@ public final class Tools {
varArgMap.put("version_name", versionName); varArgMap.put("version_name", versionName);
varArgMap.put("version_type", versionInfo.type); varArgMap.put("version_type", versionInfo.type);
List<String> minecraftArgs = new ArrayList<String>(); List<String> minecraftArgs = new ArrayList<>();
if (versionInfo.arguments != null) { if (versionInfo.arguments != null) {
// Support Minecraft 1.13+ // Support Minecraft 1.13+
for (Object arg : versionInfo.arguments.game) { for (Object arg : versionInfo.arguments.game) {
if (arg instanceof String) { if (arg instanceof String) {
minecraftArgs.add((String) arg); minecraftArgs.add((String) arg);
} else { } //TODO: implement else clause
/*
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
}
}
*/
}
} }
} }
String[] argsFromJson = JSONUtils.insertJSONValueList( return JSONUtils.insertJSONValueList(
splitAndFilterEmpty( splitAndFilterEmpty(
versionInfo.minecraftArguments == null ? versionInfo.minecraftArguments == null ?
fromStringArray(minecraftArgs.toArray(new String[0])): fromStringArray(minecraftArgs.toArray(new String[0])):
versionInfo.minecraftArguments versionInfo.minecraftArguments
), varArgMap ), varArgMap
); );
// Tools.dialogOnUiThread(this, "Result args", Arrays.asList(argsFromJson).toString());
return argsFromJson;
} }
public static String fromStringArray(String[] strArr) { public static String fromStringArray(String[] strArr) {
@ -387,7 +373,7 @@ public final class Tools {
} }
private static String[] splitAndFilterEmpty(String argStr) { private static String[] splitAndFilterEmpty(String argStr) {
List<String> strList = new ArrayList<String>(); List<String> strList = new ArrayList<>();
for (String arg : argStr.split(" ")) { for (String arg : argStr.split(" ")) {
if (!arg.isEmpty()) { if (!arg.isEmpty()) {
strList.add(arg); strList.add(arg);
@ -415,10 +401,11 @@ public final class Tools {
private static String getLWJGL3ClassPath() { private static String getLWJGL3ClassPath() {
StringBuilder libStr = new StringBuilder(); StringBuilder libStr = new StringBuilder();
File lwjgl3Folder = new File(Tools.DIR_GAME_HOME, "lwjgl3"); File lwjgl3Folder = new File(Tools.DIR_GAME_HOME, "lwjgl3");
if (/* info.arguments != null && */ lwjgl3Folder.exists()) { File[] lwjgl3Files = lwjgl3Folder.listFiles();
for (File file: lwjgl3Folder.listFiles()) { if (lwjgl3Files != null) {
for (File file: lwjgl3Files) {
if (file.getName().endsWith(".jar")) { if (file.getName().endsWith(".jar")) {
libStr.append(file.getAbsolutePath() + ":"); libStr.append(file.getAbsolutePath()).append(":");
} }
} }
} }
@ -427,7 +414,7 @@ public final class Tools {
return libStr.toString(); return libStr.toString();
} }
private static boolean isClientFirst = false; private final static boolean isClientFirst = false;
public static String generateLaunchClassPath(JMinecraftVersionList.Version info,String actualname) { public static String generateLaunchClassPath(JMinecraftVersionList.Version info,String actualname) {
StringBuilder libStr = new StringBuilder(); //versnDir + "/" + version + "/" + version + ".jar:"; StringBuilder libStr = new StringBuilder(); //versnDir + "/" + version + "/" + version + ".jar:";
@ -441,7 +428,7 @@ public final class Tools {
Log.d(APP_NAME, "Ignored non-exists file: " + perJar); Log.d(APP_NAME, "Ignored non-exists file: " + perJar);
continue; continue;
} }
libStr.append((isClientFirst ? ":" : "") + perJar + (!isClientFirst ? ":" : "")); libStr.append((isClientFirst ? ":" : "")).append(perJar).append(!isClientFirst ? ":" : "");
} }
if (!isClientFirst) { if (!isClientFirst) {
libStr.append(getPatchedFile(actualname)); libStr.append(getPatchedFile(actualname));
@ -520,8 +507,8 @@ public final class Tools {
public static void copyAssetFile(Context ctx, String fileName, String output, String outputName, boolean overwrite) throws IOException { public static void copyAssetFile(Context ctx, String fileName, String output, String outputName, boolean overwrite) throws IOException {
File parentFolder = new File(output); File parentFolder = new File(output);
if(!parentFolder.exists()) { if(!parentFolder.exists() && !parentFolder.mkdirs()) {
parentFolder.mkdirs(); throw new IOException("Failed to create parent directory");
} }
File destinationFile = new File(output, outputName); File destinationFile = new File(output, outputName);
if(!destinationFile.exists() || overwrite){ if(!destinationFile.exists() || overwrite){
@ -611,32 +598,6 @@ public final class Tools {
.show()); .show());
} }
public static void moveInside(String from, String to) {
File fromFile = new File(from);
for (File fromInside : fromFile.listFiles()) {
moveRecursive(fromInside.getAbsolutePath(), to);
}
fromFile.delete();
}
public static void moveRecursive(String from, String to) {
moveRecursive(new File(from), new File(to));
}
public static void moveRecursive(File from, File to) {
File toFrom = new File(to, from.getName());
try {
if (from.isDirectory()) {
for (File child : from.listFiles()) {
moveRecursive(child, toFrom);
}
}
} finally {
from.getParentFile().mkdirs();
from.renameTo(toFrom);
}
}
public static void openURL(Activity act, String url) { public static void openURL(Activity act, String url) {
Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(url)); Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
act.startActivity(browserIntent); act.startActivity(browserIntent);
@ -652,7 +613,7 @@ public final class Tools {
return true; // allow if none match return true; // allow if none match
} }
public static String[] generateLibClasspath(JMinecraftVersionList.Version info) { public static String[] generateLibClasspath(JMinecraftVersionList.Version info) {
List<String> libDir = new ArrayList<String>(); List<String> libDir = new ArrayList<>();
for (DependentLibrary libItem: info.libraries) { for (DependentLibrary libItem: info.libraries) {
if(!checkRules(libItem.rules)) continue; if(!checkRules(libItem.rules)) continue;
libDir.add(Tools.DIR_HOME_LIBRARY + "/" + Tools.artifactToPath(libItem.name)); libDir.add(Tools.DIR_HOME_LIBRARY + "/" + Tools.artifactToPath(libItem.name));
@ -664,18 +625,14 @@ public final class Tools {
return getVersionInfo(versionName, false); return getVersionInfo(versionName, false);
} }
@SuppressWarnings({"unchecked", "rawtypes"})
public static JMinecraftVersionList.Version getVersionInfo(String versionName, boolean skipInheriting) { public static JMinecraftVersionList.Version getVersionInfo(String versionName, boolean skipInheriting) {
try { try {
JMinecraftVersionList.Version customVer = Tools.GLOBAL_GSON.fromJson(read(DIR_HOME_VERSION + "/" + versionName + "/" + versionName + ".json"), JMinecraftVersionList.Version.class); JMinecraftVersionList.Version customVer = Tools.GLOBAL_GSON.fromJson(read(DIR_HOME_VERSION + "/" + versionName + "/" + versionName + ".json"), JMinecraftVersionList.Version.class);
if (skipInheriting || customVer.inheritsFrom == null || customVer.inheritsFrom.equals(customVer.id)) { if (skipInheriting || customVer.inheritsFrom == null || customVer.inheritsFrom.equals(customVer.id)) {
return customVer; return customVer;
} else { } else {
JMinecraftVersionList.Version inheritsVer = null; JMinecraftVersionList.Version inheritsVer;
/*for (JMinecraftVersionList.Version valueVer : ((JMinecraftVersionList) ExtraCore.getValue(ExtraConstants.RELEASE_TABLE)).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 //If it won't download, just search for it
try{ try{
inheritsVer = Tools.GLOBAL_GSON.fromJson(read(DIR_HOME_VERSION + "/" + customVer.inheritsFrom + "/" + customVer.inheritsFrom + ".json"), JMinecraftVersionList.Version.class); inheritsVer = Tools.GLOBAL_GSON.fromJson(read(DIR_HOME_VERSION + "/" + customVer.inheritsFrom + "/" + customVer.inheritsFrom + ".json"), JMinecraftVersionList.Version.class);
@ -689,7 +646,7 @@ public final class Tools {
"releaseTime", "time", "type" "releaseTime", "time", "type"
); );
List<DependentLibrary> libList = new ArrayList<DependentLibrary>(Arrays.asList(inheritsVer.libraries)); List<DependentLibrary> libList = new ArrayList<>(Arrays.asList(inheritsVer.libraries));
try { try {
loop_1: loop_1:
for (DependentLibrary lib : customVer.libraries) { for (DependentLibrary lib : customVer.libraries) {
@ -715,8 +672,7 @@ public final class Tools {
// Inheriting Minecraft 1.13+ with append custom args // Inheriting Minecraft 1.13+ with append custom args
if (inheritsVer.arguments != null && customVer.arguments != null) { if (inheritsVer.arguments != null && customVer.arguments != null) {
List totalArgList = new ArrayList(); List totalArgList = new ArrayList(Arrays.asList(inheritsVer.arguments.game));
totalArgList.addAll(Arrays.asList(inheritsVer.arguments.game));
int nskip = 0; int nskip = 0;
for (int i = 0; i < customVer.arguments.game.length; i++) { for (int i = 0; i < customVer.arguments.game.length; i++) {
@ -786,7 +742,9 @@ public final class Tools {
public static void write(String path, String content) throws IOException { public static void write(String path, String content) throws IOException {
File file = new File(path); File file = new File(path);
File parent = file.getParentFile(); File parent = file.getParentFile();
if(!parent.exists()) parent.mkdirs(); if(parent != null && !parent.exists()) {
if(!parent.mkdirs()) throw new IOException("Failed to create parent directory");
}
try(FileOutputStream outStream = new FileOutputStream(file)) { try(FileOutputStream outStream = new FileOutputStream(file)) {
IOUtils.write(content, outStream); IOUtils.write(content, outStream);
} }
@ -807,7 +765,7 @@ public final class Tools {
try (InputStream is = new FileInputStream(f)) { try (InputStream is = new FileInputStream(f)) {
sha1_dst = new String(Hex.encodeHex(org.apache.commons.codec.digest.DigestUtils.sha1(is))); sha1_dst = new String(Hex.encodeHex(org.apache.commons.codec.digest.DigestUtils.sha1(is)));
} }
if(sha1_dst != null && sourceSHA != null) { if(sourceSHA != null) {
return sha1_dst.equalsIgnoreCase(sourceSHA); return sha1_dst.equalsIgnoreCase(sourceSHA);
} else{ } else{
return true; // fake match return true; // fake match

View File

@ -6,6 +6,7 @@ import android.os.Looper;
import android.util.ArrayMap; import android.util.ArrayMap;
import android.util.Log; import android.util.Log;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import com.kdt.mcgui.ProgressLayout; import com.kdt.mcgui.ProgressLayout;
@ -26,6 +27,7 @@ import java.net.HttpURLConnection;
import java.net.ProtocolException; import java.net.ProtocolException;
import java.net.URL; import java.net.URL;
import java.net.URLEncoder; import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.Collections; import java.util.Collections;
import java.util.Map; import java.util.Map;
@ -52,7 +54,6 @@ public class MicrosoftBackgroundLogin {
} }
/* Fields used to fill the account */ /* Fields used to fill the account */
public boolean isRefresh;
public String msRefreshToken; public String msRefreshToken;
public String mcName; public String mcName;
public String mcToken; public String mcToken;
@ -60,10 +61,6 @@ public class MicrosoftBackgroundLogin {
public boolean doesOwnGame; public boolean doesOwnGame;
public long expiresAt; public long expiresAt;
public MicrosoftBackgroundLogin(String filename){
this(false, MinecraftAccount.load(filename).accessToken);
}
public MicrosoftBackgroundLogin(boolean isRefresh, String authCode){ public MicrosoftBackgroundLogin(boolean isRefresh, String authCode){
mIsRefresh = isRefresh; mIsRefresh = isRefresh;
mAuthCode = authCode; mAuthCode = authCode;
@ -133,14 +130,14 @@ public class MicrosoftBackgroundLogin {
HttpURLConnection conn = (HttpURLConnection)url.openConnection(); HttpURLConnection conn = (HttpURLConnection)url.openConnection();
conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded"); conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
conn.setRequestProperty("charset", "utf-8"); conn.setRequestProperty("charset", "utf-8");
conn.setRequestProperty("Content-Length", Integer.toString(formData.getBytes("UTF-8").length)); conn.setRequestProperty("Content-Length", Integer.toString(formData.getBytes(StandardCharsets.UTF_8).length));
conn.setRequestMethod("POST"); conn.setRequestMethod("POST");
conn.setUseCaches(false); conn.setUseCaches(false);
conn.setDoInput(true); conn.setDoInput(true);
conn.setDoOutput(true); conn.setDoOutput(true);
conn.connect(); conn.connect();
try(OutputStream wr = conn.getOutputStream()) { try(OutputStream wr = conn.getOutputStream()) {
wr.write(formData.getBytes("UTF-8")); wr.write(formData.getBytes(StandardCharsets.UTF_8));
} }
if(conn.getResponseCode() >= 200 && conn.getResponseCode() < 300) { if(conn.getResponseCode() >= 200 && conn.getResponseCode() < 300) {
JSONObject jo = new JSONObject(Tools.read(conn.getInputStream())); JSONObject jo = new JSONObject(Tools.read(conn.getInputStream()));
@ -150,11 +147,8 @@ public class MicrosoftBackgroundLogin {
return jo.getString("access_token"); return jo.getString("access_token");
//acquireXBLToken(jo.getString("access_token")); //acquireXBLToken(jo.getString("access_token"));
}else{ }else{
throwResponseError(conn); throw getResponseThrowable(conn);
} }
// Shouldn't happen
return null;
} }
private String acquireXBLToken(String accessToken) throws IOException, JSONException { private String acquireXBLToken(String accessToken) throws IOException, JSONException {
@ -171,11 +165,11 @@ public class MicrosoftBackgroundLogin {
String req = data.toString(); String req = data.toString();
HttpURLConnection conn = (HttpURLConnection)url.openConnection(); HttpURLConnection conn = (HttpURLConnection)url.openConnection();
setCommonProperties(conn, req, true); setCommonProperties(conn, req);
conn.connect(); conn.connect();
try(OutputStream wr = conn.getOutputStream()) { try(OutputStream wr = conn.getOutputStream()) {
wr.write(req.getBytes("UTF-8")); wr.write(req.getBytes(StandardCharsets.UTF_8));
} }
if(conn.getResponseCode() >= 200 && conn.getResponseCode() < 300) { if(conn.getResponseCode() >= 200 && conn.getResponseCode() < 300) {
JSONObject jo = new JSONObject(Tools.read(conn.getInputStream())); JSONObject jo = new JSONObject(Tools.read(conn.getInputStream()));
@ -184,15 +178,12 @@ public class MicrosoftBackgroundLogin {
return jo.getString("Token"); return jo.getString("Token");
//acquireXsts(jo.getString("Token")); //acquireXsts(jo.getString("Token"));
}else{ }else{
throwResponseError(conn); throw getResponseThrowable(conn);
} }
// Shouldn't happen
return null;
} }
/** @return [uhs, token]*/ /** @return [uhs, token]*/
private String[] acquireXsts(String xblToken) throws IOException, JSONException { private @NonNull String[] acquireXsts(String xblToken) throws IOException, JSONException {
URL url = new URL(xstsAuthUrl); URL url = new URL(xstsAuthUrl);
JSONObject data = new JSONObject(); JSONObject data = new JSONObject();
@ -206,12 +197,12 @@ public class MicrosoftBackgroundLogin {
String req = data.toString(); String req = data.toString();
Log.i("MicroAuth", req); Log.i("MicroAuth", req);
HttpURLConnection conn = (HttpURLConnection)url.openConnection(); HttpURLConnection conn = (HttpURLConnection)url.openConnection();
setCommonProperties(conn, req, true); setCommonProperties(conn, req);
Log.i("MicroAuth", conn.getRequestMethod()); Log.i("MicroAuth", conn.getRequestMethod());
conn.connect(); conn.connect();
try(OutputStream wr = conn.getOutputStream()) { try(OutputStream wr = conn.getOutputStream()) {
wr.write(req.getBytes("UTF-8")); wr.write(req.getBytes(StandardCharsets.UTF_8));
} }
if(conn.getResponseCode() >= 200 && conn.getResponseCode() < 300) { if(conn.getResponseCode() >= 200 && conn.getResponseCode() < 300) {
@ -232,10 +223,8 @@ public class MicrosoftBackgroundLogin {
} }
throw new PresentedException(new RuntimeException(responseContents), R.string.xerr_unknown, xerr); throw new PresentedException(new RuntimeException(responseContents), R.string.xerr_unknown, xerr);
}else{ }else{
throwResponseError(conn); throw getResponseThrowable(conn);
} }
return null;
} }
private String acquireMinecraftToken(String xblUhs, String xblXsts) throws IOException, JSONException { private String acquireMinecraftToken(String xblUhs, String xblXsts) throws IOException, JSONException {
@ -246,11 +235,11 @@ public class MicrosoftBackgroundLogin {
String req = data.toString(); String req = data.toString();
HttpURLConnection conn = (HttpURLConnection)url.openConnection(); HttpURLConnection conn = (HttpURLConnection)url.openConnection();
setCommonProperties(conn, req, true); setCommonProperties(conn, req);
conn.connect(); conn.connect();
try(OutputStream wr = conn.getOutputStream()) { try(OutputStream wr = conn.getOutputStream()) {
wr.write(req.getBytes("UTF-8")); wr.write(req.getBytes(StandardCharsets.UTF_8));
} }
if(conn.getResponseCode() >= 200 && conn.getResponseCode() < 300) { if(conn.getResponseCode() >= 200 && conn.getResponseCode() < 300) {
@ -262,10 +251,8 @@ public class MicrosoftBackgroundLogin {
//checkMcProfile(jo.getString("access_token")); //checkMcProfile(jo.getString("access_token"));
return jo.getString("access_token"); return jo.getString("access_token");
}else{ }else{
throwResponseError(conn); throw getResponseThrowable(conn);
} }
return null;
} }
private void checkMcProfile(String mcAccessToken) throws IOException, JSONException { private void checkMcProfile(String mcAccessToken) throws IOException, JSONException {
@ -308,20 +295,20 @@ public class MicrosoftBackgroundLogin {
} }
/** Set common properties, and enable interactivity if desired */ /** Set common properties for the connection. Given that all requests are POST, interactivity is always enabled */
private static void setCommonProperties(HttpURLConnection conn, String formData, boolean interactive) { private static void setCommonProperties(HttpURLConnection conn, String formData) {
conn.setRequestProperty("Content-Type", "application/json"); conn.setRequestProperty("Content-Type", "application/json");
conn.setRequestProperty("Accept", "application/json"); conn.setRequestProperty("Accept", "application/json");
conn.setRequestProperty("charset", "utf-8"); conn.setRequestProperty("charset", "utf-8");
try { try {
conn.setRequestProperty("Content-Length", Integer.toString(formData.getBytes("UTF-8").length)); conn.setRequestProperty("Content-Length", Integer.toString(formData.getBytes(StandardCharsets.UTF_8).length));
conn.setRequestMethod("POST"); conn.setRequestMethod("POST");
}catch (ProtocolException | UnsupportedEncodingException e) { }catch (ProtocolException e) {
Log.e("MicrosoftAuth", e.toString()); Log.e("MicrosoftAuth", e.toString());
} }
conn.setUseCaches(false); conn.setUseCaches(false);
conn.setDoInput(true); conn.setDoInput(true);
conn.setDoOutput(interactive); conn.setDoOutput(true);
} }
/** /**
@ -339,11 +326,11 @@ public class MicrosoftBackgroundLogin {
return builder.toString(); return builder.toString();
} }
private void throwResponseError(HttpURLConnection conn) throws IOException { private RuntimeException getResponseThrowable(HttpURLConnection conn) throws IOException {
Log.i("MicrosoftLogin", "Error code: " + conn.getResponseCode() + ": " + conn.getResponseMessage()); Log.i("MicrosoftLogin", "Error code: " + conn.getResponseCode() + ": " + conn.getResponseMessage());
if(conn.getResponseCode() == 429) { if(conn.getResponseCode() == 429) {
throw new PresentedException(R.string.microsoft_login_retry_later); return new PresentedException(R.string.microsoft_login_retry_later);
} }
throw new RuntimeException(conn.getResponseMessage()); return new RuntimeException(conn.getResponseMessage());
} }
} }

View File

@ -1,17 +0,0 @@
package net.kdt.pojavlaunch.authenticator.microsoft;
import net.kdt.pojavlaunch.Tools;
/**
* Simple class which tries to handle all irrecoverable failures when logging in a Microsoft account.
*/
public class MicrosoftLoginFailHandler {
/** Evaluate which error message to display, else */
public static String getErrorMessage(){
// TODO handle this for real though
return "ERROR";
}
}

View File

@ -9,7 +9,6 @@ import android.graphics.Paint;
import android.graphics.RectF; import android.graphics.RectF;
import android.graphics.Shader; import android.graphics.Shader;
import android.graphics.drawable.Drawable; import android.graphics.drawable.Drawable;
import android.graphics.drawable.GradientDrawable;
import android.util.AttributeSet; import android.util.AttributeSet;
import android.view.MotionEvent; import android.view.MotionEvent;
import android.view.View; import android.view.View;

View File

@ -1,6 +1,5 @@
package net.kdt.pojavlaunch.colorselector; package net.kdt.pojavlaunch.colorselector;
import android.app.AlertDialog;
import android.content.Context; import android.content.Context;
import android.content.res.ColorStateList; import android.content.res.ColorStateList;
import android.graphics.Color; import android.graphics.Color;
@ -12,7 +11,6 @@ import android.view.ViewGroup;
import android.widget.EditText; import android.widget.EditText;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.constraintlayout.widget.ConstraintLayout;
import net.kdt.pojavlaunch.R; import net.kdt.pojavlaunch.R;

View File

@ -1,23 +1,25 @@
package net.kdt.pojavlaunch.customcontrols; package net.kdt.pojavlaunch.customcontrols;
import android.util.*;
import java.lang.ref.WeakReference;
import java.lang.reflect.Modifier;
import java.util.*;
import net.kdt.pojavlaunch.*;
import net.kdt.pojavlaunch.prefs.LauncherPreferences;
import net.kdt.pojavlaunch.utils.*;
import net.objecthunter.exp4j.*;
import net.objecthunter.exp4j.function.Function;
import org.lwjgl.glfw.*;
import static net.kdt.pojavlaunch.LwjglGlfwKeycode.GLFW_KEY_UNKNOWN; import static net.kdt.pojavlaunch.LwjglGlfwKeycode.GLFW_KEY_UNKNOWN;
import static org.lwjgl.glfw.CallbackBridge.sendKeyPress;
import android.util.ArrayMap;
import androidx.annotation.Keep; import androidx.annotation.Keep;
import net.kdt.pojavlaunch.Tools;
import net.kdt.pojavlaunch.prefs.LauncherPreferences;
import net.kdt.pojavlaunch.utils.JSONUtils;
import net.objecthunter.exp4j.ExpressionBuilder;
import net.objecthunter.exp4j.function.Function;
import org.lwjgl.glfw.CallbackBridge;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
@Keep @Keep
public class ControlData { public class ControlData {
@ -76,7 +78,7 @@ public class ControlData {
public static List<String> buildSpecialButtonArray() { public static List<String> buildSpecialButtonArray() {
if (SPECIAL_BUTTON_NAME_ARRAY == null) { if (SPECIAL_BUTTON_NAME_ARRAY == null) {
List<String> nameList = new ArrayList<String>(); List<String> nameList = new ArrayList<>();
for (ControlData btn : getSpecialButtons()) { for (ControlData btn : getSpecialButtons()) {
nameList.add("SPECIAL_" + btn.name); nameList.add("SPECIAL_" + btn.name);
} }
@ -107,7 +109,7 @@ public class ControlData {
} }
public ControlData(String name, int[] keycodes) { public ControlData(String name, int[] keycodes) {
this(name, keycodes, Tools.currentDisplayMetrics.widthPixels/2, Tools.currentDisplayMetrics.heightPixels/2); this(name, keycodes, Tools.currentDisplayMetrics.widthPixels/2f, Tools.currentDisplayMetrics.heightPixels/2f);
} }
public ControlData(String name, int[] keycodes, float x, float y) { public ControlData(String name, int[] keycodes, float x, float y) {
@ -176,12 +178,6 @@ public class ControlData {
controlData.cornerRadius controlData.cornerRadius
); );
} }
public void execute(boolean isDown) {
for(int keycode : keycodes){
sendKeyPress(keycode, 0, isDown);
}
}
public float insertDynamicPos(String dynamicPos) { public float insertDynamicPos(String dynamicPos) {
@ -204,6 +200,7 @@ public class ControlData {
} }
@SuppressWarnings("BooleanMethodIsAlwaysInverted")
public boolean containsKeycode(int keycodeToCheck){ public boolean containsKeycode(int keycodeToCheck){
for(int keycode : keycodes) for(int keycode : keycodes)
if(keycodeToCheck == keycode) if(keycodeToCheck == keycode)

View File

@ -10,13 +10,11 @@ import static net.kdt.pojavlaunch.customcontrols.ControlDrawerData.Orientation.R
import static net.kdt.pojavlaunch.customcontrols.ControlDrawerData.Orientation.UP; import static net.kdt.pojavlaunch.customcontrols.ControlDrawerData.Orientation.UP;
import static net.kdt.pojavlaunch.customcontrols.ControlDrawerData.Orientation.FREE; import static net.kdt.pojavlaunch.customcontrols.ControlDrawerData.Orientation.FREE;
import androidx.annotation.Keep;
@androidx.annotation.Keep @androidx.annotation.Keep
public class ControlDrawerData { public class ControlDrawerData {
public ArrayList<ControlData> buttonProperties; public final ArrayList<ControlData> buttonProperties;
public ControlData properties; public final ControlData properties;
public Orientation orientation; public Orientation orientation;
@androidx.annotation.Keep @androidx.annotation.Keep
@ -59,7 +57,7 @@ public class ControlDrawerData {
} }
public ControlDrawerData(ArrayList<ControlData> buttonProperties){ public ControlDrawerData(ArrayList<ControlData> buttonProperties){
this(buttonProperties, new ControlData("Drawer", new int[] {}, Tools.currentDisplayMetrics.widthPixels/2, Tools.currentDisplayMetrics.heightPixels/2)); this(buttonProperties, new ControlData("Drawer", new int[] {}, Tools.currentDisplayMetrics.widthPixels/2f, Tools.currentDisplayMetrics.heightPixels/2f));
} }
public ControlDrawerData(ArrayList<ControlData> buttonProperties, ControlData properties){ public ControlDrawerData(ArrayList<ControlData> buttonProperties, ControlData properties){

View File

@ -2,6 +2,7 @@ package net.kdt.pojavlaunch.customcontrols;
import static android.content.Context.INPUT_METHOD_SERVICE; import static android.content.Context.INPUT_METHOD_SERVICE;
import static net.kdt.pojavlaunch.Tools.currentDisplayMetrics; import static net.kdt.pojavlaunch.Tools.currentDisplayMetrics;
import android.annotation.SuppressLint;
import android.content.*; import android.content.*;
import android.util.*; import android.util.*;
import android.view.*; import android.view.*;
@ -213,12 +214,9 @@ public class ControlLayout extends FrameLayout {
} }
public void setModifiable(boolean isModifiable) { public void setModifiable(boolean isModifiable) {
if(isModifiable){ if(!isModifiable && mModifiable){
}else { removeEditWindow();
if(mModifiable)
removeEditWindow();
} }
mModifiable = isModifiable; mModifiable = isModifiable;
} }
@ -298,20 +296,20 @@ public class ControlLayout extends FrameLayout {
} }
HashMap<View, ControlInterface> mapTable = new HashMap<>(); final HashMap<View, ControlInterface> mapTable = new HashMap<>();
int[] location = new int[2]; final int[] location = new int[2];
//While this is called onTouch, this should only be called from a ControlButton. //While this is called onTouch, this should only be called from a ControlButton.
public boolean onTouch(View v, MotionEvent ev) { public void onTouch(View v, MotionEvent ev) {
ControlInterface lastControlButton = mapTable.get(v); ControlInterface lastControlButton = mapTable.get(v);
//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.sendKeyPresses(false); if(lastControlButton != null) lastControlButton.sendKeyPresses(false);
mapTable.put(v, null); mapTable.put(v, null);
return true; return;
} }
if(ev.getActionMasked() != MotionEvent.ACTION_MOVE) return false; if(ev.getActionMasked() != MotionEvent.ACTION_MOVE) return;
getLocationOnScreen(location); getLocationOnScreen(location);
@ -321,7 +319,7 @@ public class ControlLayout extends FrameLayout {
&& ev.getRawX() < lastControlButton.getControlView().getX() + lastControlButton.getControlView().getWidth() + location[0] && ev.getRawX() < lastControlButton.getControlView().getX() + lastControlButton.getControlView().getWidth() + location[0]
&& ev.getRawY() > lastControlButton.getControlView().getY() && ev.getRawY() > lastControlButton.getControlView().getY()
&& ev.getRawY() < lastControlButton.getControlView().getY() + lastControlButton.getControlView().getHeight()){ && ev.getRawY() < lastControlButton.getControlView().getY() + lastControlButton.getControlView().getHeight()){
return true; return;
} }
} }
@ -342,14 +340,14 @@ public class ControlLayout extends FrameLayout {
if(!button.equals(lastControlButton)){ if(!button.equals(lastControlButton)){
button.sendKeyPresses(true); button.sendKeyPresses(true);
mapTable.put(v, button); mapTable.put(v, button);
return true; return;
} }
} }
} }
return false;
} }
@SuppressLint("ClickableViewAccessibility")
@Override @Override
public boolean onTouchEvent(MotionEvent event) { public boolean onTouchEvent(MotionEvent event) {
if (mModifiable && event.getActionMasked() != MotionEvent.ACTION_UP || mControlPopup == null) if (mModifiable && event.getActionMasked() != MotionEvent.ACTION_UP || mControlPopup == null)

View File

@ -47,7 +47,7 @@ public class CustomControls {
this.mControlDataList.add(new ControlData(ctx, R.string.control_inventory, new int[]{LwjglGlfwKeycode.GLFW_KEY_E}, "${margin} * 3 + ${width} * 2", "${bottom} - ${margin}", true)); this.mControlDataList.add(new ControlData(ctx, R.string.control_inventory, new int[]{LwjglGlfwKeycode.GLFW_KEY_E}, "${margin} * 3 + ${width} * 2", "${bottom} - ${margin}", true));
ControlData shiftData = new ControlData(ctx, R.string.control_shift, new int[]{LwjglGlfwKeycode.GLFW_KEY_LEFT_SHIFT}, "${margin} * 2 + ${width}", "${screen_height} - ${margin} * 2 - ${height} * 2", true); ControlData shiftData = new ControlData(ctx, R.string.control_shift, new int[]{LwjglGlfwKeycode.GLFW_KEY_LEFT_SHIFT}, "${margin} * 2 + ${width}", "${screen_height} - ${margin} * 2 - ${height} * 2", true);
shiftData.isToggle = true; shiftData.isToggle = true;
this.mControlDataList.add(shiftData); this.mControlDataList.add(shiftData);
this.mControlDataList.add(new ControlData(ctx, R.string.control_jump, new int[]{LwjglGlfwKeycode.GLFW_KEY_SPACE}, "${right} - ${margin} * 2 - ${width}", "${bottom} - ${margin} * 2 - ${height}", true)); this.mControlDataList.add(new ControlData(ctx, R.string.control_jump, new int[]{LwjglGlfwKeycode.GLFW_KEY_SPACE}, "${right} - ${margin} * 2 - ${width}", "${bottom} - ${margin} * 2 - ${height}", true));

View File

@ -14,7 +14,6 @@ import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
public class LayoutConverter { public class LayoutConverter {
public static boolean convertLookType = false; //false = flat; true = classic
public static CustomControls loadAndConvertIfNecessary(String jsonPath) throws IOException, JsonSyntaxException { public static CustomControls loadAndConvertIfNecessary(String jsonPath) throws IOException, JsonSyntaxException {
String jsonLayoutData = Tools.read(jsonPath); String jsonLayoutData = Tools.read(jsonPath);
@ -107,14 +106,8 @@ public class LayoutConverter {
n_button.isToggle = button.getBoolean("isToggle"); n_button.isToggle = button.getBoolean("isToggle");
n_button.setHeight(button.getInt("height")); n_button.setHeight(button.getInt("height"));
n_button.setWidth(button.getInt("width")); n_button.setWidth(button.getInt("width"));
if(convertLookType) { n_button.bgColor = 0x4d000000;
n_button.strokeColor = 0xdd7f7f7f; n_button.strokeWidth = 0;
n_button.bgColor = 0x807f7f7f;
n_button.strokeWidth = 10;
}else{
n_button.bgColor = 0x4d000000;
n_button.strokeWidth = 0;
}
if(button.getBoolean("isRound")) { n_button.cornerRadius = 35f; } if(button.getBoolean("isRound")) { n_button.cornerRadius = 35f; }
int next_idx = 0; int next_idx = 0;
if(button.getBoolean("holdShift")) { keycodes[next_idx] = LwjglGlfwKeycode.GLFW_KEY_LEFT_SHIFT; next_idx++; } if(button.getBoolean("holdShift")) { keycodes[next_idx] = LwjglGlfwKeycode.GLFW_KEY_LEFT_SHIFT; next_idx++; }

View File

@ -1,25 +1,30 @@
package net.kdt.pojavlaunch.customcontrols.buttons; package net.kdt.pojavlaunch.customcontrols.buttons;
import android.annotation.SuppressLint;
import android.graphics.*;
import android.util.*;
import android.view.*;
import android.widget.*;
import net.kdt.pojavlaunch.customcontrols.ControlButtonMenuListener;
import net.kdt.pojavlaunch.customcontrols.ControlData;
import net.kdt.pojavlaunch.customcontrols.ControlLayout;
import net.kdt.pojavlaunch.customcontrols.handleview.*;
import net.kdt.pojavlaunch.*;
import net.kdt.pojavlaunch.prefs.LauncherPreferences;
import org.lwjgl.glfw.*;
import static net.kdt.pojavlaunch.LwjglGlfwKeycode.GLFW_KEY_UNKNOWN; import static net.kdt.pojavlaunch.LwjglGlfwKeycode.GLFW_KEY_UNKNOWN;
import static org.lwjgl.glfw.CallbackBridge.sendKeyPress; import static org.lwjgl.glfw.CallbackBridge.sendKeyPress;
import static org.lwjgl.glfw.CallbackBridge.sendMouseButton; import static org.lwjgl.glfw.CallbackBridge.sendMouseButton;
import android.annotation.SuppressLint;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.util.Log;
import android.util.TypedValue;
import android.view.Gravity;
import android.view.MotionEvent;
import android.view.View;
import android.widget.TextView;
import net.kdt.pojavlaunch.LwjglGlfwKeycode;
import net.kdt.pojavlaunch.MainActivity;
import net.kdt.pojavlaunch.R;
import net.kdt.pojavlaunch.customcontrols.ControlData;
import net.kdt.pojavlaunch.customcontrols.ControlLayout;
import net.kdt.pojavlaunch.customcontrols.handleview.EditControlPopup;
import net.kdt.pojavlaunch.prefs.LauncherPreferences;
import org.lwjgl.glfw.CallbackBridge;
@SuppressLint({"ViewConstructor", "AppCompatCustomView"}) @SuppressLint({"ViewConstructor", "AppCompatCustomView"})
public class ControlButton extends TextView implements ControlInterface { public class ControlButton extends TextView implements ControlInterface {
private final Paint mRectPaint = new Paint(); private final Paint mRectPaint = new Paint();
@ -103,6 +108,7 @@ public class ControlButton extends TextView implements ControlInterface {
} }
@SuppressLint("ClickableViewAccessibility")
@Override @Override
public boolean onTouchEvent(MotionEvent event) { public boolean onTouchEvent(MotionEvent event) {
switch (event.getActionMasked()){ switch (event.getActionMasked()){
@ -169,6 +175,7 @@ public class ControlButton extends TextView implements ControlInterface {
@SuppressWarnings("BooleanMethodIsAlwaysInverted")
public boolean triggerToggle(){ public boolean triggerToggle(){
//returns true a the toggle system is triggered //returns true a the toggle system is triggered
if(mProperties.isToggle){ if(mProperties.isToggle){

View File

@ -2,7 +2,6 @@ package net.kdt.pojavlaunch.customcontrols.buttons;
import android.annotation.SuppressLint; import android.annotation.SuppressLint;
import android.view.MotionEvent; import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import net.kdt.pojavlaunch.Tools; import net.kdt.pojavlaunch.Tools;
@ -19,9 +18,9 @@ import java.util.ArrayList;
public class ControlDrawer extends ControlButton { public class ControlDrawer extends ControlButton {
public ArrayList<ControlSubButton> buttons; public final ArrayList<ControlSubButton> buttons;
public ControlDrawerData drawerData; public final ControlDrawerData drawerData;
public ControlLayout parentLayout; public final ControlLayout parentLayout;
public boolean areButtonsVisible; public boolean areButtonsVisible;
@ -164,9 +163,9 @@ public class ControlDrawer extends ControlButton {
} }
@Override @Override
public boolean canSnap(ControlInterface button) { public boolean cantSnap(ControlInterface button) {
boolean result = super.canSnap(button); boolean result = !super.cantSnap(button);
return result && !containsChild(button); return !result || containsChild(button);
} }
//Getters //Getters

View File

@ -2,9 +2,8 @@ package net.kdt.pojavlaunch.customcontrols.buttons;
import static net.kdt.pojavlaunch.prefs.LauncherPreferences.PREF_BUTTONSIZE; import static net.kdt.pojavlaunch.prefs.LauncherPreferences.PREF_BUTTONSIZE;
import android.graphics.Color; import android.annotation.SuppressLint;
import android.graphics.drawable.GradientDrawable; import android.graphics.drawable.GradientDrawable;
import android.util.TypedValue;
import android.view.MotionEvent; import android.view.MotionEvent;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
@ -13,8 +12,6 @@ import android.widget.FrameLayout;
import androidx.annotation.CallSuper; import androidx.annotation.CallSuper;
import androidx.core.math.MathUtils; import androidx.core.math.MathUtils;
import net.kdt.pojavlaunch.MinecraftGLSurface;
import net.kdt.pojavlaunch.R;
import net.kdt.pojavlaunch.Tools; import net.kdt.pojavlaunch.Tools;
import net.kdt.pojavlaunch.customcontrols.ControlData; import net.kdt.pojavlaunch.customcontrols.ControlData;
import net.kdt.pojavlaunch.customcontrols.ControlLayout; import net.kdt.pojavlaunch.customcontrols.ControlLayout;
@ -182,24 +179,22 @@ public interface ControlInterface extends View.OnLongClickListener {
} }
/** /**
* Passe a series of checks to determine if the ControlButton is available to be snapped on. * Passe a series of checks to determine if the ControlButton isn't available to be snapped on.
* *
* @param button The button to check * @param button The button to check
* @return whether or not the button * @return whether or not the button
*/ */
default boolean canSnap(ControlInterface button){ default boolean cantSnap(ControlInterface button){
float MIN_DISTANCE = Tools.dpToPx(8); float MIN_DISTANCE = Tools.dpToPx(8);
if(button == this) return false; if(button == this) return true;
if(net.kdt.pojavlaunch.utils.MathUtils.dist( return net.kdt.pojavlaunch.utils.MathUtils.dist(
button.getControlView().getX() + button.getControlView().getWidth()/2f, button.getControlView().getX() + button.getControlView().getWidth() / 2f,
button.getControlView().getY() + button.getControlView().getHeight()/2f, button.getControlView().getY() + button.getControlView().getHeight() / 2f,
getControlView().getX() + getControlView().getWidth()/2f, getControlView().getX() + getControlView().getWidth() / 2f,
getControlView().getY() + getControlView().getHeight()/2f) getControlView().getY() + getControlView().getHeight() / 2f)
> Math.max(button.getControlView().getWidth()/2f + getControlView().getWidth()/2f, > Math.max(button.getControlView().getWidth() / 2f + getControlView().getWidth() / 2f,
button.getControlView().getHeight()/2f + getControlView().getHeight()/2f) + MIN_DISTANCE) return false; button.getControlView().getHeight() / 2f + getControlView().getHeight() / 2f) + MIN_DISTANCE;
return true;
} }
/** /**
@ -222,7 +217,7 @@ public interface ControlInterface extends View.OnLongClickListener {
for(ControlInterface button : ((ControlLayout) getControlView().getParent()).getButtonChildren()){ for(ControlInterface button : ((ControlLayout) getControlView().getParent()).getButtonChildren()){
//Step 1: Filter unwanted buttons //Step 1: Filter unwanted buttons
if(!canSnap(button)) continue; if(cantSnap(button)) continue;
//Step 2: Get Coordinates //Step 2: Get Coordinates
float button_top = button.getControlView().getY(); float button_top = button.getControlView().getY();
@ -282,11 +277,11 @@ public interface ControlInterface extends View.OnLongClickListener {
/** Inject a touch listener on the view to make editing controls straight forward */ /** Inject a touch listener on the view to make editing controls straight forward */
default void injectTouchEventBehavior(){ default void injectTouchEventBehavior(){
getControlView().setOnTouchListener(new View.OnTouchListener() { getControlView().setOnTouchListener(new View.OnTouchListener() {
private boolean mIsPointerOutOfBounds = false;
private boolean mCanTriggerLongClick = true; private boolean mCanTriggerLongClick = true;
private float downX, downY; private float downX, downY;
private float downRawX, downRawY; private float downRawX, downRawY;
@SuppressLint("ClickableViewAccessibility")
@Override @Override
public boolean onTouch(View view, MotionEvent event) { public boolean onTouch(View view, MotionEvent event) {
if(!getControlLayoutParent().getModifiable()){ if(!getControlLayoutParent().getModifiable()){

View File

@ -1,12 +1,10 @@
package net.kdt.pojavlaunch.customcontrols.buttons; package net.kdt.pojavlaunch.customcontrols.buttons;
import android.annotation.SuppressLint; import android.annotation.SuppressLint;
import android.view.GestureDetector;
import android.view.MotionEvent; import android.view.MotionEvent;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import net.kdt.pojavlaunch.SingleTapConfirm;
import net.kdt.pojavlaunch.customcontrols.ControlData; import net.kdt.pojavlaunch.customcontrols.ControlData;
import net.kdt.pojavlaunch.customcontrols.ControlDrawerData; import net.kdt.pojavlaunch.customcontrols.ControlDrawerData;
import net.kdt.pojavlaunch.customcontrols.ControlLayout; import net.kdt.pojavlaunch.customcontrols.ControlLayout;
@ -14,7 +12,7 @@ import net.kdt.pojavlaunch.customcontrols.ControlLayout;
@SuppressLint("ViewConstructor") @SuppressLint("ViewConstructor")
public class ControlSubButton extends ControlButton { public class ControlSubButton extends ControlButton {
public ControlDrawer parentDrawer; public final ControlDrawer parentDrawer;
public ControlSubButton(ControlLayout layout, ControlData properties, ControlDrawer parentDrawer) { public ControlSubButton(ControlLayout layout, ControlData properties, ControlDrawer parentDrawer) {
super(layout, properties); super(layout, properties);
@ -44,6 +42,7 @@ public class ControlSubButton extends ControlButton {
super.setLayoutParams(params); super.setLayoutParams(params);
} }
@SuppressLint("ClickableViewAccessibility")
@Override @Override
public boolean onTouchEvent(MotionEvent event) { public boolean onTouchEvent(MotionEvent event) {
if(!getControlLayoutParent().getModifiable() || parentDrawer.drawerData.orientation == ControlDrawerData.Orientation.FREE){ if(!getControlLayoutParent().getModifiable() || parentDrawer.drawerData.orientation == ControlDrawerData.Orientation.FREE){

View File

@ -58,7 +58,7 @@ public class Gamepad implements GrabListener {
private float mLastHorizontalValue = 0.0f; private float mLastHorizontalValue = 0.0f;
private float mLastVerticalValue = 0.0f; private float mLastVerticalValue = 0.0f;
private final double MOUSE_MAX_ACCELERATION = 2f; private static final double MOUSE_MAX_ACCELERATION = 2f;
private double mMouseMagnitude; private double mMouseMagnitude;
private double mMouseAngle; private double mMouseAngle;
@ -79,7 +79,8 @@ public class Gamepad implements GrabListener {
private long mLastFrameTime; private long mLastFrameTime;
/* Listen for change in gui scale */ /* Listen for change in gui scale */
private MCOptionUtils.MCOptionListener mGuiScaleListener = () -> notifyGUISizeChange(getMcScale()); @SuppressWarnings("FieldCanBeLocal") //the field is used in a WeakReference
private final MCOptionUtils.MCOptionListener mGuiScaleListener = () -> notifyGUISizeChange(getMcScale());
public Gamepad(View contextView, InputDevice inputDevice){ public Gamepad(View contextView, InputDevice inputDevice){
mScreenChoreographer = Choreographer.getInstance(); mScreenChoreographer = Choreographer.getInstance();
@ -124,8 +125,8 @@ public class Gamepad implements GrabListener {
int size = (int) ((22 * getMcScale()) / mScaleFactor); int size = (int) ((22 * getMcScale()) / mScaleFactor);
mPointerImageView.setLayoutParams(new FrameLayout.LayoutParams(size, size)); mPointerImageView.setLayoutParams(new FrameLayout.LayoutParams(size, size));
mMouse_x = CallbackBridge.windowWidth/2; mMouse_x = CallbackBridge.windowWidth/2f;
mMouse_y = CallbackBridge.windowHeight/2; mMouse_y = CallbackBridge.windowHeight/2f;
CallbackBridge.sendCursorPos(mMouse_x, mMouse_y); CallbackBridge.sendCursorPos(mMouse_x, mMouse_y);
placePointerView(CallbackBridge.physicalWidth/2, CallbackBridge.physicalHeight/2); placePointerView(CallbackBridge.physicalWidth/2, CallbackBridge.physicalHeight/2);
@ -418,8 +419,8 @@ public class Gamepad implements GrabListener {
} }
private void placePointerView(int x, int y){ private void placePointerView(int x, int y){
mPointerImageView.setX(x - mPointerImageView.getWidth()/2); mPointerImageView.setX(x - mPointerImageView.getWidth()/2f);
mPointerImageView.setY(y - mPointerImageView.getHeight()/2); mPointerImageView.setY(y - mPointerImageView.getHeight()/2f);
} }
/** Update the grabbing state, and change the currentMap, mouse position and sensibility */ /** Update the grabbing state, and change the currentMap, mouse position and sensibility */
@ -441,8 +442,8 @@ public class Gamepad implements GrabListener {
mCurrentMap = mMenuMap; mCurrentMap = mMenuMap;
sendDirectionalKeycode(mCurrentJoystickDirection, false, mGameMap); // removing what we were doing sendDirectionalKeycode(mCurrentJoystickDirection, false, mGameMap); // removing what we were doing
mMouse_x = CallbackBridge.windowWidth/2; mMouse_x = CallbackBridge.windowWidth/2f;
mMouse_y = CallbackBridge.windowHeight/2; mMouse_y = CallbackBridge.windowHeight/2f;
CallbackBridge.sendCursorPos(mMouse_x, mMouse_y); CallbackBridge.sendCursorPos(mMouse_x, mMouse_y);
placePointerView(CallbackBridge.physicalWidth/2, CallbackBridge.physicalHeight/2); placePointerView(CallbackBridge.physicalWidth/2, CallbackBridge.physicalHeight/2);
mPointerImageView.setVisibility(View.VISIBLE); mPointerImageView.setVisibility(View.VISIBLE);

View File

@ -1,11 +1,6 @@
package net.kdt.pojavlaunch.customcontrols.gamepad; package net.kdt.pojavlaunch.customcontrols.gamepad;
import android.view.InputDevice;
import android.view.KeyEvent;
import android.view.MotionEvent;
import static android.view.InputDevice.KEYBOARD_TYPE_ALPHABETIC; import static android.view.InputDevice.KEYBOARD_TYPE_ALPHABETIC;
import static android.view.InputDevice.KEYBOARD_TYPE_NON_ALPHABETIC;
import static android.view.InputDevice.SOURCE_GAMEPAD; import static android.view.InputDevice.SOURCE_GAMEPAD;
import static android.view.KeyEvent.KEYCODE_DPAD_CENTER; import static android.view.KeyEvent.KEYCODE_DPAD_CENTER;
import static android.view.KeyEvent.KEYCODE_DPAD_DOWN; import static android.view.KeyEvent.KEYCODE_DPAD_DOWN;
@ -13,6 +8,10 @@ import static android.view.KeyEvent.KEYCODE_DPAD_LEFT;
import static android.view.KeyEvent.KEYCODE_DPAD_RIGHT; import static android.view.KeyEvent.KEYCODE_DPAD_RIGHT;
import static android.view.KeyEvent.KEYCODE_DPAD_UP; import static android.view.KeyEvent.KEYCODE_DPAD_UP;
import android.view.InputDevice;
import android.view.KeyEvent;
import android.view.MotionEvent;
public class GamepadDpad { public class GamepadDpad {
private int mLastKeycode = KEYCODE_DPAD_CENTER; private int mLastKeycode = KEYCODE_DPAD_CENTER;
@ -50,7 +49,7 @@ public class GamepadDpad {
} }
public static boolean isDpadEvent(MotionEvent event) { @SuppressWarnings("unused") public static boolean isDpadEvent(MotionEvent event) {
// Check that input comes from a device with directional pads. // Check that input comes from a device with directional pads.
// And... also the joystick since it declares sometimes as a joystick. // And... also the joystick since it declares sometimes as a joystick.
return (event.getSource() & InputDevice.SOURCE_JOYSTICK) == InputDevice.SOURCE_JOYSTICK; return (event.getSource() & InputDevice.SOURCE_JOYSTICK) == InputDevice.SOURCE_JOYSTICK;

View File

@ -14,32 +14,32 @@ public class GamepadMap {
Be warned, you should define ALL keys if you want to avoid a non defined exception Be warned, you should define ALL keys if you want to avoid a non defined exception
*/ */
public GamepadButton BUTTON_A = new GamepadButton(); public final GamepadButton BUTTON_A = new GamepadButton();
public GamepadButton BUTTON_B = new GamepadButton(); public final GamepadButton BUTTON_B = new GamepadButton();
public GamepadButton BUTTON_X = new GamepadButton(); public final GamepadButton BUTTON_X = new GamepadButton();
public GamepadButton BUTTON_Y = new GamepadButton(); public final GamepadButton BUTTON_Y = new GamepadButton();
public GamepadButton BUTTON_START = new GamepadButton(); public final GamepadButton BUTTON_START = new GamepadButton();
public GamepadButton BUTTON_SELECT = new GamepadButton(); public final GamepadButton BUTTON_SELECT = new GamepadButton();
public GamepadButton TRIGGER_RIGHT = new GamepadButton(); //R2 public final GamepadButton TRIGGER_RIGHT = new GamepadButton(); //R2
public GamepadButton TRIGGER_LEFT = new GamepadButton(); //L2 public final GamepadButton TRIGGER_LEFT = new GamepadButton(); //L2
public GamepadButton SHOULDER_RIGHT = new GamepadButton(); //R1 public final GamepadButton SHOULDER_RIGHT = new GamepadButton(); //R1
public GamepadButton SHOULDER_LEFT = new GamepadButton(); //L1 public final GamepadButton SHOULDER_LEFT = new GamepadButton(); //L1
public int[] DIRECTION_FORWARD; public int[] DIRECTION_FORWARD;
public int[] DIRECTION_BACKWARD; public int[] DIRECTION_BACKWARD;
public int[] DIRECTION_RIGHT; public int[] DIRECTION_RIGHT;
public int[] DIRECTION_LEFT; public int[] DIRECTION_LEFT;
public GamepadButton THUMBSTICK_RIGHT = new GamepadButton(); //R3 public final GamepadButton THUMBSTICK_RIGHT = new GamepadButton(); //R3
public GamepadButton THUMBSTICK_LEFT = new GamepadButton(); //L3 public final GamepadButton THUMBSTICK_LEFT = new GamepadButton(); //L3
public GamepadButton DPAD_UP = new GamepadButton(); public final GamepadButton DPAD_UP = new GamepadButton();
public GamepadButton DPAD_RIGHT = new GamepadButton(); public final GamepadButton DPAD_RIGHT = new GamepadButton();
public GamepadButton DPAD_DOWN = new GamepadButton(); public final GamepadButton DPAD_DOWN = new GamepadButton();
public GamepadButton DPAD_LEFT = new GamepadButton(); public final GamepadButton DPAD_LEFT = new GamepadButton();
/* /*
@ -158,7 +158,7 @@ public class GamepadMap {
/* /*
* Returns an pre-initialized GamepadMap with only empty keycodes * Returns an pre-initialized GamepadMap with only empty keycodes
*/ */
public static GamepadMap getEmptyMap(){ @SuppressWarnings("unused") public static GamepadMap getEmptyMap(){
GamepadMap emptyMap = new GamepadMap(); GamepadMap emptyMap = new GamepadMap();
for(GamepadButton button : emptyMap.getButtons()) for(GamepadButton button : emptyMap.getButtons())
button.keycodes = new int[]{}; button.keycodes = new int[]{};

View File

@ -7,14 +7,12 @@ import android.util.AttributeSet;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.view.ViewTreeObserver; import android.view.ViewTreeObserver;
import android.widget.Button;
import android.widget.LinearLayout; import android.widget.LinearLayout;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.core.math.MathUtils; import androidx.core.math.MathUtils;
import net.kdt.pojavlaunch.R; import net.kdt.pojavlaunch.R;
import net.kdt.pojavlaunch.Tools;
import net.kdt.pojavlaunch.customcontrols.buttons.ControlInterface; import net.kdt.pojavlaunch.customcontrols.buttons.ControlInterface;
/** /**
@ -22,11 +20,11 @@ import net.kdt.pojavlaunch.customcontrols.buttons.ControlInterface;
*/ */
public class ActionRow extends LinearLayout { public class ActionRow extends LinearLayout {
public static int SIDE_LEFT = 0x0; public static final int SIDE_LEFT = 0x0;
public static int SIDE_TOP = 0x1; public static final int SIDE_TOP = 0x1;
public static int SIDE_RIGHT = 0x2; public static final int SIDE_RIGHT = 0x2;
public static int SIDE_BOTTOM = 0x3; public static final int SIDE_BOTTOM = 0x3;
public static int SIDE_AUTO = 0x4; public static final int SIDE_AUTO = 0x4;
public ActionRow(Context context) { public ActionRow(Context context) {
super(context); init(); super(context); init();
@ -49,7 +47,7 @@ public class ActionRow extends LinearLayout {
}; };
private final ActionButtonInterface[] actionButtons = new ActionButtonInterface[3]; private final ActionButtonInterface[] actionButtons = new ActionButtonInterface[3];
private View mFollowedView = null; private View mFollowedView = null;
private int mSide = SIDE_TOP; private final int mSide = SIDE_TOP;
/** Add action buttons and configure them */ /** Add action buttons and configure them */
private void init(){ private void init(){
@ -130,9 +128,9 @@ public class ActionRow extends LinearLayout {
: SIDE_RIGHT; : SIDE_RIGHT;
float futurePos = getYPosition(side); float futurePos = getYPosition(side);
if(futurePos + getHeight() > (parent.getHeight() + getHeight()/2)){ if(futurePos + getHeight() > (parent.getHeight() + getHeight()/2f)){
side = SIDE_TOP; side = SIDE_TOP;
}else if (futurePos < -getHeight()/2){ }else if (futurePos < -getHeight()/2f){
side = SIDE_BOTTOM; side = SIDE_BOTTOM;
} }

View File

@ -2,10 +2,7 @@ package net.kdt.pojavlaunch.customcontrols.handleview;
import android.annotation.SuppressLint; import android.annotation.SuppressLint;
import android.content.Context; import android.content.Context;
import android.graphics.Color;
import android.util.AttributeSet; import android.util.AttributeSet;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button; import android.widget.Button;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;

View File

@ -2,17 +2,12 @@ package net.kdt.pojavlaunch.customcontrols.handleview;
import android.annotation.SuppressLint; import android.annotation.SuppressLint;
import android.content.Context; import android.content.Context;
import android.graphics.Color;
import android.util.AttributeSet; import android.util.AttributeSet;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button; import android.widget.Button;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import net.kdt.pojavlaunch.R; import net.kdt.pojavlaunch.R;
import net.kdt.pojavlaunch.customcontrols.ControlLayout;
import net.kdt.pojavlaunch.customcontrols.buttons.ControlButton;
import net.kdt.pojavlaunch.customcontrols.buttons.ControlInterface; import net.kdt.pojavlaunch.customcontrols.buttons.ControlInterface;
@SuppressLint("AppCompatCustomView") @SuppressLint("AppCompatCustomView")

View File

@ -1,11 +1,9 @@
package net.kdt.pojavlaunch.customcontrols.handleview; package net.kdt.pojavlaunch.customcontrols.handleview;
import android.annotation.SuppressLint;
import android.content.Context; import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.drawable.Drawable; import android.graphics.drawable.Drawable;
import android.util.AttributeSet; import android.util.AttributeSet;
import android.view.DragEvent;
import android.view.MotionEvent; import android.view.MotionEvent;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
@ -15,7 +13,6 @@ import androidx.annotation.Nullable;
import androidx.core.content.res.ResourcesCompat; import androidx.core.content.res.ResourcesCompat;
import net.kdt.pojavlaunch.R; import net.kdt.pojavlaunch.R;
import net.kdt.pojavlaunch.customcontrols.buttons.ControlButton;
import net.kdt.pojavlaunch.customcontrols.buttons.ControlInterface; import net.kdt.pojavlaunch.customcontrols.buttons.ControlInterface;
public class ControlHandleView extends View { public class ControlHandleView extends View {
@ -66,6 +63,7 @@ public class ControlHandleView extends View {
setY(controlInterface.getControlView().getY() + controlInterface.getControlView().getHeight()); setY(controlInterface.getControlView().getY() + controlInterface.getControlView().getHeight());
} }
@SuppressLint("ClickableViewAccessibility")
@Override @Override
public boolean onTouchEvent(MotionEvent event) { public boolean onTouchEvent(MotionEvent event) {
switch (event.getActionMasked()){ switch (event.getActionMasked()){

View File

@ -2,16 +2,12 @@ package net.kdt.pojavlaunch.customcontrols.handleview;
import android.annotation.SuppressLint; import android.annotation.SuppressLint;
import android.content.Context; import android.content.Context;
import android.graphics.Color;
import android.util.AttributeSet; import android.util.AttributeSet;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button; import android.widget.Button;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import net.kdt.pojavlaunch.R; import net.kdt.pojavlaunch.R;
import net.kdt.pojavlaunch.customcontrols.buttons.ControlButton;
import net.kdt.pojavlaunch.customcontrols.buttons.ControlInterface; import net.kdt.pojavlaunch.customcontrols.buttons.ControlInterface;
@SuppressLint("AppCompatCustomView") @SuppressLint("AppCompatCustomView")

View File

@ -4,7 +4,6 @@ import android.content.Context;
import android.graphics.Canvas; import android.graphics.Canvas;
import android.graphics.Color; import android.graphics.Color;
import android.graphics.Paint; import android.graphics.Paint;
import android.graphics.drawable.VectorDrawable;
import android.util.AttributeSet; import android.util.AttributeSet;
import android.view.View; import android.view.View;
@ -31,9 +30,9 @@ public class DrawerPullButton extends View {
canvas.drawArc(0,-getHeight(),getWidth(), getHeight(), 0, 180, true, mPaint); canvas.drawArc(0,-getHeight(),getWidth(), getHeight(), 0, 180, true, mPaint);
mPaint.setColor(Color.WHITE); mPaint.setColor(Color.WHITE);
mDrawable.setBounds(0, 0, canvas.getHeight(), canvas.getHeight()); mDrawable.setBounds(0, 0, getHeight(), getHeight());
canvas.save(); canvas.save();
canvas.translate((canvas.getWidth()-canvas.getHeight())/2, 0); canvas.translate((getWidth()-getHeight())/2f, 0);
mDrawable.draw(canvas); mDrawable.draw(canvas);
canvas.restore(); canvas.restore();
} }

View File

@ -16,7 +16,6 @@ import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.view.animation.AccelerateDecelerateInterpolator; import android.view.animation.AccelerateDecelerateInterpolator;
import android.view.animation.DecelerateInterpolator;
import android.view.animation.Interpolator; import android.view.animation.Interpolator;
import android.widget.AdapterView; import android.widget.AdapterView;
import android.widget.ArrayAdapter; import android.widget.ArrayAdapter;
@ -32,16 +31,12 @@ import com.kdt.DefocusableScrollView;
import net.kdt.pojavlaunch.EfficientAndroidLWJGLKeycode; import net.kdt.pojavlaunch.EfficientAndroidLWJGLKeycode;
import net.kdt.pojavlaunch.R; import net.kdt.pojavlaunch.R;
import net.kdt.pojavlaunch.colorselector.ColorSelectionListener;
import net.kdt.pojavlaunch.colorselector.ColorSelector; import net.kdt.pojavlaunch.colorselector.ColorSelector;
import net.kdt.pojavlaunch.customcontrols.ControlData; import net.kdt.pojavlaunch.customcontrols.ControlData;
import net.kdt.pojavlaunch.customcontrols.ControlDrawerData; import net.kdt.pojavlaunch.customcontrols.ControlDrawerData;
import net.kdt.pojavlaunch.customcontrols.buttons.ControlButton;
import net.kdt.pojavlaunch.customcontrols.buttons.ControlDrawer; import net.kdt.pojavlaunch.customcontrols.buttons.ControlDrawer;
import net.kdt.pojavlaunch.customcontrols.buttons.ControlInterface; import net.kdt.pojavlaunch.customcontrols.buttons.ControlInterface;
import java.util.Arrays;
import java.util.Collections;
import java.util.List; import java.util.List;
/** /**
@ -83,7 +78,7 @@ public class EditControlPopup {
@SuppressLint("UseSwitchCompatOrMaterialCode") @SuppressLint("UseSwitchCompatOrMaterialCode")
protected Switch mToggleSwitch, mPassthroughSwitch, mSwipeableSwitch; protected Switch mToggleSwitch, mPassthroughSwitch, mSwipeableSwitch;
protected Spinner mOrientationSpinner; protected Spinner mOrientationSpinner;
protected Spinner[] mKeycodeSpinners = new Spinner[4]; protected final Spinner[] mKeycodeSpinners = new Spinner[4];
protected SeekBar mStrokeWidthSeekbar, mCornerRadiusSeekbar, mAlphaSeekbar; protected SeekBar mStrokeWidthSeekbar, mCornerRadiusSeekbar, mAlphaSeekbar;
protected TextView mStrokePercentTextView, mCornerRadiusPercentTextView, mAlphaPercentTextView; protected TextView mStrokePercentTextView, mCornerRadiusPercentTextView, mAlphaPercentTextView;
protected TextView mSelectBackgroundColor, mSelectStrokeColor; protected TextView mSelectBackgroundColor, mSelectStrokeColor;
@ -247,7 +242,7 @@ public class EditControlPopup {
public static void setPercentageText(TextView textView, int progress){ public static void setPercentageText(TextView textView, int progress){
textView.setText(progress + " %"); textView.setText(textView.getContext().getString(R.string.percent_format, progress));
} }
/* LOADING VALUES */ /* LOADING VALUES */
@ -305,7 +300,7 @@ public class EditControlPopup {
} }
/** Load values for the joystick */ /** Load values for the joystick */
public void loadJoystickValues(ControlData data){ @SuppressWarnings("unused") public void loadJoystickValues(ControlData data){
loadValues(data); loadValues(data);
mMappingTextView.setVisibility(GONE); mMappingTextView.setVisibility(GONE);

View File

@ -3,11 +3,8 @@ package net.kdt.pojavlaunch.customcontrols.keyboard;
import static android.content.Context.INPUT_METHOD_SERVICE; import static android.content.Context.INPUT_METHOD_SERVICE;
import static org.lwjgl.glfw.CallbackBridge.sendKeyPress;
import android.annotation.SuppressLint; import android.annotation.SuppressLint;
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 android.view.inputmethod.InputMethodManager;
@ -15,15 +12,13 @@ import android.view.inputmethod.InputMethodManager;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import net.kdt.pojavlaunch.LwjglGlfwKeycode;
import net.kdt.pojavlaunch.R; import net.kdt.pojavlaunch.R;
import org.lwjgl.glfw.CallbackBridge;
/** /**
* This class is intended for sending characters used in chat via the virtual keyboard * This class is intended for sending characters used in chat via the virtual keyboard
*/ */
public class TouchCharInput extends androidx.appcompat.widget.AppCompatEditText { public class TouchCharInput extends androidx.appcompat.widget.AppCompatEditText {
public static final String TEXT_FILLER = " ";
public TouchCharInput(@NonNull Context context) { public TouchCharInput(@NonNull Context context) {
this(context, null); this(context, null);
} }
@ -89,20 +84,16 @@ public class TouchCharInput extends androidx.appcompat.widget.AppCompatEditText
/** /**
* Toggle on and off the soft keyboard, depending of the state * Toggle on and off the soft keyboard, depending of the state
*
* @return if the keyboard is set to be shown.
*/ */
public boolean switchKeyboardState(){ public void switchKeyboardState(){
InputMethodManager imm = (InputMethodManager) getContext().getSystemService(INPUT_METHOD_SERVICE); InputMethodManager imm = (InputMethodManager) getContext().getSystemService(INPUT_METHOD_SERVICE);
// Allow, regardless of whether or not a hardware keyboard is declared // Allow, regardless of whether or not a hardware keyboard is declared
if(hasFocus()){ if(hasFocus()){
clear(); clear();
disable(); disable();
return false;
}else{ }else{
enable(); enable();
imm.showSoftInput(this, InputMethodManager.SHOW_IMPLICIT); imm.showSoftInput(this, InputMethodManager.SHOW_IMPLICIT);
return true;
} }
} }
@ -116,8 +107,8 @@ public class TouchCharInput extends androidx.appcompat.widget.AppCompatEditText
mIsDoingInternalChanges = true; mIsDoingInternalChanges = true;
//Braille space, doesn't trigger keyboard auto-complete //Braille space, doesn't trigger keyboard auto-complete
//replacing directly the text without though setText avoids notifying changes //replacing directly the text without though setText avoids notifying changes
setText(" "); setText(TEXT_FILLER);
setSelection(getText().length()); setSelection(TEXT_FILLER.length());
mIsDoingInternalChanges = false; mIsDoingInternalChanges = false;
} }

View File

@ -3,8 +3,6 @@ package net.kdt.pojavlaunch.extra;
public class ExtraConstants { public class ExtraConstants {
/* ExtraCore constant: a HashMap for converting values such as latest-snapshot or latest-release to actual game version names */ /* ExtraCore constant: a HashMap for converting values such as latest-snapshot or latest-release to actual game version names */
public static final String RELEASE_TABLE = "release_table"; public static final String RELEASE_TABLE = "release_table";
/* ExtraCore constant: an ArrayList of Strings, where each String is a Minecraft version name */
public static final String VERSION_LIST = "lac_version_list";
/* ExtraCore constant: Serpent's back button tracking thing */ /* ExtraCore constant: Serpent's back button tracking thing */
public static final String BACK_PREFERENCE = "back_preference"; public static final String BACK_PREFERENCE = "back_preference";
/* ExtraCore constant: The OPENGL version that should be exposed */ /* ExtraCore constant: The OPENGL version that should be exposed */

View File

@ -12,12 +12,13 @@ import java.util.concurrent.ConcurrentLinkedQueue;
* *
* This class uses a singleton pattern to simplify access to it * This class uses a singleton pattern to simplify access to it
*/ */
@SuppressWarnings({"rawtypes", "unchecked"})
public final class ExtraCore { public final class ExtraCore {
// No unwanted instantiation // No unwanted instantiation
private ExtraCore(){} private ExtraCore(){}
// Singleton instance // Singleton instance
private static ExtraCore sExtraCoreSingleton = null; private static volatile ExtraCore sExtraCoreSingleton = null;
// Store the key-value pair // Store the key-value pair
private final Map<String, Object> mValueMap = new ConcurrentHashMap<>(); private final Map<String, Object> mValueMap = new ConcurrentHashMap<>();

View File

@ -1,7 +1,6 @@
package net.kdt.pojavlaunch.extra; package net.kdt.pojavlaunch.extra;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
/** /**
* Listener class for the ExtraCore * Listener class for the ExtraCore
@ -15,6 +14,7 @@ public interface ExtraListener<T> {
* @param value The new value as a string * @param value The new value as a string
* @return Whether you consume the Listener (stop listening) * @return Whether you consume the Listener (stop listening)
*/ */
@SuppressWarnings("SameReturnValue")
boolean onValueSet(String key, @NonNull T value); boolean onValueSet(String key, @NonNull T value);
} }

View File

@ -2,7 +2,6 @@ package net.kdt.pojavlaunch.fragments;
import android.os.Bundle; import android.os.Bundle;
import android.view.View; import android.view.View;
import android.widget.Button;
import android.widget.EditText; import android.widget.EditText;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
@ -20,7 +19,6 @@ public class LocalLoginFragment extends Fragment {
public static final String TAG = "LOCAL_LOGIN_FRAGMENT"; public static final String TAG = "LOCAL_LOGIN_FRAGMENT";
private EditText mUsernameEditText; private EditText mUsernameEditText;
private Button mLoginButton;
public LocalLoginFragment(){ public LocalLoginFragment(){
super(R.layout.fragment_local_login); super(R.layout.fragment_local_login);
@ -29,8 +27,7 @@ public class LocalLoginFragment extends Fragment {
@Override @Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
mUsernameEditText = view.findViewById(R.id.login_edit_email); mUsernameEditText = view.findViewById(R.id.login_edit_email);
mLoginButton = view.findViewById(R.id.login_button); view.findViewById(R.id.login_button).setOnClickListener(v -> {
mLoginButton.setOnClickListener(v -> {
if(!checkEditText()) return; if(!checkEditText()) return;
ExtraCore.setValue(ExtraConstants.MOJANG_LOGIN_TODO, new String[]{ ExtraCore.setValue(ExtraConstants.MOJANG_LOGIN_TODO, new String[]{

View File

@ -21,8 +21,6 @@ import net.kdt.pojavlaunch.extra.ExtraConstants;
import net.kdt.pojavlaunch.extra.ExtraCore; import net.kdt.pojavlaunch.extra.ExtraCore;
import net.kdt.pojavlaunch.progresskeeper.ProgressKeeper; import net.kdt.pojavlaunch.progresskeeper.ProgressKeeper;
import java.io.File;
public class MainMenuFragment extends Fragment { public class MainMenuFragment extends Fragment {
public static final String TAG = "MainMenuFragment"; public static final String TAG = "MainMenuFragment";

View File

@ -1,5 +1,6 @@
package net.kdt.pojavlaunch.fragments; package net.kdt.pojavlaunch.fragments;
import android.annotation.SuppressLint;
import android.graphics.Bitmap; import android.graphics.Bitmap;
import android.net.Uri; import android.net.Uri;
import android.os.Bundle; import android.os.Bundle;
@ -27,7 +28,12 @@ public class MicrosoftLoginFragment extends Fragment {
@Override @Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
mWebview = (WebView) inflater.inflate(R.layout.fragment_microsoft_login, container, false); mWebview = (WebView) inflater.inflate(R.layout.fragment_microsoft_login, container, false);
CookieManager.getInstance().removeAllCookie(); // The non deprecated method is not async CookieManager.getInstance().removeAllCookies(this::onCookiesRemoved);
return mWebview;
}
@SuppressLint("SetJavaScriptEnabled") // required for Microsoft log-in
public void onCookiesRemoved(Boolean b) {
WebSettings settings = mWebview.getSettings(); WebSettings settings = mWebview.getSettings();
settings.setJavaScriptEnabled(true); settings.setJavaScriptEnabled(true);
@ -42,8 +48,6 @@ public class MicrosoftLoginFragment extends Fragment {
"&response_type=code" + "&response_type=code" +
"&scope=service%3A%3Auser.auth.xboxlive.com%3A%3AMBI_SSL" + "&scope=service%3A%3Auser.auth.xboxlive.com%3A%3AMBI_SSL" +
"&redirect_url=https%3A%2F%2Flogin.live.com%2Foauth20_desktop.srf"); "&redirect_url=https%3A%2F%2Flogin.live.com%2Foauth20_desktop.srf");
return mWebview;
} }
/* Expose webview actions to others */ /* Expose webview actions to others */

View File

@ -142,12 +142,11 @@ public class ProfileEditorFragment extends Fragment {
loadValues(LauncherPreferences.DEFAULT_PREF.getString(LauncherPreferences.PREF_KEY_CURRENT_PROFILE, "")); loadValues(LauncherPreferences.DEFAULT_PREF.getString(LauncherPreferences.PREF_KEY_CURRENT_PROFILE, ""), view.getContext());
} }
private void loadValues(@NonNull String profile){ private void loadValues(@NonNull String profile, @NonNull Context context){
Context context = getContext();
if(mTempProfile == null){ if(mTempProfile == null){
mTempProfile = getProfile(profile); mTempProfile = getProfile(profile);
} }
@ -237,10 +236,4 @@ public class ProfileEditorFragment extends Fragment {
LauncherProfiles.update(); LauncherProfiles.update();
ExtraCore.setValue(ExtraConstants.REFRESH_VERSION_SPINNER, mProfileKey); ExtraCore.setValue(ExtraConstants.REFRESH_VERSION_SPINNER, mProfileKey);
} }
/** Called on the UI thread, the profile is already saved in the files */
public interface ProfileEditorDone {
void onProfileSaved(MinecraftProfile profile);
}
} }

View File

@ -6,7 +6,6 @@ import android.app.AlertDialog;
import android.content.Intent; import android.content.Intent;
import android.webkit.MimeTypeMap; import android.webkit.MimeTypeMap;
import androidx.annotation.Nullable;
import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView; import androidx.recyclerview.widget.RecyclerView;
@ -34,7 +33,7 @@ public class MultiRTConfigDialog {
public void prepare(Activity activity) { public void prepare(Activity activity) {
mDialogView = new RecyclerView(activity); mDialogView = new RecyclerView(activity);
mDialogView.setLayoutManager(new LinearLayoutManager(activity, LinearLayoutManager.VERTICAL, false)); mDialogView.setLayoutManager(new LinearLayoutManager(activity, LinearLayoutManager.VERTICAL, false));
mDialogView.setAdapter(new RTRecyclerViewAdapter(this)); mDialogView.setAdapter(new RTRecyclerViewAdapter());
mDialog = new AlertDialog.Builder(activity) mDialog = new AlertDialog.Builder(activity)
.setTitle(R.string.multirt_config_title) .setTitle(R.string.multirt_config_title)

View File

@ -1,10 +1,8 @@
package net.kdt.pojavlaunch.multirt; package net.kdt.pojavlaunch.multirt;
import static net.kdt.pojavlaunch.Tools.NATIVE_LIB_DIR; import static net.kdt.pojavlaunch.Tools.NATIVE_LIB_DIR;
import static net.kdt.pojavlaunch.Tools.getMinecraftClientArgs;
import static org.apache.commons.io.FileUtils.listFiles; import static org.apache.commons.io.FileUtils.listFiles;
import android.content.Context;
import android.system.Os; import android.system.Os;
import android.util.Log; import android.util.Log;
@ -20,7 +18,6 @@ import org.apache.commons.compress.compressors.xz.XZCompressorInputStream;
import org.apache.commons.io.FileUtils; import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils; import org.apache.commons.io.IOUtils;
import java.io.BufferedInputStream;
import java.io.File; import java.io.File;
import java.io.FileInputStream; import java.io.FileInputStream;
import java.io.FileOutputStream; import java.io.FileOutputStream;
@ -41,13 +38,16 @@ public class MultiRTUtils {
private static String sSelectedRuntimeName; private static String sSelectedRuntimeName;
public static List<Runtime> getRuntimes() { public static List<Runtime> getRuntimes() {
if(!RUNTIME_FOLDER.exists()) RUNTIME_FOLDER.mkdirs(); if(!RUNTIME_FOLDER.exists() && !RUNTIME_FOLDER.mkdirs()) {
throw new RuntimeException("Failed to create runtime directory");
}
ArrayList<Runtime> runtimes = new ArrayList<>(); ArrayList<Runtime> runtimes = new ArrayList<>();
System.out.println("Fetch runtime list"); File[] files = RUNTIME_FOLDER.listFiles();
for(File f : RUNTIME_FOLDER.listFiles()) { if(files != null) for(File f : files) {
runtimes.add(read(f.getName())); runtimes.add(read(f.getName()));
} }
else throw new RuntimeException("The runtime directory does not exist");
return runtimes; return runtimes;
} }
@ -80,8 +80,6 @@ public class MultiRTUtils {
public static void installRuntimeNamed(String nativeLibDir, InputStream runtimeInputStream, String name) throws IOException { public static void installRuntimeNamed(String nativeLibDir, InputStream runtimeInputStream, String name) throws IOException {
File dest = new File(RUNTIME_FOLDER,"/"+name); File dest = new File(RUNTIME_FOLDER,"/"+name);
if(dest.exists()) FileUtils.deleteDirectory(dest); if(dest.exists()) FileUtils.deleteDirectory(dest);
dest.mkdirs();
uncompressTarXZ(runtimeInputStream,dest); uncompressTarXZ(runtimeInputStream,dest);
runtimeInputStream.close(); runtimeInputStream.close();
unpack200(nativeLibDir,RUNTIME_FOLDER + "/" + name); unpack200(nativeLibDir,RUNTIME_FOLDER + "/" + name);
@ -98,17 +96,16 @@ public class MultiRTUtils {
File ftIn = new File(dest, libFolder + "/libfreetype.so.6"); File ftIn = new File(dest, libFolder + "/libfreetype.so.6");
File ftOut = new File(dest, libFolder + "/libfreetype.so"); File ftOut = new File(dest, libFolder + "/libfreetype.so");
if (ftIn.exists() && (!ftOut.exists() || ftIn.length() != ftOut.length())) { if (ftIn.exists() && (!ftOut.exists() || ftIn.length() != ftOut.length())) {
ftIn.renameTo(ftOut); if(!ftIn.renameTo(ftOut)) throw new IOException("Failed to rename freetype");
} }
// Refresh libraries // Refresh libraries
copyDummyNativeLib("libawt_xawt.so", dest, libFolder); copyDummyNativeLib("libawt_xawt.so", dest, libFolder);
} }
public static Runtime installRuntimeNamedBinpack(InputStream universalFileInputStream, InputStream platformBinsInputStream, String name, String binpackVersion) throws IOException { public static void installRuntimeNamedBinpack(InputStream universalFileInputStream, InputStream platformBinsInputStream, String name, String binpackVersion) throws IOException {
File dest = new File(RUNTIME_FOLDER,"/"+name); File dest = new File(RUNTIME_FOLDER,"/"+name);
if(dest.exists()) FileUtils.deleteDirectory(dest); if(dest.exists()) FileUtils.deleteDirectory(dest);
dest.mkdirs();
installRuntimeNamedNoRemove(universalFileInputStream,dest); installRuntimeNamedNoRemove(universalFileInputStream,dest);
installRuntimeNamedNoRemove(platformBinsInputStream,dest); installRuntimeNamedNoRemove(platformBinsInputStream,dest);
@ -121,8 +118,7 @@ public class MultiRTUtils {
ProgressLayout.clearProgress(ProgressLayout.UNPACK_RUNTIME); ProgressLayout.clearProgress(ProgressLayout.UNPACK_RUNTIME);
sCache.remove(name); // Force reread forceReread(name);
return read(name);
} }
@ -148,7 +144,7 @@ public class MultiRTUtils {
} }
} }
public static void setRuntimeNamed(String name) throws IOException { public static void setRuntimeNamed(String name) {
File dest = new File(RUNTIME_FOLDER,"/"+name); File dest = new File(RUNTIME_FOLDER,"/"+name);
if((!dest.exists()) || MultiRTUtils.forceReread(name).versionString == null) throw new RuntimeException("Selected runtime is broken!"); if((!dest.exists()) || MultiRTUtils.forceReread(name).versionString == null) throw new RuntimeException("Selected runtime is broken!");
Tools.DIR_HOME_JRE = dest.getAbsolutePath(); Tools.DIR_HOME_JRE = dest.getAbsolutePath();
@ -185,11 +181,7 @@ public class MultiRTUtils {
} else { } else {
javaVersionInt = Integer.parseInt(javaVersionSplit[0]); javaVersionInt = Integer.parseInt(javaVersionSplit[0]);
} }
Runtime runtime = new Runtime(name); returnRuntime = new Runtime(name, javaVersion, osArch, javaVersionInt);
runtime.arch = osArch;
runtime.javaVersion = javaVersionInt;
runtime.versionString = javaVersion;
returnRuntime = runtime;
}else{ }else{
returnRuntime = new Runtime(name); returnRuntime = new Runtime(name);
} }
@ -223,9 +215,9 @@ public class MultiRTUtils {
} }
} }
@SuppressWarnings("SameParameterValue")
private static void copyDummyNativeLib(String name, File dest, String libFolder) throws IOException { private static void copyDummyNativeLib(String name, File dest, String libFolder) throws IOException {
File fileLib = new File(dest, "/"+libFolder + "/" + name); File fileLib = new File(dest, "/"+libFolder + "/" + name);
fileLib.delete();
FileInputStream is = new FileInputStream(new File(NATIVE_LIB_DIR, name)); FileInputStream is = new FileInputStream(new File(NATIVE_LIB_DIR, name));
FileOutputStream os = new FileOutputStream(fileLib); FileOutputStream os = new FileOutputStream(fileLib);
IOUtils.copy(is, os); IOUtils.copy(is, os);
@ -239,7 +231,8 @@ public class MultiRTUtils {
} }
private static void uncompressTarXZ(final InputStream tarFileInputStream, final File dest) throws IOException { private static void uncompressTarXZ(final InputStream tarFileInputStream, final File dest) throws IOException {
dest.mkdirs(); if(dest.isFile()) throw new IOException("Attempting to unpack into a file");
if(!dest.exists() && !dest.mkdirs()) throw new IOException("Failed to create destination directory");
byte[] buffer = new byte[8192]; byte[] buffer = new byte[8192];
TarArchiveInputStream tarIn = new TarArchiveInputStream( TarArchiveInputStream tarIn = new TarArchiveInputStream(
@ -254,8 +247,10 @@ public class MultiRTUtils {
ProgressLayout.setProgress(ProgressLayout.UNPACK_RUNTIME, 100, R.string.global_unpacking, tarEntryName); ProgressLayout.setProgress(ProgressLayout.UNPACK_RUNTIME, 100, R.string.global_unpacking, tarEntryName);
File destPath = new File(dest, tarEntry.getName()); File destPath = new File(dest, tarEntry.getName());
File destParent = destPath.getParentFile();
if (tarEntry.isSymbolicLink()) { if (tarEntry.isSymbolicLink()) {
destPath.getParentFile().mkdirs(); if(destParent != null && !destParent.exists() && !destParent.mkdirs())
throw new IOException("Failed to create parent directory for symlink");
try { try {
// android.system.Os // android.system.Os
// Libcore one support all Android versions // Libcore one support all Android versions
@ -265,11 +260,11 @@ public class MultiRTUtils {
} }
} else if (tarEntry.isDirectory()) { } else if (tarEntry.isDirectory()) {
destPath.mkdirs(); if(!destPath.exists() && !destPath.mkdirs())
destPath.setExecutable(true); throw new IOException("Failed to create directory");
} else if (!destPath.exists() || destPath.length() != tarEntry.getSize()) { } else if (!destPath.exists() || destPath.length() != tarEntry.getSize()) {
destPath.getParentFile().mkdirs(); if(destParent != null && !destParent.exists() && !destParent.mkdirs())
destPath.createNewFile(); throw new IOException("Failed to create parent directory for file");
FileOutputStream os = new FileOutputStream(destPath); FileOutputStream os = new FileOutputStream(destPath);
IOUtils.copyLarge(tarIn, os, buffer); IOUtils.copyLarge(tarIn, os, buffer);

View File

@ -26,11 +26,6 @@ import java.util.List;
public class RTRecyclerViewAdapter extends RecyclerView.Adapter<RTRecyclerViewAdapter.RTViewHolder> { public class RTRecyclerViewAdapter extends RecyclerView.Adapter<RTRecyclerViewAdapter.RTViewHolder> {
MultiRTConfigDialog mConfigDialog;
public RTRecyclerViewAdapter(MultiRTConfigDialog dialog) {
this.mConfigDialog = dialog;
}
@NonNull @NonNull
@Override @Override
public RTViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { public RTViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
@ -81,6 +76,7 @@ public class RTRecyclerViewAdapter extends RecyclerView.Adapter<RTRecyclerViewAd
itemView.findViewById(R.id.multirt_view_removebtn).setOnClickListener(this); itemView.findViewById(R.id.multirt_view_removebtn).setOnClickListener(this);
} }
@SuppressLint("NotifyDataSetChanged") // same as all the other ones
@Override @Override
public void onClick(View view) { public void onClick(View view) {
if(view.getId() == R.id.multirt_view_removebtn) { if(view.getId() == R.id.multirt_view_removebtn) {

View File

@ -17,11 +17,10 @@ import java.util.List;
public class RTSpinnerAdapter implements SpinnerAdapter { public class RTSpinnerAdapter implements SpinnerAdapter {
final Context mContext; final Context mContext;
List<Runtime> mRuntimes; final List<Runtime> mRuntimes;
public RTSpinnerAdapter(@NonNull Context context, List<Runtime> runtimes) { public RTSpinnerAdapter(@NonNull Context context, List<Runtime> runtimes) {
mRuntimes = runtimes; mRuntimes = runtimes;
Runtime runtime = new Runtime("<Default>"); Runtime runtime = new Runtime("<Default>", "", null, 0);
runtime.versionString = "";
mRuntimes.add(runtime); mRuntimes.add(runtime);
mContext = context; mContext = context;
} }

View File

@ -3,14 +3,24 @@ package net.kdt.pojavlaunch.multirt;
import java.util.Objects; import java.util.Objects;
public class Runtime { public class Runtime {
public final String name;
public final String versionString;
public final String arch;
public final int javaVersion;
public Runtime(String name) { public Runtime(String name) {
this.name = name; this.name = name;
this.versionString = null;
this.arch = null;
this.javaVersion = 0;
}
Runtime(String name, String versionString, String arch, int javaVersion) {
this.name = name;
this.versionString = versionString;
this.arch = arch;
this.javaVersion = javaVersion;
} }
public String name;
public String versionString;
public String arch;
public int javaVersion;
@Override @Override
public boolean equals(Object o) { public boolean equals(Object o) {

View File

@ -33,7 +33,7 @@ public class LauncherPreferences {
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 boolean PREF_FORCE_ENGLISH = false; public static boolean PREF_FORCE_ENGLISH = false;
public static String PREF_VERSION_REPOS = "https://piston-meta.mojang.com/mc/game/version_manifest_v2.json"; public static final String PREF_VERSION_REPOS = "https://piston-meta.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 boolean PREF_DISABLE_SWAP_HAND = false; public static boolean PREF_DISABLE_SWAP_HAND = false;

View File

@ -1,24 +1,18 @@
package net.kdt.pojavlaunch.prefs.screens; package net.kdt.pojavlaunch.prefs.screens;
import android.content.SharedPreferences;
import android.graphics.Color; import android.graphics.Color;
import android.os.*; import android.os.Bundle;
import android.view.View;
import androidx.activity.OnBackPressedCallback;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.preference.*; import androidx.preference.PreferenceFragmentCompat;
import net.kdt.pojavlaunch.R; import net.kdt.pojavlaunch.R;
import net.kdt.pojavlaunch.prefs.LauncherPreferences; import net.kdt.pojavlaunch.prefs.LauncherPreferences;
import android.content.*;
import android.view.View;
import android.widget.Toast;
import static net.kdt.pojavlaunch.Architecture.is32BitsDevice;
import static net.kdt.pojavlaunch.Tools.getTotalDeviceMemory;
import static net.kdt.pojavlaunch.prefs.LauncherPreferences.PREF_NOTCH_SIZE;
/** /**
* Preference for the main screen, any sub-screen should inherit this class for consistent behavior, * Preference for the main screen, any sub-screen should inherit this class for consistent behavior,
* overriding only onCreatePreferences * overriding only onCreatePreferences

View File

@ -1,10 +1,7 @@
package net.kdt.pojavlaunch.prefs.screens; package net.kdt.pojavlaunch.prefs.screens;
import android.os.Build;
import android.os.Bundle; import android.os.Bundle;
import androidx.preference.SwitchPreference;
import net.kdt.pojavlaunch.R; import net.kdt.pojavlaunch.R;
public class LauncherPreferenceMiscellaneousFragment extends LauncherPreferenceFragment { public class LauncherPreferenceMiscellaneousFragment extends LauncherPreferenceFragment {

View File

@ -6,7 +6,6 @@ import android.content.SharedPreferences;
import android.os.Build; import android.os.Build;
import android.os.Bundle; import android.os.Bundle;
import androidx.preference.PreferenceFragmentCompat;
import androidx.preference.SwitchPreference; import androidx.preference.SwitchPreference;
import androidx.preference.SwitchPreferenceCompat; import androidx.preference.SwitchPreferenceCompat;

View File

@ -4,7 +4,6 @@ import static net.kdt.pojavlaunch.profiles.ProfileAdapter.CREATE_PROFILE_MAGIC;
import android.content.Context; import android.content.Context;
import android.content.res.Resources; import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory; import android.graphics.BitmapFactory;
import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable; import android.graphics.drawable.Drawable;
@ -12,7 +11,6 @@ import android.util.Base64;
import android.util.Log; import android.util.Log;
import androidx.core.content.res.ResourcesCompat; import androidx.core.content.res.ResourcesCompat;
import androidx.core.graphics.drawable.RoundedBitmapDrawableFactory;
import net.kdt.pojavlaunch.R; import net.kdt.pojavlaunch.R;
@ -28,11 +26,7 @@ public class ProfileIconCache {
public static void initDefault(Context context) { public static void initDefault(Context context) {
if(sDefaultIcon != null) return; if(sDefaultIcon != null) return;
sDefaultIcon = ResourcesCompat.getDrawable(context.getResources(), R.mipmap.ic_launcher_foreground, null); sDefaultIcon = ResourcesCompat.getDrawable(context.getResources(), R.mipmap.ic_launcher_foreground, null);
sDefaultIcon.setBounds(0, 0, 10, 10); if(sDefaultIcon != null) sDefaultIcon.setBounds(0, 0, 10, 10);
}
public static void clearIconCache() {
sIconCache.clear();
} }
public static Drawable getCachedIcon(String key) { public static Drawable getCachedIcon(String key) {

View File

@ -6,7 +6,6 @@ import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.widget.BaseExpandableListAdapter; import android.widget.BaseExpandableListAdapter;
import android.widget.ExpandableListAdapter; import android.widget.ExpandableListAdapter;
import android.widget.ExpandableListView;
import android.widget.TextView; import android.widget.TextView;
import net.kdt.pojavlaunch.JMinecraftVersionList; import net.kdt.pojavlaunch.JMinecraftVersionList;
@ -23,17 +22,16 @@ public class VersionListAdapter extends BaseExpandableListAdapter implements Exp
private final LayoutInflater mLayoutInflater; private final LayoutInflater mLayoutInflater;
private final String[] mGroups; private final String[] mGroups;
private final List<JMinecraftVersionList.Version> mReleaseList, mSnapshotList, mBetaList, mAlphaList;
private final String[] mInstalledVersions; private final String[] mInstalledVersions;
private final List<JMinecraftVersionList.Version>[] mData; private final List<?>[] mData;
public VersionListAdapter(JMinecraftVersionList.Version[] versionList, Context ctx){ public VersionListAdapter(JMinecraftVersionList.Version[] versionList, Context ctx){
mLayoutInflater = (LayoutInflater) ctx.getSystemService(Context.LAYOUT_INFLATER_SERVICE); mLayoutInflater = (LayoutInflater) ctx.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
mReleaseList = new FilteredSubList<>(versionList, item -> item.type.equals("release")); List<JMinecraftVersionList.Version> releaseList = new FilteredSubList<>(versionList, item -> item.type.equals("release"));
mSnapshotList = new FilteredSubList<>(versionList, item -> item.type.equals("snapshot")); List<JMinecraftVersionList.Version> snapshotList = new FilteredSubList<>(versionList, item -> item.type.equals("snapshot"));
mBetaList = new FilteredSubList<>(versionList, item -> item.type.equals("old_beta")); List<JMinecraftVersionList.Version> betaList = new FilteredSubList<>(versionList, item -> item.type.equals("old_beta"));
mAlphaList = new FilteredSubList<>(versionList, item -> item.type.equals("old_alpha")); List<JMinecraftVersionList.Version> alphaList = new FilteredSubList<>(versionList, item -> item.type.equals("old_alpha"));
// Query installed versions // Query installed versions
mInstalledVersions = new File(Tools.DIR_GAME_NEW + "/versions").list(); mInstalledVersions = new File(Tools.DIR_GAME_NEW + "/versions").list();
@ -44,7 +42,7 @@ public class VersionListAdapter extends BaseExpandableListAdapter implements Exp
ctx.getString(R.string.mcl_setting_veroption_oldbeta), ctx.getString(R.string.mcl_setting_veroption_oldbeta),
ctx.getString(R.string.mcl_setting_veroption_oldalpha) ctx.getString(R.string.mcl_setting_veroption_oldalpha)
}; };
mData = new List[]{ mReleaseList, mSnapshotList, mBetaList, mAlphaList}; mData = new List[]{ releaseList, snapshotList, betaList, alphaList};
}else{ }else{
mGroups = new String[]{ mGroups = new String[]{
ctx.getString(R.string.mcl_setting_veroption_installed), ctx.getString(R.string.mcl_setting_veroption_installed),
@ -53,7 +51,7 @@ public class VersionListAdapter extends BaseExpandableListAdapter implements Exp
ctx.getString(R.string.mcl_setting_veroption_oldbeta), ctx.getString(R.string.mcl_setting_veroption_oldbeta),
ctx.getString(R.string.mcl_setting_veroption_oldalpha) ctx.getString(R.string.mcl_setting_veroption_oldalpha)
}; };
mData = new List[]{Arrays.asList(mInstalledVersions), mReleaseList, mSnapshotList, mBetaList, mAlphaList}; mData = new List[]{Arrays.asList(mInstalledVersions), releaseList, snapshotList, betaList, alphaList};
} }
} }
@ -77,7 +75,7 @@ public class VersionListAdapter extends BaseExpandableListAdapter implements Exp
if(isInstalledVersionSelected(groupPosition)){ if(isInstalledVersionSelected(groupPosition)){
return mInstalledVersions[childPosition]; return mInstalledVersions[childPosition];
} }
return mData[groupPosition].get(childPosition).id; return ((JMinecraftVersionList.Version)mData[groupPosition].get(childPosition)).id;
} }
@Override @Override
@ -109,14 +107,7 @@ public class VersionListAdapter extends BaseExpandableListAdapter implements Exp
public View getChildView(int groupPosition, int childPosition, boolean isLastChild, View convertView, ViewGroup parent) { public View getChildView(int groupPosition, int childPosition, boolean isLastChild, View convertView, ViewGroup parent) {
if(convertView == null) if(convertView == null)
convertView = mLayoutInflater.inflate(android.R.layout.simple_expandable_list_item_1, parent, false); convertView = mLayoutInflater.inflate(android.R.layout.simple_expandable_list_item_1, parent, false);
if(isInstalledVersionSelected(groupPosition)){ ((TextView) convertView).setText(getChild(groupPosition, childPosition));
// Installed version is a String inside
((TextView) convertView).setText(mInstalledVersions[childPosition]);
}else{
((TextView) convertView).setText(mData[groupPosition].get(childPosition).id);
}
return convertView; return convertView;
} }

View File

@ -1,7 +1,6 @@
package net.kdt.pojavlaunch.services; package net.kdt.pojavlaunch.services;
import android.content.Context; import android.content.Context;
import android.util.Log;
import net.kdt.pojavlaunch.progresskeeper.TaskCountListener; import net.kdt.pojavlaunch.progresskeeper.TaskCountListener;

View File

@ -27,9 +27,8 @@ public class AsyncAssetManager {
/** /**
* Attempt to install the java 8 runtime, if necessary * Attempt to install the java 8 runtime, if necessary
* @param am App context * @param am App context
* @param otherRuntimesAvailable Whether other runtimes have been detected
*/ */
public static void unpackRuntime(AssetManager am, boolean otherRuntimesAvailable) { public static void unpackRuntime(AssetManager am) {
/* Check if JRE is included */ /* Check if JRE is included */
String rt_version = null; String rt_version = null;
String current_rt_version = MultiRTUtils.__internal__readBinpackVersion("Internal"); String current_rt_version = MultiRTUtils.__internal__readBinpackVersion("Internal");

View File

@ -218,7 +218,7 @@ public class AsyncMinecraftDownloader {
(int) Math.max((float)curr/max*100,0), R.string.mcl_launch_downloading_progress, destination.getName(), curr/BYTE_TO_MB, max/BYTE_TO_MB)); (int) Math.max((float)curr/max*100,0), R.string.mcl_launch_downloading_progress, destination.getName(), curr/BYTE_TO_MB, max/BYTE_TO_MB));
} }
public void downloadAssets(final JAssets assets, String assetsVersion, final File outputDir) throws IOException { public void downloadAssets(final JAssets assets, String assetsVersion, final File outputDir) {
LinkedBlockingQueue<Runnable> workQueue = new LinkedBlockingQueue<>(); LinkedBlockingQueue<Runnable> workQueue = new LinkedBlockingQueue<>();
final ThreadPoolExecutor executor = new ThreadPoolExecutor(5, 5, 500, TimeUnit.MILLISECONDS, workQueue); final ThreadPoolExecutor executor = new ThreadPoolExecutor(5, 5, 500, TimeUnit.MILLISECONDS, workQueue);

View File

@ -50,6 +50,7 @@ public class AsyncVersionList {
} }
@SuppressWarnings("SameParameterValue")
private JMinecraftVersionList downloadVersionList(String mirror){ private JMinecraftVersionList downloadVersionList(String mirror){
JMinecraftVersionList list = null; JMinecraftVersionList list = null;
try{ try{

View File

@ -8,6 +8,7 @@ import java.nio.charset.*;
import net.kdt.pojavlaunch.*; import net.kdt.pojavlaunch.*;
import org.apache.commons.io.*; import org.apache.commons.io.*;
@SuppressWarnings("IOStreamConstructor")
public class DownloadUtils { public class DownloadUtils {
public static final String USER_AGENT = Tools.APP_NAME; public static final String USER_AGENT = Tools.APP_NAME;

View File

@ -264,16 +264,8 @@ public class JREUtils {
// return ldLibraryPath; // return ldLibraryPath;
} }
public static int launchJavaVM(final Activity activity, String gameDirectory, final List<String> JVMArgs, final String userArgsString) throws Throwable { public static int launchJavaVM(final Activity activity, File gameDirectory, final List<String> JVMArgs, final String userArgsString) throws Throwable {
JREUtils.relocateLibPath(); JREUtils.relocateLibPath();
// For debugging only!
/*
StringBuilder sbJavaArgs = new StringBuilder();
for (String s : javaArgList) {
sbJavaArgs.append(s + " ");
}
ctx.appendlnToLog("Executing JVM: \"" + sbJavaArgs.toString() + "\"");
*/
setJavaEnvironment(activity); setJavaEnvironment(activity);
@ -299,7 +291,7 @@ public class JREUtils {
initJavaRuntime(); initJavaRuntime();
setupExitTrap(activity.getApplication()); setupExitTrap(activity.getApplication());
chdir(gameDirectory == null ? Tools.DIR_GAME_NEW : gameDirectory); chdir(gameDirectory == null ? Tools.DIR_GAME_NEW : gameDirectory.getAbsolutePath());
userArgs.add(0,"java"); //argv[0] is the program name according to C standard. userArgs.add(0,"java"); //argv[0] is the program name according to C standard.
final int exitCode = VMLauncher.launchJVM(userArgs.toArray(new String[0])); final int exitCode = VMLauncher.launchJVM(userArgs.toArray(new String[0]));
@ -376,45 +368,6 @@ public class JREUtils {
return userArguments; return userArguments;
} }
/*
* more better arguments parser that allows escapes and doesnt change up args
* @param _args all args as a string
* @return a list of split args
*/
/*public static ArrayList<String> parseJavaArguments(String _args) {
char bracketOpen = '\0';
char[] str = _args.toCharArray();
StringBuilder sb = new StringBuilder();
ArrayList<String> ret = new ArrayList<String>();
for(int i = 0; i < str.length; i++) {
if(str[i] == '\\') {
sb.append(str[i+1]);
i++;
continue;
}
if(str[i] == ' ' && bracketOpen == '\0') {
if(sb.length() > 0) {
ret.add(sb.toString());
sb = new StringBuilder();
}
continue;
}
if(str[i] == '"' || str[i] == '\'') {
if(bracketOpen == str[i]) {
bracketOpen = '\0';
continue;
}else if(bracketOpen == '\0') {
bracketOpen = str[i];
continue;
}
}
sb.append(str[i]);
}
ret.add(sb.toString());
return ret;
}*/
/** /**
* Parse and separate java arguments in a user friendly fashion * Parse and separate java arguments in a user friendly fashion
* It supports multi line and absence of spaces between arguments * It supports multi line and absence of spaces between arguments
@ -508,16 +461,16 @@ public class JREUtils {
* @param argStart The argument to purge from the list. * @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++) { Iterator<String> args = argList.iterator();
final String arg = argList.get(i); while(args.hasNext()) {
if(arg.startsWith(argStart)) { String arg = args.next();
argList.remove(i); if(arg.startsWith(argStart)) args.remove();
}
} }
} }
private static final int EGL_OPENGL_ES_BIT = 0x0001; private static final int EGL_OPENGL_ES_BIT = 0x0001;
private static final int EGL_OPENGL_ES2_BIT = 0x0004; private static final int EGL_OPENGL_ES2_BIT = 0x0004;
private static final int EGL_OPENGL_ES3_BIT_KHR = 0x0040; private static final int EGL_OPENGL_ES3_BIT_KHR = 0x0040;
@SuppressWarnings("SameParameterValue")
private static boolean hasExtension(String extensions, String name) { private static boolean hasExtension(String extensions, String name) {
int start = extensions.indexOf(name); int start = extensions.indexOf(name);
while (start >= 0) { while (start >= 0) {

View File

@ -12,7 +12,7 @@ public class DependentLibrary {
@Keep @Keep
public static class LibraryDownloads { public static class LibraryDownloads {
public MinecraftLibraryArtifact artifact; public final MinecraftLibraryArtifact artifact;
public LibraryDownloads(MinecraftLibraryArtifact artifact) { public LibraryDownloads(MinecraftLibraryArtifact artifact) {
this.artifact = artifact; this.artifact = artifact;
} }

View File

@ -14,6 +14,7 @@ import androidx.annotation.Keep;
import org.apache.commons.io.IOUtils; import org.apache.commons.io.IOUtils;
@SuppressWarnings("IOStreamConstructor")
@Keep @Keep
public class MinecraftAccount { public class MinecraftAccount {
public String accessToken = "0"; // access token public String accessToken = "0"; // access token

View File

@ -1,51 +0,0 @@
package net.kdt.pojavlaunch.value;
import androidx.annotation.Keep;
import com.google.gson.JsonSyntaxException;
import com.google.gson.reflect.TypeToken;
import net.kdt.pojavlaunch.Tools;
import net.kdt.pojavlaunch.value.launcherprofiles.MinecraftLauncherProfiles;
import java.io.File;
import java.io.IOException;
import java.util.HashMap;
@Keep
public class PerVersionConfig {
static File pvcFile;
public static HashMap<String,VersionConfig> configMap;
public static void update() throws IOException {
if(configMap == null) {
pvcFile = new File(Tools.DIR_GAME_HOME,"per-version-config.json");
if(pvcFile.exists()) {
try {
configMap = Tools.GLOBAL_GSON.fromJson(Tools.read(pvcFile.getAbsolutePath()), new TypeToken<HashMap<String, VersionConfig>>() {
}.getType());
}catch(JsonSyntaxException ex) {
ex.printStackTrace();
configMap = new HashMap<>();
}
}else{
configMap = new HashMap<>();
}
}else{
Tools.write(pvcFile.getAbsolutePath(),Tools.GLOBAL_GSON.toJson(configMap));
}
}
public static boolean erase() {
return new File(Tools.DIR_GAME_HOME,"per-version-config.json").delete();
}
public static boolean exists() {
return new File(Tools.DIR_GAME_HOME,"per-version-config.json").exists();
}
@Keep
public static class VersionConfig {
public String jvmArgs;
public String gamePath;
public String selectedRuntime;
public String renderer;
}
}

View File

@ -1,16 +1,17 @@
package net.kdt.pojavlaunch.value.launcherprofiles; package net.kdt.pojavlaunch.value.launcherprofiles;
import android.util.Log; import android.util.Log;
import com.google.gson.*; import net.kdt.pojavlaunch.Tools;
import net.kdt.pojavlaunch.*;
import java.io.*; import java.io.File;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.UUID; import java.util.UUID;
public class LauncherProfiles { public class LauncherProfiles {
public static MinecraftLauncherProfiles mainProfileJson; public static MinecraftLauncherProfiles mainProfileJson;
public static File launcherProfilesFile = new File(Tools.DIR_GAME_NEW + "/launcher_profiles.json"); public static final File launcherProfilesFile = new File(Tools.DIR_GAME_NEW, "launcher_profiles.json");
public static MinecraftLauncherProfiles update() { public static MinecraftLauncherProfiles update() {
try { try {
if (mainProfileJson == null) { if (mainProfileJson == null) {
@ -47,7 +48,7 @@ public class LauncherProfiles {
// Detect denormalized keys // Detect denormalized keys
for(String profileKey : launcherProfiles.profiles.keySet()){ for(String profileKey : launcherProfiles.profiles.keySet()){
try{ try{
UUID.fromString(profileKey); if(!UUID.fromString(profileKey).toString().equals(profileKey)) keys.add(profileKey);
}catch (IllegalArgumentException exception){ }catch (IllegalArgumentException exception){
keys.add(profileKey); keys.add(profileKey);
Log.w(LauncherProfiles.class.toString(), "Illegal profile uuid: " + profileKey); Log.w(LauncherProfiles.class.toString(), "Illegal profile uuid: " + profileKey);
@ -68,14 +69,4 @@ public class LauncherProfiles {
return hasNormalized; return hasNormalized;
} }
/*
public static String insert;
private static void insertMissing() {
if (mainProfileJson.authenticationDatabase == null) {
MinecraftAuthenticationDatabase mad = new MinecraftAuthenticationDatabase();
mainProfileJson.authenticationDatabase = mad;
}
}
*/
} }