mirror of
https://github.com/AngelAuraMC/Amethyst-Android.git
synced 2025-09-16 16:16:04 -04:00
Add OptiFine automatic installation
Unlike other modloaders, it does require the game being installed beforehand, so it's also implemented here
This commit is contained in:
parent
3cfaec3b4c
commit
84a2bd24c7
Binary file not shown.
@ -1 +1 @@
|
|||||||
1687971356220
|
1688118307460
|
@ -1,9 +1,11 @@
|
|||||||
package net.kdt.pojavlaunch.fragments;
|
package net.kdt.pojavlaunch.fragments;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
import android.content.Intent;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.widget.ExpandableListAdapter;
|
import android.widget.ExpandableListAdapter;
|
||||||
|
|
||||||
|
import net.kdt.pojavlaunch.JavaGUILauncherActivity;
|
||||||
import net.kdt.pojavlaunch.R;
|
import net.kdt.pojavlaunch.R;
|
||||||
import net.kdt.pojavlaunch.Tools;
|
import net.kdt.pojavlaunch.Tools;
|
||||||
import net.kdt.pojavlaunch.modloaders.ModloaderListenerProxy;
|
import net.kdt.pojavlaunch.modloaders.ModloaderListenerProxy;
|
||||||
@ -55,6 +57,8 @@ public class OptiFineInstallFragment extends ModVersionListFragment<OptiFineUtil
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onDownloadFinished(Context context, File downloadedFile) {
|
public void onDownloadFinished(Context context, File downloadedFile) {
|
||||||
Tools.dialog(context, "Not yet complete", "Installation of OptiFine is not yet implemented. To be done!");
|
Intent modInstallerStartIntent = new Intent(context, JavaGUILauncherActivity.class);
|
||||||
|
OptiFineUtils.addAutoInstallArgs(modInstallerStartIntent, downloadedFile);
|
||||||
|
context.startActivity(modInstallerStartIntent);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,18 +2,25 @@ package net.kdt.pojavlaunch.modloaders;
|
|||||||
|
|
||||||
import com.kdt.mcgui.ProgressLayout;
|
import com.kdt.mcgui.ProgressLayout;
|
||||||
|
|
||||||
|
import net.kdt.pojavlaunch.JMinecraftVersionList;
|
||||||
import net.kdt.pojavlaunch.R;
|
import net.kdt.pojavlaunch.R;
|
||||||
import net.kdt.pojavlaunch.Tools;
|
import net.kdt.pojavlaunch.Tools;
|
||||||
import net.kdt.pojavlaunch.progresskeeper.ProgressKeeper;
|
import net.kdt.pojavlaunch.progresskeeper.ProgressKeeper;
|
||||||
|
import net.kdt.pojavlaunch.tasks.AsyncMinecraftDownloader;
|
||||||
import net.kdt.pojavlaunch.utils.DownloadUtils;
|
import net.kdt.pojavlaunch.utils.DownloadUtils;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.util.regex.Matcher;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
public class OptiFineDownloadTask implements Runnable, Tools.DownloaderFeedback{
|
public class OptiFineDownloadTask implements Runnable, Tools.DownloaderFeedback, AsyncMinecraftDownloader.DoneListener {
|
||||||
|
private static final Pattern sMcVersionPattern = Pattern.compile("([0-9]+)\\.([0-9]+)\\.?([0-9]+)?");
|
||||||
private final OptiFineUtils.OptiFineVersion mOptiFineVersion;
|
private final OptiFineUtils.OptiFineVersion mOptiFineVersion;
|
||||||
private final File mDestinationFile;
|
private final File mDestinationFile;
|
||||||
private final ModloaderDownloadListener mListener;
|
private final ModloaderDownloadListener mListener;
|
||||||
|
private final Object mMinecraftDownloadLock = new Object();
|
||||||
|
private Throwable mDownloaderThrowable;
|
||||||
|
|
||||||
public OptiFineDownloadTask(OptiFineUtils.OptiFineVersion mOptiFineVersion, File mDestinationFile, ModloaderDownloadListener mListener) {
|
public OptiFineDownloadTask(OptiFineUtils.OptiFineVersion mOptiFineVersion, File mDestinationFile, ModloaderDownloadListener mListener) {
|
||||||
this.mOptiFineVersion = mOptiFineVersion;
|
this.mOptiFineVersion = mOptiFineVersion;
|
||||||
@ -23,7 +30,7 @@ public class OptiFineDownloadTask implements Runnable, Tools.DownloaderFeedback{
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
ProgressKeeper.submitProgress(ProgressLayout.INSTALL_MODPACK, 0, R.string.of_dl_progress, mOptiFineVersion.downloadUrl);
|
ProgressKeeper.submitProgress(ProgressLayout.INSTALL_MODPACK, 0, R.string.of_dl_progress, mOptiFineVersion.versionName);
|
||||||
try {
|
try {
|
||||||
if(runCatching()) mListener.onDownloadFinished(mDestinationFile);
|
if(runCatching()) mListener.onDownloadFinished(mDestinationFile);
|
||||||
}catch (IOException e) {
|
}catch (IOException e) {
|
||||||
@ -35,6 +42,17 @@ public class OptiFineDownloadTask implements Runnable, Tools.DownloaderFeedback{
|
|||||||
public boolean runCatching() throws IOException {
|
public boolean runCatching() throws IOException {
|
||||||
String downloadUrl = scrapeDownloadsPage();
|
String downloadUrl = scrapeDownloadsPage();
|
||||||
if(downloadUrl == null) return false;
|
if(downloadUrl == null) return false;
|
||||||
|
String minecraftVersion = determineMinecraftVersion();
|
||||||
|
if(minecraftVersion == null) return false;
|
||||||
|
if(!downloadMinecraft(minecraftVersion)) {
|
||||||
|
if(mDownloaderThrowable instanceof Exception) {
|
||||||
|
mListener.onDownloadError((Exception) mDownloaderThrowable);
|
||||||
|
}else {
|
||||||
|
Exception exception = new Exception(mDownloaderThrowable);
|
||||||
|
mListener.onDownloadError(exception);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
DownloadUtils.downloadFileMonitored(downloadUrl, mDestinationFile, new byte[8192], this);
|
DownloadUtils.downloadFileMonitored(downloadUrl, mDestinationFile, new byte[8192], this);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -45,9 +63,59 @@ public class OptiFineDownloadTask implements Runnable, Tools.DownloaderFeedback{
|
|||||||
return scrapeResult;
|
return scrapeResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String determineMinecraftVersion() {
|
||||||
|
Matcher matcher = sMcVersionPattern.matcher(mOptiFineVersion.minecraftVersion);
|
||||||
|
if(matcher.find()) {
|
||||||
|
StringBuilder mcVersionBuilder = new StringBuilder();
|
||||||
|
mcVersionBuilder.append(matcher.group(1));
|
||||||
|
mcVersionBuilder.append('.');
|
||||||
|
mcVersionBuilder.append(matcher.group(2));
|
||||||
|
String thirdGroup = matcher.group(3);
|
||||||
|
if(thirdGroup != null && !thirdGroup.isEmpty() && !"0".equals(thirdGroup)) {
|
||||||
|
mcVersionBuilder.append('.');
|
||||||
|
mcVersionBuilder.append(thirdGroup);
|
||||||
|
}
|
||||||
|
return mcVersionBuilder.toString();
|
||||||
|
}else{
|
||||||
|
mListener.onDataNotAvailable();
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean downloadMinecraft(String minecraftVersion) {
|
||||||
|
// the string is always normalized
|
||||||
|
JMinecraftVersionList.Version minecraftJsonVersion = AsyncMinecraftDownloader.getListedVersion(minecraftVersion);
|
||||||
|
if(minecraftJsonVersion == null) return false;
|
||||||
|
try {
|
||||||
|
synchronized (mMinecraftDownloadLock) {
|
||||||
|
new AsyncMinecraftDownloader(null, minecraftJsonVersion, minecraftVersion, this);
|
||||||
|
mMinecraftDownloadLock.wait();
|
||||||
|
}
|
||||||
|
}catch (InterruptedException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return mDownloaderThrowable == null;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void updateProgress(int curr, int max) {
|
public void updateProgress(int curr, int max) {
|
||||||
int progress100 = (int)(((float)curr / (float)max)*100f);
|
int progress100 = (int)(((float)curr / (float)max)*100f);
|
||||||
ProgressKeeper.submitProgress(ProgressLayout.INSTALL_MODPACK, progress100, R.string.of_dl_progress, mOptiFineVersion.versionName);
|
ProgressKeeper.submitProgress(ProgressLayout.INSTALL_MODPACK, progress100, R.string.of_dl_progress, mOptiFineVersion.versionName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onDownloadDone() {
|
||||||
|
synchronized (mMinecraftDownloadLock) {
|
||||||
|
mDownloaderThrowable = null;
|
||||||
|
mMinecraftDownloadLock.notifyAll();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onDownloadFailed(Throwable throwable) {
|
||||||
|
synchronized (mMinecraftDownloadLock) {
|
||||||
|
mDownloaderThrowable = throwable;
|
||||||
|
mMinecraftDownloadLock.notifyAll();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -55,6 +55,7 @@ public class OptiFineScraper implements DownloadUtils.ParseCallback<OptiFineUtil
|
|||||||
|
|
||||||
private void traverseDownloadLine(TagNode tagNode) {
|
private void traverseDownloadLine(TagNode tagNode) {
|
||||||
OptiFineUtils.OptiFineVersion optiFineVersion = new OptiFineUtils.OptiFineVersion();
|
OptiFineUtils.OptiFineVersion optiFineVersion = new OptiFineUtils.OptiFineVersion();
|
||||||
|
optiFineVersion.minecraftVersion = mMinecraftVersion;
|
||||||
for(TagNode subNode : tagNode.getChildTags()) {
|
for(TagNode subNode : tagNode.getChildTags()) {
|
||||||
if(!subNode.getName().equals("td")) continue;
|
if(!subNode.getName().equals("td")) continue;
|
||||||
switch(subNode.getAttributeByName("class")) {
|
switch(subNode.getAttributeByName("class")) {
|
||||||
|
@ -1,7 +1,11 @@
|
|||||||
package net.kdt.pojavlaunch.modloaders;
|
package net.kdt.pojavlaunch.modloaders;
|
||||||
|
|
||||||
|
import android.content.Intent;
|
||||||
|
|
||||||
|
import net.kdt.pojavlaunch.Tools;
|
||||||
import net.kdt.pojavlaunch.utils.DownloadUtils;
|
import net.kdt.pojavlaunch.utils.DownloadUtils;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@ -17,11 +21,19 @@ public class OptiFineUtils {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void addAutoInstallArgs(Intent intent, File modInstallerJar) {
|
||||||
|
intent.putExtra("javaArgs", "-javaagent:"+ Tools.DIR_DATA+"/forge_installer/forge_installer.jar"
|
||||||
|
+ "=OFNPS" +// No Profile Suppression
|
||||||
|
" -jar "+modInstallerJar.getAbsolutePath());
|
||||||
|
intent.putExtra("skipDetectMod", true);
|
||||||
|
}
|
||||||
|
|
||||||
public static class OptiFineVersions {
|
public static class OptiFineVersions {
|
||||||
public List<String> minecraftVersions;
|
public List<String> minecraftVersions;
|
||||||
public List<List<OptiFineVersion>> optifineVersions;
|
public List<List<OptiFineVersion>> optifineVersions;
|
||||||
}
|
}
|
||||||
public static class OptiFineVersion {
|
public static class OptiFineVersion {
|
||||||
|
public String minecraftVersion;
|
||||||
public String versionName;
|
public String versionName;
|
||||||
public String downloadUrl;
|
public String downloadUrl;
|
||||||
}
|
}
|
||||||
|
@ -46,7 +46,7 @@ public class AsyncMinecraftDownloader {
|
|||||||
/* Allows each downloading thread to have its own RECYCLED buffer */
|
/* Allows each downloading thread to have its own RECYCLED buffer */
|
||||||
private final ConcurrentHashMap<Thread, byte[]> mThreadBuffers = new ConcurrentHashMap<>(5);
|
private final ConcurrentHashMap<Thread, byte[]> mThreadBuffers = new ConcurrentHashMap<>(5);
|
||||||
|
|
||||||
public AsyncMinecraftDownloader(@NonNull Activity activity, JMinecraftVersionList.Version version, String realVersion,
|
public AsyncMinecraftDownloader(Activity activity, JMinecraftVersionList.Version version, String realVersion,
|
||||||
@NonNull DoneListener listener){ // this was there for a reason
|
@NonNull DoneListener listener){ // this was there for a reason
|
||||||
sExecutorService.execute(() -> {
|
sExecutorService.execute(() -> {
|
||||||
try {
|
try {
|
||||||
@ -58,7 +58,7 @@ public class AsyncMinecraftDownloader {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
/* we do the throws DownloaderException thing to avoid blanket-catching Exception as a form of anti-lazy-developer protection */
|
/* we do the throws DownloaderException thing to avoid blanket-catching Exception as a form of anti-lazy-developer protection */
|
||||||
private void downloadGame(@NonNull Activity activity, JMinecraftVersionList.Version verInfo, String versionName) throws DownloaderException {
|
private void downloadGame(Activity activity, JMinecraftVersionList.Version verInfo, String versionName) throws DownloaderException {
|
||||||
final String downVName = "/" + versionName + "/" + versionName;
|
final String downVName = "/" + versionName + "/" + versionName;
|
||||||
|
|
||||||
//Downloading libraries
|
//Downloading libraries
|
||||||
@ -88,7 +88,7 @@ public class AsyncMinecraftDownloader {
|
|||||||
verInfo = Tools.getVersionInfo(versionName);
|
verInfo = Tools.getVersionInfo(versionName);
|
||||||
|
|
||||||
// THIS one function need the activity in the case of an error
|
// THIS one function need the activity in the case of an error
|
||||||
if(!JRE17Util.installNewJreIfNeeded(activity, verInfo)){
|
if(activity != null && !JRE17Util.installNewJreIfNeeded(activity, verInfo)){
|
||||||
ProgressKeeper.submitProgress(ProgressLayout.DOWNLOAD_MINECRAFT, -1, -1);
|
ProgressKeeper.submitProgress(ProgressLayout.DOWNLOAD_MINECRAFT, -1, -1);
|
||||||
throw new DownloaderException();
|
throw new DownloaderException();
|
||||||
}
|
}
|
||||||
|
@ -392,7 +392,7 @@
|
|||||||
<string name="create_profile_modded_versions">Modded versions</string>
|
<string name="create_profile_modded_versions">Modded versions</string>
|
||||||
<string name="fabric_dl_loader_title">Select versions</string>
|
<string name="fabric_dl_loader_title">Select versions</string>
|
||||||
<string name="of_dl_select_version">Select OptiFine version</string>
|
<string name="of_dl_select_version">Select OptiFine version</string>
|
||||||
<string name="of_dl_failed_to_scrape">Failed to get the OptiFine download link</string>
|
<string name="of_dl_failed_to_scrape">Failed to collect data for OptiFine installation</string>
|
||||||
<string name="of_dl_progress">Downloading %s</string>
|
<string name="of_dl_progress">Downloading %s</string>
|
||||||
<string name="create_profile_optifine">Create OptiFine profile</string>
|
<string name="create_profile_optifine">Create OptiFine profile</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
@ -20,11 +20,12 @@ import javax.swing.JOptionPane;
|
|||||||
public class Agent implements AWTEventListener {
|
public class Agent implements AWTEventListener {
|
||||||
private boolean forgeWindowHandled = false;
|
private boolean forgeWindowHandled = false;
|
||||||
private final boolean suppressProfileCreation;
|
private final boolean suppressProfileCreation;
|
||||||
|
private final boolean optiFineInstallation;
|
||||||
private final Timer componentTimer = new Timer();
|
private final Timer componentTimer = new Timer();
|
||||||
|
|
||||||
public Agent(boolean ps) {
|
public Agent(boolean nps, boolean of) {
|
||||||
this.suppressProfileCreation = ps;
|
this.suppressProfileCreation = !nps;
|
||||||
|
this.optiFineInstallation = of;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -33,7 +34,7 @@ public class Agent implements AWTEventListener {
|
|||||||
Window window = windowEvent.getWindow();
|
Window window = windowEvent.getWindow();
|
||||||
if(windowEvent.getID() == WindowEvent.WINDOW_OPENED) {
|
if(windowEvent.getID() == WindowEvent.WINDOW_OPENED) {
|
||||||
if(!forgeWindowHandled) { // false at startup, so we will handle the first window as the Forge one
|
if(!forgeWindowHandled) { // false at startup, so we will handle the first window as the Forge one
|
||||||
forgeWindowHandled = handleForgeWindow(window);
|
forgeWindowHandled = handleMainWindow(window);
|
||||||
if(forgeWindowHandled) {
|
if(forgeWindowHandled) {
|
||||||
componentTimer.cancel();
|
componentTimer.cancel();
|
||||||
componentTimer.purge();
|
componentTimer.purge();
|
||||||
@ -46,34 +47,47 @@ public class Agent implements AWTEventListener {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean handleForgeWindow(Window window) {
|
public boolean handleMainWindow(Window window) {
|
||||||
List<Component> components = new ArrayList<>();
|
List<Component> components = new ArrayList<>();
|
||||||
insertAllComponents(components, window, new MainWindowFilter());
|
insertAllComponents(components, window, new MainWindowFilter());
|
||||||
AbstractButton okButton = null;
|
AbstractButton okButton = null;
|
||||||
for(Component component : components) {
|
for(Component component : components) {
|
||||||
if(component instanceof AbstractButton) {
|
if(component instanceof AbstractButton) {
|
||||||
AbstractButton abstractButton = (AbstractButton) component;
|
AbstractButton abstractButton = (AbstractButton) component;
|
||||||
switch(abstractButton.getText()) {
|
abstractButton = optiFineInstallation ?
|
||||||
case "OK":
|
handleOptiFineButton(abstractButton) :
|
||||||
okButton = abstractButton; // store the button, so we can press it after processing other stuff
|
handleForgeButton(abstractButton);
|
||||||
break;
|
if(abstractButton != null) okButton = abstractButton;
|
||||||
case "Install client":
|
|
||||||
abstractButton.doClick(); // It should be the default, but let's make sure
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(okButton == null) {
|
if(okButton == null) {
|
||||||
System.out.println("Failed to set all the UI components, wil try again in the next window");
|
System.out.println("Failed to set all the UI components, wil try again in the next window");
|
||||||
System.exit(17);
|
|
||||||
return false;
|
return false;
|
||||||
}else{
|
}else{
|
||||||
ProfileFixer.storeProfile();
|
ProfileFixer.storeProfile(optiFineInstallation ? "OptiFine" : "forge");
|
||||||
EventQueue.invokeLater(okButton::doClick); // do that after forge actually builds its window, otherwise we set the path too fast
|
EventQueue.invokeLater(okButton::doClick); // do that after forge actually builds its window, otherwise we set the path too fast
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public AbstractButton handleForgeButton(AbstractButton abstractButton) {
|
||||||
|
switch(abstractButton.getText()) {
|
||||||
|
case "OK":
|
||||||
|
return abstractButton; // return the button, so we can press it after processing other stuff
|
||||||
|
case "Install client":
|
||||||
|
abstractButton.doClick(); // It should be the default, but let's make sure
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public AbstractButton handleOptiFineButton(AbstractButton abstractButton) {
|
||||||
|
if ("Install".equals(abstractButton.getText())) {
|
||||||
|
return abstractButton;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
public void handleDialog(Window window) {
|
public void handleDialog(Window window) {
|
||||||
List<Component> components = new ArrayList<>();
|
List<Component> components = new ArrayList<>();
|
||||||
insertAllComponents(components, window, new DialogFilter()); // ensure that it's a JOptionPane dialog
|
insertAllComponents(components, window, new DialogFilter()); // ensure that it's a JOptionPane dialog
|
||||||
@ -84,7 +98,7 @@ public class Agent implements AWTEventListener {
|
|||||||
JOptionPane optionPane = (JOptionPane) components.get(0);
|
JOptionPane optionPane = (JOptionPane) components.get(0);
|
||||||
if(optionPane.getMessageType() == JOptionPane.INFORMATION_MESSAGE) { // forge doesn't emit information messages for other reasons yet
|
if(optionPane.getMessageType() == JOptionPane.INFORMATION_MESSAGE) { // forge doesn't emit information messages for other reasons yet
|
||||||
System.out.println("The install was successful!");
|
System.out.println("The install was successful!");
|
||||||
ProfileFixer.reinsertProfile(suppressProfileCreation);
|
ProfileFixer.reinsertProfile(optiFineInstallation ? "OptiFine" : "forge", suppressProfileCreation);
|
||||||
System.exit(0); // again, forge doesn't call exit for some reason, so we do that ourselves here
|
System.exit(0); // again, forge doesn't call exit for some reason, so we do that ourselves here
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -102,8 +116,15 @@ public class Agent implements AWTEventListener {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static void premain(String args, Instrumentation inst) {
|
public static void premain(String args, Instrumentation inst) {
|
||||||
|
boolean noProfileSuppression = false;
|
||||||
|
boolean optifine = false;
|
||||||
|
if(args != null ) {
|
||||||
|
noProfileSuppression = args.contains("NPS"); // No Profile Suppression
|
||||||
|
optifine = args.contains("OF"); // OptiFine
|
||||||
|
}
|
||||||
|
Agent agent = new Agent(noProfileSuppression, optifine);
|
||||||
Toolkit.getDefaultToolkit()
|
Toolkit.getDefaultToolkit()
|
||||||
.addAWTEventListener(new Agent(!"NPS".equals(args)), // No Profile Suppression
|
.addAWTEventListener(agent,
|
||||||
AWTEvent.WINDOW_EVENT_MASK);
|
AWTEvent.WINDOW_EVENT_MASK);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -15,23 +15,23 @@ public class ProfileFixer {
|
|||||||
private static final Random random = new Random();
|
private static final Random random = new Random();
|
||||||
private static final Path profilesPath = Paths.get(System.getProperty("user.home"), ".minecraft", "launcher_profiles.json");
|
private static final Path profilesPath = Paths.get(System.getProperty("user.home"), ".minecraft", "launcher_profiles.json");
|
||||||
private static JSONObject oldProfile = null;
|
private static JSONObject oldProfile = null;
|
||||||
public static void storeProfile() {
|
public static void storeProfile(String profileName) {
|
||||||
try {
|
try {
|
||||||
JSONObject minecraftProfiles = new JSONObject(
|
JSONObject minecraftProfiles = new JSONObject(
|
||||||
new String(Files.readAllBytes(profilesPath),
|
new String(Files.readAllBytes(profilesPath),
|
||||||
StandardCharsets.UTF_8)
|
StandardCharsets.UTF_8)
|
||||||
);
|
);
|
||||||
JSONObject profilesArray = minecraftProfiles.getJSONObject("profiles");
|
JSONObject profilesArray = minecraftProfiles.getJSONObject("profiles");
|
||||||
oldProfile = profilesArray.optJSONObject("forge", null);
|
oldProfile = profilesArray.optJSONObject(profileName, null);
|
||||||
}catch (IOException | JSONException e) {
|
}catch (IOException | JSONException e) {
|
||||||
System.out.println("Failed to store Forge profile: "+e);
|
System.out.println("Failed to store Forge profile: "+e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String pickProfileName() {
|
private static String pickProfileName(String profileName) {
|
||||||
return "forge"+random.nextInt();
|
return profileName+random.nextInt();
|
||||||
}
|
}
|
||||||
public static void reinsertProfile(boolean suppressProfileCreation) {
|
public static void reinsertProfile(String profileName, boolean suppressProfileCreation) {
|
||||||
try {
|
try {
|
||||||
JSONObject minecraftProfiles = new JSONObject(
|
JSONObject minecraftProfiles = new JSONObject(
|
||||||
new String(Files.readAllBytes(profilesPath),
|
new String(Files.readAllBytes(profilesPath),
|
||||||
@ -41,8 +41,8 @@ public class ProfileFixer {
|
|||||||
if(oldProfile != null) {
|
if(oldProfile != null) {
|
||||||
if(suppressProfileCreation) profilesArray.put("forge", oldProfile); // restore the old profile
|
if(suppressProfileCreation) profilesArray.put("forge", oldProfile); // restore the old profile
|
||||||
else {
|
else {
|
||||||
String name = pickProfileName();
|
String name = pickProfileName(profileName);
|
||||||
while(profilesArray.has(name)) name = pickProfileName();
|
while(profilesArray.has(name)) name = pickProfileName(profileName);
|
||||||
profilesArray.put(name, oldProfile); // restore the old profile under a new name
|
profilesArray.put(name, oldProfile); // restore the old profile under a new name
|
||||||
}
|
}
|
||||||
}else{
|
}else{
|
||||||
|
Loading…
x
Reference in New Issue
Block a user