From 70f0383b1d7c1c7f9309119677f7a76d2bdc7466 Mon Sep 17 00:00:00 2001 From: huanghongxun Date: Tue, 11 Aug 2015 13:02:02 +0800 Subject: [PATCH] Add mod modification. --- HMCL/proguard.pro | 2 + .../hellominecraft/launcher/Launcher.java | 6 +- .../launch/AbstractMinecraftLoader.java | 3 +- .../launcher/launch/IMinecraftProvider.java | 3 + .../launcher/settings/Profile.java | 6 +- .../launcher/utils/MCUtils.java | 32 + .../launcher/utils/ModInfo.java | 98 + .../liteloader/LiteLoaderInstaller.java | 4 +- .../optifine/OptiFineInstaller.java | 4 +- .../version/MinecraftVersionManager.java | 39 +- .../launcher/views/GameSettingsPanel.form | 1748 +++++++++-------- .../launcher/views/GameSettingsPanel.java | 651 ++++-- .../tasks/TaskRunnableArg1.java | 4 +- .../hellominecraft/tasks/TaskWindow.form | 44 +- .../hellominecraft/tasks/TaskWindow.java | 40 +- ...ator.java => PreviousResultRegistrar.java} | 2 +- .../tasks/download/FileDownloadTask.java | 4 +- .../hellominecraft/utils/SwingUtils.java | 44 +- .../utils/system/FileUtils.java | 10 +- .../hellominecraft/utils/system/Java.java | 10 + .../hellominecraft/launcher/I18N.properties | 9 +- .../launcher/I18N_en_US.properties | 13 +- .../launcher/I18N_zh_CN.properties | 29 +- .../launcher/I18N_zh_TW.properties | 16 +- 24 files changed, 1729 insertions(+), 1092 deletions(-) create mode 100644 HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/utils/ModInfo.java rename HMCLAPI/src/main/java/org/jackhuang/hellominecraft/tasks/communication/{PreviousResultRegistrator.java => PreviousResultRegistrar.java} (95%) diff --git a/HMCL/proguard.pro b/HMCL/proguard.pro index 2d217bed6..d85b60f74 100644 --- a/HMCL/proguard.pro +++ b/HMCL/proguard.pro @@ -57,6 +57,8 @@ -keepclassmembers class org.jackhuang.hellominecraft.launcher.utils.assets.AssetsObject { ; } -keepclassmembers class org.jackhuang.hellominecraft.launcher.utils.assets.AssetsIndex { ; } +-keepclassmembers class org.jackhuang.hellominecraft.launcher.utils.ModInfo { ; } + -keepclassmembers class org.jackhuang.hellominecraft.launcher.utils.installers.forge.InstallProfile { public ; } -keepclassmembers class org.jackhuang.hellominecraft.launcher.utils.installers.forge.Install { public ; } diff --git a/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/Launcher.java b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/Launcher.java index 61f7fecc8..60136f92d 100644 --- a/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/Launcher.java +++ b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/Launcher.java @@ -22,6 +22,8 @@ import java.lang.reflect.Method; import java.net.URL; import java.net.URLClassLoader; import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; import javax.swing.SwingUtilities; import org.jackhuang.hellominecraft.C; import org.jackhuang.hellominecraft.HMCLog; @@ -42,8 +44,6 @@ import org.jackhuang.hellominecraft.utils.Utils; */ public final class Launcher { - private static final Launcher instance = new Launcher(); - public static void println(String s) { System.out.println(s); } @@ -84,7 +84,7 @@ public final class Launcher { println("Failed to add log file appender."); e.printStackTrace(); } - + println("Arguments: {\n" + StrUtils.parseParams(" ", args, "\n") + "\n}"); println("Main Class: " + mainClass); println("Class Path: {\n" + StrUtils.parseParams(" ", tokenized, "\n") + "\n}"); diff --git a/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/launch/AbstractMinecraftLoader.java b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/launch/AbstractMinecraftLoader.java index a85f024a7..30786445a 100644 --- a/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/launch/AbstractMinecraftLoader.java +++ b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/launch/AbstractMinecraftLoader.java @@ -127,7 +127,8 @@ public abstract class AbstractMinecraftLoader implements IMinecraftLoader { if (OS.os() != OS.WINDOWS) res.add("-Duser.home=" + gameDir.getParent()); - + res.add("-Dhellominecraftlauncher.gamedir=" + gameDir.getAbsolutePath()); + if (!v.isCanceledWrapper()) { res.add("-cp"); res.add(StrUtils.parseParams("", Utils.getURL(), File.pathSeparator)); diff --git a/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/launch/IMinecraftProvider.java b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/launch/IMinecraftProvider.java index 2b31a36e9..465b661fb 100644 --- a/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/launch/IMinecraftProvider.java +++ b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/launch/IMinecraftProvider.java @@ -22,6 +22,7 @@ import java.util.List; import org.jackhuang.hellominecraft.launcher.utils.auth.UserProfileProvider; import org.jackhuang.hellominecraft.launcher.utils.download.DownloadType; import org.jackhuang.hellominecraft.launcher.settings.Profile; +import org.jackhuang.hellominecraft.launcher.utils.ModInfo; import org.jackhuang.hellominecraft.launcher.version.MinecraftVersion; /** @@ -56,6 +57,8 @@ public abstract class IMinecraftProvider { public abstract void open(String version, String folder); public abstract File getAssets(); + + public abstract List listMods(); /** * Returns the thing like ".minecraft/resourcepacks". diff --git a/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/settings/Profile.java b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/settings/Profile.java index 7896bc462..7c1d63b21 100644 --- a/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/settings/Profile.java +++ b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/settings/Profile.java @@ -125,6 +125,7 @@ public final class Profile { public Profile setGameDir(String gameDir) { this.gameDir = gameDir; + getMinecraftProvider().refreshVersions(); Settings.save(); return this; } @@ -153,9 +154,8 @@ public final class Profile { } public int getJavaIndexInAllJavas() { - if(StrUtils.isBlank(java) && StrUtils.isNotBlank(javaDir)) { + if (StrUtils.isBlank(java) && StrUtils.isNotBlank(javaDir)) java = "Custom"; - } int idx = Settings.JAVA.indexOf(new Java(java, null)); if (idx == -1) { java = "Default"; @@ -172,7 +172,7 @@ public final class Profile { } public File getFolder(String folder) { - return new File(getGameDir(), folder); + return new File(getMinecraftProvider().getRunDirectory(getSelectedMinecraftVersion().id), folder); } public String getName() { diff --git a/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/utils/MCUtils.java b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/utils/MCUtils.java index b70067f16..a4c40cb93 100644 --- a/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/utils/MCUtils.java +++ b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/utils/MCUtils.java @@ -20,8 +20,15 @@ import com.google.gson.Gson; import com.google.gson.JsonSyntaxException; import java.io.File; import java.io.IOException; +import java.io.InputStreamReader; +import java.util.Map; +import java.util.jar.JarEntry; +import java.util.jar.JarFile; +import java.util.logging.Level; +import java.util.logging.Logger; import java.util.zip.ZipEntry; import java.util.zip.ZipFile; +import org.jackhuang.hellominecraft.C; import org.jackhuang.hellominecraft.HMCLog; import org.jackhuang.hellominecraft.launcher.utils.assets.AssetsIndex; import org.jackhuang.hellominecraft.launcher.utils.assets.AssetsObject; @@ -35,6 +42,7 @@ import org.jackhuang.hellominecraft.utils.system.FileUtils; import org.jackhuang.hellominecraft.utils.system.IOUtils; import org.jackhuang.hellominecraft.version.MinecraftVersionRequest; import org.jackhuang.hellominecraft.utils.NetUtils; +import org.jackhuang.hellominecraft.utils.Pair; import org.jackhuang.hellominecraft.utils.system.OS; /** @@ -244,6 +252,30 @@ public final class MCUtils { } return null; } + + public static boolean downloadMinecraftJar(File gameDir, String id, DownloadType sourceType) { + String vurl = sourceType.getProvider().getVersionsDownloadURL() + id + "/"; + File vpath = new File(gameDir, "versions/" + id); + File mvv = new File(vpath, id + ".jar"), moved = null; + if (mvv.exists()) { + moved = new File(vpath, id + "-renamed.jar"); + mvv.renameTo(moved); + } + File mvt = new File(vpath, id + ".jar"); + vpath.mkdirs(); + if (TaskWindow.getInstance() + .addTask(new FileDownloadTask(vurl + id + ".jar", IOUtils.tryGetCanonicalFile(mvt)).setTag(id + ".jar")) + .start()) { + if (moved != null) + moved.delete(); + return true; + } else { + mvt.delete(); + if (moved != null) + moved.renameTo(mvt); + return false; + } + } public static boolean downloadMinecraftVersionJson(File gameDir, String id, DownloadType sourceType) { String vurl = sourceType.getProvider().getVersionsDownloadURL() + id + "/"; diff --git a/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/utils/ModInfo.java b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/utils/ModInfo.java new file mode 100644 index 000000000..ae9ff6223 --- /dev/null +++ b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/utils/ModInfo.java @@ -0,0 +1,98 @@ +/* + * Copyright 2013 huangyuhui + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. + */ +package org.jackhuang.hellominecraft.launcher.utils; + +import com.google.gson.JsonSyntaxException; +import com.google.gson.reflect.TypeToken; +import java.io.File; +import java.io.IOException; +import java.io.InputStreamReader; +import java.util.List; +import java.util.zip.ZipEntry; +import java.util.zip.ZipFile; +import org.jackhuang.hellominecraft.C; +import org.jackhuang.hellominecraft.HMCLog; +import org.jackhuang.hellominecraft.utils.system.FileUtils; + +/** + * + * @author huangyuhui + */ +public class ModInfo implements Comparable { + + public File location; + public String modid, name, description, version, mcversion, url, updateUrl, credits; + public String[] authorList; + + public boolean isActive() { + return !location.getName().endsWith(".disabled"); + } + + @Override + public int compareTo(ModInfo o) { + return getFileName().toLowerCase().compareTo(o.getFileName().toLowerCase()); + } + + public String getName() { + return name == null ? FileUtils.removeExtension(location.getName()) : name; + } + + @Override + public boolean equals(Object obj) { + return obj != null && obj instanceof ModInfo && (((ModInfo) obj).location == location || ((ModInfo) obj).location.equals(location)); + } + + @Override + public int hashCode() { + return location.hashCode(); + } + + public String getFileName() { + String n = location.getName(); + return FileUtils.removeExtension(isActive() ? n : n.substring(0, n.length() - ".disabled".length())); + } + + public static boolean isFileMod(File file) { + if (file == null) return false; + String name = file.getName(); + boolean disabled = name.endsWith(".disabled"); + if (disabled) name = name.substring(0, name.length() - ".disabled".length()); + return name.endsWith(".zip") || name.endsWith(".jar"); + } + + public static ModInfo readModInfo(File f) { + ModInfo i = new ModInfo(); + i.location = f; + try { + ZipFile jar = new ZipFile(f); + ZipEntry entry = jar.getEntry("mcmod.info"); + if (entry == null) return i; + else { + List m = C.gson.fromJson(new InputStreamReader(jar.getInputStream(entry)), new TypeToken>() { + }.getType()); + if (m != null && m.size() > 0) { i = m.get(0); i.location = f; } + } + jar.close(); + return i; + } catch (IOException ex) { + HMCLog.warn("File " + f + " is not a jar.", ex); + return i; + } catch (JsonSyntaxException e) { + return i; + } + } +} diff --git a/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/utils/installers/liteloader/LiteLoaderInstaller.java b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/utils/installers/liteloader/LiteLoaderInstaller.java index 7f92fa7a1..2ee192413 100644 --- a/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/utils/installers/liteloader/LiteLoaderInstaller.java +++ b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/utils/installers/liteloader/LiteLoaderInstaller.java @@ -23,7 +23,7 @@ import org.jackhuang.hellominecraft.C; import org.jackhuang.hellominecraft.HMCLog; import org.jackhuang.hellominecraft.tasks.Task; import org.jackhuang.hellominecraft.tasks.communication.PreviousResult; -import org.jackhuang.hellominecraft.tasks.communication.PreviousResultRegistrator; +import org.jackhuang.hellominecraft.tasks.communication.PreviousResultRegistrar; import org.jackhuang.hellominecraft.launcher.settings.Profile; import org.jackhuang.hellominecraft.utils.system.FileUtils; import org.jackhuang.hellominecraft.launcher.version.MinecraftLibrary; @@ -33,7 +33,7 @@ import org.jackhuang.hellominecraft.launcher.version.MinecraftVersion; * * @author huangyuhui */ -public class LiteLoaderInstaller extends Task implements PreviousResultRegistrator { +public class LiteLoaderInstaller extends Task implements PreviousResultRegistrar { public LiteLoaderVersionList.LiteLoaderInstallerVersion version; public File installer; diff --git a/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/utils/installers/optifine/OptiFineInstaller.java b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/utils/installers/optifine/OptiFineInstaller.java index c80a0b7a2..b43fd3845 100644 --- a/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/utils/installers/optifine/OptiFineInstaller.java +++ b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/utils/installers/optifine/OptiFineInstaller.java @@ -24,7 +24,7 @@ import org.jackhuang.hellominecraft.C; import org.jackhuang.hellominecraft.launcher.settings.Profile; import org.jackhuang.hellominecraft.tasks.Task; import org.jackhuang.hellominecraft.tasks.communication.PreviousResult; -import org.jackhuang.hellominecraft.tasks.communication.PreviousResultRegistrator; +import org.jackhuang.hellominecraft.tasks.communication.PreviousResultRegistrar; import org.jackhuang.hellominecraft.utils.system.FileUtils; import org.jackhuang.hellominecraft.launcher.version.MinecraftLibrary; import org.jackhuang.hellominecraft.launcher.version.MinecraftVersion; @@ -33,7 +33,7 @@ import org.jackhuang.hellominecraft.launcher.version.MinecraftVersion; * * @author huangyuhui */ -public class OptiFineInstaller extends Task implements PreviousResultRegistrator { +public class OptiFineInstaller extends Task implements PreviousResultRegistrar { public File installer; public Profile profile; diff --git a/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/version/MinecraftVersionManager.java b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/version/MinecraftVersionManager.java index 123ced5ac..ccef7612c 100644 --- a/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/version/MinecraftVersionManager.java +++ b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/version/MinecraftVersionManager.java @@ -22,8 +22,11 @@ import java.io.File; import java.io.IOException; import java.util.ArrayList; import java.util.Collection; +import java.util.Collections; +import java.util.LinkedList; import java.util.List; import java.util.Map; +import java.util.Queue; import java.util.TreeMap; import org.jackhuang.hellominecraft.C; import org.jackhuang.hellominecraft.HMCLog; @@ -38,9 +41,9 @@ import org.jackhuang.hellominecraft.launcher.utils.auth.UserProfileProvider; import org.jackhuang.hellominecraft.launcher.utils.download.DownloadType; import org.jackhuang.hellominecraft.launcher.settings.Profile; import org.jackhuang.hellominecraft.launcher.settings.Settings; +import org.jackhuang.hellominecraft.launcher.utils.ModInfo; import org.jackhuang.hellominecraft.utils.system.IOUtils; import org.jackhuang.hellominecraft.utils.system.MessageBox; -import org.jackhuang.hellominecraft.utils.StrUtils; import org.jackhuang.hellominecraft.utils.Utils; /** @@ -115,13 +118,8 @@ public final class MinecraftVersionManager extends IMinecraftProvider { jsons[0].renameTo(new File(jsons[0].getParent(), id + ".json")); } if (!jsonFile.exists()) { - if (StrUtils.formatVersion(id) == null) { - if (MessageBox.Show(C.i18n("launcher.versions_json_not_matched_cannot_auto_completion", id), MessageBox.YES_NO_OPTION) == MessageBox.YES_OPTION) - FileUtils.deleteDirectoryQuietly(dir); - } else if (MessageBox.Show(C.i18n("launcher.versions_json_not_matched_needs_auto_completion", id), MessageBox.YES_NO_OPTION) == MessageBox.YES_OPTION) - if (!refreshJson(id)) - if (MessageBox.Show(C.i18n("launcher.versions_json_not_matched_cannot_auto_completion", id), MessageBox.YES_NO_OPTION) == MessageBox.YES_OPTION) - FileUtils.deleteDirectoryQuietly(dir); + if (MessageBox.Show(C.i18n("launcher.versions_json_not_matched_cannot_auto_completion", id), MessageBox.YES_NO_OPTION) == MessageBox.YES_OPTION) + FileUtils.deleteDirectoryQuietly(dir); continue; } MinecraftVersion mcVersion; @@ -130,7 +128,7 @@ public final class MinecraftVersionManager extends IMinecraftProvider { if (mcVersion == null) throw new RuntimeException("Wrong json format, got null."); } catch (IOException | RuntimeException e) { HMCLog.warn("Found wrong format json, try to fix it.", e); - if (MessageBox.Show(C.i18n("launcher.versions_json_not_formattedn", id), MessageBox.YES_NO_OPTION) == MessageBox.YES_OPTION) { + if (MessageBox.Show(C.i18n("launcher.versions_json_not_formatted", id), MessageBox.YES_NO_OPTION) == MessageBox.YES_OPTION) { refreshJson(id); try { mcVersion = gson.fromJson(FileUtils.readFileToString(jsonFile), MinecraftVersion.class); @@ -222,6 +220,29 @@ public final class MinecraftVersionManager extends IMinecraftProvider { } } + @Override + public List listMods() { + File modsFolder = new File(getRunDirectory(profile.getSelectedMinecraftVersion().id), "mods"); + ArrayList mods = new ArrayList<>(); + Queue queue = new LinkedList<>(); + queue.add(modsFolder); + while (!queue.isEmpty()) { + File dir = queue.poll(); + File[] fs = dir.listFiles(); + if (fs != null) + for (File f : fs) + if (ModInfo.isFileMod(f)) { + ModInfo m = ModInfo.readModInfo(f); + if (m != null) + mods.add(m); + } else if(f.isDirectory()) { + queue.add(f); + } + } + Collections.sort(mods); + return mods; + } + @Override public List getDownloadLibraries(DownloadType downloadType) { ArrayList downloadLibraries = new ArrayList<>(); diff --git a/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/views/GameSettingsPanel.form b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/views/GameSettingsPanel.form index 457d8a464..f8303b651 100644 --- a/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/views/GameSettingsPanel.form +++ b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/views/GameSettingsPanel.form @@ -44,6 +44,949 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -258,811 +1201,6 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/views/GameSettingsPanel.java b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/views/GameSettingsPanel.java index 62599abfa..4941b0e45 100644 --- a/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/views/GameSettingsPanel.java +++ b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/views/GameSettingsPanel.java @@ -17,6 +17,14 @@ package org.jackhuang.hellominecraft.launcher.views; import java.awt.Color; +import java.awt.datatransfer.DataFlavor; +import java.awt.datatransfer.Transferable; +import java.awt.dnd.DnDConstants; +import java.awt.dnd.DropTarget; +import java.awt.dnd.DropTargetDragEvent; +import java.awt.dnd.DropTargetDropEvent; +import java.awt.dnd.DropTargetEvent; +import java.awt.dnd.DropTargetListener; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.ItemEvent; @@ -32,6 +40,9 @@ import javax.swing.JOptionPane; import javax.swing.JPopupMenu; import javax.swing.JTable; import javax.swing.SwingUtilities; +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; +import javax.swing.event.TableModelEvent; import javax.swing.table.DefaultTableModel; import org.jackhuang.hellominecraft.C; import org.jackhuang.hellominecraft.HMCLog; @@ -49,6 +60,7 @@ import org.jackhuang.hellominecraft.launcher.utils.download.DownloadType; import org.jackhuang.hellominecraft.launcher.settings.Profile; import org.jackhuang.hellominecraft.launcher.settings.Settings; import org.jackhuang.hellominecraft.launcher.utils.FileNameFilter; +import org.jackhuang.hellominecraft.launcher.utils.ModInfo; import org.jackhuang.hellominecraft.launcher.version.GameDirType; import org.jackhuang.hellominecraft.launcher.version.MinecraftVersion; import org.jackhuang.hellominecraft.tasks.Task; @@ -63,6 +75,8 @@ import org.jackhuang.hellominecraft.version.MinecraftVersionRequest; import org.jackhuang.hellominecraft.utils.system.OS; import org.jackhuang.hellominecraft.utils.StrUtils; import org.jackhuang.hellominecraft.utils.SwingUtils; +import org.jackhuang.hellominecraft.utils.Utils; +import org.jackhuang.hellominecraft.utils.system.FileUtils; import org.jackhuang.hellominecraft.utils.system.Java; import org.jackhuang.hellominecraft.version.MinecraftRemoteVersion; import org.jackhuang.hellominecraft.version.MinecraftRemoteVersions; @@ -72,7 +86,7 @@ import org.jackhuang.hellominecraft.views.Selector; * * @author huangyuhui */ -public class GameSettingsPanel extends javax.swing.JPanel { +public class GameSettingsPanel extends javax.swing.JPanel implements DropTargetListener { /** * Creates new form GameSettingsPanel @@ -161,12 +175,80 @@ public class GameSettingsPanel extends javax.swing.JPanel { ppmManage.add(itm); // + lstExternalMods.getColumnModel().getSelectionModel().setSelectionMode(javax.swing.ListSelectionModel.SINGLE_SELECTION); + if (lstExternalMods.getColumnModel().getColumnCount() > 0) { + lstExternalMods.getColumnModel().getColumn(0).setMinWidth(17); + lstExternalMods.getColumnModel().getColumn(0).setPreferredWidth(17); + lstExternalMods.getColumnModel().getColumn(0).setMaxWidth(17); + } + lstExternalMods.getSelectionModel().addListSelectionListener(e -> { + int row = lstExternalMods.getSelectedRow(); + if (mods != null && 0 <= row && row < mods.size()) { + ModInfo m = mods.get(row); + boolean hasLink = m.url != null; + String text = "" + (hasLink ? "" : "") + m.getName() + (hasLink ? "" : ""); + if (m.authorList != null && m.authorList.length > 0) + text += " by " + StrUtils.parseParams("", m.authorList, ", "); + text += "
" + (m.description == null ? "No mcmod.info found" : SwingUtils.getParsedJPanelText(lblModInfo, m.description)); + lblModInfo.setText(text); + lblModInfo.setCursor(new java.awt.Cursor(hasLink ? java.awt.Cursor.HAND_CURSOR : java.awt.Cursor.DEFAULT_CURSOR)); + } + }); + ((DefaultTableModel) lstExternalMods.getModel()).addTableModelListener(e -> { + if (e.getType() == TableModelEvent.UPDATE && e.getColumn() == 0) { + int row = lstExternalMods.getSelectedRow(); + if (mods != null && mods.size() > row && row >= 0) { + File f = mods.get(row).location, newf; + if (f.getName().endsWith(".disabled")) + newf = new File(f.getParentFile(), f.getName().substring(0, f.getName().length() - ".disabled".length())); + else + newf = new File(f.getParentFile(), f.getName() + ".disabled"); + if (f.renameTo(newf)) + mods.get(row).location = newf; + } + } + }); + tabVersionEdit.addChangeListener(new ChangeListener() { + boolean a = false, b = false; + + @Override + public void stateChanged(ChangeEvent e) { + if (tabVersionEdit.getSelectedComponent() == pnlGameDownloads && !a) { + a = true; + refreshDownloads(Settings.getInstance().getDownloadSource()); + } else if (tabVersionEdit.getSelectedComponent() == pnlAutoInstall && !b) { + b = true; + forge.refreshVersions(); + } + } + }); + tabInstallers.addChangeListener(new ChangeListener() { + boolean a = false, b = false, c = false; + + @Override + public void stateChanged(ChangeEvent e) { + switch (tabInstallers.getSelectedIndex()) { + case 0: if (!a) forge.refreshVersions(); + a = true; + break; + case 1: if (!b) optifine.refreshVersions(); + b = true; + break; + case 2: if (!c) liteloader.refreshVersions(); + c = true; + break; + } + } + }); + for (Java j : Settings.JAVA) { String name = j.getName(); if (name.equals("Default")) name = C.i18n("settings.default"); if (name.equals("Custom")) name = C.i18n("settings.custom"); cboJava.addItem(name); } + + dropTarget = new DropTarget(lstExternalMods, DnDConstants.ACTION_COPY_OR_MOVE, this); } /** @@ -178,19 +260,6 @@ public class GameSettingsPanel extends javax.swing.JPanel { // //GEN-BEGIN:initComponents private void initComponents() { - jPanel1 = new javax.swing.JPanel(); - jPanel4 = new javax.swing.JPanel(); - jLabel1 = new javax.swing.JLabel(); - cboProfiles = new javax.swing.JComboBox(); - cboVersions = new javax.swing.JComboBox(); - jLabel2 = new javax.swing.JLabel(); - jPanel5 = new javax.swing.JPanel(); - btnModify = new javax.swing.JButton(); - btnRefreshVersions = new javax.swing.JButton(); - txtMinecraftVersion = new javax.swing.JTextField(); - btnNewProfile = new javax.swing.JButton(); - btnRemoveProfile = new javax.swing.JButton(); - btnExplore = new javax.swing.JButton(); tabVersionEdit = new javax.swing.JTabbedPane(); jPanel22 = new javax.swing.JPanel(); jLabel24 = new javax.swing.JLabel(); @@ -212,6 +281,7 @@ public class GameSettingsPanel extends javax.swing.JPanel { cboGameDirType = new javax.swing.JComboBox(); btnChoosingJavaDir = new javax.swing.JButton(); cboJava = new javax.swing.JComboBox(); + btnChoosingGameDir = new javax.swing.JButton(); jPanel2 = new javax.swing.JPanel(); chkDebug = new javax.swing.JCheckBox(); jLabel26 = new javax.swing.JLabel(); @@ -226,6 +296,13 @@ public class GameSettingsPanel extends javax.swing.JPanel { txtWrapperLauncher = new javax.swing.JTextField(); jLabel31 = new javax.swing.JLabel(); txtServerIP = new javax.swing.JTextField(); + jPanel6 = new javax.swing.JPanel(); + jPanel7 = new javax.swing.JPanel(); + jScrollPane1 = new javax.swing.JScrollPane(); + lstExternalMods = new javax.swing.JTable(); + btnAddMod = new javax.swing.JButton(); + btnRemoveMod = new javax.swing.JButton(); + lblModInfo = new javax.swing.JLabel(); pnlAutoInstall = new javax.swing.JPanel(); tabInstallers = new javax.swing.JTabbedPane(); jPanel16 = new javax.swing.JPanel(); @@ -248,152 +325,26 @@ public class GameSettingsPanel extends javax.swing.JPanel { jScrollPane2 = new javax.swing.JScrollPane(); lstDownloads = new javax.swing.JTable(); btnRefreshGameDownloads = new javax.swing.JButton(); + jPanel1 = new javax.swing.JPanel(); + jPanel4 = new javax.swing.JPanel(); + jLabel1 = new javax.swing.JLabel(); + cboProfiles = new javax.swing.JComboBox(); + cboVersions = new javax.swing.JComboBox(); + jLabel2 = new javax.swing.JLabel(); + jPanel5 = new javax.swing.JPanel(); + btnModify = new javax.swing.JButton(); + btnRefreshVersions = new javax.swing.JButton(); + txtMinecraftVersion = new javax.swing.JTextField(); + btnNewProfile = new javax.swing.JButton(); + btnRemoveProfile = new javax.swing.JButton(); + btnExplore = new javax.swing.JButton(); btnIncludeMinecraft = new javax.swing.JButton(); setBackground(new java.awt.Color(255, 255, 255)); - java.util.ResourceBundle bundle = java.util.ResourceBundle.getBundle("org/jackhuang/hellominecraft/launcher/I18N"); // NOI18N - jLabel1.setText(bundle.getString("ui.label.profile")); // NOI18N - - cboProfiles.setMinimumSize(new java.awt.Dimension(32, 23)); - cboProfiles.setPreferredSize(new java.awt.Dimension(32, 23)); - cboProfiles.addItemListener(new java.awt.event.ItemListener() { - public void itemStateChanged(java.awt.event.ItemEvent evt) { - cboProfilesItemStateChanged(evt); - } - }); - - cboVersions.addItemListener(new java.awt.event.ItemListener() { - public void itemStateChanged(java.awt.event.ItemEvent evt) { - cboVersionsItemStateChanged(evt); - } - }); - - jLabel2.setText(bundle.getString("ui.label.version")); // NOI18N - - javax.swing.GroupLayout jPanel4Layout = new javax.swing.GroupLayout(jPanel4); - jPanel4.setLayout(jPanel4Layout); - jPanel4Layout.setHorizontalGroup( - jPanel4Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(jPanel4Layout.createSequentialGroup() - .addContainerGap() - .addGroup(jPanel4Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(jPanel4Layout.createSequentialGroup() - .addComponent(jLabel1) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(cboProfiles, 0, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) - .addGroup(jPanel4Layout.createSequentialGroup() - .addComponent(jLabel2) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(cboVersions, 0, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)))) - ); - jPanel4Layout.setVerticalGroup( - jPanel4Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(jPanel4Layout.createSequentialGroup() - .addContainerGap() - .addGroup(jPanel4Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) - .addComponent(cboProfiles, javax.swing.GroupLayout.PREFERRED_SIZE, 26, javax.swing.GroupLayout.PREFERRED_SIZE) - .addComponent(jLabel1)) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addGroup(jPanel4Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) - .addComponent(cboVersions, javax.swing.GroupLayout.PREFERRED_SIZE, 26, javax.swing.GroupLayout.PREFERRED_SIZE) - .addComponent(jLabel2)) - .addContainerGap(11, Short.MAX_VALUE)) - ); - - btnModify.setText(bundle.getString("settings.manage")); // NOI18N - btnModify.addMouseListener(new java.awt.event.MouseAdapter() { - public void mouseClicked(java.awt.event.MouseEvent evt) { - btnModifyMouseClicked(evt); - } - }); - - btnRefreshVersions.setText(bundle.getString("ui.button.refresh")); // NOI18N - btnRefreshVersions.addActionListener(new java.awt.event.ActionListener() { - public void actionPerformed(java.awt.event.ActionEvent evt) { - btnRefreshVersionsActionPerformed(evt); - } - }); - - txtMinecraftVersion.setEditable(false); - - btnNewProfile.setText(bundle.getString("setupwindow.new")); // NOI18N - btnNewProfile.addActionListener(new java.awt.event.ActionListener() { - public void actionPerformed(java.awt.event.ActionEvent evt) { - btnNewProfileActionPerformed(evt); - } - }); - - btnRemoveProfile.setText(bundle.getString("ui.button.delete")); // NOI18N - btnRemoveProfile.addActionListener(new java.awt.event.ActionListener() { - public void actionPerformed(java.awt.event.ActionEvent evt) { - btnRemoveProfileActionPerformed(evt); - } - }); - - btnExplore.setText(bundle.getString("settings.explore")); // NOI18N - btnExplore.setToolTipText(""); - btnExplore.addMouseListener(new java.awt.event.MouseAdapter() { - public void mouseClicked(java.awt.event.MouseEvent evt) { - btnExploreMouseClicked(evt); - } - }); - - javax.swing.GroupLayout jPanel5Layout = new javax.swing.GroupLayout(jPanel5); - jPanel5.setLayout(jPanel5Layout); - jPanel5Layout.setHorizontalGroup( - jPanel5Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(jPanel5Layout.createSequentialGroup() - .addGap(0, 0, 0) - .addGroup(jPanel5Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false) - .addComponent(btnNewProfile, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) - .addComponent(txtMinecraftVersion)) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addGroup(jPanel5Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false) - .addComponent(btnRemoveProfile, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) - .addComponent(btnRefreshVersions, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addGroup(jPanel5Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false) - .addComponent(btnModify, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) - .addComponent(btnExplore, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) - .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) - ); - jPanel5Layout.setVerticalGroup( - jPanel5Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(jPanel5Layout.createSequentialGroup() - .addContainerGap() - .addGroup(jPanel5Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) - .addComponent(btnNewProfile, javax.swing.GroupLayout.PREFERRED_SIZE, 26, javax.swing.GroupLayout.PREFERRED_SIZE) - .addComponent(btnRemoveProfile, javax.swing.GroupLayout.PREFERRED_SIZE, 26, javax.swing.GroupLayout.PREFERRED_SIZE) - .addComponent(btnExplore, javax.swing.GroupLayout.PREFERRED_SIZE, 26, javax.swing.GroupLayout.PREFERRED_SIZE)) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addGroup(jPanel5Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) - .addComponent(txtMinecraftVersion, javax.swing.GroupLayout.PREFERRED_SIZE, 26, javax.swing.GroupLayout.PREFERRED_SIZE) - .addComponent(btnRefreshVersions, javax.swing.GroupLayout.PREFERRED_SIZE, 26, javax.swing.GroupLayout.PREFERRED_SIZE) - .addComponent(btnModify, javax.swing.GroupLayout.PREFERRED_SIZE, 26, javax.swing.GroupLayout.PREFERRED_SIZE)) - .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) - ); - - javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1); - jPanel1.setLayout(jPanel1Layout); - jPanel1Layout.setHorizontalGroup( - jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(jPanel1Layout.createSequentialGroup() - .addComponent(jPanel4, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(jPanel5, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) - ); - jPanel1Layout.setVerticalGroup( - jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(jPanel1Layout.createSequentialGroup() - .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false) - .addComponent(jPanel4, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) - .addComponent(jPanel5, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) - .addGap(0, 0, Short.MAX_VALUE)) - ); - tabVersionEdit.setName("tabVersionEdit"); // NOI18N + java.util.ResourceBundle bundle = java.util.ResourceBundle.getBundle("org/jackhuang/hellominecraft/launcher/I18N"); // NOI18N jLabel24.setText(bundle.getString("settings.game_directory")); // NOI18N txtGameDir.addFocusListener(new java.awt.event.FocusAdapter() { @@ -483,6 +434,13 @@ public class GameSettingsPanel extends javax.swing.JPanel { } }); + btnChoosingGameDir.setText(bundle.getString("ui.button.explore")); // NOI18N + btnChoosingGameDir.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + btnChoosingGameDirActionPerformed(evt); + } + }); + javax.swing.GroupLayout jPanel22Layout = new javax.swing.GroupLayout(jPanel22); jPanel22.setLayout(jPanel22Layout); jPanel22Layout.setHorizontalGroup( @@ -505,7 +463,6 @@ public class GameSettingsPanel extends javax.swing.JPanel { .addGroup(jPanel22Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addComponent(cboGameDirType, javax.swing.GroupLayout.Alignment.TRAILING, 0, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addComponent(cboLauncherVisibility, javax.swing.GroupLayout.Alignment.TRAILING, 0, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) - .addComponent(txtGameDir) .addGroup(jPanel22Layout.createSequentialGroup() .addComponent(txtWidth, javax.swing.GroupLayout.PREFERRED_SIZE, 100, javax.swing.GroupLayout.PREFERRED_SIZE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) @@ -515,16 +472,19 @@ public class GameSettingsPanel extends javax.swing.JPanel { .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 320, Short.MAX_VALUE) .addComponent(chkFullscreen)) .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel22Layout.createSequentialGroup() - .addGroup(jPanel22Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(txtMaxMemory) - .addGroup(jPanel22Layout.createSequentialGroup() - .addComponent(cboJava, javax.swing.GroupLayout.PREFERRED_SIZE, 100, javax.swing.GroupLayout.PREFERRED_SIZE) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(txtJavaDir))) + .addComponent(txtMaxMemory) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addGroup(jPanel22Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(btnChoosingJavaDir, javax.swing.GroupLayout.Alignment.TRAILING) - .addComponent(lblMaxMemory, javax.swing.GroupLayout.Alignment.TRAILING)))))) + .addComponent(lblMaxMemory)) + .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel22Layout.createSequentialGroup() + .addComponent(txtGameDir) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(btnChoosingGameDir)) + .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel22Layout.createSequentialGroup() + .addComponent(cboJava, javax.swing.GroupLayout.PREFERRED_SIZE, 100, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(txtJavaDir) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(btnChoosingJavaDir))))) .addContainerGap()) ); jPanel22Layout.setVerticalGroup( @@ -533,7 +493,8 @@ public class GameSettingsPanel extends javax.swing.JPanel { .addContainerGap() .addGroup(jPanel22Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addComponent(txtGameDir, javax.swing.GroupLayout.PREFERRED_SIZE, 26, javax.swing.GroupLayout.PREFERRED_SIZE) - .addComponent(jLabel24)) + .addComponent(jLabel24) + .addComponent(btnChoosingGameDir, javax.swing.GroupLayout.PREFERRED_SIZE, 26, javax.swing.GroupLayout.PREFERRED_SIZE)) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addGroup(jPanel22Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addComponent(txtJavaDir, javax.swing.GroupLayout.PREFERRED_SIZE, 26, javax.swing.GroupLayout.PREFERRED_SIZE) @@ -560,7 +521,7 @@ public class GameSettingsPanel extends javax.swing.JPanel { .addComponent(jLabel9, javax.swing.GroupLayout.PREFERRED_SIZE, 26, javax.swing.GroupLayout.PREFERRED_SIZE) .addComponent(jLabel25) .addComponent(txtWidth, javax.swing.GroupLayout.PREFERRED_SIZE, 26, javax.swing.GroupLayout.PREFERRED_SIZE)) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 92, Short.MAX_VALUE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 95, Short.MAX_VALUE) .addComponent(btnDownloadAllAssets) .addContainerGap()) ); @@ -684,7 +645,7 @@ public class GameSettingsPanel extends javax.swing.JPanel { .addComponent(jLabel31) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(txtServerIP, javax.swing.GroupLayout.PREFERRED_SIZE, 26, javax.swing.GroupLayout.PREFERRED_SIZE) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 86, Short.MAX_VALUE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 90, Short.MAX_VALUE) .addGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addComponent(chkDebug) .addComponent(chkNoJVMArgs) @@ -694,6 +655,84 @@ public class GameSettingsPanel extends javax.swing.JPanel { tabVersionEdit.addTab(bundle.getString("advancedsettings"), jPanel2); // NOI18N + lstExternalMods.setModel(SwingUtils.makeDefaultTableModel(new String[]{"", "Mod", C.i18n("ui.label.version")}, new Class[]{Boolean.class,String.class,String.class}, new boolean[]{true,false,false})); + lstExternalMods.setColumnSelectionAllowed(true); + lstExternalMods.getTableHeader().setReorderingAllowed(false); + lstExternalMods.addKeyListener(new java.awt.event.KeyAdapter() { + public void keyPressed(java.awt.event.KeyEvent evt) { + lstExternalModsKeyPressed(evt); + } + }); + jScrollPane1.setViewportView(lstExternalMods); + lstExternalMods.getColumnModel().getSelectionModel().setSelectionMode(javax.swing.ListSelectionModel.SINGLE_SELECTION); + + btnAddMod.setText("添加"); + btnAddMod.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + btnAddModActionPerformed(evt); + } + }); + + btnRemoveMod.setText("删除"); + btnRemoveMod.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + btnRemoveModActionPerformed(evt); + } + }); + + lblModInfo.setText(bundle.getString("mods.default_information")); // NOI18N + lblModInfo.setCursor(new java.awt.Cursor(java.awt.Cursor.DEFAULT_CURSOR)); + lblModInfo.addMouseListener(new java.awt.event.MouseAdapter() { + public void mouseClicked(java.awt.event.MouseEvent evt) { + lblModInfoMouseClicked(evt); + } + }); + + javax.swing.GroupLayout jPanel7Layout = new javax.swing.GroupLayout(jPanel7); + jPanel7.setLayout(jPanel7Layout); + jPanel7Layout.setHorizontalGroup( + jPanel7Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jPanel7Layout.createSequentialGroup() + .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 606, Short.MAX_VALUE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(jPanel7Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(btnRemoveMod) + .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel7Layout.createSequentialGroup() + .addComponent(btnAddMod) + .addContainerGap()))) + .addGroup(jPanel7Layout.createSequentialGroup() + .addContainerGap() + .addComponent(lblModInfo) + .addContainerGap()) + ); + jPanel7Layout.setVerticalGroup( + jPanel7Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jPanel7Layout.createSequentialGroup() + .addGroup(jPanel7Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jPanel7Layout.createSequentialGroup() + .addComponent(btnAddMod) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(btnRemoveMod) + .addGap(0, 0, Short.MAX_VALUE)) + .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 279, Short.MAX_VALUE)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(lblModInfo, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addContainerGap()) + ); + + javax.swing.GroupLayout jPanel6Layout = new javax.swing.GroupLayout(jPanel6); + jPanel6.setLayout(jPanel6Layout); + jPanel6Layout.setHorizontalGroup( + jPanel6Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(jPanel7, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + ); + jPanel6Layout.setVerticalGroup( + jPanel6Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(jPanel7, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + ); + + tabVersionEdit.addTab(bundle.getString("mods"), jPanel6); // NOI18N + lstForge.setModel(SwingUtils.makeDefaultTableModel(new String[]{C.I18N.getString("install.version"), C.I18N.getString("install.mcversion")}, new Class[]{String.class, String.class}, new boolean[]{false, false})); lstForge.setSelectionMode(javax.swing.ListSelectionModel.SINGLE_SELECTION); @@ -727,7 +766,7 @@ public class GameSettingsPanel extends javax.swing.JPanel { ); jPanel16Layout.setVerticalGroup( jPanel16Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(jScrollPane11, javax.swing.GroupLayout.DEFAULT_SIZE, 292, Short.MAX_VALUE) + .addComponent(jScrollPane11, javax.swing.GroupLayout.DEFAULT_SIZE, 296, Short.MAX_VALUE) .addGroup(jPanel16Layout.createSequentialGroup() .addComponent(btnDownloadForge) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) @@ -775,7 +814,7 @@ btnRefreshOptifine.addActionListener(new java.awt.event.ActionListener() { .addComponent(btnDownloadOptifine) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(btnRefreshOptifine) - .addGap(0, 240, Short.MAX_VALUE)) + .addGap(0, 244, Short.MAX_VALUE)) ); tabInstallers.addTab("OptiFine", pnlOptifine); @@ -813,7 +852,7 @@ btnRefreshLiteLoader.addActionListener(new java.awt.event.ActionListener() { ); jPanel3Layout.setVerticalGroup( jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(jScrollPane12, javax.swing.GroupLayout.DEFAULT_SIZE, 292, Short.MAX_VALUE) + .addComponent(jScrollPane12, javax.swing.GroupLayout.DEFAULT_SIZE, 296, Short.MAX_VALUE) .addGroup(jPanel3Layout.createSequentialGroup() .addComponent(btnInstallLiteLoader) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) @@ -873,11 +912,150 @@ btnRefreshLiteLoader.addActionListener(new java.awt.event.ActionListener() { .addComponent(btnRefreshGameDownloads) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addComponent(btnDownload)) - .addComponent(jScrollPane2, javax.swing.GroupLayout.DEFAULT_SIZE, 321, Short.MAX_VALUE) + .addComponent(jScrollPane2, javax.swing.GroupLayout.DEFAULT_SIZE, 325, Short.MAX_VALUE) ); tabVersionEdit.addTab(bundle.getString("settings.tabs.game_download"), pnlGameDownloads); // NOI18N + jLabel1.setText(bundle.getString("ui.label.profile")); // NOI18N + + cboProfiles.setMinimumSize(new java.awt.Dimension(32, 23)); + cboProfiles.setPreferredSize(new java.awt.Dimension(32, 23)); + cboProfiles.addItemListener(new java.awt.event.ItemListener() { + public void itemStateChanged(java.awt.event.ItemEvent evt) { + cboProfilesItemStateChanged(evt); + } + }); + + cboVersions.addItemListener(new java.awt.event.ItemListener() { + public void itemStateChanged(java.awt.event.ItemEvent evt) { + cboVersionsItemStateChanged(evt); + } + }); + + jLabel2.setText(bundle.getString("ui.label.version")); // NOI18N + + javax.swing.GroupLayout jPanel4Layout = new javax.swing.GroupLayout(jPanel4); + jPanel4.setLayout(jPanel4Layout); + jPanel4Layout.setHorizontalGroup( + jPanel4Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jPanel4Layout.createSequentialGroup() + .addContainerGap() + .addGroup(jPanel4Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jPanel4Layout.createSequentialGroup() + .addComponent(jLabel1) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(cboProfiles, 0, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) + .addGroup(jPanel4Layout.createSequentialGroup() + .addComponent(jLabel2) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(cboVersions, 0, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)))) + ); + jPanel4Layout.setVerticalGroup( + jPanel4Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jPanel4Layout.createSequentialGroup() + .addContainerGap() + .addGroup(jPanel4Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(cboProfiles, javax.swing.GroupLayout.PREFERRED_SIZE, 26, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(jLabel1)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(jPanel4Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(cboVersions, javax.swing.GroupLayout.PREFERRED_SIZE, 26, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(jLabel2)) + .addContainerGap(11, Short.MAX_VALUE)) + ); + + btnModify.setText(bundle.getString("settings.manage")); // NOI18N + btnModify.addMouseListener(new java.awt.event.MouseAdapter() { + public void mouseClicked(java.awt.event.MouseEvent evt) { + btnModifyMouseClicked(evt); + } + }); + + btnRefreshVersions.setText(bundle.getString("ui.button.refresh")); // NOI18N + btnRefreshVersions.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + btnRefreshVersionsActionPerformed(evt); + } + }); + + txtMinecraftVersion.setEditable(false); + + btnNewProfile.setText(bundle.getString("setupwindow.new")); // NOI18N + btnNewProfile.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + btnNewProfileActionPerformed(evt); + } + }); + + btnRemoveProfile.setText(bundle.getString("ui.button.delete")); // NOI18N + btnRemoveProfile.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + btnRemoveProfileActionPerformed(evt); + } + }); + + btnExplore.setText(bundle.getString("settings.explore")); // NOI18N + btnExplore.setToolTipText(""); + btnExplore.addMouseListener(new java.awt.event.MouseAdapter() { + public void mouseClicked(java.awt.event.MouseEvent evt) { + btnExploreMouseClicked(evt); + } + }); + + javax.swing.GroupLayout jPanel5Layout = new javax.swing.GroupLayout(jPanel5); + jPanel5.setLayout(jPanel5Layout); + jPanel5Layout.setHorizontalGroup( + jPanel5Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jPanel5Layout.createSequentialGroup() + .addGap(0, 0, 0) + .addGroup(jPanel5Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false) + .addComponent(btnNewProfile, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(txtMinecraftVersion)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(jPanel5Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false) + .addComponent(btnRemoveProfile, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(btnRefreshVersions, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(jPanel5Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false) + .addComponent(btnModify, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(btnExplore, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) + .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) + ); + jPanel5Layout.setVerticalGroup( + jPanel5Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jPanel5Layout.createSequentialGroup() + .addContainerGap() + .addGroup(jPanel5Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(btnNewProfile, javax.swing.GroupLayout.PREFERRED_SIZE, 26, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(btnRemoveProfile, javax.swing.GroupLayout.PREFERRED_SIZE, 26, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(btnExplore, javax.swing.GroupLayout.PREFERRED_SIZE, 26, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(jPanel5Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(txtMinecraftVersion, javax.swing.GroupLayout.PREFERRED_SIZE, 26, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(btnRefreshVersions, javax.swing.GroupLayout.PREFERRED_SIZE, 26, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(btnModify, javax.swing.GroupLayout.PREFERRED_SIZE, 26, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) + ); + + javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1); + jPanel1.setLayout(jPanel1Layout); + jPanel1Layout.setHorizontalGroup( + jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jPanel1Layout.createSequentialGroup() + .addComponent(jPanel4, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(jPanel5, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) + ); + jPanel1Layout.setVerticalGroup( + jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jPanel1Layout.createSequentialGroup() + .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false) + .addComponent(jPanel4, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(jPanel5, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) + .addGap(0, 0, Short.MAX_VALUE)) + ); + btnIncludeMinecraft.setText(bundle.getString("setupwindow.include_minecraft")); // NOI18N btnIncludeMinecraft.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { @@ -1174,6 +1352,82 @@ btnRefreshLiteLoader.addActionListener(new java.awt.event.ActionListener() { } }//GEN-LAST:event_cboJavaItemStateChanged + private void btnAddModActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnAddModActionPerformed + JFileChooser fc = new JFileChooser(); + fc.setFileSelectionMode(JFileChooser.FILES_ONLY); + fc.setDialogTitle(C.I18N.getString("mods.choose_mod")); + fc.setMultiSelectionEnabled(true); + if (fc.showOpenDialog(this) != JFileChooser.APPROVE_OPTION) return; + boolean flag = false; + for (File f : fc.getSelectedFiles()) + if (!addMod(f)) flag |= true; + if (flag) + MessageBox.Show(C.I18N.getString("mods.failed")); + }//GEN-LAST:event_btnAddModActionPerformed + + boolean addMod(File f) { + try { + if (!ModInfo.isFileMod(f) || mods == null) return false; + File newf = profile.getFolder("mods"); + newf.mkdirs(); + newf = new File(newf, f.getName()); + FileUtils.copyFile(f, newf); + ModInfo i = ModInfo.readModInfo(f); + mods.add(i); + ((DefaultTableModel) lstExternalMods.getModel()).addRow(new Object[]{i.isActive(), i.location.getName(), i.version}); + return true; + } catch (IOException ex) { + HMCLog.warn("Failed to copy mod", ex); + return false; + } + } + + private void btnRemoveModActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnRemoveModActionPerformed + DefaultTableModel model = (DefaultTableModel) lstExternalMods.getModel(); + int[] rows = lstExternalMods.getSelectedRows(); + Arrays.sort(rows); + int removed = 0; + for (int idx : rows) { + ModInfo mi = mods.get(idx - removed); + File f = mi.location; + mods.remove(idx - removed); + model.removeRow(idx - removed); + removed++; + f.delete(); + } + }//GEN-LAST:event_btnRemoveModActionPerformed + + private void lstExternalModsKeyPressed(java.awt.event.KeyEvent evt) {//GEN-FIRST:event_lstExternalModsKeyPressed + btnRemoveModActionPerformed(null); + }//GEN-LAST:event_lstExternalModsKeyPressed + + private void lblModInfoMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_lblModInfoMouseClicked + int idx = lstExternalMods.getSelectedRow(); + if (idx > 0 && idx < mods.size()) { + ModInfo m = mods.get(idx); + if (m.url != null) + Utils.openLink(m.url); + } + }//GEN-LAST:event_lblModInfoMouseClicked + + private void btnChoosingGameDirActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnChoosingGameDirActionPerformed + JFileChooser fc = new JFileChooser(); + fc.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY); + fc.setDialogTitle(C.i18n("settings.choose_gamedir")); + fc.setMultiSelectionEnabled(false); + fc.showOpenDialog(this); + if (fc.getSelectedFile() == null) + return; + try { + String path = fc.getSelectedFile().getCanonicalPath(); + txtGameDir.setText(path); + profile.setGameDir(path); + } catch (IOException e) { + HMCLog.warn("Failed to set game dir.", e); + MessageBox.Show(C.i18n("ui.label.failed_set") + e.getMessage()); + } + }//GEN-LAST:event_btnChoosingGameDirActionPerformed + // // private void loadProfiles() { @@ -1250,6 +1504,8 @@ btnRefreshLiteLoader.addActionListener(new java.awt.event.ActionListener() { } isLoading = false; if (index < cboVersions.getItemCount()) cboVersions.setSelectedIndex(index); + + reloadMods(); } void loadMinecraftVersion() { @@ -1343,6 +1599,36 @@ btnRefreshLiteLoader.addActionListener(new java.awt.event.ActionListener() { return minecraftVersion == null ? "" : (StrUtils.formatVersion(minecraftVersion.version) == null) ? mcVersion : minecraftVersion.version; } + @Override + public void dragEnter(DropTargetDragEvent dtde) { + DataFlavor[] f = dtde.getCurrentDataFlavors(); + if (f[0].match(DataFlavor.javaFileListFlavor)) + try { + Transferable tr = dtde.getTransferable(); + List files = (List) tr.getTransferData(DataFlavor.javaFileListFlavor); + for (File file : files) + addMod(file); + } catch (Exception ex) { + HMCLog.warn("Failed to drop file.", ex); + } + } + + @Override + public void dragOver(DropTargetDragEvent dtde) { + } + + @Override + public void dropActionChanged(DropTargetDragEvent dtde) { + } + + @Override + public void dragExit(DropTargetEvent dte) { + } + + @Override + public void drop(DropTargetDropEvent dtde) { + } + class InstallerHelper { List versions; @@ -1406,6 +1692,17 @@ btnRefreshLiteLoader.addActionListener(new java.awt.event.ActionListener() { String mcVersion; // + // + List mods; + + private void reloadMods() { + mods = profile.getMinecraftProvider().listMods(); + SwingUtils.clearDefaultTable(lstExternalMods); + DefaultTableModel model = (DefaultTableModel) lstExternalMods.getModel(); + for (ModInfo info : mods) + model.addRow(new Object[]{info.isActive(), info.getFileName(), info.version}); + } + // public void versionChanged(Profile profile, String version) { this.mcVersion = version; @@ -1413,6 +1710,8 @@ btnRefreshLiteLoader.addActionListener(new java.awt.event.ActionListener() { optifine.loadVersions(); liteloader.loadVersions(); + reloadMods(); + MinecraftVersion v = profile.getMinecraftProvider().getVersionById(version); if (v != null) for (IAssetsHandler ph : IAssetsHandler.getAssetsHandlers()) @@ -1433,7 +1732,11 @@ btnRefreshLiteLoader.addActionListener(new java.awt.event.ActionListener() { // JPopupMenu ppmManage, ppmExplore; + + DropTarget dropTarget; // Variables declaration - do not modify//GEN-BEGIN:variables + private javax.swing.JButton btnAddMod; + private javax.swing.JButton btnChoosingGameDir; private javax.swing.JButton btnChoosingJavaDir; private javax.swing.JButton btnDownload; private javax.swing.JButton btnDownloadAllAssets; @@ -1449,6 +1752,7 @@ btnRefreshLiteLoader.addActionListener(new java.awt.event.ActionListener() { private javax.swing.JButton btnRefreshLiteLoader; private javax.swing.JButton btnRefreshOptifine; private javax.swing.JButton btnRefreshVersions; + private javax.swing.JButton btnRemoveMod; private javax.swing.JButton btnRemoveProfile; private javax.swing.JComboBox cboGameDirType; private javax.swing.JComboBox cboJava; @@ -1480,12 +1784,17 @@ btnRefreshLiteLoader.addActionListener(new java.awt.event.ActionListener() { private javax.swing.JPanel jPanel3; private javax.swing.JPanel jPanel4; private javax.swing.JPanel jPanel5; + private javax.swing.JPanel jPanel6; + private javax.swing.JPanel jPanel7; + private javax.swing.JScrollPane jScrollPane1; private javax.swing.JScrollPane jScrollPane11; private javax.swing.JScrollPane jScrollPane12; private javax.swing.JScrollPane jScrollPane13; private javax.swing.JScrollPane jScrollPane2; private javax.swing.JLabel lblMaxMemory; + private javax.swing.JLabel lblModInfo; private javax.swing.JTable lstDownloads; + private javax.swing.JTable lstExternalMods; private javax.swing.JTable lstForge; private javax.swing.JTable lstLiteLoader; private javax.swing.JTable lstOptifine; diff --git a/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/tasks/TaskRunnableArg1.java b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/tasks/TaskRunnableArg1.java index 2189f77ff..b491e82bf 100644 --- a/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/tasks/TaskRunnableArg1.java +++ b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/tasks/TaskRunnableArg1.java @@ -18,7 +18,7 @@ package org.jackhuang.hellominecraft.tasks; import java.util.ArrayList; import org.jackhuang.hellominecraft.tasks.communication.PreviousResult; -import org.jackhuang.hellominecraft.tasks.communication.PreviousResultRegistrator; +import org.jackhuang.hellominecraft.tasks.communication.PreviousResultRegistrar; import org.jackhuang.hellominecraft.utils.functions.Consumer; /** @@ -26,7 +26,7 @@ import org.jackhuang.hellominecraft.utils.functions.Consumer; * @author huangyuhui * @param Runnable<T> */ -public class TaskRunnableArg1 extends TaskInfo implements PreviousResultRegistrator { +public class TaskRunnableArg1 extends TaskInfo implements PreviousResultRegistrar { private final Consumer r; public TaskRunnableArg1(String info, Consumer r) { super(info); diff --git a/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/tasks/TaskWindow.form b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/tasks/TaskWindow.form index d390b2600..b7f5f1378 100644 --- a/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/tasks/TaskWindow.form +++ b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/tasks/TaskWindow.form @@ -31,40 +31,26 @@ - - - - - - - - - - - - + + + - + - + - - - - - - - - - + + + + @@ -83,18 +69,6 @@ - - - - - - - - - - - - diff --git a/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/tasks/TaskWindow.java b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/tasks/TaskWindow.java index 79c3240c4..2bad27182 100644 --- a/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/tasks/TaskWindow.java +++ b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/tasks/TaskWindow.java @@ -70,7 +70,6 @@ public class TaskWindow extends javax.swing.JDialog public boolean start() { if (taskList.isAlive()) return false; - pgsSingle.setValue(0); pgsTotal.setValue(0); suc = false; SwingUtils.clearDefaultTable(lstDownload); @@ -97,8 +96,6 @@ public class TaskWindow extends javax.swing.JDialog private void initComponents() { btnCancel = new javax.swing.JButton(); - pgsSingle = new javax.swing.JProgressBar(); - lblSingleProgress = new javax.swing.JLabel(); lblTotalProgress = new javax.swing.JLabel(); pgsTotal = new javax.swing.JProgressBar(); srlDownload = new javax.swing.JScrollPane(); @@ -120,10 +117,6 @@ public class TaskWindow extends javax.swing.JDialog } }); - pgsSingle.setStringPainted(true); - - lblSingleProgress.setText(bundle.getString("taskwindow.single_progress")); // NOI18N - lblTotalProgress.setText(bundle.getString("taskwindow.total_progress")); // NOI18N pgsTotal.setStringPainted(true); @@ -140,35 +133,24 @@ public class TaskWindow extends javax.swing.JDialog layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(layout.createSequentialGroup() .addContainerGap() - .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(layout.createSequentialGroup() - .addComponent(lblSingleProgress) - .addGap(349, 349, 349)) - .addComponent(pgsSingle, javax.swing.GroupLayout.DEFAULT_SIZE, 434, Short.MAX_VALUE) - .addGroup(layout.createSequentialGroup() - .addComponent(lblTotalProgress) - .addGap(0, 0, Short.MAX_VALUE)) - .addComponent(pgsTotal, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) + .addComponent(lblTotalProgress) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(pgsTotal, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(btnCancel) .addContainerGap()) - .addComponent(srlDownload) + .addComponent(srlDownload, javax.swing.GroupLayout.DEFAULT_SIZE, 517, Short.MAX_VALUE) ); layout.setVerticalGroup( layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(layout.createSequentialGroup() - .addComponent(srlDownload, javax.swing.GroupLayout.DEFAULT_SIZE, 232, Short.MAX_VALUE) + .addComponent(srlDownload, javax.swing.GroupLayout.DEFAULT_SIZE, 289, Short.MAX_VALUE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(btnCancel, javax.swing.GroupLayout.Alignment.TRAILING) - .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup() - .addComponent(lblSingleProgress) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(pgsSingle, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(lblTotalProgress) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(pgsTotal, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))) + .addComponent(btnCancel, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.PREFERRED_SIZE, 22, javax.swing.GroupLayout.PREFERRED_SIZE) + .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(pgsTotal, javax.swing.GroupLayout.PREFERRED_SIZE, 22, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(lblTotalProgress, javax.swing.GroupLayout.PREFERRED_SIZE, 22, javax.swing.GroupLayout.PREFERRED_SIZE))) .addContainerGap()) ); @@ -196,10 +178,8 @@ public class TaskWindow extends javax.swing.JDialog // Variables declaration - do not modify//GEN-BEGIN:variables private javax.swing.JButton btnCancel; - private javax.swing.JLabel lblSingleProgress; private javax.swing.JLabel lblTotalProgress; private javax.swing.JTable lstDownload; - private javax.swing.JProgressBar pgsSingle; private javax.swing.JProgressBar pgsTotal; private javax.swing.JScrollPane srlDownload; // End of variables declaration//GEN-END:variables @@ -218,8 +198,6 @@ public class TaskWindow extends javax.swing.JDialog progresses.set(idx, pgs); } if (task.isParallelExecuting()) return; - pgsSingle.setMaximum(max); - pgsSingle.setValue(progress); }); } diff --git a/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/tasks/communication/PreviousResultRegistrator.java b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/tasks/communication/PreviousResultRegistrar.java similarity index 95% rename from HMCLAPI/src/main/java/org/jackhuang/hellominecraft/tasks/communication/PreviousResultRegistrator.java rename to HMCLAPI/src/main/java/org/jackhuang/hellominecraft/tasks/communication/PreviousResultRegistrar.java index 47b19edfb..548846d87 100644 --- a/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/tasks/communication/PreviousResultRegistrator.java +++ b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/tasks/communication/PreviousResultRegistrar.java @@ -23,7 +23,7 @@ import org.jackhuang.hellominecraft.tasks.Task; * @author huangyuhui * @param Previous task result type */ -public interface PreviousResultRegistrator { +public interface PreviousResultRegistrar { /** * diff --git a/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/tasks/download/FileDownloadTask.java b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/tasks/download/FileDownloadTask.java index bb528f72a..c84145123 100644 --- a/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/tasks/download/FileDownloadTask.java +++ b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/tasks/download/FileDownloadTask.java @@ -33,7 +33,7 @@ import org.jackhuang.hellominecraft.C; import org.jackhuang.hellominecraft.HMCLog; import org.jackhuang.hellominecraft.tasks.Task; import org.jackhuang.hellominecraft.tasks.communication.PreviousResult; -import org.jackhuang.hellominecraft.tasks.communication.PreviousResultRegistrator; +import org.jackhuang.hellominecraft.tasks.communication.PreviousResultRegistrar; import org.jackhuang.hellominecraft.utils.system.IOUtils; /** @@ -41,7 +41,7 @@ import org.jackhuang.hellominecraft.utils.system.IOUtils; * @author huangyuhui */ // This class downloads a file from a URL. -public class FileDownloadTask extends Task implements PreviousResult, PreviousResultRegistrator { +public class FileDownloadTask extends Task implements PreviousResult, PreviousResultRegistrar { private static final X509TrustManager xtm = new X509TrustManager() { @Override diff --git a/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/utils/SwingUtils.java b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/utils/SwingUtils.java index 0f7b07c50..399764e80 100644 --- a/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/utils/SwingUtils.java +++ b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/utils/SwingUtils.java @@ -16,8 +16,10 @@ */ package org.jackhuang.hellominecraft.utils; +import java.awt.FontMetrics; import java.net.URI; import javax.swing.DefaultListModel; +import javax.swing.JLabel; import javax.swing.JList; import javax.swing.JScrollBar; import javax.swing.JScrollPane; @@ -33,12 +35,13 @@ import org.jackhuang.hellominecraft.HMCLog; public class SwingUtils { /** - * Make DefaultTableModel by overriding getColumnClass and isCellEditable of DefaultTableModel. - * + * Make DefaultTableModel by overriding getColumnClass and isCellEditable of + * DefaultTableModel. + * * @param titleA The title of each column. * @param typesA The type of each column value. * @param canEditA Is column editable? - * @return + * @return */ public static DefaultTableModel makeDefaultTableModel(String[] titleA, final Class[] typesA, final boolean[] canEditA) { return new javax.swing.table.DefaultTableModel( @@ -61,7 +64,8 @@ public class SwingUtils { /** * Open URL by java.awt.Desktop - * @param link + * + * @param link */ public static void openLink(URI link) { try { @@ -73,7 +77,8 @@ public class SwingUtils { /** * Move the cursor to the end of TextArea. - * @param tf the TextArea + * + * @param tf the TextArea */ public static void moveEnd(JTextArea tf) { int position = tf.getText().length(); @@ -82,6 +87,7 @@ public class SwingUtils { /** * Move the cursor to the end of ScrollPane. + * * @param pane the ScrollPane */ public static void moveEnd(JScrollPane pane) { @@ -91,6 +97,7 @@ public class SwingUtils { /** * Get the DefaultListModel from JList. + * * @param list * @return Forcely Type casted to DefaultListModel */ @@ -100,6 +107,7 @@ public class SwingUtils { /** * Append new element to JList + * * @param list the JList * @param element the Element */ @@ -118,6 +126,7 @@ public class SwingUtils { /** * Clear the JTable + * * @param table JTable with DefaultTableModel. */ public static void clearDefaultTable(JTable table) { @@ -126,20 +135,39 @@ public class SwingUtils { model.removeRow(0); table.updateUI(); } - + public static void appendLast(JTable table, Object... elements) { DefaultTableModel model = (DefaultTableModel) table.getModel(); model.addRow(elements); } - + public static void setValueAt(JTable table, Object element, int row, int col) { DefaultTableModel model = (DefaultTableModel) table.getModel(); model.setValueAt(element, row, col); } - + public static void removeRow(JTable table, int row) { DefaultTableModel model = (DefaultTableModel) table.getModel(); model.removeRow(row); } + public static String getParsedJPanelText(JLabel jLabel1, String longString) { + if(StrUtils.isBlank(longString)) return longString; + StringBuilder builder = new StringBuilder(); + char[] chars = longString.toCharArray(); + FontMetrics fontMetrics = jLabel1.getFontMetrics(jLabel1.getFont()); + for (int beginIndex = 0, limit = 1;; limit++) { + if (fontMetrics.charsWidth(chars, beginIndex, limit) < jLabel1.getWidth()) { + if (beginIndex + limit < chars.length) + continue; + builder.append(chars, beginIndex, limit); + break; + } + builder.append(chars, beginIndex, limit - 1).append("
"); + beginIndex += limit - 1; + limit = 1; + } + return builder.toString(); + } + } diff --git a/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/utils/system/FileUtils.java b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/utils/system/FileUtils.java index 2730f9c64..ed436e374 100644 --- a/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/utils/system/FileUtils.java +++ b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/utils/system/FileUtils.java @@ -16,7 +16,6 @@ */ package org.jackhuang.hellominecraft.utils.system; -import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileFilter; import java.io.FileInputStream; @@ -26,7 +25,6 @@ import java.io.IOException; import java.io.OutputStream; import java.nio.channels.FileChannel; import java.util.ArrayList; -import java.util.Arrays; import java.util.List; import org.jackhuang.hellominecraft.HMCLog; import org.jackhuang.hellominecraft.utils.NetUtils; @@ -230,6 +228,14 @@ public class FileUtils { return ""; } } + + public static void copyFileQuietly(File srcFile, File destFile) { + try { + copyFile(srcFile, destFile); + } catch (IOException ex) { + HMCLog.warn("Failed to copy file", ex); + } + } public static void copyFile(File srcFile, File destFile) throws IOException { diff --git a/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/utils/system/Java.java b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/utils/system/Java.java index 2d39a017a..90bf952db 100644 --- a/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/utils/system/Java.java +++ b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/utils/system/Java.java @@ -72,6 +72,16 @@ public class Java { if (javahome != null) ans.add(new Java(java.substring("HKEY_LOCAL_MACHINE\\SOFTWARE\\JavaSoft\\Java Runtime Environment\\".length()), javahome)); } + javas = queryRegSubFolders("HKEY_LOCAL_MACHINE\\SOFTWARE\\JavaSoft\\Java Development Kit"); + for (String java : javas) { + int s = 0; + for (char c : java.toCharArray()) + if (c == '.') s++; + if (s <= 1) continue; + String javahome = queryRegValue(java, "JavaHome"); + if (javahome != null) + ans.add(new Java(java.substring("HKEY_LOCAL_MACHINE\\SOFTWARE\\JavaSoft\\Java Development Kit\\".length()), javahome)); + } return ans; } catch (IOException | InterruptedException ex) { HMCLog.err("Faield to query java", ex); diff --git a/HMCLAPI/src/main/resources/org/jackhuang/hellominecraft/launcher/I18N.properties b/HMCLAPI/src/main/resources/org/jackhuang/hellominecraft/launcher/I18N.properties index b3358122d..09144542e 100644 --- a/HMCLAPI/src/main/resources/org/jackhuang/hellominecraft/launcher/I18N.properties +++ b/HMCLAPI/src/main/resources/org/jackhuang/hellominecraft/launcher/I18N.properties @@ -195,9 +195,15 @@ settings.physical_memory=\u7269\u7406\u5185\u5b58\u5927\u5c0f settings.choose_javapath=\u9009\u62e9Java\u8def\u5f84 settings.default=\u9ed8\u8ba4 settings.custom=\u81ea\u5b9a\u4e49 +settings.choose_gamepath=\u9009\u62e9\u6e38\u620f\u8def\u5f84 settings.failed_load=\u8bbe\u7f6e\u6587\u4ef6\u52a0\u8f7d\u5931\u8d25\uff0c\u53ef\u80fd\u662f\u5347\u7ea7\u4e86\u542f\u52a8\u5668\u6216\u88ab\u4eba\u5de5\u4fee\u6539\u9020\u6210\u9519\u8bef\uff0c\u662f\u5426\u6e05\u9664\uff1f +mods=Mod\u7ba1\u7406 +mods.choose_mod=\u9009\u62e9\u6a21\u7ec4 +mods.failed=\u6dfb\u52a0\u5931\u8d25 +mods.default_information=\u60a8\u53ef\u4ee5\u4ece\u8d44\u6e90\u7ba1\u7406\u5668\u62d6\u52a8mod\u6587\u4ef6\u5230\u5217\u8868\u4e2d\u6765\u6dfb\u52a0mod\uff0c\u540c\u65f6\u4f7f\u7528\u5220\u9664\u952e\u53ef\u5feb\u901f\u5220\u9664\u9009\u4e2dmod
\u70b9\u6389mod\u524d\u9762\u7684\u52fe\u53ef\u7981\u7528mod\uff0c\u4e0d\u4f1a\u52a0\u8f7d\uff1b\u9009\u62e9mod\u53ef\u4ee5\u83b7\u53d6mod\u4fe1\u606f
+ advancedsettings=\u9ad8\u7ea7\u8bbe\u7f6e advancedsettings.launcher_visible=\u542f\u52a8\u5668\u53ef\u89c1\u6027 advancedsettings.run_directory=\u8fd0\u884c\u8def\u5f84 @@ -227,8 +233,7 @@ launcher.download_source=\u4e0b\u8f7d\u6e90 launcher.background_location=\u80cc\u666f\u5730\u5740 launcher.exit_failed=\u5f3a\u5236\u9000\u51fa\u5931\u8d25\uff0c\u53ef\u80fd\u662fForge 1.7.10\u53ca\u66f4\u9ad8\u7248\u672c\u5bfc\u81f4\u7684\uff0c\u65e0\u6cd5\u89e3\u51b3\u3002 launcher.versions_json_not_matched=\u7248\u672c%s\u683c\u5f0f\u4e0d\u89c4\u8303\uff01\u8be5\u7248\u672c\u6587\u4ef6\u5939\u4e0b\u6709json:%s\uff0c\u662f\u5426\u66f4\u540d\u8fd9\u4e2a\u6587\u4ef6\u6765\u89c4\u8303\u683c\u5f0f\uff1f -launcher.versions_json_not_matched_needs_auto_completion=\u7248\u672c%s\u7f3a\u5931\u5fc5\u8981\u7684\u7248\u672c\u4fe1\u606f(JSON)\u6587\u4ef6\uff0c\u662f\u5426\u81ea\u52a8\u8865\u5168\uff1f -launcher.versions_json_not_matched_cannot_auto_completion=\u7248\u672c%s\u7f3a\u5931\u5fc5\u8981\u7684\u7248\u672c\u4fe1\u606f(JSON)\u6587\u4ef6\uff0c\u4f46\u662f\u4f3c\u4e4e\u4e0d\u662f\u539f\u7248\uff0c\u65e0\u6cd5\u81ea\u52a8\u8865\u5168\uff0c\u662f\u5426\u5220\u9664\u8be5\u7248\u672c\uff1f +launcher.versions_json_not_matched_cannot_auto_completion=\u7248\u672c%s\u7f3a\u5931\u5fc5\u8981\u7684\u7248\u672c\u4fe1\u606f\u6587\u4ef6\uff0c\u662f\u5426\u5220\u9664\u8be5\u7248\u672c\uff1f launcher.versions_json_not_formatted=\u7248\u672c%s\u4fe1\u606f\u6587\u4ef6\u683c\u5f0f\u9519\u8bef\uff0c\u662f\u5426\u91cd\u65b0\u4e0b\u8f7d\uff1f launcher.choose_bgpath=\u9009\u62e9\u80cc\u666f\u8def\u5f84 launcher.background_tooltip=\n\n\u542f\u52a8\u5668\u9ed8\u8ba4\u4f7f\u7528\u81ea\u5e26\u7684\u80cc\u666f
\n\u5982\u679c\u5f53\u524d\u76ee\u5f55\u6709background.png\uff0c\u5219\u4f1a\u4f7f\u7528\u8be5\u6587\u4ef6\u4f5c\u4e3a\u80cc\u666f
\n\u5982\u679c\u5f53\u524d\u76ee\u5f55\u6709bgskin\u5b50\u76ee\u5f55\uff0c\u5219\u4f1a\u968f\u673a\u4f7f\u7528\u91cc\u9762\u7684\u4e00\u5f20\u56fe\u4f5c\u4e3a\u80cc\u666f
\n\u5982\u679c\u8be5\u80cc\u666f\u5730\u5740\u88ab\u4fee\u6539\uff0c\u5219\u4f1a\u4f7f\u7528\u80cc\u666f\u5730\u5740\u91cc\u7684\u4e00\u5f20\u56fe\u4f5c\u4e3a\u80cc\u666f
\n\u80cc\u666f\u5730\u5740\u5141\u8bb8\u6709\u591a\u4e2a\u5730\u5740\uff0c\u4f7f\u7528\u534a\u89d2\u5206\u53f7";"(\u4e0d\u5305\u542b\u53cc\u5f15\u53f7)\u5206\u9694\n\n diff --git a/HMCLAPI/src/main/resources/org/jackhuang/hellominecraft/launcher/I18N_en_US.properties b/HMCLAPI/src/main/resources/org/jackhuang/hellominecraft/launcher/I18N_en_US.properties index e3b773a1d..076f1111b 100644 --- a/HMCLAPI/src/main/resources/org/jackhuang/hellominecraft/launcher/I18N_en_US.properties +++ b/HMCLAPI/src/main/resources/org/jackhuang/hellominecraft/launcher/I18N_en_US.properties @@ -75,6 +75,11 @@ login.username=Name login.account=Email login.no_valid_character=No Valid Character, please visit skinme.cc and create your own character. +proxy.username=Account +proxy.password=Password +proxy.host=Host +proxy.port=Port + login.failed.connect_authentication_server=Cannot connect the authentication server. Check your network. login.profile.not_logged_in=Not Logged In and Cannot modify the profile. @@ -190,9 +195,14 @@ settings.physical_memory=Physical Memory Size settings.choose_javapath=Choose Java Directory. settings.default=Default settings.custom=Custom +settings.choose_gamepath=Choose Game Directory settings.failed_load=Failed to load settings file. Remove it? +mods=Mods +mods.choose_mod=Choose your mods +mods.failed=Failed to add mods + advancedsettings=Advanced advancedsettings.launcher_visible=Launcher Visibility advancedsettings.run_directory=Run Directory @@ -222,8 +232,7 @@ launcher.download_source=Download Source launcher.background_location=Background Location launcher.exit_failed=Failed to shutdown. launcher.versions_json_not_matched=The version %s is malformed! There are a json:%s in this version. Do you want to fix this problem? -launcher.versions_json_not_matched_needs_auto_completion=The version %s lost json, needs auto completion? -launcher.versions_json_not_matched_cannot_auto_completion=The version %s lost json, but cannot auto complete it, delete it? +launcher.versions_json_not_matched_cannot_auto_completion=The version %s lost version information file, delete it? launcher.choose_bgpath=Choose background path. launcher.background_tooltip=\n\nThis app uses the default background at first.
\nIf there is background.png in the directory, it will be used.
\nIf there is "bgskin" subdirectory, this app will chooses one picture in "bgskin" randomly.
\nIf you set the background setting, this app will use it.\n\n launcher.update_launcher=Check for update diff --git a/HMCLAPI/src/main/resources/org/jackhuang/hellominecraft/launcher/I18N_zh_CN.properties b/HMCLAPI/src/main/resources/org/jackhuang/hellominecraft/launcher/I18N_zh_CN.properties index c897a5b40..09144542e 100644 --- a/HMCLAPI/src/main/resources/org/jackhuang/hellominecraft/launcher/I18N_zh_CN.properties +++ b/HMCLAPI/src/main/resources/org/jackhuang/hellominecraft/launcher/I18N_zh_CN.properties @@ -19,7 +19,7 @@ launch.failed_packing_jar=\u5728\u6253\u5305jar\u65f6\u53d1\u751f\u9519\u8bef launch.unsupported_launcher_version=\u5bf9\u4e0d\u8d77\uff0c\u672c\u542f\u52a8\u5668\u73b0\u5728\u53ef\u80fd\u4e0d\u80fd\u542f\u52a8\u8fd9\u4e2a\u7248\u672c\u7684Minecraft\uff0c\u4f46\u542f\u52a8\u5668\u8fd8\u662f\u4f1a\u5c1d\u8bd5\u542f\u52a8\uff0c\u8bf7\u5c3d\u5feb\u5c06\u6b64\u95ee\u9898\u62a5\u544a\u7ed9\u4f5c\u8005\u3002 launch.too_big_memory_alloc_64bit=\u60a8\u8bbe\u7f6e\u7684\u5185\u5b58\u5927\u5c0f\u8fc7\u5927\uff0c\u7531\u4e8e\u53ef\u80fd\u8d85\u8fc7\u4e8632\u4f4dJava\u7684\u5185\u5b58\u5206\u914d\u9650\u5236\uff0c\u6240\u4ee5\u53ef\u80fd\u65e0\u6cd5\u542f\u52a8\u6e38\u620f\uff0c\u8bf7\u5c06\u5185\u5b58\u8c03\u81f31024MB\u6216\u66f4\u5c0f\uff0c\u542f\u52a8\u5668\u4ecd\u4f1a\u5c1d\u8bd5\u542f\u52a8\u3002 launch.too_big_memory_alloc_free_space_too_low=\u60a8\u8bbe\u7f6e\u7684\u5185\u5b58\u5927\u5c0f\u8fc7\u5927\uff0c\u7531\u4e8e\u8d85\u8fc7\u4e86\u7cfb\u7edf\u5185\u5b58\u5927\u5c0f%dMB\uff0c\u6240\u4ee5\u53ef\u80fd\u5f71\u54cd\u6e38\u620f\u4f53\u9a8c\u6216\u65e0\u6cd5\u542f\u52a8\u6e38\u620f\uff0c\u542f\u52a8\u5668\u4ecd\u4f1a\u5c1d\u8bd5\u542f\u52a8\u3002 -launch.cannot_create_jvm=\u622a\u83b7\u5230\u65e0\u6cd5\u521b\u5efaJava\u865a\u62df\u673a\uff0c\u53ef\u80fd\u662fJava\u53c2\u6570\u6709\u95ee\u9898\uff0c\u53ef\u4ee5\u5728\u8bbe\u7f6e\u4e2d\u5f00\u542f\u65e0\u53c2\u6570\u6a21\u5f0f\u542f\u52a8\u3002 +launch.cannot_create_jvm=\u622a\u83b7\u5230\u65e0\u6cd5\u521b\u5efaJava\u865a\u62df\u673a\uff0c\u53ef\u80fd\u662fJava\u53c2\u6570\u6709\u95ee\u9898\uff0c\u53ef\u4ee5\u5728\u8bbe\u7f6e\u4e2d\u5f00\u542f\u65e0\u53c2\u6570\u6a21\u5f0f\u542f\u52a8 launch.circular_dependency_versions=\u53d1\u73b0\u6e38\u620f\u7248\u672c\u5faa\u73af\u5f15\u7528\uff0c\u8bf7\u786e\u8ba4\u60a8\u7684\u5ba2\u6237\u7aef\u672a\u88ab\u4fee\u6539\u6216\u4fee\u6539\u5bfc\u81f4\u51fa\u73b0\u6b64\u95ee\u9898\u3002 launch.not_finished_downloading_libraries=\u672a\u5b8c\u6210\u6e38\u620f\u4f9d\u8d56\u5e93\u7684\u4e0b\u8f7d\uff0c\u8fd8\u8981\u7ee7\u7eed\u542f\u52a8\u6e38\u620f\u5417\uff1f launch.not_finished_decompressing_natives=\u672a\u80fd\u89e3\u538b\u6e38\u620f\u672c\u5730\u5e93\uff0c\u8fd8\u8981\u7ee7\u7eed\u542f\u52a8\u6e38\u620f\u5417\uff1f @@ -36,8 +36,8 @@ install.forge.get_list=\u83b7\u53d6Forge\u5217\u8868 install.forge.install=\u5b89\u88c5Forge install.forge.get_changelogs=\u83b7\u53d6Forge\u66f4\u65b0\u8bb0\u5f55 -install.optifine.install=\u5b89\u88c5Optifine -install.optifine.get_list=\u83b7\u53d6Optifine\u5217\u8868 +install.optifine.install=\u5b89\u88c5OptiFine +install.optifine.get_list=\u83b7\u53d6OptiFine\u5217\u8868 install.optifine.get_download_link=\u83b7\u53d6OptiFine\u4e0b\u8f7d\u5730\u5740 install.failed_forge=\u5b89\u88c5Forge\u5931\u8d25 @@ -75,6 +75,11 @@ login.username=\u540d\u5b57 login.account=\u90ae\u7bb1 login.no_valid_character=\u65e0\u6709\u6548\u7684\u89d2\u8272\uff0c\u81ea\u884c\u5230skinme.cc\u767b\u9646\u5e76\u521b\u5efa\u89d2\u8272 +proxy.username=\u8d26\u6237 +proxy.password=\u5bc6\u7801 +proxy.host=\u4e3b\u673a +proxy.port=\u7aef\u53e3 + login.failed.connect_authentication_server=\u65e0\u6cd5\u8fde\u63a5\u8ba4\u8bc1\u670d\u52a1\u5668,\u53ef\u80fd\u662f\u7f51\u7edc\u95ee\u9898 login.profile.not_logged_in=\u65e0\u6cd5\u4fee\u6539\u6e38\u620f\u8d44\u6599\u540c\u65f6\u672a\u767b\u5f55 @@ -97,7 +102,7 @@ ui.more=\u66f4\u591a crash.advice.UnsupportedClassVersionError=\u8fd9\u53ef\u80fd\u662f\u56e0\u4e3a\u60a8\u7684Java\u7248\u672c\u8fc7\u4e8e\u8001\u65e7\uff0c\u53ef\u4ee5\u5c1d\u8bd5\u66f4\u6362\u6700\u65b0Java\u5e76\u5728\u7248\u672c\u8bbe\u7f6e\u7684Java\u8def\u5f84\u4e2d\u8bbe\u7f6e. crash.advice.ConcurrentModificationException=\u8fd9\u53ef\u80fd\u662f\u56e0\u4e3a\u60a8\u7684Java\u7248\u672c\u9ad8\u4e8eJava 1.8.0_11\u5bfc\u81f4\u7684,\u53ef\u4ee5\u5c1d\u8bd5\u5378\u8f7dJava8\u5b89\u88c5Java7\u3002 -crash.advice.ClassNotFoundException=Minecraft\u4e0d\u5b8c\u6574\u6216Mod\u51b2\u7a81\uff0c\u5982\u679c\u6709\u672a\u80fd\u4e0b\u8f7d\u7684\u6587\u4ef6\u8bf7\u4e0b\u8f7d\u6210\u529f\u540e\u91cd\u8bd5\u6216\u662f\u5ba2\u6237\u7aef\u635f\u574f\u8bf7\u91cd\u65b0\u5236\u4f5c\u5ba2\u6237\u7aef\u6216\u4e0b\u8f7d\u6574\u5408\u5305\u89e3\u51b3\u95ee\u9898\u3002 +crash.advice.ClassNotFoundException=Minecraft\u4e0d\u5b8c\u6574\u6216Mod\u51b2\u7a81\uff0c\u5982\u679c\u6709\u672a\u80fd\u4e0b\u8f7d\u7684\u6587\u4ef6\u8bf7\u4e0b\u8f7d\u6210\u529f\u540e\u91cd\u8bd5\u6216\u662f\u5ba2\u6237\u7aef\u635f\u574f\u8bf7\u91cd\u8bd5\u8bf7\u91cd\u65b0\u5236\u4f5c\u5ba2\u6237\u7aef\u6216\u4e0b\u8f7d\u6574\u5408\u5305\u89e3\u51b3\u95ee\u9898\u3002 crash.advice.NoSuchFieldError=Minecraft\u4e0d\u5b8c\u6574\u6216Mod\u51b2\u7a81\uff0c\u5982\u679c\u6709\u672a\u80fd\u4e0b\u8f7d\u7684\u6587\u4ef6\u8bf7\u4e0b\u8f7d\u6210\u529f\u540e\u91cd\u8bd5\u6216\u662f\u5ba2\u6237\u7aef\u635f\u574f\u8bf7\u91cd\u8bd5\u8bf7\u91cd\u65b0\u5236\u4f5c\u5ba2\u6237\u7aef\u6216\u4e0b\u8f7d\u6574\u5408\u5305\u89e3\u51b3\u95ee\u9898\u3002 crash.advice.LWJGLException=\u60a8\u7684\u7535\u8111\u4e0d\u6b63\u5e38\uff0c\u53ef\u80fd\u9700\u8981\u4f7f\u7528\u9a71\u52a8\u7cbe\u7075\u6216\u5176\u4ed6\u5b89\u88c5\u5668\u66f4\u65b0\u663e\u5361\u9a71\u52a8\u3002 crash.advice.SecurityException=\u53ef\u80fd\u662f\u60a8\u4fee\u6539\u4e86minecraft.jar\u4f46\u672a\u5220\u9664META-INF\u6587\u4ef6\u5939\u7684\u539f\u56e0\u3002\u8bf7\u901a\u8fc7\u538b\u7f29\u8f6f\u4ef6\u5220\u9664jar\u4e2d\u7684META-INF\u6587\u4ef6\u5939\u3002 @@ -148,7 +153,7 @@ ui.message.making=\u751f\u6210\u4e2d ui.message.sure_remove=\u771f\u7684\u8981\u5220\u9664\u914d\u7f6e%s\u5417\uff1f ui.label.settings=\u9009\u9879 -ui.label.crashing=Hello Minecraft! Launcher\u9047\u5230\u4e86\u65e0\u6cd5\u5904\u7406\u7684\u9519\u8bef\uff0c\u8bf7\u590d\u5236\u4e0b\u5217\u5185\u5bb9\u5e76\u901a\u8fc7mcbbs\u3001\u8d34\u5427\u6216Minecraft Forum\u53cd\u9988bug\u3002 +ui.label.crashing=Hello Minecraft!\u9047\u5230\u4e86\u65e0\u6cd5\u5904\u7406\u7684\u9519\u8bef\uff0c\u8bf7\u590d\u5236\u4e0b\u5217\u5185\u5bb9\u5e76\u901a\u8fc7mcbbs\u3001\u8d34\u5427\u3001Github\u6216Minecraft Forum\u53cd\u9988bug\u3002 ui.label.crashing_out_dated=Hello Minecraft! Launcher\u9047\u5230\u4e86\u65e0\u6cd5\u5904\u7406\u7684\u9519\u8bef\uff0c\u5df2\u68c0\u6d4b\u5230\u60a8\u7684\u542f\u52a8\u5668\u4e0d\u662f\u6700\u65b0\u7248\u672c\uff0c\u8bf7\u66f4\u65b0\u540e\u518d\u8bd5\uff01 ui.label.failed_set=\u8bbe\u7f6e\u5931\u8d25\uff1a @@ -190,14 +195,20 @@ settings.physical_memory=\u7269\u7406\u5185\u5b58\u5927\u5c0f settings.choose_javapath=\u9009\u62e9Java\u8def\u5f84 settings.default=\u9ed8\u8ba4 settings.custom=\u81ea\u5b9a\u4e49 +settings.choose_gamepath=\u9009\u62e9\u6e38\u620f\u8def\u5f84 settings.failed_load=\u8bbe\u7f6e\u6587\u4ef6\u52a0\u8f7d\u5931\u8d25\uff0c\u53ef\u80fd\u662f\u5347\u7ea7\u4e86\u542f\u52a8\u5668\u6216\u88ab\u4eba\u5de5\u4fee\u6539\u9020\u6210\u9519\u8bef\uff0c\u662f\u5426\u6e05\u9664\uff1f +mods=Mod\u7ba1\u7406 +mods.choose_mod=\u9009\u62e9\u6a21\u7ec4 +mods.failed=\u6dfb\u52a0\u5931\u8d25 +mods.default_information=\u60a8\u53ef\u4ee5\u4ece\u8d44\u6e90\u7ba1\u7406\u5668\u62d6\u52a8mod\u6587\u4ef6\u5230\u5217\u8868\u4e2d\u6765\u6dfb\u52a0mod\uff0c\u540c\u65f6\u4f7f\u7528\u5220\u9664\u952e\u53ef\u5feb\u901f\u5220\u9664\u9009\u4e2dmod
\u70b9\u6389mod\u524d\u9762\u7684\u52fe\u53ef\u7981\u7528mod\uff0c\u4e0d\u4f1a\u52a0\u8f7d\uff1b\u9009\u62e9mod\u53ef\u4ee5\u83b7\u53d6mod\u4fe1\u606f
+ advancedsettings=\u9ad8\u7ea7\u8bbe\u7f6e advancedsettings.launcher_visible=\u542f\u52a8\u5668\u53ef\u89c1\u6027 advancedsettings.run_directory=\u8fd0\u884c\u8def\u5f84 advencedsettings.debug_mode=\u8c03\u8bd5\u6a21\u5f0f -advancedsettings.java_permanent_generation_space=\u5185\u5b58\u6c38\u4e45\u4fdd\u5b58\u533a\u57df/MB +advancedsettings.java_permanent_generation_space=\u5185\u5b58\u6c38\u4e45\u4fdd\u5b58\u533a\u57df(\u4e0d\u5fc5\u586b\u5199,MB) advancedsettings.jvm_args=Java\u865a\u62df\u673a\u53c2\u6570(\u4e0d\u5fc5\u586b\u5199) advancedsettings.Minecraft_arguments=Minecraft\u989d\u5916\u53c2\u6570(\u4e0d\u5fc5\u586b\u5199) advancedsettings.launcher_visibility.close=\u6e38\u620f\u542f\u52a8\u540e\u7ed3\u675f\u542f\u52a8\u5668 @@ -222,14 +233,14 @@ launcher.download_source=\u4e0b\u8f7d\u6e90 launcher.background_location=\u80cc\u666f\u5730\u5740 launcher.exit_failed=\u5f3a\u5236\u9000\u51fa\u5931\u8d25\uff0c\u53ef\u80fd\u662fForge 1.7.10\u53ca\u66f4\u9ad8\u7248\u672c\u5bfc\u81f4\u7684\uff0c\u65e0\u6cd5\u89e3\u51b3\u3002 launcher.versions_json_not_matched=\u7248\u672c%s\u683c\u5f0f\u4e0d\u89c4\u8303\uff01\u8be5\u7248\u672c\u6587\u4ef6\u5939\u4e0b\u6709json:%s\uff0c\u662f\u5426\u66f4\u540d\u8fd9\u4e2a\u6587\u4ef6\u6765\u89c4\u8303\u683c\u5f0f\uff1f -launcher.versions_json_not_matched_needs_auto_completion=\u7248\u672c%s\u7f3a\u5931\u5fc5\u8981\u7684\u7248\u672c\u4fe1\u606f(JSON)\u6587\u4ef6\uff0c\u662f\u5426\u81ea\u52a8\u8865\u5168\uff1f -launcher.versions_json_not_matched_cannot_auto_completion=\u7248\u672c%s\u7f3a\u5931\u5fc5\u8981\u7684\u7248\u672c\u4fe1\u606f(JSON)\u6587\u4ef6\uff0c\u4f46\u662f\u4f3c\u4e4e\u4e0d\u662f\u539f\u7248\uff0c\u65e0\u6cd5\u81ea\u52a8\u8865\u5168\uff0c\u662f\u5426\u5220\u9664\u8be5\u7248\u672c\uff1f +launcher.versions_json_not_matched_cannot_auto_completion=\u7248\u672c%s\u7f3a\u5931\u5fc5\u8981\u7684\u7248\u672c\u4fe1\u606f\u6587\u4ef6\uff0c\u662f\u5426\u5220\u9664\u8be5\u7248\u672c\uff1f launcher.versions_json_not_formatted=\u7248\u672c%s\u4fe1\u606f\u6587\u4ef6\u683c\u5f0f\u9519\u8bef\uff0c\u662f\u5426\u91cd\u65b0\u4e0b\u8f7d\uff1f launcher.choose_bgpath=\u9009\u62e9\u80cc\u666f\u8def\u5f84 launcher.background_tooltip=\n\n\u542f\u52a8\u5668\u9ed8\u8ba4\u4f7f\u7528\u81ea\u5e26\u7684\u80cc\u666f
\n\u5982\u679c\u5f53\u524d\u76ee\u5f55\u6709background.png\uff0c\u5219\u4f1a\u4f7f\u7528\u8be5\u6587\u4ef6\u4f5c\u4e3a\u80cc\u666f
\n\u5982\u679c\u5f53\u524d\u76ee\u5f55\u6709bgskin\u5b50\u76ee\u5f55\uff0c\u5219\u4f1a\u968f\u673a\u4f7f\u7528\u91cc\u9762\u7684\u4e00\u5f20\u56fe\u4f5c\u4e3a\u80cc\u666f
\n\u5982\u679c\u8be5\u80cc\u666f\u5730\u5740\u88ab\u4fee\u6539\uff0c\u5219\u4f1a\u4f7f\u7528\u80cc\u666f\u5730\u5740\u91cc\u7684\u4e00\u5f20\u56fe\u4f5c\u4e3a\u80cc\u666f
\n\u80cc\u666f\u5730\u5740\u5141\u8bb8\u6709\u591a\u4e2a\u5730\u5740\uff0c\u4f7f\u7528\u534a\u89d2\u5206\u53f7";"(\u4e0d\u5305\u542b\u53cc\u5f15\u53f7)\u5206\u9694\n\n launcher.update_launcher=\u68c0\u67e5\u66f4\u65b0 launcher.enable_shadow=\u542f\u7528\u7a97\u53e3\u9634\u5f71(\u91cd\u542f\u542f\u52a8\u5668\u751f\u6548,\u53ef\u52a0\u5feb\u6e32\u67d3\u901f\u5ea6) launcher.theme=\u4e3b\u9898 +launcher.proxy=\u4ee3\u7406 launcher.title.game=\u6e38\u620f\u8bbe\u7f6e launcher.title.main=\u4e3b\u9875 @@ -299,4 +310,4 @@ color.blue=\u84dd\u8272 color.green=\u7eff\u8272 color.orange=\u6a59\u8272 color.dark_blue=\u6df1\u84dd\u8272 -color.purple=\u7d2b\u8272 \ No newline at end of file +color.purple=\u7d2b\u8272 diff --git a/HMCLAPI/src/main/resources/org/jackhuang/hellominecraft/launcher/I18N_zh_TW.properties b/HMCLAPI/src/main/resources/org/jackhuang/hellominecraft/launcher/I18N_zh_TW.properties index 97a9562b5..b4f16c67b 100644 --- a/HMCLAPI/src/main/resources/org/jackhuang/hellominecraft/launcher/I18N_zh_TW.properties +++ b/HMCLAPI/src/main/resources/org/jackhuang/hellominecraft/launcher/I18N_zh_TW.properties @@ -75,6 +75,11 @@ login.username=\u540d\u5b57 login.account=\u90ae\u7bb1 login.no_valid_character=\u7121\u6709\u6548\u7684\u89d2\u8272\uff0c\u81ea\u884c\u5230skinme.cc\u767b\u9678\u4e26\u5275\u5efa\u89d2\u8272 +proxy.username=\u8d26\u6236 +proxy.password=\u5bc6\u78bc +proxy.host=\u4e3b\u673a +proxy.port=\u7aef\u53e3 + login.failed.connect_authentication_server=\u7121\u6cd5\u9023\u63a5\u8a8d\u8b49\u670d\u52d9\u5668,\u53ef\u80fd\u662f\u7db2\u7d61\u554f\u984c login.profile.not_logged_in=\u7121\u6cd5\u4fee\u6539\u904a\u6232\u8cc7\u6599\u540c\u6642\u672a\u767b\u9304 @@ -190,9 +195,15 @@ settings.physical_memory=\u7269\u7406\u5185\u5b58\u5927\u5c0f settings.choose_javapath=\u9009\u62e9Java\u8def\u5f84 settings.default=\u9ed8\u8a8d settings.custom=\u81ea\u5b9a\u7fa9 +settings.choose_gamepath=\u9009\u62e9\u6e38\u620f\u8def\u5f84 settings.failed_load=\u8a2d\u5b9a\u6587\u4ef6\u52a0\u8f09\u5931\u6557\uff0c\u53ef\u80fd\u662f\u5347\u7d1a\u4e86\u555f\u52d5\u5668\u6216\u88ab\u4eba\u5de5\u4fee\u6539\u9020\u6210\u932f\u8aa4\uff0c\u662f\u5426\u6e05\u9664\uff1f +mods=Mod\u7ba1\u7406 +mods.choose_mod=\u9009\u62e9\u6a21\u7ec4 +mods.failed=\u6dfb\u52a0\u5931\u8d25 +mods.default_information=\u60a8\u53ef\u4ee5\u62d6\u52a8mod\u5230\u5217\u8868\u4e2d\u6765\u6dfb\u52a0mod\uff0c\u540c\u65f6\u4f7f\u7528\u5220\u9664\u952e\u53ef\u5feb\u901f\u5220\u9664\u9009\u4e2dmod
\u9009\u62e9mod\u53ef\u4ee5\u83b7\u53d6mod\u4fe1\u606f + advancedsettings=\u9ad8\u7d1a\u8a2d\u5b9a advancedsettings.launcher_visible=\u555f\u52d5\u5668\u53ef\u898b\u6027 advancedsettings.run_directory=\u904b\u884c\u8def\u5f91 @@ -222,13 +233,14 @@ launcher.download_source=\u4e0b\u8f09\u6e90 launcher.background_location=\u80cc\u666f\u5730\u5740 launcher.exit_failed=\u5f37\u5236\u9000\u51fa\u5931\u6557\uff0c\u53ef\u80fd\u662fForge 1.7.10\u53ca\u66f4\u9ad8\u7248\u672c\u5c0e\u81f4\u7684\uff0c\u7121\u6cd5\u89e3\u6c7a\u3002 launcher.versions_json_not_matched=\u7248\u672c%s\u683c\u5f0f\u4e0d\u898f\u7bc4\uff01\u8a72\u7248\u672c\u6587\u4ef6\u593e\u4e0b\u6709json:%s\uff0c\u662f\u5426\u66f4\u540d\u9019\u500b\u6587\u4ef6\u4f86\u898f\u7bc4\u683c\u5f0f\uff1f -launcher.versions_json_not_matched_needs_auto_completion=\u7248\u672c%s\u7f3a\u5931\u5fc5\u8981\u7684\u7248\u672c\u4fe1\u606f(JSON)\u6587\u4ef6\uff0c\u662f\u5426\u81ea\u52a8\u8865\u5168\uff1f -launcher.versions_json_not_matched_cannot_auto_completion=\u7248\u672c%s\u7f3a\u5931\u5fc5\u8981\u7684\u7248\u672c\u4fe1\u606f(JSON)\u6587\u4ef6\uff0c\u4f46\u662f\u4f3c\u4e4e\u4e0d\u662f\u539f\u7248\uff0c\u65e0\u6cd5\u81ea\u52a8\u8865\u5168\uff0c\u662f\u5426\u5220\u9664\u8be5\u7248\u672c\uff1f +launcher.versions_json_not_matched_cannot_auto_completion=\u7248\u672c%s\u7f3a\u5931\u5fc5\u8981\u7684\u7248\u672c\u4fe1\u606f\u6587\u4ef6\uff0c\u662f\u5426\u5220\u9664\u8be5\u7248\u672c\uff1f +launcher.versions_json_not_formatted=\u7248\u672c%s\u4fe1\u606f\u6587\u4ef6\u683c\u5f0f\u9519\u8bef\uff0c\u662f\u5426\u91cd\u65b0\u4e0b\u8f7d\uff1f launcher.choose_bgpath=\u9078\u64c7\u80cc\u666f\u8def\u5f91 launcher.background_tooltip=\n\n\u555f\u52d5\u5668\u9ed8\u8a8d\u4f7f\u7528\u81ea\u5e36\u7684\u80cc\u666f
\n\u5982\u679c\u7576\u524d\u76ee\u9304\u6709background.png\uff0c\u5247\u6703\u4f7f\u7528\u8a72\u6587\u4ef6\u4f5c\u70ba\u80cc\u666f
\n\u5982\u679c\u7576\u524d\u76ee\u9304\u6709bgskin\u5b50\u76ee\u9304\uff0c\u5247\u6703\u96a8\u6a5f\u4f7f\u7528\u88e1\u9762\u7684\u4e00\u5f35\u5716\u4f5c\u70ba\u80cc\u666f
\n\u5982\u679c\u8a72\u80cc\u666f\u5730\u5740\u88ab\u4fee\u6539\uff0c\u5247\u6703\u4f7f\u7528\u80cc\u666f\u5730\u5740\u88e1\u7684\u4e00\u5f35\u5716\u4f5c\u70ba\u80cc\u666f
\n\u80cc\u666f\u5730\u5740\u5141\u8a31\u6709\u591a\u500b\u5730\u5740\uff0c\u4f7f\u7528\u534a\u89d2\u5206\u865f";"(\u4e0d\u5305\u542b\u96d9\u5f15\u865f)\u5206\u9694\n\n launcher.update_launcher=\u68c0\u67e5\u66f4\u65b0 launcher.enable_shadow=\u542f\u7528\u7a97\u53e3\u9634\u5f71(\u91cd\u542f\u542f\u52a8\u5668\u751f\u6548) launcher.theme=\u4e3b\u9898 +launcher.proxy=\u4ee3\u7406 launcher.title.game=\u904a\u6232\u8a2d\u5b9a launcher.title.main=\u4e3b\u9801