diff --git a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/BaseLauncherActivity.java b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/BaseLauncherActivity.java index cc35505cb..daecc188d 100644 --- a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/BaseLauncherActivity.java +++ b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/BaseLauncherActivity.java @@ -12,14 +12,20 @@ import android.widget.*; import androidx.annotation.Nullable; import java.io.*; - +import java.util.ArrayList; +import java.util.Map; +import net.kdt.pojavlaunch.extra.ExtraCore; import net.kdt.pojavlaunch.multirt.MultiRTConfigDialog; import net.kdt.pojavlaunch.multirt.MultiRTUtils; import net.kdt.pojavlaunch.prefs.*; +import net.kdt.pojavlaunch.extra.ExtraConstants; import net.kdt.pojavlaunch.tasks.*; import androidx.appcompat.app.AlertDialog; + import net.kdt.pojavlaunch.value.*; +import net.kdt.pojavlaunch.value.launcherprofiles.LauncherProfiles; +import net.kdt.pojavlaunch.value.launcherprofiles.MinecraftProfile; import org.apache.commons.io.IOUtils; @@ -33,7 +39,7 @@ public abstract class BaseLauncherActivity extends BaseActivity { public JMinecraftVersionList mVersionList; public MinecraftDownloaderTask mTask; public MinecraftAccount mProfile; - public String[] mAvailableVersions; + //public String[] mAvailableVersions; public boolean mIsAssetsProcessing = false; protected boolean canBack = false; @@ -99,26 +105,38 @@ public abstract class BaseLauncherActivity extends BaseActivity { } else if (canBack) { v.setEnabled(false); mTask = new MinecraftDownloaderTask(this); - // TODO: better check!!! - if (mProfile.accessToken.equals("0")) { - File verJsonFile = new File(Tools.DIR_HOME_VERSION, - mProfile.selectedVersion + "/" + mProfile.selectedVersion + ".json"); - if (verJsonFile.exists()) { - mTask.onPostExecute(null); - } else { - new AlertDialog.Builder(this) - .setTitle(R.string.global_error) - .setMessage(R.string.mcl_launch_error_localmode) - .setPositiveButton(android.R.string.ok, null) - .show(); + LauncherProfiles.update(); + if (LauncherProfiles.mainProfileJson != null && LauncherProfiles.mainProfileJson.profiles != null && LauncherProfiles.mainProfileJson.profiles.containsKey(mProfile.selectedProfile + "")) { + MinecraftProfile prof = LauncherProfiles.mainProfileJson.profiles.get(mProfile.selectedProfile + ""); + if (prof != null && prof.lastVersionId != null) { + if (mProfile.accessToken.equals("0")) { + String versionId = getVersionId(prof.lastVersionId); + File verJsonFile = new File(Tools.DIR_HOME_VERSION, + versionId + "/" + versionId + ".json"); + if (verJsonFile.exists()) { + mTask.onPostExecute(null); + return; + } + Tools.dialogOnUiThread(this, + getString(R.string.global_error), + getString(R.string.mcl_launch_error_localmode) + ); + }else { + mTask.execute(getVersionId(prof.lastVersionId)); + } + } } - } else { - mTask.execute(mProfile.selectedVersion); - } - } } - + + public static String getVersionId(String input) { + Map releaseTable = (Map)ExtraCore.getValue(ExtraConstants.RELEASE_TABLE); + if(releaseTable == null || releaseTable.isEmpty()) return input; + if("latest-release".equals(input)) return releaseTable.get("release"); + if("latest-snapshot".equals(input)) return releaseTable.get("snapshot"); + return input; + } + @Override public void onBackPressed() { if (canBack) { @@ -133,10 +151,35 @@ public abstract class BaseLauncherActivity extends BaseActivity { Tools.updateWindowSize(this); System.out.println("call to onPostResume; E"); } - + + public static void updateVersionSpinner(Context ctx, ArrayList value, Spinner mVersionSelector, String defaultSelection) { + if(value != null && value.size() > 0) { + ArrayAdapter adapter = new ArrayAdapter(ctx, android.R.layout.simple_spinner_item, value); + adapter.setDropDownViewResource(android.R.layout.simple_list_item_single_choice); + mVersionSelector.setAdapter(adapter); + mVersionSelector.setSelection(RefreshVersionListTask.selectAt(value, defaultSelection)); + return; + } + mVersionSelector.setSelection(RefreshVersionListTask.selectAt(PojavLauncherActivity.basicVersionList, defaultSelection)); + } @Override protected void onResume(){ super.onResume(); + new RefreshVersionListTask(this).execute(); + if(listRefreshListener != null) { + LauncherPreferences.DEFAULT_PREF.unregisterOnSharedPreferenceChangeListener(listRefreshListener); + } + listRefreshListener = (sharedPreferences, key) -> { + if(key.startsWith("vertype_")) { + System.out.println("Verlist update needed!"); + LauncherPreferences.PREF_VERTYPE_RELEASE = sharedPreferences.getBoolean("vertype_release",true); + LauncherPreferences.PREF_VERTYPE_SNAPSHOT = sharedPreferences.getBoolean("vertype_snapshot",false); + LauncherPreferences.PREF_VERTYPE_OLDALPHA = sharedPreferences.getBoolean("vertype_oldalpha",false); + LauncherPreferences.PREF_VERTYPE_OLDBETA = sharedPreferences.getBoolean("vertype_oldbeta",false); + new RefreshVersionListTask(this).execute(); + } + }; + LauncherPreferences.DEFAULT_PREF.registerOnSharedPreferenceChangeListener(listRefreshListener); System.out.println("call to onResume"); final int uiOptions = View.SYSTEM_UI_FLAG_HIDE_NAVIGATION; final View decorView = getWindow().getDecorView(); @@ -145,20 +188,10 @@ public abstract class BaseLauncherActivity extends BaseActivity { } SharedPreferences.OnSharedPreferenceChangeListener listRefreshListener = null; + SharedPreferences.OnSharedPreferenceChangeListener profileEnableListener = null; @Override protected void onResumeFragments() { super.onResumeFragments(); - if(listRefreshListener == null) { - final BaseLauncherActivity thiz = this; - listRefreshListener = (sharedPreferences, key) -> { - if(key.startsWith("vertype_")) { - System.out.println("Verlist update needed!"); - new RefreshVersionListTask(thiz).execute(); - } - }; - } - LauncherPreferences.DEFAULT_PREF.registerOnSharedPreferenceChangeListener(listRefreshListener); - new RefreshVersionListTask(this).execute(); System.out.println("call to onResumeFragments"); mRuntimeConfigDialog = new MultiRTConfigDialog(); mRuntimeConfigDialog.prepare(this); diff --git a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/BaseMainActivity.java b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/BaseMainActivity.java index 800ef48cf..21b9628c1 100644 --- a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/BaseMainActivity.java +++ b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/BaseMainActivity.java @@ -29,6 +29,9 @@ import net.kdt.pojavlaunch.multirt.MultiRTUtils; 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.lwjgl.glfw.*; public class BaseMainActivity extends BaseActivity { @@ -45,7 +48,8 @@ public class BaseMainActivity extends BaseActivity { private static Touchpad touchpad; private LoggerView loggerView; - private MinecraftAccount mProfile; + MinecraftAccount mProfile; + MinecraftProfile minecraftProfile; private DrawerLayout drawerLayout; private NavigationView navDrawer; @@ -55,11 +59,10 @@ public class BaseMainActivity extends BaseActivity { protected volatile JMinecraftVersionList.Version mVersionInfo; - private PerVersionConfig.VersionConfig config; + //private PerVersionConfig.VersionConfig config; protected void initLayout(int resId) { setContentView(resId); - try { Logger.getInstance().reset(); // FIXME: is it safe fot multi thread? @@ -68,22 +71,30 @@ public class BaseMainActivity extends BaseActivity { loggerView = findViewById(R.id.mainLoggerView); mProfile = PojavProfile.getCurrentProfileContent(this); - mVersionInfo = Tools.getVersionInfo(null,mProfile.selectedVersion); - - setTitle("Minecraft " + mProfile.selectedVersion); - PerVersionConfig.update(); - config = PerVersionConfig.configMap.get(mProfile.selectedVersion); + minecraftProfile = LauncherProfiles.mainProfileJson.profiles.get(mProfile.selectedProfile); + if(minecraftProfile == null) { + Toast.makeText(this,"Attempted to launch nonexistent profile",Toast.LENGTH_SHORT).show(); + finish(); + return; + } String runtime = LauncherPreferences.PREF_DEFAULT_RUNTIME; - if(config != null) { - if(config.selectedRuntime != null) { - if(MultiRTUtils.forceReread(config.selectedRuntime).versionString != null) { - runtime = config.selectedRuntime; + LauncherProfiles.update(); + + mVersionInfo = Tools.getVersionInfo(null, BaseLauncherActivity.getVersionId( + minecraftProfile.lastVersionId)); + if(minecraftProfile.javaDir != null && minecraftProfile.javaDir.startsWith(Tools.LAUNCHERPROFILES_RTPREFIX)) { + String runtimeName = minecraftProfile.javaDir.substring(Tools.LAUNCHERPROFILES_RTPREFIX.length()); + if(MultiRTUtils.forceReread(runtimeName).versionString != null) { + runtime = runtimeName; } } - if(config.renderer != null) { - Tools.LOCAL_RENDERER = config.renderer; + if(minecraftProfile.pojavRendererName != null) { + Log.i("RdrDebug","__P_renderer="+minecraftProfile.pojavRendererName); + Tools.LOCAL_RENDERER = minecraftProfile.pojavRendererName; } - } + + setTitle("Minecraft " + minecraftProfile.lastVersionId); + MultiRTUtils.setRuntimeNamed(this,runtime); // Minecraft 1.13+ isInputStackCall = mVersionInfo.arguments != null; @@ -204,8 +215,11 @@ public class BaseMainActivity extends BaseActivity { ((mVersionInfo.inheritsFrom == null || mVersionInfo.inheritsFrom.equals(mVersionInfo.id)) ? "" : " (" + mVersionInfo.inheritsFrom + ")")); + JREUtils.redirectAndPrintJRELog(); - Tools.launchMinecraft(this, mProfile, mProfile.selectedVersion); + LauncherProfiles.update(); + Tools.launchMinecraft(this, mProfile, BaseLauncherActivity.getVersionId( + minecraftProfile.lastVersionId)); } private void checkJavaArgsIsLaunchable(String jreVersion) throws Throwable { diff --git a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/PojavLauncherActivity.java b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/PojavLauncherActivity.java index 9607983a0..9fc055870 100644 --- a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/PojavLauncherActivity.java +++ b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/PojavLauncherActivity.java @@ -6,6 +6,7 @@ import static net.kdt.pojavlaunch.prefs.LauncherPreferences.PREF_HIDE_SIDEBAR; import static net.kdt.pojavlaunch.prefs.LauncherPreferences.PREF_NOTCH_SIZE; import android.animation.ValueAnimator; +import android.content.Context; import android.content.res.Configuration; import android.graphics.Color; import android.graphics.Typeface; @@ -37,9 +38,15 @@ import net.kdt.pojavlaunch.fragments.CrashFragment; import net.kdt.pojavlaunch.fragments.LauncherFragment; import net.kdt.pojavlaunch.prefs.LauncherPreferences; import net.kdt.pojavlaunch.prefs.screens.LauncherPreferenceFragment; +import net.kdt.pojavlaunch.profiles.ProfileAdapter; +import net.kdt.pojavlaunch.extra.ExtraConstants; +import net.kdt.pojavlaunch.profiles.ProfileEditor; +import net.kdt.pojavlaunch.profiles.ProfileIconCache; import net.kdt.pojavlaunch.value.MinecraftAccount; +import net.kdt.pojavlaunch.value.launcherprofiles.LauncherProfiles; import java.io.File; +import java.io.IOException; import java.util.ArrayList; import java.util.List; @@ -81,6 +88,14 @@ public class PojavLauncherActivity extends BaseLauncherActivity public PojavLauncherActivity() { } + @Override + protected void onDestroy() { + ExtraCore.removeExtraListenerFromValue(ExtraConstants.BACK_PREFERENCE, backPreferenceListener); + super.onDestroy(); + ProfileIconCache.clearIconCache(); + Log.i("LauncherActivity","Destroyed!"); + } + @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); @@ -125,7 +140,7 @@ public class PojavLauncherActivity extends BaseLauncherActivity } return false; }; - ExtraCore.addExtraListener("back_preference", backPreferenceListener); + ExtraCore.addExtraListener(ExtraConstants.BACK_PREFERENCE, backPreferenceListener); // Try to load the temporary account @@ -174,31 +189,51 @@ public class PojavLauncherActivity extends BaseLauncherActivity }); // Setup the minecraft version list - List versions = new ArrayList<>(); - final File fVers = new File(Tools.DIR_HOME_VERSION); - - try { - if (fVers.listFiles().length < 1) { - throw new Exception(getString(R.string.error_no_version)); - } - - for (File fVer : fVers.listFiles()) { - if (fVer.isDirectory()) - versions.add(fVer.getName()); - } - } catch (Exception e) { - versions.add(getString(R.string.global_error) + ":"); - versions.add(e.getMessage()); - - } finally { - mAvailableVersions = versions.toArray(new String[0]); - } + setupBasicList(this); //mAvailableVersions; - ArrayAdapter adapterVer = new ArrayAdapter<>(this, android.R.layout.simple_spinner_item, mAvailableVersions); - adapterVer.setDropDownViewResource(android.R.layout.simple_list_item_single_choice); - mVersionSelector.setAdapter(adapterVer); + ProfileAdapter profileAdapter = new ProfileAdapter(this, true); + ProfileEditor profileEditor = new ProfileEditor(this,(name, isNew, deleting)->{ + LauncherProfiles.update(); + if(isNew) { + mVersionSelector.setSelection(profileAdapter.resolveProfileIndex(name)); + } + if(deleting) { + mVersionSelector.setSelection(0); + } + profileAdapter.notifyDataSetChanged(); + }); + mVersionSelector.setOnLongClickListener((v)->profileEditor.show(mProfile.selectedProfile)); + mVersionSelector.setAdapter(profileAdapter); + mVersionSelector.setSelection(profileAdapter.resolveProfileIndex(mProfile.selectedProfile)); + mVersionSelector.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener(){ + @Override + public void onItemSelected(AdapterView p1, View p2, int p3, long p4) + { + String profileName = p1.getItemAtPosition(p3).toString(); + if(profileName.equals(ProfileAdapter.CREATE_PROFILE_MAGIC)) { + profileEditor.show(profileName); + mVersionSelector.setSelection(0); + return; + } + mProfile.selectedProfile = p1.getItemAtPosition(p3).toString(); + PojavProfile.setCurrentProfile(PojavLauncherActivity.this, mProfile); + if (PojavProfile.isFileType(PojavLauncherActivity.this)) { + try { + PojavProfile.setCurrentProfile(PojavLauncherActivity.this, mProfile.save()); + } catch (IOException e) { + Tools.showError(PojavLauncherActivity.this, e); + } + } + } + @Override + public void onNothingSelected(AdapterView p1) + { + // TODO: Implement this method + } + }); + // statusIsLaunching(false); @@ -216,12 +251,33 @@ public class PojavLauncherActivity extends BaseLauncherActivity }); changeLookAndFeel(PREF_HIDE_SIDEBAR); } - private void selectTabPage(int pageIndex){ viewPager.setCurrentItem(pageIndex); setTabActive(pageIndex); } + public static String[] basicVersionList; + public static void setupBasicList(Context ctx) { + List versions = new ArrayList<>(); + final File fVers = new File(Tools.DIR_HOME_VERSION); + try { + if (fVers.listFiles().length < 1) { + throw new Exception(ctx.getString(R.string.error_no_version)); + } + + for (File fVer : fVers.listFiles()) { + if (fVer.isDirectory()) + versions.add(fVer.getName()); + } + } catch (Exception e) { + versions.add(ctx.getString(R.string.global_error) + ":"); + versions.add(e.getMessage()); + + } finally { + basicVersionList = versions.toArray(new String[0]); + ExtraCore.setValue(ExtraConstants.VERSION_LIST,versions); + } + } private void pickAccount() { try { mProfile = PojavProfile.getCurrentProfileContent(this); @@ -340,7 +396,7 @@ public class PojavLauncherActivity extends BaseLauncherActivity }else{ super.onBackPressed(); //additional code - ExtraCore.removeExtraListenerFromValue("back_preference", backPreferenceListener); + ExtraCore.removeExtraListenerFromValue(ExtraConstants.BACK_PREFERENCE, backPreferenceListener); finish(); } } diff --git a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/PojavLoginActivity.java b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/PojavLoginActivity.java index dd91ed26a..6b015f889 100644 --- a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/PojavLoginActivity.java +++ b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/PojavLoginActivity.java @@ -51,6 +51,9 @@ import net.kdt.pojavlaunch.multirt.MultiRTUtils; import net.kdt.pojavlaunch.prefs.LauncherPreferences; import net.kdt.pojavlaunch.utils.LocaleUtils; import net.kdt.pojavlaunch.value.MinecraftAccount; +import net.kdt.pojavlaunch.value.PerVersionConfig; +import net.kdt.pojavlaunch.value.launcherprofiles.LauncherProfiles; +import net.kdt.pojavlaunch.value.launcherprofiles.MinecraftProfile; import org.apache.commons.io.FileUtils; @@ -336,6 +339,7 @@ public class PojavLoginActivity extends BaseActivity { mLockSelectJRE.wait(); } } + migrateToProfiles(); if(Build.VERSION.SDK_INT > 28) runOnUiThread(this::showStorageDialog); LauncherPreferences.loadPreferences(getApplicationContext()); } @@ -388,6 +392,33 @@ public class PojavLoginActivity extends BaseActivity { } } } + private void migrateToProfiles() { + try { + if(!PerVersionConfig.exists()) return; + LauncherProfiles.update(); + PerVersionConfig.update(); + if(PerVersionConfig.erase()) { + for (String version : PerVersionConfig.configMap.keySet()) { + PerVersionConfig.VersionConfig config = PerVersionConfig.configMap.get(version); + if (config != null) { + MinecraftProfile profile = new MinecraftProfile(); + profile.lastVersionId = version; + profile.name = getString(R.string.migrated_profile_str, version); + profile.pojavRendererName = config.renderer; + profile.gameDir = config.gamePath; + profile.javaDir = Tools.LAUNCHERPROFILES_RTPREFIX + config.selectedRuntime; + profile.javaArgs = config.jvmArgs; + LauncherProfiles.mainProfileJson.profiles.put("pvc-migrated-" + version, profile); + } + } + LauncherProfiles.update(); + }else{ + Log.e("ProfileMigrator"," Unable to remove Per Version Config files."); + } + }catch (IOException e) { + Log.e("ProfileMigrator","Failed to migrate!",e); + } + } private boolean installRuntimeAutomatically(AssetManager am, boolean otherRuntimesAvailable) { /* Check if JRE is included */ String rt_version = null; diff --git a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/Tools.java b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/Tools.java index b3c9c0bfb..59dae5c6c 100644 --- a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/Tools.java +++ b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/Tools.java @@ -23,6 +23,7 @@ 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.codec.digest.DigestUtils; @@ -50,6 +51,7 @@ public final class Tools { public static String MULTIRT_HOME; public static String LOCAL_RENDERER = null; public static int DEVICE_ARCHITECTURE; + public static String LAUNCHERPROFILES_RTPREFIX = "pojav://"; // New since 3.3.1 public static String DIR_ACCOUNT_NEW; @@ -117,13 +119,16 @@ public final class Tools { } JMinecraftVersionList.Version versionInfo = Tools.getVersionInfo(null,versionName); - PerVersionConfig.update(); - PerVersionConfig.VersionConfig pvcConfig = PerVersionConfig.configMap.get(versionName); - - String gamedirPath; - if(pvcConfig != null && pvcConfig.gamePath != null && !pvcConfig.gamePath.isEmpty()) gamedirPath = pvcConfig.gamePath; - else gamedirPath = Tools.DIR_GAME_NEW; - if(pvcConfig != null && pvcConfig.jvmArgs != null && !pvcConfig.jvmArgs.isEmpty()) LauncherPreferences.PREF_CUSTOM_JAVA_ARGS = pvcConfig.jvmArgs; + String gamedirPath = Tools.DIR_GAME_NEW; + if(activity instanceof BaseMainActivity) { + LauncherProfiles.update(); + MinecraftProfile minecraftProfile = ((BaseMainActivity)activity).minecraftProfile; + if(minecraftProfile == null) throw new Exception("Launching empty Profile"); + if(minecraftProfile.gameDir != null && !minecraftProfile.gameDir.isEmpty()) + gamedirPath = minecraftProfile.gameDir; + if(minecraftProfile.javaArgs != null && !minecraftProfile.javaArgs.isEmpty()) + LauncherPreferences.PREF_CUSTOM_JAVA_ARGS = minecraftProfile.javaArgs; + } PojavLoginActivity.disableSplash(gamedirPath); String[] launchArgs = getMinecraftArgs(profile, versionInfo, gamedirPath); diff --git a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/customcontrols/ControlDrawerData.java b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/customcontrols/ControlDrawerData.java index 1a1b086e1..68374be0f 100644 --- a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/customcontrols/ControlDrawerData.java +++ b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/customcontrols/ControlDrawerData.java @@ -12,7 +12,7 @@ import static net.kdt.pojavlaunch.customcontrols.ControlDrawerData.Orientation.F import androidx.annotation.Keep; -@Keep +@androidx.annotation.Keep public class ControlDrawerData { public ArrayList buttonProperties; diff --git a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/extra/ExtraConstants.java b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/extra/ExtraConstants.java new file mode 100644 index 000000000..7f25bb7b2 --- /dev/null +++ b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/extra/ExtraConstants.java @@ -0,0 +1,10 @@ +package net.kdt.pojavlaunch.extra; + +public class ExtraConstants { + /* 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"; + /* ExtraCore constant: an ArrayList of Strings, where each String is a Minecraft version name */ + public static final String VERSION_LIST= "lac_version_list"; + /* ExraCore constant: Serpent's back button tracking thing */ + public static final String BACK_PREFERENCE = "back_preference"; +} diff --git a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/prefs/BackButtonPreference.java b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/prefs/BackButtonPreference.java index 8621cbe2f..5745513b0 100644 --- a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/prefs/BackButtonPreference.java +++ b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/prefs/BackButtonPreference.java @@ -6,6 +6,7 @@ import android.util.AttributeSet; import androidx.preference.Preference; import net.kdt.pojavlaunch.R; +import net.kdt.pojavlaunch.extra.ExtraConstants; import net.kdt.pojavlaunch.extra.ExtraCore; public class BackButtonPreference extends Preference { @@ -31,6 +32,6 @@ public class BackButtonPreference extends Preference { @Override protected void onClick() { // It is caught by an ExtraListener in the LauncherActivity - ExtraCore.setValue("back_preference", "true"); + ExtraCore.setValue(ExtraConstants.BACK_PREFERENCE, "true"); } } diff --git a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/prefs/PerVersionConfigDialog.java b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/prefs/PerVersionConfigDialog.java deleted file mode 100644 index 2b5f000e9..000000000 --- a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/prefs/PerVersionConfigDialog.java +++ /dev/null @@ -1,124 +0,0 @@ -package net.kdt.pojavlaunch.prefs; - -import android.content.Context; -import android.content.DialogInterface; -import android.view.LayoutInflater; -import android.view.View; -import android.widget.ArrayAdapter; -import android.widget.EditText; -import android.widget.Spinner; - -import androidx.appcompat.app.AlertDialog; - -import net.kdt.pojavlaunch.R; -import net.kdt.pojavlaunch.multirt.MultiRTUtils; -import net.kdt.pojavlaunch.multirt.RTSpinnerAdapter; -import net.kdt.pojavlaunch.multirt.Runtime; -import net.kdt.pojavlaunch.value.PerVersionConfig; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; - -public class PerVersionConfigDialog{ - final Context mContext; - final AlertDialog mDialog; - final View mRootView; - List mRuntimes; - final Spinner mJvmSpinner; - final Spinner mRendererSpinner; - final EditText mCustomDirEditText; - final EditText mJvmArgsEditText; - final List mRendererNames; - String mSelectedGameVersion = null; - - public PerVersionConfigDialog(Context ctx) { - mContext = ctx; - mRootView = LayoutInflater.from(mContext).inflate(R.layout.dialog_per_version_control,null); - mJvmSpinner = mRootView.findViewById(R.id.pvc_javaVm); - mRendererSpinner = mRootView.findViewById(R.id.pvc_renderer); - - ArrayList renderList = new ArrayList<>(5); - Collections.addAll(renderList, mContext.getResources().getStringArray(R.array.renderer)); - renderList.add("Default"); - mRendererNames = Arrays.asList(mContext.getResources().getStringArray(R.array.renderer_values)); - mRendererSpinner.setAdapter(new ArrayAdapter<>(mContext, android.R.layout.simple_spinner_dropdown_item, renderList)); - - mCustomDirEditText = mRootView.findViewById(R.id.pvc_customDir); - mJvmArgsEditText = mRootView.findViewById(R.id.pvc_jvmArgs); - AlertDialog.Builder builder = new AlertDialog.Builder(mContext); - builder.setView(mRootView); - builder.setTitle(R.string.pvc_title); - builder.setNegativeButton(android.R.string.cancel, null); - builder.setPositiveButton(android.R.string.ok, this::save); - mDialog = builder.create(); - } - - public void refreshRuntimes() { - if(mRuntimes !=null) mRuntimes.clear(); - mRuntimes = MultiRTUtils.getRuntimes(); - //runtimes.add(new Runtime("")); - } - - private void save(DialogInterface dialogInterface, int which) { - if(mSelectedGameVersion == null) { - dialogInterface.dismiss(); - return; - } - - PerVersionConfig.VersionConfig versionConfig = PerVersionConfig.configMap.get(mSelectedGameVersion); - if(versionConfig == null){ - versionConfig = new PerVersionConfig.VersionConfig(); - } - versionConfig.jvmArgs= mJvmArgsEditText.getText().toString(); - versionConfig.gamePath= mCustomDirEditText.getText().toString(); - - if(mRendererSpinner.getSelectedItemPosition() == mRendererNames.size()) versionConfig.renderer = null; - else versionConfig.renderer = mRendererNames.get(mRendererSpinner.getSelectedItemPosition()); - - String runtime=((Runtime) mJvmSpinner.getSelectedItem()).name;; - if(!runtime.equals(""))versionConfig.selectedRuntime=runtime; - else versionConfig.selectedRuntime = null; - - PerVersionConfig.configMap.put(mSelectedGameVersion, versionConfig); - try{ - PerVersionConfig.update(); - }catch(IOException e){ - e.printStackTrace(); - } - } - - public boolean openConfig(String selectedVersion) { - mSelectedGameVersion = selectedVersion; - try{ - PerVersionConfig.update(); - }catch(IOException e){ - e.printStackTrace(); - } - PerVersionConfig.VersionConfig versionConfig = PerVersionConfig.configMap.get(mSelectedGameVersion); - refreshRuntimes(); - mJvmSpinner.setAdapter(new RTSpinnerAdapter(mContext, mRuntimes)); - - int jvmIndex = mRuntimes.indexOf(new Runtime("")); - int rendererIndex = mRendererSpinner.getAdapter().getCount()-1; - if (versionConfig != null) { - mCustomDirEditText.setText(versionConfig.gamePath); - mJvmArgsEditText.setText(versionConfig.jvmArgs); - if (versionConfig.selectedRuntime != null) { - int nIndex = mRuntimes.indexOf(new Runtime(versionConfig.selectedRuntime)); - if (nIndex != -1) jvmIndex = nIndex; - } - if(versionConfig.renderer != null) { - int nIndex = mRendererNames.indexOf(versionConfig.renderer); - if (nIndex != -1) rendererIndex = nIndex; - } - } - mJvmSpinner.setSelection(jvmIndex); - mRendererSpinner.setSelection(rendererIndex); - - mDialog.show(); - return true; - } -} diff --git a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/profiles/ProfileAdapter.java b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/profiles/ProfileAdapter.java new file mode 100644 index 000000000..2f81fad53 --- /dev/null +++ b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/profiles/ProfileAdapter.java @@ -0,0 +1,126 @@ +package net.kdt.pojavlaunch.profiles; + +import android.content.Context; +import android.graphics.Bitmap; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.BaseAdapter; +import android.widget.ImageView; +import android.widget.TextView; + +import net.kdt.pojavlaunch.R; +import net.kdt.pojavlaunch.value.launcherprofiles.LauncherProfiles; +import net.kdt.pojavlaunch.value.launcherprofiles.MinecraftProfile; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +/* + * Adapter for listing launcher profiles in a Spinner + */ +public class ProfileAdapter extends BaseAdapter { + private Map mProfiles; + public static final String CREATE_PROFILE_MAGIC = "___extra____profile-create"; + private final MinecraftProfile dummy = new MinecraftProfile(); + private MinecraftProfile mCreateProfile; + private List mProfileList; + public ProfileAdapter(Context context, boolean enableCreateButton) { + ProfileIconCache.initDefault(context); + LauncherProfiles.update(); + mProfiles = new HashMap<>(LauncherProfiles.mainProfileJson.profiles); + if(enableCreateButton) { + mCreateProfile = new MinecraftProfile(); + mCreateProfile.name = "Create new profile"; + mCreateProfile.lastVersionId = ""; + } + mProfileList = new ArrayList<>(Arrays.asList(mProfiles.keySet().toArray(new String[0]))); + if(enableCreateButton) { + mProfileList.add(ProfileAdapter.CREATE_PROFILE_MAGIC); + mProfiles.put(CREATE_PROFILE_MAGIC, mCreateProfile); + } + } + /* + * Gets how much profiles are loaded in the adapter right now + * @returns loaded profile count + */ + @Override + public int getCount() { + return mProfileList.size(); + } + /* + * Gets the profile at a given index + * @param position index to retreive + * @returns MinecraftProfile name or null + */ + @Override + public Object getItem(int position) { + //safe since the second check in the and statement will be skipped if the first one fails + if(position < mProfileList.size() && mProfiles.containsKey(mProfileList.get(position))) { + return mProfileList.get(position); + }else{ + return null; + } + } + + public int resolveProfileIndex(String name) { + return mProfileList.indexOf(name); + } + + public void fireProfileEdit() { + notifyDataSetChanged(); + } + /* + * Gets the item ID (crc64 hash of the profile name) for a given index + * @param position index to get the hash for + * @returns ID (crc64 of a profile name string) or -1 if the index is out of bounds + */ + @Override + public long getItemId(int position) { + return position; + } + + @Override + public void notifyDataSetChanged() { + mProfiles = new HashMap<>(LauncherProfiles.mainProfileJson.profiles); + mProfileList = new ArrayList<>(Arrays.asList(mProfiles.keySet().toArray(new String[0]))); + mProfileList.add(ProfileAdapter.CREATE_PROFILE_MAGIC); + mProfiles.put(CREATE_PROFILE_MAGIC, mCreateProfile); + super.notifyDataSetChanged(); + } + + @Override + public View getView(int position, View convertView, ViewGroup parent) { + View v = convertView; + if (v == null) v = LayoutInflater.from(parent.getContext()).inflate(R.layout.version_profile_layout,parent,false); + setViewProfile(v,mProfileList.get(position)); + return v; + } + public void setViewProfile(View v, String nm) { + MinecraftProfile minecraftProfile = mProfiles.get(nm); + if(minecraftProfile == null) minecraftProfile = dummy; + Bitmap cachedIcon = ProfileIconCache.getCachedIcon(nm); + ImageView iconView = v.findViewById(R.id.vprof_icon_view); + if(cachedIcon == null) { + cachedIcon = ProfileIconCache.tryResolveIcon(nm,minecraftProfile.icon); + } + iconView.setImageBitmap(cachedIcon); + if(minecraftProfile.name != null && !minecraftProfile.name.isEmpty()) + ((TextView)v.findViewById(R.id.vprof_profile_name_view)).setText(minecraftProfile.name); + else + ((TextView)v.findViewById(R.id.vprof_profile_name_view)).setText(R.string.unnamed); + + TextView tv = v.findViewById(R.id.vprof_version_id_view); + if(minecraftProfile.lastVersionId != null) switch (minecraftProfile.lastVersionId) { + case "latest-release": + tv.setText(R.string.profiles_latest_release); + case "latest-snapshot": + tv.setText(R.string.profiles_latest_snapshot); + default: + tv.setText(minecraftProfile.lastVersionId); + } else tv.setText(android.R.string.unknownName); + + } +} diff --git a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/profiles/ProfileEditor.java b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/profiles/ProfileEditor.java new file mode 100644 index 000000000..ea4a7fc66 --- /dev/null +++ b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/profiles/ProfileEditor.java @@ -0,0 +1,197 @@ +package net.kdt.pojavlaunch.profiles; + +import android.app.AlertDialog; +import android.content.Context; +import android.content.DialogInterface; +import android.graphics.Bitmap; +import android.os.Handler; +import android.os.Looper; +import android.view.LayoutInflater; +import android.view.View; +import android.widget.ArrayAdapter; +import android.widget.ImageView; +import android.widget.Spinner; +import android.widget.TextView; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + +import net.kdt.pojavlaunch.BaseLauncherActivity; +import net.kdt.pojavlaunch.PojavLauncherActivity; +import net.kdt.pojavlaunch.R; +import net.kdt.pojavlaunch.Tools; +import net.kdt.pojavlaunch.extra.ExtraCore; +import net.kdt.pojavlaunch.extra.ExtraListener; +import net.kdt.pojavlaunch.extra.ExtraConstants; +import net.kdt.pojavlaunch.multirt.MultiRTUtils; +import net.kdt.pojavlaunch.multirt.RTSpinnerAdapter; +import net.kdt.pojavlaunch.value.launcherprofiles.LauncherProfiles; +import net.kdt.pojavlaunch.value.launcherprofiles.MinecraftProfile; +import net.kdt.pojavlaunch.multirt.Runtime; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.UUID; + +public class ProfileEditor implements ExtraListener> { + private final View mainView; + private final TextView profileNameView; + private final ImageView profileIconView; + private final Spinner versionSpinner; + private final Spinner javaRuntimeSpinner; + private final Spinner rendererSpinner; + private final List renderNames; + private final AlertDialog dialog; + private String selectedVersionId; + private String editingProfile; + private final EditSaveCallback editSaveCallback; + private final Handler uiThreadHandler; + public static MinecraftProfile generateTemplate() { + MinecraftProfile TEMPLATE = new MinecraftProfile(); + TEMPLATE.name = "New"; + TEMPLATE.lastVersionId = "latest-release"; + return TEMPLATE; + } + public ProfileEditor(Context _ctx, EditSaveCallback editSaveCallback) { + this.editSaveCallback = editSaveCallback; + uiThreadHandler = new Handler(Looper.getMainLooper()); + LayoutInflater inflater = LayoutInflater.from(_ctx); + mainView = inflater.inflate(R.layout.version_profile_editor,null); + AlertDialog.Builder builder = new AlertDialog.Builder(_ctx); + builder.setView(mainView); + profileNameView = mainView.findViewById(R.id.vprof_editior_profile_name); + versionSpinner = mainView.findViewById(R.id.vprof_editor_version_spinner); + javaRuntimeSpinner = mainView.findViewById(R.id.vprof_editor_spinner_runtime); + rendererSpinner = mainView.findViewById(R.id.vprof_editor_profile_renderer); + { + Context context = rendererSpinner.getContext(); + List renderList = new ArrayList<>(); + Collections.addAll(renderList, context.getResources().getStringArray(R.array.renderer)); + renderList.add("Default"); + renderNames = Arrays.asList(context.getResources().getStringArray(R.array.renderer_values)); + rendererSpinner.setAdapter(new ArrayAdapter<>(context, android.R.layout.simple_spinner_dropdown_item,renderList)); + } + profileIconView = mainView.findViewById(R.id.vprof_editor_icon); + builder.setPositiveButton(R.string.global_save,this::save); + builder.setNegativeButton(android.R.string.cancel,(dialog,which)->destroy(dialog)); + builder.setNeutralButton(R.string.global_delete,(dialogInterface, i) -> { + LauncherProfiles.mainProfileJson.profiles.remove(editingProfile); + this.editSaveCallback.onSave(editingProfile,false, true); + }); + builder.setOnDismissListener(this::destroy); + dialog = builder.create(); + } + public boolean show(@NonNull String profile) { + MinecraftProfile minecraftProfile; + if(!ProfileAdapter.CREATE_PROFILE_MAGIC.equals(profile)) { + minecraftProfile = LauncherProfiles.mainProfileJson.profiles.get(profile); + if (minecraftProfile == null) return true; + editingProfile = profile; + }else{ + minecraftProfile = generateTemplate(); + String uuid = UUID.randomUUID().toString(); + while(LauncherProfiles.mainProfileJson.profiles.containsKey(uuid)) { + uuid = UUID.randomUUID().toString(); + } + editingProfile = uuid; + } + List runtimes = MultiRTUtils.getRuntimes(); + Context context = javaRuntimeSpinner.getContext(); + javaRuntimeSpinner.setAdapter(new RTSpinnerAdapter(context, runtimes)); + int jvmIndex = runtimes.indexOf(new Runtime("")); + int rendererIndex = rendererSpinner.getAdapter().getCount()-1; + if (minecraftProfile.javaDir != null) { + String selectedRuntime = minecraftProfile.javaDir.substring(Tools.LAUNCHERPROFILES_RTPREFIX.length()); + int nindex = runtimes.indexOf(new Runtime(selectedRuntime)); + if (nindex != -1) jvmIndex = nindex; + } + if(minecraftProfile.pojavRendererName != null) { + int nindex = renderNames.indexOf(minecraftProfile.pojavRendererName); + if(nindex != -1) rendererIndex = nindex; + } + javaRuntimeSpinner.setSelection(jvmIndex); + rendererSpinner.setSelection(rendererIndex); + ExtraCore.addExtraListener(ExtraConstants.VERSION_LIST,this); + profileNameView.setText(minecraftProfile.name); + Bitmap profileIcon = ProfileIconCache.getCachedIcon(profile); + if(profileIcon == null) { + profileIcon = ProfileIconCache.tryResolveIcon(profile,minecraftProfile.icon); + } + profileIconView.setImageBitmap(profileIcon); + if(minecraftProfile.lastVersionId != null && !"latest-release".equals(minecraftProfile.lastVersionId) && !"latest-snapshot".equals(minecraftProfile.lastVersionId)) + selectedVersionId = minecraftProfile.lastVersionId; + else if(minecraftProfile.lastVersionId != null) { + Map releaseTable = (Map)ExtraCore.getValue(ExtraConstants.RELEASE_TABLE); + if(releaseTable != null) { + switch (minecraftProfile.lastVersionId) { + case "latest-release": + selectedVersionId = releaseTable.get("release"); + case "latest-snapshot": + selectedVersionId = releaseTable.get("snapshot"); + } + }else{ + selectedVersionId = null; + } + } + else{ + if(PojavLauncherActivity.basicVersionList.length > 0) { + selectedVersionId = PojavLauncherActivity.basicVersionList[0]; + } + } + ArrayList versions = (ArrayList) ExtraCore.getValue(ExtraConstants.VERSION_LIST); + BaseLauncherActivity.updateVersionSpinner(context,versions,versionSpinner, selectedVersionId); + dialog.show(); + return true; + } + public void save(DialogInterface dialog, int which) { + System.out.println(editingProfile); + MinecraftProfile profile; + boolean isNew; + if(LauncherProfiles.mainProfileJson.profiles.containsKey(editingProfile)) { + profile = LauncherProfiles.mainProfileJson.profiles.get(editingProfile); + if(profile == null) { + profile = new MinecraftProfile(); + isNew = true; + }else{ + isNew = false; + } + LauncherProfiles.mainProfileJson.profiles.remove(editingProfile); + }else{ + profile = new MinecraftProfile(); + isNew = true; + } + profile.name = profileNameView.getText().toString(); + profile.lastVersionId = (String)versionSpinner.getSelectedItem(); + Runtime selectedRuntime = (Runtime) javaRuntimeSpinner.getSelectedItem(); + if(selectedRuntime.name.equals("")) { + profile.javaDir = null; + }else if(selectedRuntime.versionString == null) { + profile.javaDir = null; + }else{ + profile.javaDir = Tools.LAUNCHERPROFILES_RTPREFIX+selectedRuntime.name; + } + if(rendererSpinner.getSelectedItemPosition() == renderNames.size()) profile.pojavRendererName = null; + else profile.pojavRendererName = renderNames.get(rendererSpinner.getSelectedItemPosition()); + LauncherProfiles.mainProfileJson.profiles.put(editingProfile,profile); + editSaveCallback.onSave(editingProfile,isNew, false); + destroy(dialog); + } + public void destroy(@NonNull DialogInterface dialog) { + ExtraCore.removeExtraListenerFromValue(ExtraConstants.VERSION_LIST,this); + editingProfile = null; + selectedVersionId = null; + } + @Override + public boolean onValueSet(String key, @Nullable ArrayList value) { + if(value != null) { + uiThreadHandler.post(() -> BaseLauncherActivity.updateVersionSpinner(mainView.getContext(), value, versionSpinner, selectedVersionId)); + } + return false; + } + public interface EditSaveCallback { + void onSave(String name, boolean isNew, boolean isRemoving); + } +} diff --git a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/profiles/ProfileIconCache.java b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/profiles/ProfileIconCache.java new file mode 100644 index 000000000..0d0356c0b --- /dev/null +++ b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/profiles/ProfileIconCache.java @@ -0,0 +1,54 @@ +package net.kdt.pojavlaunch.profiles; + +import android.content.Context; +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; +import android.util.Base64; +import android.util.Log; + +import net.kdt.pojavlaunch.R; + +import java.util.HashMap; +import java.util.Map; + +public class ProfileIconCache { + private static final String BASE64_PNG_HEADER = "data:image/png;base64,"; + private static final Map iconCache = new HashMap<>(); + private static Bitmap defaultIcon; + public static void initDefault(Context context) { + if(defaultIcon == null) + defaultIcon = BitmapFactory.decodeResource(context.getResources(), R.drawable.ic_menu_java); + } + public static void clearIconCache() { + for(String key : iconCache.keySet()) { + Bitmap bitmap = iconCache.get(key); + if(bitmap != defaultIcon && bitmap != null) { + bitmap.recycle(); + } + } + iconCache.clear(); + } + public static Bitmap getCachedIcon(String key) { + return iconCache.get(key); + } + public static Bitmap submitIcon(String key, String base64) { + byte[] pngBytes = Base64.decode(base64, Base64.DEFAULT); + Bitmap cachedIcon = BitmapFactory.decodeByteArray(pngBytes,0,pngBytes.length); + iconCache.put(key, cachedIcon); + return cachedIcon; + } + public static Bitmap tryResolveIcon(String profileName, String b64Icon) { + Bitmap icon; + if (b64Icon != null && b64Icon.startsWith(BASE64_PNG_HEADER)) { + icon = ProfileIconCache.submitIcon(profileName, b64Icon.substring(BASE64_PNG_HEADER.length())); + }else{ + Log.i("IconParser","Unsupported icon: "+b64Icon); + icon = ProfileIconCache.pushDefaultIcon(profileName); + } + return icon; + } + public static Bitmap pushDefaultIcon(String key) { + iconCache.put(key, defaultIcon); + return defaultIcon; + } +} diff --git a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/tasks/MinecraftDownloaderTask.java b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/tasks/MinecraftDownloaderTask.java index 42b7463f6..a4030835f 100644 --- a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/tasks/MinecraftDownloaderTask.java +++ b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/tasks/MinecraftDownloaderTask.java @@ -14,6 +14,8 @@ import net.kdt.pojavlaunch.multirt.Runtime; 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.io.*; @@ -89,19 +91,19 @@ public class MinecraftDownloaderTask extends AsyncTask{ AlertDialog.Builder bldr = new AlertDialog.Builder(mActivity); @@ -378,6 +380,8 @@ public class MinecraftDownloaderTask extends AsyncTask + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app_pojavlauncher/src/main/res/layout/version_profile_layout.xml b/app_pojavlauncher/src/main/res/layout/version_profile_layout.xml new file mode 100644 index 000000000..b936e5df0 --- /dev/null +++ b/app_pojavlauncher/src/main/res/layout/version_profile_layout.xml @@ -0,0 +1,41 @@ + + + + + + + + + \ No newline at end of file diff --git a/app_pojavlauncher/src/main/res/values/strings.xml b/app_pojavlauncher/src/main/res/values/strings.xml index 43a560083..bf4276659 100644 --- a/app_pojavlauncher/src/main/res/values/strings.xml +++ b/app_pojavlauncher/src/main/res/values/strings.xml @@ -283,11 +283,22 @@ Don\'t shrink textures Divides all textures by 2 Divides big textures by /2 or /4 - + Unnamed + Latest snapshot + Latest release + Editing profile + Name + Version + Profiles + Use Minecraft Launcher profiles instead of the regular version list. Supports icons! Disable VBOs Help with compatibility on some old versions + Delete + Java Runtime + Renderer Force openGL 1 Help with compatibility on some old versions Arc Capes Enables capes from Arc. For more information please visit https://arccapes.com. Requires OptiFine. + %s version configuration diff --git a/app_pojavlauncher/src/main/res/xml/pref_experimental.xml b/app_pojavlauncher/src/main/res/xml/pref_experimental.xml index 67edc6beb..cc2326d90 100644 --- a/app_pojavlauncher/src/main/res/xml/pref_experimental.xml +++ b/app_pojavlauncher/src/main/res/xml/pref_experimental.xml @@ -18,6 +18,11 @@ android:defaultValue="false" android:key="vbo_disable_hack" /> +