Compare commits

..
Author SHA1 Message Date
huangyuhui 112a3b1a86 add api 2016-01-01 13:03:37 +08:00
huangyuhui f3dc605491 test 2016-01-01 12:58:45 +08:00
873 changed files with 48600 additions and 59622 deletions

No files matched your search

-17
View File
@@ -1,17 +0,0 @@
*.class
# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
hs_err_pid*
.gradle
.nb-gradle
*.log
.mine*
*.json
*.hmd
/HMCL/build/
/HMCLaF/build/
/HMCLAPI/build/
/HMCLCore/build/
-36
View File
@@ -1,36 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<gradle-project-properties>
<!--DO NOT EDIT THIS FILE! - Used by the Gradle plugin of NetBeans.-->
<target-platform-name>j2se</target-platform-name>
<target-platform>1.8</target-platform>
<source-level>1.8</source-level>
<common-tasks>
<task>
<display-name>launch4j</display-name>
<non-blocking>no</non-blocking>
<task-names>
<name must-exist="yes">launch4j</name>
</task-names>
<task-args/>
<task-jvm-args/>
</task>
<task>
<display-name>createApp</display-name>
<non-blocking>no</non-blocking>
<task-names>
<name must-exist="yes">createApp</name>
</task-names>
<task-args/>
<task-jvm-args/>
</task>
</common-tasks>
<script-platform>
<spec-name>j2se</spec-name>
<spec-version>1.8</spec-version>
</script-platform>
<license-header>
<name>GNU General Public License</name>
<template>license-header.txt</template>
<property name="organization">huangyuhui</property>
</license-header>
</gradle-project-properties>
-14
View File
@@ -1,14 +0,0 @@
language: java
jdk:
- oraclejdk8
branches:
only:
- master
before_install:
- chmod +x gradlew
script: "bash ./gradlew clean build --stacktrace"
before_cache:
- rm -f $HOME/.gradle/caches/modules-2/modules-2.lock
cache:
directories:
- "$HOME/.gradle/caches/"
Binary file not shown.
Binary file not shown.
-197
View File
@@ -1,197 +0,0 @@
/*
* Hello Minecraft! Launcher.
* Copyright (C) 2013 huangyuhui <huanghongxun2008@126.com>
*
* 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 3 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. If not, see {http://www.gnu.org/licenses/}.
*/
import java.util.jar.JarFile
import java.util.jar.Pack200
import java.util.zip.GZIPOutputStream
import java.security.MessageDigest
import java.util.jar.JarOutputStream
import java.util.zip.ZipEntry
import java.util.zip.ZipFile
plugins {
id "edu.sc.seis.macAppBundle" version "2.1.8"
id "me.tatarka.retrolambda" version "3.7.0"
id 'edu.sc.seis.launch4j' version '2.4.2'
//id "org.jetbrains.kotlin.jvm" version "1.1.2-2"
}
if (!hasProperty('mainClass')) {
ext.mainClass = 'org.jackhuang.hmcl.Main'
}
def buildnumber = System.getenv("TRAVIS_BUILD_NUMBER")
if (buildnumber == null)
buildnumber = System.getenv("BUILD_NUMBER")
if (buildnumber == null)
buildnumber = "60"
def versionroot = System.getenv("VERSION_ROOT")
if (versionroot == null)
versionroot = "2.7.10"
String mavenGroupId = 'HMCL'
String mavenVersion = versionroot + '.' + buildnumber
String bundleName = "Hello Minecraft! Launcher"
group = mavenGroupId
version = mavenVersion
String mavenArtifactId = name
task generateSources(type: Sync) {
from 'src/main/java'
into "$buildDir/generated-src"
filter(org.apache.tools.ant.filters.ReplaceTokens, tokens: [
'HELLO_MINECRAFT_LAUNCHER_VERSION_FOR_GRADLE_REPLACING': mavenVersion
])
}
compileJava.setSource "$buildDir/generated-src"
compileJava.dependsOn generateSources
configurations {
coreCompile.extendsFrom compile
coreRuntime.extendsFrom runtime
}
configure(install.repositories.mavenInstaller) {
pom.project {
groupId = mavenGroupId
artifactId = mavenArtifactId
version = mavenVersion
}
}
dependencies {
compile project(":HMCLaF")
compile project(":HMCLAPI")
compile project(":HMCLCore")
}
retrolambda {
javaVersion = JavaVersion.VERSION_1_7
}
jar {
from { configurations.compile.collect { it.isDirectory() ? it : zipTree(it) } }
manifest {
attributes 'Created-By' : 'Copyright(c) 2013-2017 huangyuhui.',
'Main-Class' : mainClass
}
doLast {
new File("build/signed").mkdirs()
ant.signjar(signedjar: archivePath, jar: archivePath,
keystore: "HMCL.keystore", storepass: "123456",
alias: "HMCL")
def messageDigest = MessageDigest.getInstance("SHA1")
archivePath.eachByte 1024 * 1024, { byte[] buf, int bytesRead ->
messageDigest.update(buf, 0, bytesRead);
}
def sha1Hex = new BigInteger(1, messageDigest.digest()).toString(16).padLeft(40, '0')
def fileEx = new File(project.buildDir, "libs/" + archivePath.getName() + ".sha1")
if (!fileEx.exists()) fileEx.createNewFile()
fileEx.append sha1Hex
}
}
launch4j {
supportUrl = 'http://www.mcbbs.net/thread-142335-1-1.html'
jreMinVersion = '1.7.0'
mainClassName = mainClass
icon = new File(project.buildDir, '../icon.ico').absolutePath
version = mavenVersion
downloadUrl = 'http://java.com/download'
copyright = "Copyright(c) 2013-2017 huangyuhui."
jar = new File(project.buildDir, 'libs/' + mavenGroupId + '-' + mavenVersion + '.jar').absolutePath
outfile = mavenGroupId + '-' + mavenVersion + '.exe'
messagesJreVersionError = 'This application requires a Java Runtime Environment installation, or the runtime is corrupted.\n\u6ca1\u6709\u627e\u5230\u004a\u0061\u0076\u0061\u8fd0\u884c\u65f6\uff0c\u8bf7\u4e0d\u8981\u4f7f\u7528\u7eff\u8272\u004a\u0061\u0076\u0061\uff0c\u8bf7\u4f7f\u7528\u5b89\u88c5\u7248\u7684\u004a\u0061\u0076\u0061\uff0c\u70b9\u51fb\u786e\u5b9a\u8fdb\u5165\u004a\u0061\u0076\u0061\u5b89\u88c5\u9875\u9762\u3002'
}
processResources {
from(sourceSets.main.resources.srcDirs) {
exclude 'icon.icns'
}
}
task makeExecutable(dependsOn: jar) doLast {
ext {
jar.classifier = ''
makeExecutableinjar = jar.archivePath
jar.classifier = ''
makeExecutableoutjar = jar.archivePath
jar.classifier = ''
}
def loc = new File(project.buildDir, "libs/" + makeExecutableoutjar.getName().substring(0, makeExecutableoutjar.getName().length()-4)+".exe")
def fos = new FileOutputStream(loc)
def is = new FileInputStream(new File(project.buildDir, '../HMCLauncher.exe'))
int read
def bytes = new byte[8192]
while((read = is.read(bytes)) != -1)
fos.write(bytes, 0, read);
is.close()
is = new FileInputStream(makeExecutableinjar)
while((read = is.read(bytes)) != -1)
fos.write(bytes, 0, read);
is.close()
fos.close()
}
task makePackGZ(dependsOn: jar) doLast {
ext {
jar.classifier = ''
makeExecutableinjar = jar.archivePath
jar.classifier = ''
makeExecutableoutjar = jar.archivePath
jar.classifier = ''
}
def loc = new File(project.buildDir, "libs/" + makeExecutableoutjar.getName().substring(0, makeExecutableoutjar.getName().length()-4)+".pack.gz")
def os = new GZIPOutputStream(new FileOutputStream(loc))
Pack200.newPacker().pack new JarFile(makeExecutableinjar), os
os.close()
def messageDigest = MessageDigest.getInstance("SHA1")
loc.eachByte 1024 * 1024, { byte[] buf, int bytesRead ->
messageDigest.update(buf, 0, bytesRead);
}
def sha1Hex = new BigInteger(1, messageDigest.digest()).toString(16).padLeft(40, '0')
def fileEx = new File(project.buildDir, "libs/" + makeExecutableoutjar.getName().substring(0, makeExecutableoutjar.getName().length()-4)+".pack.gz.sha1")
if (!fileEx.exists()) fileEx.createNewFile()
fileEx.append sha1Hex
}
task macAppCompressed(type: Zip, dependsOn: createApp) doLast {
archiveName "HMCL-$mavenVersion-MacOSApp.zip"
include '**'
destinationDir file("$buildDir/libs/")
from "$buildDir/macApp"
}
macAppBundle {
mainClassName = mainClass
icon = "src/main/icon.icns"
javaProperties.put("apple.laf.useScreenMenuBar", "true")
}
build.dependsOn makeExecutable
build.dependsOn makePackGZ
build.dependsOn macAppCompressed
BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 35 KiB

File renamed without changes.

Before

Width:  |  Height:  |  Size: 5.2 KiB

After

Width:  |  Height:  |  Size: 5.2 KiB

Binary file not shown.
@@ -1,251 +0,0 @@
/*
* Hello Minecraft! Launcher.
* Copyright (C) 2013 huangyuhui <huanghongxun2008@126.com>
*
* 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 3 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. If not, see {http://www.gnu.org/licenses/}.
*/
package org.jackhuang.hmcl;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.Authenticator;
import java.net.PasswordAuthentication;
import java.net.Proxy;
import java.security.GeneralSecurityException;
import java.security.cert.X509Certificate;
import java.util.Arrays;
import java.util.Locale;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.X509TrustManager;
import javax.swing.ImageIcon;
import javax.swing.JOptionPane;
import javax.swing.RepaintManager;
import org.jackhuang.hmcl.api.HMCLApi;
import org.jackhuang.hmcl.api.HMCLog;
import org.jackhuang.hmcl.api.ILogger;
import org.jackhuang.hmcl.api.PluginManager;
import org.jackhuang.hmcl.api.VersionNumber;
import org.jackhuang.hmcl.core.MCUtils;
import org.jackhuang.hmcl.setting.Settings;
import org.jackhuang.hmcl.ui.LogWindow;
import org.jackhuang.hmcl.ui.MainFrame;
import org.jackhuang.hmcl.util.CrashReporter;
import org.jackhuang.hmcl.util.DefaultPlugin;
import org.jackhuang.hmcl.util.ui.MessageBox;
import org.jackhuang.hmcl.util.StrUtils;
import org.jackhuang.hmcl.util.lang.SupportedLocales;
import org.jackhuang.hmcl.util.log.Configuration;
import org.jackhuang.hmcl.util.log.appender.ConsoleAppender;
import org.jackhuang.hmcl.util.log.layout.DefaultLayout;
import org.jackhuang.hmcl.util.ui.MyRepaintManager;
import org.jackhuang.hmcl.util.upgrade.IUpgrader;
import org.jackhuang.hmcl.laf.BeautyEyeLNFHelper;
/**
*
* @author huangyuhui
*/
public final class Main {
private static final X509TrustManager XTM = new X509TrustManager() {
@Override
public void checkClientTrusted(X509Certificate[] chain, String authType) {
}
@Override
public void checkServerTrusted(X509Certificate[] chain, String authType) {
}
@Override
public X509Certificate[] getAcceptedIssuers() {
return new X509Certificate[0];
}
};
private static final HostnameVerifier HNV = (hostname, session) -> true;
public static final String LAUNCHER_NAME = "Hello Minecraft! Launcher";
public static final String LAUNCHER_VERSION = "@HELLO_MINECRAFT_LAUNCHER_VERSION_FOR_GRADLE_REPLACING@";
public static final int MINIMUM_LAUNCHER_VERSION = 16;
/**
* Make the main window title.
*
* @return the MainWindow title.
*/
public static String makeTitle() {
return LAUNCHER_NAME + ' ' + LAUNCHER_VERSION;
}
public static String shortTitle() {
return "HMCL" + ' ' + LAUNCHER_VERSION;
}
public static final Logger LOGGER = Logger.getLogger(Main.class.getName());
public static void main(String[] args) throws IOException {
{
if (new File("").getAbsolutePath().contains("!")) {
MessageBox.show("HMCL cannot run at such path that contains '!'");
return;
}
try {
File file = new File("hmcl.log").getAbsoluteFile();
if (!file.exists() && !file.createNewFile())
LOGGER.log(Level.WARNING, "Failed to create log file {0}", file);
Configuration.DEFAULT.appenders.add(new ConsoleAppender("File", new DefaultLayout(), true, new FileOutputStream(file), true));
} catch (IOException ex) {
LOGGER.log(Level.SEVERE, "Failed to add log appender File because an error occurred while creating or opening hmcl.log", ex);
}
org.jackhuang.hmcl.util.log.logger.Logger logger = new org.jackhuang.hmcl.util.log.logger.Logger("HMCL");
HMCLog.LOGGER = new ILogger() {
@Override
public void log(String msg) {
logger.info(msg);
}
@Override
public void warn(String msg) {
logger.warn(msg);
}
@Override
public void warn(String msg, Throwable t) {
logger.warn(msg, t);
}
@Override
public void err(String msg) {
logger.error(msg);
}
@Override
public void err(String msg, Throwable t) {
logger.error(msg, t);
}
};
HMCLApi.HMCL_VERSION = VersionNumber.asVersion(LAUNCHER_VERSION);
PluginManager.getPlugin(DefaultPlugin.class);
for (String s : args)
if (s.startsWith("--plugin=")) {
String c = s.substring("--plugin=".length());
try {
PluginManager.getPlugin(Class.forName(c));
} catch (ClassNotFoundException ex) {
HMCLog.warn("Class: " + c + " not found, please add your plugin jar to class path.", ex);
}
} else if (s.startsWith("--help")) {
System.out.println("HMCL command line help");
System.out.println("--noupdate: this arg will prevent HMCL from initializing the newest app version in %appdata%/.hmcl");
System.out.println("--plugin=<your plugin class>: this arg will allow a new plugin to be loaded, please keep your jar in system class path and this class extends IPlugin.");
return;
}
PluginManager.loadPlugins();
IUpgrader.NOW_UPGRADER.parseArguments(HMCLApi.HMCL_VERSION, Arrays.asList(args));
System.setProperty("awt.useSystemAAFontSettings", "on");
System.setProperty("swing.aatext", "true");
System.setProperty("sun.java2d.noddraw", "true");
System.setProperty("sun.java2d.dpiaware", "false");
System.setProperty("https.protocols", "SSLv3,TLSv1");
try {
SSLContext c = SSLContext.getInstance("SSL");
c.init(null, new X509TrustManager[] { XTM }, new java.security.SecureRandom());
HttpsURLConnection.setDefaultSSLSocketFactory(c.getSocketFactory());
} catch (GeneralSecurityException ignore) {
}
HttpsURLConnection.setDefaultHostnameVerifier(HNV);
Thread.setDefaultUncaughtExceptionHandler(new CrashReporter(true));
HMCLog.log("*** " + Main.makeTitle() + " ***");
String s = Settings.getInstance().getLocalization();
for (SupportedLocales sl : SupportedLocales.values())
if (sl.name().equals(s)) {
SupportedLocales.setNowLocale(sl);
Locale.setDefault(sl.self);
JOptionPane.setDefaultLocale(sl.self);
}
if (System.getProperty("java.vm.name").contains("Open")) // OpenJDK
MessageBox.showLocalized("ui.message.open_jdk");
try {
BeautyEyeLNFHelper.launchBeautyEyeLNF();
RepaintManager.setCurrentManager(new MyRepaintManager());
} catch (Exception ex) {
HMCLog.warn("Failed to set look and feel...", ex);
}
LogWindow.INSTANCE.clean();
Settings.UPDATE_CHECKER.upgrade.register(IUpgrader.NOW_UPGRADER);
Settings.UPDATE_CHECKER.process(false).reg(t -> Main.invokeUpdate()).execute();
if (Settings.getInstance().getProxyType() != Proxy.Type.DIRECT && StrUtils.isNotBlank(Settings.getInstance().getProxyHost())) {
switch (Settings.getInstance().getProxyType()) {
case DIRECT:
break;
case HTTP:
System.setProperty("http.proxyHost", Settings.getInstance().getProxyHost());
if (StrUtils.isNotBlank(Settings.getInstance().getProxyPort()))
System.setProperty("http.proxyPort", Settings.getInstance().getProxyPort());
HMCLog.log("Initialized HTTP proxy.");
break;
case SOCKS:
System.setProperty("socksProxyHost", Settings.getInstance().getProxyHost());
if (StrUtils.isNotBlank(Settings.getInstance().getProxyPort()))
System.setProperty("socksProxyPort", Settings.getInstance().getProxyPort());
HMCLog.log("Initialized Socks v4/v5 proxy.");
break;
}
if (StrUtils.isNotBlank(Settings.getInstance().getProxyUserName()) && StrUtils.isNotBlank(Settings.getInstance().getProxyPassword()))
Authenticator.setDefault(new Authenticator() {
@Override
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(Settings.getInstance().getProxyUserName(), Settings.getInstance().getProxyPassword().toCharArray());
}
});
}
MainFrame.showMainFrame();
}
}
public static void invokeUpdate() {
MainFrame.INSTANCE.invokeUpdate();
}
public static ImageIcon getIcon(String path) {
try {
return new ImageIcon(Main.class.getResource("/org/jackhuang/hmcl/" + path));
} catch (Exception e) {
HMCLog.err("Failed to load icon", e);
return null;
}
}
}
@@ -1,37 +0,0 @@
/*
* Hello Minecraft! Launcher.
* Copyright (C) 2013 huangyuhui <huanghongxun2008@126.com>
*
* 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 3 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. If not, see {http://www.gnu.org/licenses/}.
*/
package org.jackhuang.hmcl.api.event.config;
import org.jackhuang.hmcl.api.event.SimpleEvent;
import org.jackhuang.hmcl.setting.Profile;
/**
* This event gets fired when the selected profile changed.
* <br>
* This event is fired on the {@link org.jackhuang.hmcl.api.HMCLApi#EVENT_BUS}
* @param source {@link org.jackhuang.hmcl.setting.Settings}
* @param Profile the new profile.
* @author huangyuhui
*/
public class ProfileChangedEvent extends SimpleEvent<Profile> {
public ProfileChangedEvent(Object source, Profile value) {
super(source, value);
}
}
@@ -1,35 +0,0 @@
/*
* Hello Minecraft! Launcher.
* Copyright (C) 2013 huangyuhui <huanghongxun2008@126.com>
*
* 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 3 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. If not, see {http://www.gnu.org/licenses/}.
*/
package org.jackhuang.hmcl.api.event.config;
import java.util.EventObject;
/**
* This event gets fired when loading profiles.
* <br>
* This event is fired on the {@link org.jackhuang.hmcl.api.HMCLApi#EVENT_BUS}
* @param source {@link org.jackhuang.hmcl.setting.Settings}
* @author huangyuhui
*/
public class ProfileLoadingEvent extends EventObject {
public ProfileLoadingEvent(Object source) {
super(source);
}
}
@@ -1,358 +0,0 @@
/*
* Hello Minecraft! Launcher.
* Copyright (C) 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 3 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. If not, see {http://www.gnu.org/licenses/}.
*/
package org.jackhuang.hmcl.setting;
import org.jackhuang.hmcl.core.download.DownloadType;
import com.google.gson.annotations.SerializedName;
import java.awt.Font;
import java.net.Proxy;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import java.util.UUID;
import org.jackhuang.hmcl.core.auth.AbstractAuthenticator;
import org.jackhuang.hmcl.laf.LAFTheme;
import org.jackhuang.hmcl.api.HMCLApi;
import org.jackhuang.hmcl.api.event.config.AuthenticatorChangedEvent;
import org.jackhuang.hmcl.api.event.config.DownloadTypeChangedEvent;
import org.jackhuang.hmcl.api.event.config.ThemeChangedEvent;
import org.jackhuang.hmcl.core.MCUtils;
import org.jackhuang.hmcl.util.sys.JdkVersion;
import org.jackhuang.hmcl.util.sys.OS;
import org.jackhuang.hmcl.api.auth.IAuthenticator;
import org.jackhuang.hmcl.api.ui.Theme;
/**
*
* @author huangyuhui
*/
public final class Config implements Cloneable {
@SerializedName("last")
private String last;
@SerializedName("bgpath")
private String bgpath;
@SerializedName("commonpath")
private String commonpath;
@SerializedName("clientToken")
private final String clientToken;
@SerializedName("proxyHost")
private String proxyHost;
@SerializedName("proxyPort")
private String proxyPort;
@SerializedName("proxyUserName")
private String proxyUserName;
@SerializedName("proxyPassword")
private String proxyPassword;
@SerializedName("proxyType")
private int proxyType;
@SerializedName("enableShadow")
private boolean enableShadow;
@SerializedName("enableBlur")
private boolean enableBlur;
@SerializedName("enableAnimation")
private boolean enableAnimation;
@SerializedName("decorated")
private boolean decorated;
@SerializedName("theme")
private String theme;
@SerializedName("java")
private List<JdkVersion> java;
@SerializedName("localization")
private String localization;
@SerializedName("logintype")
private int logintype;
@SerializedName("downloadtype")
private int downloadtype;
@SerializedName("configurations")
private TreeMap<String, Profile> configurations;
@SerializedName("auth")
private Map<String, Map> auth;
@SerializedName("fontFamily")
private String fontFamily;
@SerializedName("fontSize")
private int fontSize;
@SerializedName("logLines")
private int logLines;
public Config() {
clientToken = UUID.randomUUID().toString();
proxyType = logintype = downloadtype = 0;
logLines = 100;
enableAnimation = enableBlur = true;
if (OS.os() == OS.WINDOWS)
enableShadow = true;
theme = LAFTheme.BLUE.id;
decorated = OS.os() == OS.LINUX;
auth = new HashMap<>();
Font font = Font.decode("Consolas");
if (font == null)
font = Font.decode("Monospace");
if (font != null)
fontFamily = font.getFamily();
fontSize = 12;
commonpath = MCUtils.getLocation().getPath();
}
public List<JdkVersion> getJava() {
return java == null ? java = new ArrayList<>() : java;
}
public Theme getTheme() {
if (!Theme.THEMES.containsKey(theme))
theme = LAFTheme.BLUE.id;
return Theme.THEMES.get(theme);
}
public void setTheme(String theme) {
this.theme = theme;
HMCLApi.EVENT_BUS.fireChannel(new ThemeChangedEvent(this, getTheme()));
Settings.save();
}
public boolean isDecorated() {
return decorated;
}
public void setDecorated(boolean decorated) {
this.decorated = decorated;
}
public boolean isEnableShadow() {
return enableShadow && OS.os() == OS.WINDOWS;
}
public void setEnableShadow(boolean enableShadow) {
this.enableShadow = enableShadow;
Settings.save();
}
public boolean isEnableAnimation() {
return enableAnimation;
}
public void setEnableAnimation(boolean enableAnimation) {
this.enableAnimation = enableAnimation;
Settings.save();
}
public boolean isEnableBlur() {
return enableBlur;
}
public void setEnableBlur(boolean enableBlur) {
this.enableBlur = enableBlur;
Settings.save();
}
/**
* Last selected profile name.
*/
public String getLast() {
if (last == null)
last = Settings.DEFAULT_PROFILE;
return last;
}
public void setLast(String last) {
this.last = last;
Settings.onProfileChanged();
Settings.save();
}
public String getBgpath() {
return bgpath;
}
public void setBgpath(String bgpath) {
this.bgpath = bgpath;
Settings.save();
}
public String getCommonpath() {
return commonpath;
}
public void setCommonpath(String commonpath) {
this.commonpath = commonpath;
Settings.save();
}
public String getClientToken() {
return clientToken;
}
public IAuthenticator getAuthenticator() {
return AbstractAuthenticator.LOGINS.get(getLoginType());
}
public int getLoginType() {
if (logintype < 0 || logintype >= AbstractAuthenticator.LOGINS.size())
logintype = 0;
return logintype;
}
public void setLoginType(int logintype) {
if (logintype < 0 || logintype >= AbstractAuthenticator.LOGINS.size())
return;
this.logintype = logintype;
HMCLApi.EVENT_BUS.fireChannel(new AuthenticatorChangedEvent(this, AbstractAuthenticator.LOGINS.get(logintype)));
Settings.save();
}
public int getDownloadType() {
return downloadtype;
}
public void setDownloadType(int downloadtype) {
this.downloadtype = downloadtype;
HMCLApi.EVENT_BUS.fireChannel(new DownloadTypeChangedEvent(this, getDownloadSource().name()));
Settings.save();
}
public TreeMap<String, Profile> getConfigurations() {
if (configurations == null)
configurations = new TreeMap<>();
if (configurations.isEmpty()) {
Profile profile = new Profile();
configurations.put(profile.getName(), profile);
}
return configurations;
}
public Map getAuthenticatorConfig(String authId) {
return auth.get(authId);
}
public void setAuthenticatorConfig(String authId, Map map) {
auth.put(authId, map);
Settings.save();
}
public DownloadType getDownloadSource() {
if (downloadtype >= DownloadType.values().length || downloadtype < 0) {
downloadtype = 0;
Settings.save();
}
return DownloadType.values()[downloadtype];
}
public String getProxyHost() {
return proxyHost == null ? "" : proxyHost;
}
public void setProxyHost(String proxyHost) {
this.proxyHost = proxyHost;
Settings.save();
}
public String getProxyPort() {
return proxyPort == null ? "" : proxyPort;
}
public void setProxyPort(String proxyPort) {
this.proxyPort = proxyPort;
Settings.save();
}
public Proxy.Type getProxyType() {
if (proxyType < 0 || proxyType >= 3) {
proxyType = 0;
Settings.save();
}
return Proxy.Type.values()[proxyType];
}
public void setProxyType(Proxy.Type proxyType) {
this.proxyType = proxyType.ordinal();
Settings.save();
}
public String getProxyUserName() {
return proxyUserName == null ? "" : proxyUserName;
}
public void setProxyUserName(String proxyUserName) {
this.proxyUserName = proxyUserName;
Settings.save();
}
public String getProxyPassword() {
return proxyPassword == null ? "" : proxyPassword;
}
public void setProxyPassword(String proxyPassword) {
this.proxyPassword = proxyPassword;
Settings.save();
}
public int getFontSize() {
return fontSize;
}
public void setFontSize(int fontSize) {
this.fontSize = fontSize;
Settings.save();
}
public Font getConsoleFont() {
return Font.decode(fontFamily + "-" + fontSize);
}
public String getFontFamily() {
return Font.decode(fontFamily).getFamily();
}
public void setFontFamily(String fontFamily) {
this.fontFamily = Font.decode(fontFamily).getFamily(); // avoid invalid font family
Settings.save();
}
public String getLocalization() {
return localization;
}
public void setLocalization(String localization) {
this.localization = localization;
Settings.save();
}
public int getLogLines() {
if (logLines == 100 || logLines == 1000 || logLines == 5000)
return logLines;
else
return logLines = 100;
}
public void setLogLines(int logLines) {
this.logLines = logLines;
Settings.save();
}
@Override
public Object clone() {
try {
return super.clone();
} catch (CloneNotSupportedException e) {
throw new Error(e);
}
}
}
@@ -1,182 +0,0 @@
/*
* Hello Minecraft! Launcher.
* Copyright (C) 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 3 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. If not, see {http://www.gnu.org/licenses/}.
*/
package org.jackhuang.hmcl.setting;
import org.jackhuang.hmcl.core.service.IProfile;
import com.google.gson.annotations.SerializedName;
import org.jackhuang.hmcl.util.HMCLGameLauncher;
import org.jackhuang.hmcl.util.HMCLMinecraftService;
import java.io.File;
import org.jackhuang.hmcl.core.MCUtils;
import org.jackhuang.hmcl.core.version.MinecraftVersion;
import org.jackhuang.hmcl.util.StrUtils;
import org.jackhuang.hmcl.api.event.EventHandler;
import org.jackhuang.hmcl.api.event.PropertyChangedEvent;
/**
*
* @author huangyuhui
*/
public final class Profile implements IProfile {
@SerializedName("selectedMinecraftVersion")
private String selectedVersion = "";
@SerializedName("gameDir")
private String gameDir;
@SerializedName("noCommon")
private boolean noCommon;
@SerializedName("global")
private VersionSetting global;
private transient String name;
private transient HMCLMinecraftService service = new HMCLMinecraftService(this);
private transient HMCLGameLauncher launcher = new HMCLGameLauncher(this);
public transient final EventHandler<PropertyChangedEvent<String>> propertyChanged = new EventHandler<>();
public Profile() {
this("Default");
}
public Profile(String name) {
this(name, ".minecraft");
}
public Profile(String name, String gameDir) {
this.name = name;
this.gameDir = gameDir;
this.global = new VersionSetting();
}
public Profile(String name, Profile v) {
this();
if (v == null)
return;
this.name = name;
gameDir = v.gameDir;
}
@Override
public HMCLMinecraftService service() {
return service;
}
public HMCLGameLauncher launcher() {
return launcher;
}
public VersionSetting getSelectedVersionSetting() {
return getVersionSetting(getSelectedVersion());
}
public VersionSetting getVersionSetting(String id) {
VersionSetting vs = service().getVersionSetting(id);
if (vs == null || vs.isUsesGlobal()) {
global.isGlobal = true;
global.id = id;
return global;
} else
return vs;
}
public boolean isVersionSettingGlobe(String id) {
VersionSetting vs = service().getVersionSetting(id);
return vs == null || vs.isUsesGlobal();
}
public void makeVersionSettingSpecial(String id) {
VersionSetting vs = service().getVersionSetting(id);
if (vs == null) {
service().createVersionSetting(id);
vs = service().getVersionSetting(id);
if (vs == null)
return;
vs.setUsesGlobal(false);
} else
vs.setUsesGlobal(false);
propertyChanged.fire(new PropertyChangedEvent<>(this, "selectedVersion", selectedVersion, selectedVersion));
}
public void makeVersionSettingGlobal(String id) {
VersionSetting vs = service().getVersionSetting(id);
if (vs == null)
return;
vs.setUsesGlobal(true);
propertyChanged.fire(new PropertyChangedEvent<>(this, "selectedVersion", selectedVersion, selectedVersion));
}
@Override
public String getSelectedVersion() {
String v = selectedVersion;
if (StrUtils.isBlank(v) || service().version().getVersionById(v) == null || service().version().getVersionById(v).hidden) {
MinecraftVersion mv = service().version().getOneVersion(t -> !t.hidden);
if (mv != null)
v = mv.id;
if (StrUtils.isNotBlank(v))
setSelectedVersion(v);
}
return StrUtils.isBlank(v) ? null : v;
}
@Override
public void setSelectedVersion(String newVersion) {
PropertyChangedEvent event = new PropertyChangedEvent<>(this, "selectedVersion", this.selectedVersion, newVersion);
this.selectedVersion = newVersion;
propertyChanged.fire(event);
}
@Override
public File getGameDir() {
if (StrUtils.isBlank(gameDir))
gameDir = MCUtils.getInitGameDir().getPath();
return new File(gameDir.replace('\\', '/'));
}
@Override
public void setGameDir(File gameDir) {
PropertyChangedEvent event = new PropertyChangedEvent<>(this, "gameDir", this.gameDir, gameDir);
this.gameDir = gameDir.getPath();
service().version().refreshVersions();
propertyChanged.fire(event);
}
public boolean isNoCommon() {
return noCommon;
}
public void setNoCommon(boolean noCommon) {
PropertyChangedEvent event = new PropertyChangedEvent(this, "noCommon", this.noCommon, noCommon);
this.noCommon = noCommon;
propertyChanged.fire(event);
}
@Override
public String getName() {
return name;
}
void setName(String name) {
PropertyChangedEvent event = new PropertyChangedEvent<>(this, "name", this.name, name);
this.name = name;
propertyChanged.fire(event);
}
@Override
public void onSelected() {
service().version().refreshVersions();
}
}
@@ -1,172 +0,0 @@
/*
* Hello Minecraft! Launcher.
* Copyright (C) 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 3 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. If not, see {http://www.gnu.org/licenses/}.
*/
package org.jackhuang.hmcl.setting;
import com.google.gson.JsonSyntaxException;
import java.io.File;
import java.io.IOException;
import java.util.Collection;
import java.util.Map;
import org.jackhuang.hmcl.util.C;
import org.jackhuang.hmcl.api.HMCLog;
import org.jackhuang.hmcl.core.MCUtils;
import org.jackhuang.hmcl.core.download.DownloadType;
import org.jackhuang.hmcl.util.CollectionUtils;
import org.jackhuang.hmcl.api.HMCLApi;
import org.jackhuang.hmcl.api.event.config.ProfileChangedEvent;
import org.jackhuang.hmcl.api.event.config.ProfileLoadingEvent;
import org.jackhuang.hmcl.laf.utils.AnimationController;
import org.jackhuang.hmcl.util.sys.FileUtils;
import org.jackhuang.hmcl.util.ui.MessageBox;
import org.jackhuang.hmcl.util.upgrade.UpdateChecker;
import org.jackhuang.hmcl.util.sys.IOUtils;
/**
*
* @author huangyuhui
*/
public final class Settings {
public static final String DEFAULT_PROFILE = "Default";
public static final String HOME_PROFILE = "Home";
public static final File SETTINGS_FILE = new File("hmcl.json").getAbsoluteFile();
private static final Config SETTINGS;
public static final UpdateChecker UPDATE_CHECKER = new UpdateChecker(HMCLApi.HMCL_VERSION, "hmcl");
public static Config getInstance() {
return SETTINGS;
}
static {
SETTINGS = initSettings();
DownloadType.setSuggestedDownloadType(SETTINGS.getDownloadSource().name());
AnimationController.ENABLE_ANIMATION = SETTINGS.isEnableAnimation();
if (!getProfiles().containsKey(DEFAULT_PROFILE))
getProfiles().put(DEFAULT_PROFILE, new Profile(DEFAULT_PROFILE));
for (Map.Entry<String, Profile> entry : getProfiles().entrySet()) {
Profile e = entry.getValue();
e.setName(entry.getKey());
e.propertyChanged.register(Settings::save);
}
}
private static Config initSettings() {
Config c = new Config();
if (SETTINGS_FILE.exists())
try {
String str = FileUtils.read(SETTINGS_FILE, IOUtils.DEFAULT_CHARSET);
if (str == null || str.trim().equals(""))
HMCLog.log("Settings file is empty, use the default settings.");
else {
Config d = C.GSON.fromJson(str, Config.class);
if (d != null)
c = d;
}
HMCLog.log("Initialized settings.");
} catch (IOException | JsonSyntaxException e) {
HMCLog.warn("Something happened wrongly when load settings.", e);
}
else {
HMCLog.log("No settings file here, may be first loading.");
if (!c.getConfigurations().containsKey(HOME_PROFILE))
c.getConfigurations().put(HOME_PROFILE, new Profile(HOME_PROFILE, MCUtils.getLocation().getPath()));
}
return c;
}
public static void save() {
try {
FileUtils.write(SETTINGS_FILE, C.GSON.toJson(SETTINGS), IOUtils.DEFAULT_CHARSET);
} catch (IOException ex) {
HMCLog.err("Failed to save config", ex);
}
}
public static Profile getLastProfile() {
if (!hasProfile(getInstance().getLast()))
getInstance().setLast(DEFAULT_PROFILE);
return getProfile(getInstance().getLast());
}
public static Profile getProfile(String name) {
if (name == null)
name = DEFAULT_PROFILE;
Profile p = getProfiles().get(name);
if (p == null)
if (getProfiles().containsKey(DEFAULT_PROFILE))
p = getProfiles().get(DEFAULT_PROFILE);
else
getProfiles().put(DEFAULT_PROFILE, p = new Profile());
return p;
}
public static boolean hasProfile(String name) {
if (name == null)
name = DEFAULT_PROFILE;
return getProfiles().containsKey(name);
}
public static Map<String, Profile> getProfiles() {
return SETTINGS.getConfigurations();
}
public static Collection<Profile> getProfilesFiltered() {
return CollectionUtils.filter(getProfiles().values(), t -> t != null && t.getName() != null);
}
public static boolean putProfile(Profile ver) {
if (ver == null || ver.getName() == null || getProfiles().containsKey(ver.getName()))
return false;
getProfiles().put(ver.getName(), ver);
return true;
}
public static boolean delProfile(Profile ver) {
return delProfile(ver.getName());
}
public static boolean delProfile(String ver) {
if (DEFAULT_PROFILE.equals(ver)) {
MessageBox.show(C.i18n("settings.cannot_remove_default_config"));
return false;
}
boolean notify = false;
if (getLastProfile().getName().equals(ver))
notify = true;
boolean flag = getProfiles().remove(ver) != null;
if (notify && flag)
onProfileChanged();
return flag;
}
static void onProfileChanged() {
Profile p = getLastProfile();
if (p == null)
throw new Error("No profiles here, it should not happen");
HMCLApi.EVENT_BUS.fireChannel(new ProfileChangedEvent(SETTINGS, p));
p.onSelected();
}
public static void onProfileLoading() {
HMCLApi.EVENT_BUS.fireChannel(new ProfileLoadingEvent(SETTINGS));
onProfileChanged();
}
}
@@ -1,341 +0,0 @@
/*
* Hello Minecraft! Launcher.
* Copyright (C) 2013 huangyuhui <huanghongxun2008@126.com>
*
* 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 3 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. If not, see {http://www.gnu.org/licenses/}.
*/
package org.jackhuang.hmcl.setting;
import com.google.gson.annotations.SerializedName;
import java.io.File;
import org.jackhuang.hmcl.Main;
import org.jackhuang.hmcl.util.LauncherVisibility;
import org.jackhuang.hmcl.api.game.LaunchOptions;
import org.jackhuang.hmcl.api.game.GameDirType;
import org.jackhuang.hmcl.util.C;
import org.jackhuang.hmcl.api.event.EventHandler;
import org.jackhuang.hmcl.api.event.PropertyChangedEvent;
import org.jackhuang.hmcl.util.StrUtils;
import org.jackhuang.hmcl.api.HMCLog;
import org.jackhuang.hmcl.util.sys.Java;
import org.jackhuang.hmcl.util.sys.OS;
/**
*
* @author huangyuhui
*/
public class VersionSetting {
public transient String id;
public transient boolean isGlobal = false;
@SerializedName("usesGlobal")
private boolean usesGlobal;
@SerializedName("javaArgs")
private String javaArgs;
@SerializedName("minecraftArgs")
private String minecraftArgs;
@SerializedName("maxMemory")
private String maxMemory;
@SerializedName("permSize")
private String permSize;
@SerializedName("width")
private String width;
@SerializedName("height")
private String height;
@SerializedName("javaDir")
private String javaDir;
@SerializedName("precalledCommand")
private String precalledCommand;
@SerializedName("serverIp")
private String serverIp;
@SerializedName("java")
private String java;
@SerializedName("wrapper")
private String wrapper;
@SerializedName("fullscreen")
private boolean fullscreen;
@SerializedName("noJVMArgs")
private boolean noJVMArgs;
@SerializedName("notCheckGame")
private boolean notCheckGame;
/**
* 0 - Close the launcher when the game starts.<br/>
* 1 - Hide the launcher when the game starts.<br/>
* 2 - Keep the launcher open.<br/>
*/
@SerializedName("launcherVisibility")
private int launcherVisibility;
/**
* 0 - .minecraft<br/>
* 1 - .minecraft/versions/&lt;version&gt;/<br/>
*/
@SerializedName("gameDirType")
private int gameDirType;
public transient final EventHandler<PropertyChangedEvent> propertyChanged = new EventHandler<>();
public VersionSetting() {
fullscreen = usesGlobal = false;
launcherVisibility = 1;
gameDirType = 0;
javaDir = java = minecraftArgs = serverIp = precalledCommand = wrapper = "";
}
public String getJavaDir() {
Java j = getJava();
if (j.getHome() == null)
return javaDir;
else
return j.getJava();
}
public String getSettingsJavaDir() {
return javaDir;
}
public File getJavaDirFile() {
return new File(getJavaDir());
}
public void setJavaDir(String javaDir) {
PropertyChangedEvent event = new PropertyChangedEvent(this, "javaDir", this.javaDir, javaDir);
this.javaDir = javaDir;
propertyChanged.fire(event);
}
public Java getJava() {
return Java.JAVA.get(getJavaIndexInAllJavas());
}
public int getJavaIndexInAllJavas() {
if (StrUtils.isBlank(java) && StrUtils.isNotBlank(javaDir))
java = "Custom";
int idx = Java.JAVA.indexOf(new Java(java, null));
if (idx == -1) {
java = Java.suggestedJava().getName();
idx = 0;
}
return idx;
}
public void setJava(Java java) {
PropertyChangedEvent event = new PropertyChangedEvent(this, "java", this.java, java);
if (java == null)
this.java = Java.JAVA.get(0).getName();
else {
int idx = Java.JAVA.indexOf(java);
if (idx == -1)
return;
this.java = java.getName();
}
propertyChanged.fire(event);
}
public String getJavaArgs() {
if (StrUtils.isBlank(javaArgs))
return "";
return javaArgs;
}
public void setJavaArgs(String javaArgs) {
PropertyChangedEvent event = new PropertyChangedEvent(this, "javaArgs", this.javaArgs, javaArgs);
this.javaArgs = javaArgs;
propertyChanged.fire(event);
}
public String getMaxMemory() {
if (StrUtils.isBlank(maxMemory))
return String.valueOf(OS.getSuggestedMemorySize());
return maxMemory;
}
public void setMaxMemory(String maxMemory) {
PropertyChangedEvent event = new PropertyChangedEvent(this, "maxMemory", this.maxMemory, maxMemory);
this.maxMemory = maxMemory;
propertyChanged.fire(event);
}
public String getWidth() {
if (StrUtils.isBlank(width))
return "854";
return width;
}
public void setWidth(String width) {
PropertyChangedEvent event = new PropertyChangedEvent(this, "width", this.width, width);
this.width = width;
propertyChanged.fire(event);
}
public String getHeight() {
if (StrUtils.isBlank(height))
return "480";
return height;
}
public void setHeight(String height) {
PropertyChangedEvent event = new PropertyChangedEvent(this, "height", this.height, height);
this.height = height;
propertyChanged.fire(event);
}
public boolean isFullscreen() {
return fullscreen;
}
public void setFullscreen(boolean fullscreen) {
PropertyChangedEvent event = new PropertyChangedEvent(this, "fullscreen", this.fullscreen, fullscreen);
this.fullscreen = fullscreen;
propertyChanged.fire(event);
}
public LauncherVisibility getLauncherVisibility() {
return LauncherVisibility.values()[launcherVisibility];
}
public void setLauncherVisibility(LauncherVisibility launcherVisibility) {
PropertyChangedEvent event = new PropertyChangedEvent(this, "launcherVisibility", this.launcherVisibility, launcherVisibility);
this.launcherVisibility = launcherVisibility.ordinal();
propertyChanged.fire(event);
}
public GameDirType getGameDirType() {
if (gameDirType < 0 || gameDirType > 1)
setGameDirType(GameDirType.ROOT_FOLDER);
return GameDirType.values()[gameDirType];
}
public void setGameDirType(GameDirType gameDirType) {
PropertyChangedEvent event = new PropertyChangedEvent(this, "gameDirType", this.gameDirType, gameDirType);
this.gameDirType = gameDirType.ordinal();
propertyChanged.fire(event);
}
public String getPermSize() {
return permSize;
}
public void setPermSize(String permSize) {
PropertyChangedEvent event = new PropertyChangedEvent(this, "permSize", this.permSize, permSize);
this.permSize = permSize;
propertyChanged.fire(event);
}
public boolean isNoJVMArgs() {
return noJVMArgs;
}
public void setNoJVMArgs(boolean noJVMArgs) {
PropertyChangedEvent event = new PropertyChangedEvent(this, "noJVMArgs", this.noJVMArgs, noJVMArgs);
this.noJVMArgs = noJVMArgs;
propertyChanged.fire(event);
}
public String getMinecraftArgs() {
return minecraftArgs;
}
public void setMinecraftArgs(String minecraftArgs) {
PropertyChangedEvent event = new PropertyChangedEvent(this, "minecraftArgs", this.minecraftArgs, minecraftArgs);
this.minecraftArgs = minecraftArgs;
propertyChanged.fire(event);
}
public String getPrecalledCommand() {
return precalledCommand;
}
public void setPrecalledCommand(String precalledCommand) {
PropertyChangedEvent event = new PropertyChangedEvent(this, "precalledCommand", this.precalledCommand, precalledCommand);
this.precalledCommand = precalledCommand;
propertyChanged.fire(event);
}
public String getWrapper() {
return wrapper;
}
public void setWrapper(String wrapper) {
PropertyChangedEvent event = new PropertyChangedEvent(this, "wrapper", this.wrapper, wrapper);
this.wrapper = wrapper;
propertyChanged.fire(event);
}
public String getServerIp() {
return serverIp;
}
public void setServerIp(String serverIp) {
PropertyChangedEvent event = new PropertyChangedEvent(this, "serverIp", this.serverIp, serverIp);
this.serverIp = serverIp;
propertyChanged.fire(event);
}
public boolean isNotCheckGame() {
return notCheckGame;
}
public void setNotCheckGame(boolean notCheckGame) {
PropertyChangedEvent event = new PropertyChangedEvent(this, "notCheckGame", this.notCheckGame, notCheckGame);
this.notCheckGame = notCheckGame;
propertyChanged.fire(event);
}
public boolean isUsesGlobal() {
return usesGlobal;
}
public void setUsesGlobal(boolean usesGlobal) {
PropertyChangedEvent event = new PropertyChangedEvent(this, "usesGlobal", this.usesGlobal, usesGlobal);
this.usesGlobal = usesGlobal;
propertyChanged.fire(event);
}
public LaunchOptions createLaunchOptions(File gameDir) {
LaunchOptions x = new LaunchOptions();
x.setFullscreen(isFullscreen());
x.setWrapper(getWrapper());
x.setGameDir(gameDir);
x.setHeight(getHeight());
x.setJavaArgs(getJavaArgs());
x.setLaunchVersion(id);
x.setMaxMemory(getMaxMemory());
x.setMinecraftArgs(getMinecraftArgs());
x.setName(Main.shortTitle());
x.setType(Main.shortTitle());
x.setVersionName(Main.shortTitle());
x.setNoJVMArgs(isNoJVMArgs());
x.setNotCheckGame(isNotCheckGame());
x.setPermSize(getPermSize());
x.setPrecalledCommand(getPrecalledCommand());
x.setProxyHost(Settings.getInstance().getProxyHost());
x.setProxyPort(Settings.getInstance().getProxyPort());
x.setProxyUser(Settings.getInstance().getProxyUserName());
x.setProxyPass(Settings.getInstance().getProxyPassword());
x.setServerIp(getServerIp());
x.setWidth(getWidth());
String str = getJavaDir();
if (!getJavaDirFile().exists()) {
HMCLog.err(C.i18n("launch.wrong_javadir"));
setJava(null);
str = getJavaDir();
}
x.setJavaDir(str);
return x;
}
}
@@ -1,73 +0,0 @@
/*
* Hello Minecraft! Launcher.
* Copyright (C) 2013 huangyuhui <huanghongxun2008@126.com>
*
* 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 3 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. If not, see {http://www.gnu.org/licenses/}.
*/
package org.jackhuang.hmcl.ui;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import javax.swing.JFrame;
/**
*
* @author huangyuhui
*/
public class DraggableFrame extends JFrame
implements MouseListener, MouseMotionListener {
private int dragGripX;
private int dragGripY;
public DraggableFrame() {
addMouseListener(this);
addMouseMotionListener(this);
}
@Override
public void mouseClicked(MouseEvent e) {
}
@Override
public void mousePressed(MouseEvent e) {
if (e.getButton() == 1 && isUndecorated()) {
this.dragGripX = e.getX();
this.dragGripY = e.getY();
}
}
@Override
public void mouseReleased(MouseEvent e) {
}
@Override
public void mouseEntered(MouseEvent e) {
}
@Override
public void mouseExited(MouseEvent e) {
}
@Override
public void mouseDragged(MouseEvent e) {
if ((e.getModifiersEx() & 0x400) != 0 && isUndecorated())
setLocation(e.getXOnScreen() - this.dragGripX, e.getYOnScreen() - this.dragGripY);
}
@Override
public void mouseMoved(MouseEvent e) {
}
}
@@ -1,172 +0,0 @@
/*
* Hello Minecraft! Launcher.
* Copyright (C) 2013 huangyuhui <huanghongxun2008@126.com>
*
* 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 3 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. If not, see {http://www.gnu.org/licenses/}.
*/
package org.jackhuang.hmcl.ui;
import org.jackhuang.hmcl.util.ui.Page;
import javax.swing.table.DefaultTableModel;
import org.jackhuang.hmcl.api.ui.TopTabPage;
import org.jackhuang.hmcl.core.download.MinecraftRemoteVersions;
import org.jackhuang.hmcl.setting.Settings;
import org.jackhuang.hmcl.util.C;
import org.jackhuang.hmcl.util.ui.MessageBox;
import org.jackhuang.hmcl.util.StrUtils;
import org.jackhuang.hmcl.util.task.ProgressProviderListener;
import org.jackhuang.hmcl.util.task.Task;
import org.jackhuang.hmcl.util.task.TaskWindow;
import org.jackhuang.hmcl.util.ui.SwingUtils;
/**
*
* @author huangyuhui
*/
public class GameDownloadPanel extends Page implements ProgressProviderListener {
GameSettingsPanel gsp;
/**
* Creates new form GameDownloadPanel
*/
public GameDownloadPanel(GameSettingsPanel gsp) {
initComponents();
this.gsp = gsp;
}
/**
* This method is called from within the constructor to initialize the form.
* WARNING: Do NOT modify this code. The content of this method is always
* regenerated by the Form Editor.
*/
@SuppressWarnings("unchecked")
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
private void initComponents() {
btnDownload = new javax.swing.JButton();
jScrollPane2 = new javax.swing.JScrollPane();
lstDownloads = new javax.swing.JTable();
btnRefreshGameDownloads = new javax.swing.JButton();
btnDownload.setText(C.i18n("ui.button.download")); // NOI18N
btnDownload.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
btnDownloadActionPerformed(evt);
}
});
lstDownloads.setModel(SwingUtils.makeDefaultTableModel(new String[]{C.i18n("install.version"), C.i18n("install.release_time"), C.i18n("install.time"), C.i18n("install.type")},new Class[]{String.class, String.class, String.class, String.class}, new boolean[]{false, false, false, false}));
lstDownloads.setToolTipText("");
lstDownloads.setSelectionMode(javax.swing.ListSelectionModel.SINGLE_SELECTION);
jScrollPane2.setViewportView(lstDownloads);
btnRefreshGameDownloads.setText(C.i18n("ui.button.refresh")); // NOI18N
btnRefreshGameDownloads.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
btnRefreshGameDownloadsActionPerformed(evt);
}
});
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
this.setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addComponent(jScrollPane2, javax.swing.GroupLayout.DEFAULT_SIZE, 350, Short.MAX_VALUE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
.addComponent(btnDownload, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(btnRefreshGameDownloads, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)))
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.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, 300, Short.MAX_VALUE)
);
}// </editor-fold>//GEN-END:initComponents
private void btnDownloadActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnDownloadActionPerformed
downloadMinecraft();
gsp.refreshVersions();
}//GEN-LAST:event_btnDownloadActionPerformed
private void btnRefreshGameDownloadsActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnRefreshGameDownloadsActionPerformed
refreshDownloads();
}//GEN-LAST:event_btnRefreshGameDownloadsActionPerformed
public void refreshDownloads() {
if (loading)
return;
loading = true;
DefaultTableModel model = SwingUtils.clearDefaultTable(lstDownloads);
model.addRow(new Object[] { C.i18n("message.loading"), "", "" });
MinecraftRemoteVersions.refreshRomoteVersions(Settings.getLastProfile().service().getDownloadType())
.reg((ver) -> model.addRow(new Object[] { ver.id, ver.releaseTime, ver.time,
StrUtils.equalsOne(ver.type, "old_beta", "old_alpha", "release", "snapshot") ? C.i18n("versions." + ver.type) : ver.type }))
.regDone(SwingUtils.invokeLater(() -> {
loading = false;
lstDownloads.requestFocus();
if (model.getRowCount() > 0)
model.removeRow(0);
})).setProgressProviderListener(this).runAsync();
}
boolean loading = false;
@Override
public void setProgress(Task task, int prog, int max) {
DefaultTableModel model = (DefaultTableModel) lstDownloads.getModel();
if (model.getRowCount() > 0)
model.setValueAt(C.i18n("message.loading") + " " + (prog < 0 ? "???" : Integer.toString(prog * 100 / max) + "%"), 0, 0);
}
@Override
public void setStatus(Task task, String sta) {
}
@Override
public void onProgressProviderDone(Task task) {
}
void downloadMinecraft() {
if (lstDownloads.getSelectedRow() < 0) {
MessageBox.show(C.i18n("gamedownload.not_refreshed"));
return;
}
String id = (String) lstDownloads.getModel().getValueAt(lstDownloads.getSelectedRow(), 0);
TaskWindow.factory().execute(Settings.getLastProfile().service().download().downloadMinecraft(id));
}
// Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.JButton btnDownload;
private javax.swing.JButton btnRefreshGameDownloads;
private javax.swing.JScrollPane jScrollPane2;
private javax.swing.JTable lstDownloads;
// End of variables declaration//GEN-END:variables
boolean refreshedDownloads = false;
@Override
public void onSelect(TopTabPage page) {
super.onSelect(page);
if (!refreshedDownloads) {
refreshedDownloads = true;
refreshDownloads();
}
}
}
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
@@ -1,108 +0,0 @@
/*
* Hello Minecraft! Launcher.
* Copyright (C) 2013 huangyuhui <huanghongxun2008@126.com>
*
* 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 3 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. If not, see {http://www.gnu.org/licenses/}.
*/
package org.jackhuang.hmcl.ui;
import java.awt.EventQueue;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import javax.swing.BorderFactory;
import javax.swing.DefaultButtonModel;
import javax.swing.JLabel;
/**
*
* @author huangyuhui
*/
public class HeaderTab extends JLabel
implements MouseListener {
private boolean isActive;
private final DefaultButtonModel model;
public HeaderTab(String text) {
super(text);
this.model = new DefaultButtonModel();
setIsActive(false);
setBorder(BorderFactory.createEmptyBorder(6, 18, 7, 18));
addMouseListener(this);
}
public boolean isActive() {
return this.isActive;
}
public final void setIsActive(boolean isActive) {
this.isActive = isActive;
setOpaque(isActive);
EventQueue.invokeLater(HeaderTab.this::repaint);
}
public void addActionListener(ActionListener listener) {
this.model.addActionListener(listener);
}
public String getActionCommand() {
return this.model.getActionCommand();
}
public ActionListener[] getActionListeners() {
return this.model.getActionListeners();
}
public void setActionCommand(String command) {
this.model.setActionCommand(command);
}
@Override
public void mouseClicked(MouseEvent e) {
}
@Override
public void mousePressed(MouseEvent e) {
if (!isEnabled())
return;
this.model.setPressed(true);
this.model.setArmed(true);
}
@Override
public void mouseReleased(MouseEvent e) {
if (!isEnabled())
return;
this.model.setPressed(false);
this.model.setArmed(false);
}
@Override
public void mouseEntered(MouseEvent e) {
if (!isEnabled())
return;
this.model.setRollover(true);
}
@Override
public void mouseExited(MouseEvent e) {
if (!isEnabled())
return;
this.model.setRollover(false);
}
}
@@ -1,85 +0,0 @@
<?xml version="1.0" encoding="UTF-8" ?>
<Form version="1.6" maxVersion="1.9" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
<AuxValues>
<AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="0"/>
<AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/>
<AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/>
<AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="false"/>
<AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="false"/>
<AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="1"/>
<AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
<AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
<AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
</AuxValues>
<Layout>
<DimensionLayout dim="0">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0">
<Component id="jScrollPane12" pref="292" max="32767" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" max="-2" attributes="0">
<Component id="btnRefresh" max="32767" attributes="0"/>
<Component id="btnInstall" max="32767" attributes="0"/>
</Group>
</Group>
</Group>
</DimensionLayout>
<DimensionLayout dim="1">
<Group type="103" groupAlignment="0" attributes="0">
<Component id="jScrollPane12" pref="147" max="32767" attributes="0"/>
<Group type="102" attributes="0">
<Component id="btnInstall" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="btnRefresh" min="-2" max="-2" attributes="0"/>
<EmptySpace min="0" pref="0" max="32767" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
</Layout>
<SubComponents>
<Component class="javax.swing.JButton" name="btnInstall">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/jackhuang/hmcl/lang/I18N.properties" key="ui.button.install" replaceFormat="C.i18n(&quot;{key}&quot;)"/>
</Property>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="btnInstallActionPerformed"/>
</Events>
</Component>
<Container class="javax.swing.JScrollPane" name="jScrollPane12">
<AuxValues>
<AuxValue name="autoScrollPane" type="java.lang.Boolean" value="true"/>
</AuxValues>
<Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/>
<SubComponents>
<Component class="javax.swing.JTable" name="lstInstallers">
<Properties>
<Property name="model" type="javax.swing.table.TableModel" editor="org.netbeans.modules.form.RADConnectionPropertyEditor">
<Connection code="SwingUtils.makeDefaultTableModel(new String[]{C.i18n(&quot;install.version&quot;), C.i18n(&quot;install.mcversion&quot;)},&#xa; new Class[]{String.class, String.class}, new boolean[]{false, false})" type="code"/>
</Property>
<Property name="selectionModel" type="javax.swing.ListSelectionModel" editor="org.netbeans.modules.form.editors2.JTableSelectionModelEditor">
<JTableSelectionModel selectionMode="0"/>
</Property>
<Property name="tableHeader" type="javax.swing.table.JTableHeader" editor="org.netbeans.modules.form.editors2.JTableHeaderEditor">
<TableHeader reorderingAllowed="true" resizingAllowed="true"/>
</Property>
</Properties>
</Component>
</SubComponents>
</Container>
<Component class="javax.swing.JButton" name="btnRefresh">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/jackhuang/hmcl/lang/I18N.properties" key="ui.button.refresh" replaceFormat="C.i18n(&quot;{key}&quot;)"/>
</Property>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="btnRefreshActionPerformed"/>
</Events>
</Component>
</SubComponents>
</Form>
@@ -1,210 +0,0 @@
/*
* Hello Minecraft! Launcher.
* Copyright (C) 2013 huangyuhui <huanghongxun2008@126.com>
*
* 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 3 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. If not, see {http://www.gnu.org/licenses/}.
*/
package org.jackhuang.hmcl.ui;
import org.jackhuang.hmcl.util.ui.Page;
import java.util.List;
import javax.swing.SwingUtilities;
import javax.swing.table.DefaultTableModel;
import org.jackhuang.hmcl.api.ui.TopTabPage;
import org.jackhuang.hmcl.util.C;
import org.jackhuang.hmcl.setting.Settings;
import org.jackhuang.hmcl.core.install.InstallerType;
import org.jackhuang.hmcl.core.install.InstallerVersionList;
import org.jackhuang.hmcl.util.task.TaskRunnable;
import org.jackhuang.hmcl.util.task.TaskWindow;
import org.jackhuang.hmcl.util.ui.MessageBox;
import org.jackhuang.hmcl.util.StrUtils;
import org.jackhuang.hmcl.util.task.ProgressProviderListener;
import org.jackhuang.hmcl.util.task.Task;
import org.jackhuang.hmcl.util.ui.SwingUtils;
/**
*
* @author huangyuhui
*/
public class InstallerPanel extends Page implements ProgressProviderListener {
GameSettingsPanel gsp;
/**
* Creates new form InstallerPanel
*
* @param gsp To get the minecraft version
* @param installerType load which installer
*/
public InstallerPanel(GameSettingsPanel gsp, InstallerType installerType) {
initComponents();
animationEnabled = Settings.getInstance().isEnableAnimation();
setOpaque(false);
this.gsp = gsp;
id = installerType;
list = Settings.getInstance().getDownloadSource().getProvider().getInstallerByType(id);
}
/**
* This method is called from within the constructor to initialize the form.
* WARNING: Do NOT modify this code. The content of this method is always
* regenerated by the Form Editor.
*/
@SuppressWarnings("unchecked")
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
private void initComponents() {
btnInstall = new javax.swing.JButton();
jScrollPane12 = new javax.swing.JScrollPane();
lstInstallers = new javax.swing.JTable();
btnRefresh = new javax.swing.JButton();
btnInstall.setText(C.i18n("ui.button.install")); // NOI18N
btnInstall.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
btnInstallActionPerformed(evt);
}
});
lstInstallers.setModel(SwingUtils.makeDefaultTableModel(new String[]{C.i18n("install.version"), C.i18n("install.mcversion")},
new Class[]{String.class, String.class}, new boolean[]{false, false}));
lstInstallers.setSelectionMode(javax.swing.ListSelectionModel.SINGLE_SELECTION);
jScrollPane12.setViewportView(lstInstallers);
btnRefresh.setText(C.i18n("ui.button.refresh")); // NOI18N
btnRefresh.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
btnRefreshActionPerformed(evt);
}
});
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
this.setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addComponent(jScrollPane12, javax.swing.GroupLayout.DEFAULT_SIZE, 292, Short.MAX_VALUE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
.addComponent(btnRefresh, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(btnInstall, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)))
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(jScrollPane12, javax.swing.GroupLayout.DEFAULT_SIZE, 147, Short.MAX_VALUE)
.addGroup(layout.createSequentialGroup()
.addComponent(btnInstall)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(btnRefresh)
.addGap(0, 0, Short.MAX_VALUE))
);
}// </editor-fold>//GEN-END:initComponents
private void btnInstallActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnInstallActionPerformed
downloadSelectedRow();
}//GEN-LAST:event_btnInstallActionPerformed
private void btnRefreshActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnRefreshActionPerformed
refreshVersions();
}//GEN-LAST:event_btnRefreshActionPerformed
transient List<InstallerVersionList.InstallerVersion> versions;
InstallerVersionList list;
InstallerType id;
void refreshVersions() {
if (loading)
return;
Task t = list.refresh(new String[] { gsp.getMinecraftVersionFormatted() });
if (t != null) {
loading = true;
DefaultTableModel model = SwingUtils.clearDefaultTable(lstInstallers);
model.addRow(new Object[] { C.i18n("message.loading"), "", "" });
t.with(new TaskRunnable(this::loadVersions)).setProgressProviderListener(this).runAsync();
}
}
boolean loading = false;
@Override
public void setProgress(Task task, int prog, int max) {
DefaultTableModel model = (DefaultTableModel) lstInstallers.getModel();
if (model.getRowCount() > 0)
model.setValueAt(C.i18n("message.loading") + " " + (prog < 0 ? "???" : Integer.toString(prog * 100 / max) + "%"), 0, 0);
}
@Override
public void setStatus(Task task, String sta) {
}
@Override
public void onProgressProviderDone(Task task) {
loading = false;
DefaultTableModel model = (DefaultTableModel) lstInstallers.getModel();
if (model.getRowCount() > 0)
model.removeRow(0);
}
public synchronized InstallerVersionList.InstallerVersion getVersion(int idx) {
return versions.get(idx);
}
synchronized void downloadSelectedRow() {
int idx = lstInstallers.getSelectedRow();
if (versions == null || idx < 0 || idx >= versions.size()) {
MessageBox.show(C.i18n("install.not_refreshed"));
return;
}
TaskWindow.factory()
.append(Settings.getLastProfile().service().install().download(Settings.getLastProfile().getSelectedVersion(), getVersion(idx), id))
.append(new TaskRunnable(() -> gsp.refreshVersions()))
.execute();
}
public void loadVersions() {
SwingUtilities.invokeLater(() -> {
synchronized (InstallerPanel.this) {
DefaultTableModel model = (DefaultTableModel) lstInstallers.getModel();
String mcver = StrUtils.formatVersion(gsp.getMinecraftVersionFormatted());
versions = list.getVersions(mcver);
SwingUtils.clearDefaultTable(lstInstallers);
if (versions != null)
for (InstallerVersionList.InstallerVersion v : versions)
if (v != null)
model.addRow(new Object[] { v.selfVersion == null ? "null" : v.selfVersion, v.mcVersion == null ? "null" : v.mcVersion });
}
});
}
boolean refreshed = false;
@Override
public void onSelect(TopTabPage page) {
super.onSelect(page);
if (!refreshed) {
refreshVersions();
refreshed = true;
}
}
// Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.JButton btnInstall;
private javax.swing.JButton btnRefresh;
private javax.swing.JScrollPane jScrollPane12;
private javax.swing.JTable lstInstallers;
// End of variables declaration//GEN-END:variables
}
@@ -1,101 +0,0 @@
/*
* Hello Minecraft! Launcher.
* Copyright (C) 2013 huangyuhui <huanghongxun2008@126.com>
*
* 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 3 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. If not, see {http://www.gnu.org/licenses/}.
*/
package org.jackhuang.hmcl.ui;
import javax.swing.JTextPane;
import javax.swing.text.AbstractDocument;
import javax.swing.text.BoxView;
import javax.swing.text.ComponentView;
import javax.swing.text.Element;
import javax.swing.text.IconView;
import javax.swing.text.LabelView;
import javax.swing.text.ParagraphView;
import javax.swing.text.StyleConstants;
import javax.swing.text.StyledEditorKit;
import javax.swing.text.View;
import javax.swing.text.ViewFactory;
/**
*
* @author huang
*/
public class JLineWrapTextPane extends JTextPane {
// 内部类
// 以下内部类全都用于实现自动强制折行
private class WarpEditorKit extends StyledEditorKit {
private ViewFactory defaultFactory = new WarpColumnFactory();
@Override
public ViewFactory getViewFactory() {
return defaultFactory;
}
}
private class WarpColumnFactory implements ViewFactory {
public View create(Element elem) {
String kind = elem.getName();
if (kind != null) {
if (kind.equals(AbstractDocument.ContentElementName)) {
return new WarpLabelView(elem);
} else if (kind.equals(AbstractDocument.ParagraphElementName)) {
return new ParagraphView(elem);
} else if (kind.equals(AbstractDocument.SectionElementName)) {
return new BoxView(elem, View.Y_AXIS);
} else if (kind.equals(StyleConstants.ComponentElementName)) {
return new ComponentView(elem);
} else if (kind.equals(StyleConstants.IconElementName)) {
return new IconView(elem);
}
}
// default to text display
return new LabelView(elem);
}
}
private class WarpLabelView extends LabelView {
public WarpLabelView(Element elem) {
super(elem);
}
@Override
public float getMinimumSpan(int axis) {
switch (axis) {
case View.X_AXIS:
return 0;
case View.Y_AXIS:
return super.getMinimumSpan(axis);
default:
throw new IllegalArgumentException("Invalid axis: " + axis);
}
}
}
// 本类
// 构造函数
public JLineWrapTextPane() {
super();
this.setEditorKit(new WarpEditorKit());
}
}
@@ -1,601 +0,0 @@
<?xml version="1.0" encoding="UTF-8" ?>
<Form version="1.3" maxVersion="1.9" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
<AuxValues>
<AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="0"/>
<AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/>
<AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/>
<AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="false"/>
<AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="false"/>
<AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="1"/>
<AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
<AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
<AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
</AuxValues>
<Layout>
<DimensionLayout dim="0">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" attributes="0">
<EmptySpace min="-2" pref="10" max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Component id="lblModpack" alignment="0" min="-2" max="-2" attributes="0"/>
<Component id="lblRestart" alignment="0" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace max="32767" attributes="0"/>
</Group>
<Component id="tabLauncherSettings" alignment="0" max="32767" attributes="0"/>
</Group>
</DimensionLayout>
<DimensionLayout dim="1">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0">
<Component id="tabLauncherSettings" max="32767" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="lblModpack" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="lblRestart" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
</Layout>
<SubComponents>
<Component class="javax.swing.JLabel" name="lblModpack">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/jackhuang/hmcl/lang/I18N.properties" key="launcher.modpack" replaceFormat="C.i18n(&quot;{key}&quot;)"/>
</Property>
<Property name="cursor" type="java.awt.Cursor" editor="org.netbeans.modules.form.editors2.CursorEditor">
<Color id="&#x624b;&#x578b;&#x5149;&#x6807;"/>
</Property>
</Properties>
<Events>
<EventHandler event="mouseClicked" listener="java.awt.event.MouseListener" parameters="java.awt.event.MouseEvent" handler="lblModpackMouseClicked"/>
</Events>
</Component>
<Component class="javax.swing.JLabel" name="lblRestart">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/jackhuang/hmcl/lang/I18N.properties" key="launcher.restart" replaceFormat="C.i18n(&quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
<Container class="javax.swing.JTabbedPane" name="tabLauncherSettings">
<AccessibilityProperties>
<Property name="AccessibleContext.accessibleName" type="java.lang.String" value=""/>
</AccessibilityProperties>
<AuxValues>
<AuxValue name="JavaCodeGenerator_CreateCodeCustom" type="java.lang.String" value="new NewTabPane()"/>
</AuxValues>
<Layout class="org.netbeans.modules.form.compat2.layouts.support.JTabbedPaneSupportLayout"/>
<SubComponents>
<Container class="javax.swing.JPanel" name="pnlGeneral">
<AuxValues>
<AuxValue name="JavaCodeGenerator_CreateCodeCustom" type="java.lang.String" value="new Page().setAnimationEnabled(Settings.getInstance().isEnableAnimation())"/>
</AuxValues>
<Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.support.JTabbedPaneSupportLayout" value="org.netbeans.modules.form.compat2.layouts.support.JTabbedPaneSupportLayout$JTabbedPaneConstraintsDescription">
<JTabbedPaneConstraints tabName="General">
<Property name="tabTitle" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/jackhuang/hmcl/lang/I18N.properties" key="launcher.tab.general" replaceFormat="C.i18n(&quot;{key}&quot;)"/>
</Property>
</JTabbedPaneConstraints>
</Constraint>
</Constraints>
<Layout>
<DimensionLayout dim="0">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" attributes="0">
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0">
<Component id="btnCheckUpdate" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="btnMCBBS" min="-2" max="-2" attributes="0"/>
<EmptySpace min="0" pref="0" max="32767" attributes="0"/>
</Group>
<Group type="102" alignment="0" attributes="0">
<Group type="103" groupAlignment="0" attributes="0">
<Component id="lblDownloadSource" alignment="0" min="-2" max="-2" attributes="0"/>
<Component id="lblCommonPath" alignment="0" min="-2" max="-2" attributes="0"/>
<Component id="lblLang" alignment="0" min="-2" max="-2" attributes="0"/>
<Component id="lblProxy" alignment="0" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace min="-2" pref="28" max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0">
<Component id="cboProxyType" pref="156" max="32767" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="lblProxyHost" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="txtProxyHost" min="-2" pref="80" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="lblProxyPort" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="txtProxyPort" min="-2" pref="80" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="lblProxyUserName" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="txtProxyUsername" min="-2" pref="80" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="lblProxyPassword" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="txtProxyPassword" min="-2" pref="80" max="-2" attributes="0"/>
</Group>
<Component id="cboLang" alignment="1" max="32767" attributes="0"/>
<Group type="102" alignment="0" attributes="0">
<Component id="txtCommonPath" max="32767" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="btnSetCommonPath" min="-2" max="-2" attributes="0"/>
</Group>
<Component id="cboDownloadSource" alignment="1" max="32767" attributes="0"/>
</Group>
</Group>
</Group>
<EmptySpace max="-2" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
<DimensionLayout dim="1">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0">
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="3" attributes="0">
<Component id="lblCommonPath" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="txtCommonPath" alignment="3" min="-2" pref="26" max="-2" attributes="0"/>
<Component id="btnSetCommonPath" alignment="3" min="-2" pref="26" max="-2" attributes="0"/>
</Group>
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="3" attributes="0">
<Component id="lblDownloadSource" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="cboDownloadSource" alignment="3" min="-2" pref="26" max="-2" attributes="0"/>
</Group>
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="3" attributes="0">
<Component id="cboLang" alignment="3" min="-2" pref="26" max="-2" attributes="0"/>
<Component id="lblLang" alignment="3" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="3" attributes="0">
<Component id="txtProxyHost" alignment="3" min="-2" pref="26" max="-2" attributes="0"/>
<Component id="lblProxy" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="lblProxyHost" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="txtProxyPort" alignment="3" min="-2" pref="26" max="-2" attributes="0"/>
<Component id="lblProxyPort" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="txtProxyUsername" alignment="3" min="-2" pref="26" max="-2" attributes="0"/>
<Component id="lblProxyUserName" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="txtProxyPassword" alignment="3" min="-2" pref="26" max="-2" attributes="0"/>
<Component id="lblProxyPassword" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="cboProxyType" alignment="3" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace pref="69" max="32767" attributes="0"/>
<Group type="103" groupAlignment="3" attributes="0">
<Component id="btnCheckUpdate" alignment="3" min="-2" pref="26" max="-2" attributes="0"/>
<Component id="btnMCBBS" alignment="3" min="-2" pref="26" max="-2" attributes="0"/>
</Group>
<EmptySpace max="-2" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
</Layout>
<SubComponents>
<Component class="javax.swing.JLabel" name="lblProxy">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/jackhuang/hmcl/lang/I18N.properties" key="launcher.proxy" replaceFormat="C.i18n(&quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JLabel" name="lblProxyHost">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/jackhuang/hmcl/lang/I18N.properties" key="proxy.host" replaceFormat="C.i18n(&quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JTextField" name="txtProxyHost">
<Events>
<EventHandler event="focusLost" listener="java.awt.event.FocusListener" parameters="java.awt.event.FocusEvent" handler="txtProxyHostFocusLost"/>
</Events>
</Component>
<Component class="javax.swing.JLabel" name="lblProxyPort">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/jackhuang/hmcl/lang/I18N.properties" key="proxy.port" replaceFormat="C.i18n(&quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JTextField" name="txtProxyPort">
<Events>
<EventHandler event="focusLost" listener="java.awt.event.FocusListener" parameters="java.awt.event.FocusEvent" handler="txtProxyPortFocusLost"/>
</Events>
</Component>
<Component class="javax.swing.JLabel" name="lblProxyUserName">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/jackhuang/hmcl/lang/I18N.properties" key="proxy.username" replaceFormat="C.i18n(&quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JTextField" name="txtProxyUsername">
<Events>
<EventHandler event="focusLost" listener="java.awt.event.FocusListener" parameters="java.awt.event.FocusEvent" handler="txtProxyUsernameFocusLost"/>
</Events>
</Component>
<Component class="javax.swing.JLabel" name="lblProxyPassword">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/jackhuang/hmcl/lang/I18N.properties" key="proxy.password" replaceFormat="C.i18n(&quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JTextField" name="txtProxyPassword">
<Events>
<EventHandler event="focusLost" listener="java.awt.event.FocusListener" parameters="java.awt.event.FocusEvent" handler="txtProxyPasswordFocusLost"/>
</Events>
</Component>
<Component class="javax.swing.JComboBox" name="cboDownloadSource">
<Properties>
<Property name="model" type="javax.swing.ComboBoxModel" editor="org.netbeans.modules.form.editors2.ComboBoxModelEditor">
<StringArray count="0"/>
</Property>
</Properties>
<Events>
<EventHandler event="itemStateChanged" listener="java.awt.event.ItemListener" parameters="java.awt.event.ItemEvent" handler="cboDownloadSourceItemStateChanged"/>
</Events>
</Component>
<Component class="javax.swing.JLabel" name="lblDownloadSource">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/jackhuang/hmcl/lang/I18N.properties" key="launcher.download_source" replaceFormat="C.i18n(&quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JLabel" name="lblCommonPath">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/jackhuang/hmcl/lang/I18N.properties" key="launcher.common_location" replaceFormat="C.i18n(&quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JTextField" name="txtCommonPath">
<Properties>
<Property name="toolTipText" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/jackhuang/hmcl/lang/I18N.properties" key="launcher.commpath_tooltip" replaceFormat="C.i18n(&quot;{key}&quot;)"/>
</Property>
</Properties>
<Events>
<EventHandler event="focusLost" listener="java.awt.event.FocusListener" parameters="java.awt.event.FocusEvent" handler="txtCommonPathFocusLost"/>
</Events>
</Component>
<Component class="javax.swing.JButton" name="btnSetCommonPath">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/jackhuang/hmcl/lang/I18N.properties" key="ui.button.explore" replaceFormat="C.i18n(&quot;{key}&quot;)"/>
</Property>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="btnSetCommonPathActionPerformed"/>
</Events>
</Component>
<Component class="javax.swing.JButton" name="btnCheckUpdate">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/jackhuang/hmcl/lang/I18N.properties" key="launcher.update_launcher" replaceFormat="C.i18n(&quot;{key}&quot;)"/>
</Property>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="btnCheckUpdateActionPerformed"/>
</Events>
</Component>
<Component class="javax.swing.JButton" name="btnMCBBS">
<Properties>
<Property name="text" type="java.lang.String" value="MCBBS"/>
<Property name="toolTipText" type="java.lang.String" value=""/>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="btnMCBBSActionPerformed"/>
</Events>
</Component>
<Component class="javax.swing.JComboBox" name="cboLang">
<Properties>
<Property name="model" type="javax.swing.ComboBoxModel" editor="org.netbeans.modules.form.RADConnectionPropertyEditor">
<Connection code="new DefaultComboBoxModel(new String[]{C.i18n(&quot;color.blue&quot;),C.i18n(&quot;color.green&quot;),C.i18n(&quot;color.purple&quot;),C.i18n(&quot;color.dark_blue&quot;),C.i18n(&quot;color.orange&quot;),C.i18n(&quot;color.red&quot;)})" type="code"/>
</Property>
</Properties>
<Events>
<EventHandler event="itemStateChanged" listener="java.awt.event.ItemListener" parameters="java.awt.event.ItemEvent" handler="cboLangItemStateChanged"/>
</Events>
</Component>
<Component class="javax.swing.JLabel" name="lblLang">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/jackhuang/hmcl/lang/I18N.properties" key="launcher.lang" replaceFormat="C.i18n(&quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JComboBox" name="cboProxyType">
<Properties>
<Property name="model" type="javax.swing.ComboBoxModel" editor="org.netbeans.modules.form.editors2.ComboBoxModelEditor">
<StringArray count="3">
<StringItem index="0" value="Direct"/>
<StringItem index="1" value="HTTP"/>
<StringItem index="2" value="Socks"/>
</StringArray>
</Property>
</Properties>
<Events>
<EventHandler event="itemStateChanged" listener="java.awt.event.ItemListener" parameters="java.awt.event.ItemEvent" handler="cboProxyTypeItemStateChanged"/>
</Events>
<AuxValues>
<AuxValue name="JavaCodeGenerator_TypeParameters" type="java.lang.String" value="&lt;String&gt;"/>
</AuxValues>
</Component>
</SubComponents>
</Container>
<Container class="javax.swing.JPanel" name="pnlUI">
<AuxValues>
<AuxValue name="JavaCodeGenerator_CreateCodeCustom" type="java.lang.String" value="new Page().setAnimationEnabled(Settings.getInstance().isEnableAnimation())"/>
</AuxValues>
<Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.support.JTabbedPaneSupportLayout" value="org.netbeans.modules.form.compat2.layouts.support.JTabbedPaneSupportLayout$JTabbedPaneConstraintsDescription">
<JTabbedPaneConstraints tabName="UI">
<Property name="tabTitle" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/jackhuang/hmcl/lang/I18N.properties" key="launcher.tab.ui" replaceFormat="C.i18n(&quot;{key}&quot;)"/>
</Property>
</JTabbedPaneConstraints>
</Constraint>
</Constraints>
<Layout>
<DimensionLayout dim="0">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" attributes="0">
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" attributes="0">
<Group type="103" groupAlignment="0" attributes="0">
<Component id="chkDecorated" min="-2" max="-2" attributes="0"/>
<Group type="102" alignment="0" attributes="0">
<Component id="chkEnableShadow" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="chkEnableBlur" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="chkEnableAnimation" min="-2" max="-2" attributes="0"/>
</Group>
</Group>
<EmptySpace min="0" pref="163" max="32767" attributes="0"/>
</Group>
<Group type="102" alignment="0" attributes="0">
<Group type="103" groupAlignment="0" attributes="0">
<Component id="lblBackground" alignment="0" min="-2" max="-2" attributes="0"/>
<Component id="lblFont" alignment="0" min="-2" max="-2" attributes="0"/>
<Component id="lblTheme" alignment="0" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Component id="cboTheme" max="32767" attributes="0"/>
<Group type="102" alignment="0" attributes="0">
<Group type="103" groupAlignment="0" attributes="0">
<Component id="txtBackgroundPath" max="32767" attributes="0"/>
<Component id="cboFontFamily" max="32767" attributes="0"/>
</Group>
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" max="-2" attributes="0">
<Component id="btnSelBackgroundPath" max="32767" attributes="0"/>
<Component id="spinnerFontSize" max="32767" attributes="0"/>
</Group>
</Group>
<Group type="102" alignment="0" attributes="0">
<Component id="lblExample" min="-2" max="-2" attributes="0"/>
<EmptySpace min="0" pref="0" max="32767" attributes="0"/>
</Group>
</Group>
</Group>
</Group>
<EmptySpace max="-2" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
<DimensionLayout dim="1">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0">
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="3" attributes="0">
<Component id="lblBackground" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="txtBackgroundPath" alignment="3" min="-2" pref="26" max="-2" attributes="0"/>
<Component id="btnSelBackgroundPath" alignment="3" min="-2" pref="26" max="-2" attributes="0"/>
</Group>
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="3" attributes="0">
<Component id="cboFontFamily" alignment="3" min="-2" pref="26" max="-2" attributes="0"/>
<Component id="lblFont" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="spinnerFontSize" alignment="3" min="-2" pref="26" max="-2" attributes="0"/>
</Group>
<EmptySpace max="-2" attributes="0"/>
<Component id="lblExample" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="3" attributes="0">
<Component id="cboTheme" alignment="3" min="-2" pref="26" max="-2" attributes="0"/>
<Component id="lblTheme" alignment="3" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace pref="63" max="32767" attributes="0"/>
<Group type="103" groupAlignment="3" attributes="0">
<Component id="chkEnableShadow" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="chkEnableBlur" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="chkEnableAnimation" alignment="3" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace max="-2" attributes="0"/>
<Component id="chkDecorated" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
</Layout>
<SubComponents>
<Component class="javax.swing.JLabel" name="lblTheme">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/jackhuang/hmcl/lang/I18N.properties" key="launcher.theme" replaceFormat="C.i18n(&quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JComboBox" name="cboTheme">
<Events>
<EventHandler event="itemStateChanged" listener="java.awt.event.ItemListener" parameters="java.awt.event.ItemEvent" handler="cboThemeItemStateChanged"/>
</Events>
</Component>
<Component class="javax.swing.JLabel" name="lblBackground">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/jackhuang/hmcl/lang/I18N.properties" key="launcher.background_location" replaceFormat="C.i18n(&quot;{key}&quot;)"/>
</Property>
<Property name="toolTipText" type="java.lang.String" value=""/>
</Properties>
</Component>
<Component class="javax.swing.JTextField" name="txtBackgroundPath">
<Properties>
<Property name="toolTipText" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/jackhuang/hmcl/lang/I18N.properties" key="launcher.background_tooltip" replaceFormat="C.i18n(&quot;{key}&quot;)"/>
</Property>
</Properties>
<Events>
<EventHandler event="focusLost" listener="java.awt.event.FocusListener" parameters="java.awt.event.FocusEvent" handler="txtBackgroundPathFocusLost"/>
</Events>
</Component>
<Component class="javax.swing.JCheckBox" name="chkEnableShadow">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/jackhuang/hmcl/lang/I18N.properties" key="launcher.enable_shadow" replaceFormat="C.i18n(&quot;{key}&quot;)"/>
</Property>
</Properties>
<Events>
<EventHandler event="itemStateChanged" listener="java.awt.event.ItemListener" parameters="java.awt.event.ItemEvent" handler="chkEnableShadowItemStateChanged"/>
</Events>
</Component>
<Component class="javax.swing.JCheckBox" name="chkEnableBlur">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/jackhuang/hmcl/lang/I18N.properties" key="launcher.enable_blur" replaceFormat="C.i18n(&quot;{key}&quot;)"/>
</Property>
</Properties>
<Events>
<EventHandler event="itemStateChanged" listener="java.awt.event.ItemListener" parameters="java.awt.event.ItemEvent" handler="chkEnableBlurItemStateChanged"/>
</Events>
</Component>
<Component class="javax.swing.JCheckBox" name="chkEnableAnimation">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/jackhuang/hmcl/lang/I18N.properties" key="launcher.enable_animation" replaceFormat="C.i18n(&quot;{key}&quot;)"/>
</Property>
</Properties>
<Events>
<EventHandler event="itemStateChanged" listener="java.awt.event.ItemListener" parameters="java.awt.event.ItemEvent" handler="chkEnableAnimationItemStateChanged"/>
</Events>
</Component>
<Component class="javax.swing.JCheckBox" name="chkDecorated">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/jackhuang/hmcl/lang/I18N.properties" key="launcher.decorated" replaceFormat="C.i18n(&quot;{key}&quot;)"/>
</Property>
</Properties>
<Events>
<EventHandler event="itemStateChanged" listener="java.awt.event.ItemListener" parameters="java.awt.event.ItemEvent" handler="chkDecoratedItemStateChanged"/>
</Events>
</Component>
<Component class="javax.swing.JButton" name="btnSelBackgroundPath">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/jackhuang/hmcl/lang/I18N.properties" key="ui.button.explore" replaceFormat="C.i18n(&quot;{key}&quot;)"/>
</Property>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="btnSelBackgroundPathActionPerformed"/>
</Events>
</Component>
<Component class="javax.swing.JComboBox" name="cboFontFamily">
<Properties>
<Property name="model" type="javax.swing.ComboBoxModel" editor="org.netbeans.modules.form.RADConnectionPropertyEditor">
<SerializedValue value="-84,-19,0,5,115,114,0,32,106,97,118,97,120,46,115,119,105,110,103,46,68,101,102,97,117,108,116,67,111,109,98,111,66,111,120,77,111,100,101,108,92,-10,105,-80,-61,-104,-56,48,2,0,2,76,0,7,111,98,106,101,99,116,115,116,0,18,76,106,97,118,97,47,117,116,105,108,47,86,101,99,116,111,114,59,76,0,14,115,101,108,101,99,116,101,100,79,98,106,101,99,116,116,0,18,76,106,97,118,97,47,108,97,110,103,47,79,98,106,101,99,116,59,120,114,0,29,106,97,118,97,120,46,115,119,105,110,103,46,65,98,115,116,114,97,99,116,76,105,115,116,77,111,100,101,108,87,-79,61,-30,108,45,-87,-39,2,0,1,76,0,12,108,105,115,116,101,110,101,114,76,105,115,116,116,0,37,76,106,97,118,97,120,47,115,119,105,110,103,47,101,118,101,110,116,47,69,118,101,110,116,76,105,115,116,101,110,101,114,76,105,115,116,59,120,112,115,114,0,35,106,97,118,97,120,46,115,119,105,110,103,46,101,118,101,110,116,46,69,118,101,110,116,76,105,115,116,101,110,101,114,76,105,115,116,-79,54,-58,125,-124,-22,-42,68,3,0,0,120,112,116,0,34,106,97,118,97,120,46,115,119,105,110,103,46,101,118,101,110,116,46,76,105,115,116,68,97,116,97,76,105,115,116,101,110,101,114,115,114,0,21,106,97,118,97,120,46,115,119,105,110,103,46,74,67,111,109,98,111,66,111,120,115,-25,-16,-68,-83,109,105,-54,3,0,14,90,0,17,102,105,114,105,110,103,65,99,116,105,111,110,69,118,101,110,116,90,0,10,105,115,69,100,105,116,97,98,108,101,90,0,23,108,105,103,104,116,87,101,105,103,104,116,80,111,112,117,112,69,110,97,98,108,101,100,73,0,15,109,97,120,105,109,117,109,82,111,119,67,111,117,110,116,90,0,13,115,101,108,101,99,116,105,110,103,73,116,101,109,76,0,6,97,99,116,105,111,110,116,0,20,76,106,97,118,97,120,47,115,119,105,110,103,47,65,99,116,105,111,110,59,76,0,13,97,99,116,105,111,110,67,111,109,109,97,110,100,116,0,18,76,106,97,118,97,47,108,97,110,103,47,83,116,114,105,110,103,59,76,0,28,97,99,116,105,111,110,80,114,111,112,101,114,116,121,67,104,97,110,103,101,76,105,115,116,101,110,101,114,116,0,35,76,106,97,118,97,47,98,101,97,110,115,47,80,114,111,112,101,114,116,121,67,104,97,110,103,101,76,105,115,116,101,110,101,114,59,76,0,9,100,97,116,97,77,111,100,101,108,116,0,27,76,106,97,118,97,120,47,115,119,105,110,103,47,67,111,109,98,111,66,111,120,77,111,100,101,108,59,76,0,6,101,100,105,116,111,114,116,0,28,76,106,97,118,97,120,47,115,119,105,110,103,47,67,111,109,98,111,66,111,120,69,100,105,116,111,114,59,76,0,19,107,101,121,83,101,108,101,99,116,105,111,110,77,97,110,97,103,101,114,116,0,43,76,106,97,118,97,120,47,115,119,105,110,103,47,74,67,111,109,98,111,66,111,120,36,75,101,121,83,101,108,101,99,116,105,111,110,77,97,110,97,103,101,114,59,76,0,21,112,114,111,116,111,116,121,112,101,68,105,115,112,108,97,121,86,97,108,117,101,113,0,126,0,2,76,0,8,114,101,110,100,101,114,101,114,116,0,30,76,106,97,118,97,120,47,115,119,105,110,103,47,76,105,115,116,67,101,108,108,82,101,110,100,101,114,101,114,59,76,0,20,115,101,108,101,99,116,101,100,73,116,101,109,82,101,109,105,110,100,101,114,113,0,126,0,2,120,114,0,22,106,97,118,97,120,46,115,119,105,110,103,46,74,67,111,109,112,111,110,101,110,116,51,-17,99,38,30,108,-90,-113,3,0,16,70,0,10,97,108,105,103,110,109,101,110,116,88,70,0,10,97,108,105,103,110,109,101,110,116,89,90,0,11,97,117,116,111,115,99,114,111,108,108,115,73,0,5,102,108,97,103,115,90,0,15,105,115,65,108,105,103,110,109,101,110,116,88,83,101,116,90,0,15,105,115,65,108,105,103,110,109,101,110,116,89,83,101,116,90,0,26,118,101,114,105,102,121,73,110,112,117,116,87,104,101,110,70,111,99,117,115,84,97,114,103,101,116,76,0,9,97,99,116,105,111,110,77,97,112,116,0,23,76,106,97,118,97,120,47,115,119,105,110,103,47,65,99,116,105,111,110,77,97,112,59,76,0,16,97,110,99,101,115,116,111,114,73,110,112,117,116,77,97,112,116,0,22,76,106,97,118,97,120,47,115,119,105,110,103,47,73,110,112,117,116,77,97,112,59,76,0,6,98,111,114,100,101,114,116,0,27,76,106,97,118,97,120,47,115,119,105,110,103,47,98,111,114,100,101,114,47,66,111,114,100,101,114,59,76,0,13,102,111,99,117,115,73,110,112,117,116,77,97,112,113,0,126,0,19,76,0,13,105,110,112,117,116,86,101,114,105,102,105,101,114,116,0,27,76,106,97,118,97,120,47,115,119,105,110,103,47,73,110,112,117,116,86,101,114,105,102,105,101,114,59,76,0,12,108,105,115,116,101,110,101,114,76,105,115,116,113,0,126,0,4,76,0,9,112,111,112,117,112,77,101,110,117,116,0,24,76,106,97,118,97,120,47,115,119,105,110,103,47,74,80,111,112,117,112,77,101,110,117,59,76,0,21,118,101,116,111,97,98,108,101,67,104,97,110,103,101,83,117,112,112,111,114,116,116,0,34,76,106,97,118,97,47,98,101,97,110,115,47,86,101,116,111,97,98,108,101,67,104,97,110,103,101,83,117,112,112,111,114,116,59,76,0,14,119,105,110,100,111,119,73,110,112,117,116,77,97,112,116,0,31,76,106,97,118,97,120,47,115,119,105,110,103,47,67,111,109,112,111,110,101,110,116,73,110,112,117,116,77,97,112,59,120,114,0,18,106,97,118,97,46,97,119,116,46,67,111,110,116,97,105,110,101,114,64,7,-128,115,-3,20,12,39,3,0,8,73,0,30,99,111,110,116,97,105,110,101,114,83,101,114,105,97,108,105,122,101,100,68,97,116Line truncated
</Property>
</Properties>
<Events>
<EventHandler event="itemStateChanged" listener="java.awt.event.ItemListener" parameters="java.awt.event.ItemEvent" handler="cboFontFamilyItemStateChanged"/>
</Events>
<AuxValues>
<AuxValue name="JavaCodeGenerator_CreateCodeCustom" type="java.lang.String" value="new JFontComboBox()"/>
</AuxValues>
</Component>
<Component class="javax.swing.JLabel" name="lblFont">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/jackhuang/hmcl/lang/I18N.properties" key="launcher.log_font" replaceFormat="C.i18n(&quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JSpinner" name="spinnerFontSize">
<Events>
<EventHandler event="stateChanged" listener="javax.swing.event.ChangeListener" parameters="javax.swing.event.ChangeEvent" handler="spinnerFontSizeStateChanged"/>
</Events>
</Component>
<Component class="javax.swing.JLabel" name="lblExample">
<Properties>
<Property name="text" type="java.lang.String" value="19:10:10 [Client Thread/INFO]: Example"/>
</Properties>
</Component>
</SubComponents>
</Container>
<Container class="javax.swing.JPanel" name="pnlAbout">
<AuxValues>
<AuxValue name="JavaCodeGenerator_CreateCodeCustom" type="java.lang.String" value="new Page().setAnimationEnabled(Settings.getInstance().isEnableAnimation())"/>
</AuxValues>
<Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.support.JTabbedPaneSupportLayout" value="org.netbeans.modules.form.compat2.layouts.support.JTabbedPaneSupportLayout$JTabbedPaneConstraintsDescription">
<JTabbedPaneConstraints tabName="About">
<Property name="tabTitle" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/jackhuang/hmcl/lang/I18N.properties" key="launcher.tab.about" replaceFormat="C.i18n(&quot;{key}&quot;)"/>
</Property>
</JTabbedPaneConstraints>
</Constraint>
</Constraints>
<Layout>
<DimensionLayout dim="0">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0">
<EmptySpace max="-2" attributes="0"/>
<Component id="lblAbout" min="-2" max="-2" attributes="0"/>
<EmptySpace pref="252" max="32767" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
<DimensionLayout dim="1">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0">
<EmptySpace max="-2" attributes="0"/>
<Component id="lblAbout" min="-2" max="-2" attributes="0"/>
<EmptySpace max="32767" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
</Layout>
<SubComponents>
<Component class="javax.swing.JLabel" name="lblAbout">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/jackhuang/hmcl/lang/I18N.properties" key="launcher.about" replaceFormat="C.i18n(&quot;{key}&quot;)"/>
</Property>
<Property name="cursor" type="java.awt.Cursor" editor="org.netbeans.modules.form.editors2.CursorEditor">
<Color id="&#x9ed8;&#x8ba4;&#x5149;&#x6807;"/>
</Property>
</Properties>
</Component>
</SubComponents>
</Container>
</SubComponents>
</Container>
</SubComponents>
</Form>
@@ -1,672 +0,0 @@
/*
* Hello Minecraft! Launcher.
* Copyright (C) 2013 huangyuhui <huanghongxun2008@126.com>
*
* 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 3 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. If not, see {http://www.gnu.org/licenses/}.
*/
package org.jackhuang.hmcl.ui;
import java.io.IOException;
import java.net.Proxy;
import javax.swing.DefaultComboBoxModel;
import javax.swing.filechooser.FileNameExtensionFilter;
import org.jackhuang.hmcl.util.C;
import org.jackhuang.hmcl.api.HMCLog;
import org.jackhuang.hmcl.api.ui.Theme;
import org.jackhuang.hmcl.setting.Settings;
import org.jackhuang.hmcl.core.download.DownloadType;
import org.jackhuang.hmcl.util.MathUtils;
import org.jackhuang.hmcl.util.sys.IOUtils;
import org.jackhuang.hmcl.util.ui.MessageBox;
import org.jackhuang.hmcl.util.lang.SupportedLocales;
import org.jackhuang.hmcl.util.ui.JFontComboBox;
import org.jackhuang.hmcl.util.ui.JSystemFileChooser;
import org.jackhuang.hmcl.util.ui.Page;
import org.jackhuang.hmcl.util.ui.SwingUtils;
/**
*
* @author huangyuhui
*/
public class LauncherSettingsPanel extends RepaintPage {
public LauncherSettingsPanel() {
setRepainter(this);
}
void initGui() {
initComponents();
animationEnabled = Settings.getInstance().isEnableAnimation();
DefaultComboBoxModel<String> d = new DefaultComboBoxModel<>();
for (DownloadType type : DownloadType.values())
d.addElement(type.getName());
cboDownloadSource.setModel(d);
d = new DefaultComboBoxModel<>();
int id = 0;
for (SupportedLocales type : SupportedLocales.values()) {
d.addElement(type.showString());
if (type.name().equals(Settings.getInstance().getLocalization()))
id = type.ordinal();
}
cboLang.setModel(d);
cboLang.setSelectedIndex(id);
DefaultComboBoxModel<Theme> g = new DefaultComboBoxModel<>();
for (Theme t : Theme.THEMES.values())
g.addElement(t);
cboTheme.setModel(g);
txtBackgroundPath.setText(Settings.getInstance().getBgpath());
txtCommonPath.setText(Settings.getInstance().getCommonpath());
txtProxyHost.setText(Settings.getInstance().getProxyHost());
txtProxyPort.setText(Settings.getInstance().getProxyPort());
txtProxyUsername.setText(Settings.getInstance().getProxyUserName());
txtProxyPassword.setText(Settings.getInstance().getProxyPassword());
spinnerFontSize.setValue(Settings.getInstance().getFontSize());
cboFontFamily.setSelectedItem(Settings.getInstance().getFontFamily());
cboDownloadSource.setSelectedIndex(Settings.getInstance().getDownloadType());
cboProxyType.setSelectedIndex(Settings.getInstance().getProxyType().ordinal());
cboTheme.setSelectedItem(Settings.getInstance().getTheme());
chkEnableShadow.setSelected(Settings.getInstance().isEnableShadow());
chkEnableBlur.setSelected(Settings.getInstance().isEnableBlur());
chkEnableAnimation.setSelected(Settings.getInstance().isEnableAnimation());
chkDecorated.setSelected(Settings.getInstance().isDecorated());
}
@Override
public void onCreate() {
initGui();
super.onCreate();
}
/**
* This method is called from within the constructor to initialize the form.
* WARNING: Do NOT modify this code. The content of this method is always
* regenerated by the Form Editor.
*/
@SuppressWarnings("unchecked")
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
private void initComponents() {
lblModpack = new javax.swing.JLabel();
lblRestart = new javax.swing.JLabel();
tabLauncherSettings = new NewTabPane();
pnlGeneral = new Page().setAnimationEnabled(Settings.getInstance().isEnableAnimation());
lblProxy = new javax.swing.JLabel();
lblProxyHost = new javax.swing.JLabel();
txtProxyHost = new javax.swing.JTextField();
lblProxyPort = new javax.swing.JLabel();
txtProxyPort = new javax.swing.JTextField();
lblProxyUserName = new javax.swing.JLabel();
txtProxyUsername = new javax.swing.JTextField();
lblProxyPassword = new javax.swing.JLabel();
txtProxyPassword = new javax.swing.JTextField();
cboDownloadSource = new javax.swing.JComboBox();
lblDownloadSource = new javax.swing.JLabel();
lblCommonPath = new javax.swing.JLabel();
txtCommonPath = new javax.swing.JTextField();
btnSetCommonPath = new javax.swing.JButton();
btnCheckUpdate = new javax.swing.JButton();
btnMCBBS = new javax.swing.JButton();
cboLang = new javax.swing.JComboBox();
lblLang = new javax.swing.JLabel();
cboProxyType = new javax.swing.JComboBox<>();
pnlUI = new Page().setAnimationEnabled(Settings.getInstance().isEnableAnimation());
lblTheme = new javax.swing.JLabel();
cboTheme = new javax.swing.JComboBox();
lblBackground = new javax.swing.JLabel();
txtBackgroundPath = new javax.swing.JTextField();
chkEnableShadow = new javax.swing.JCheckBox();
chkEnableBlur = new javax.swing.JCheckBox();
chkEnableAnimation = new javax.swing.JCheckBox();
chkDecorated = new javax.swing.JCheckBox();
btnSelBackgroundPath = new javax.swing.JButton();
cboFontFamily = new JFontComboBox();
lblFont = new javax.swing.JLabel();
spinnerFontSize = new javax.swing.JSpinner();
lblExample = new javax.swing.JLabel();
pnlAbout = new Page().setAnimationEnabled(Settings.getInstance().isEnableAnimation());
lblAbout = new javax.swing.JLabel();
lblModpack.setText(C.i18n("launcher.modpack")); // NOI18N
lblModpack.setCursor(new java.awt.Cursor(java.awt.Cursor.HAND_CURSOR));
lblModpack.addMouseListener(new java.awt.event.MouseAdapter() {
public void mouseClicked(java.awt.event.MouseEvent evt) {
lblModpackMouseClicked(evt);
}
});
lblRestart.setText(C.i18n("launcher.restart")); // NOI18N
lblProxy.setText(C.i18n("launcher.proxy")); // NOI18N
lblProxyHost.setText(C.i18n("proxy.host")); // NOI18N
txtProxyHost.addFocusListener(new java.awt.event.FocusAdapter() {
public void focusLost(java.awt.event.FocusEvent evt) {
txtProxyHostFocusLost(evt);
}
});
lblProxyPort.setText(C.i18n("proxy.port")); // NOI18N
txtProxyPort.addFocusListener(new java.awt.event.FocusAdapter() {
public void focusLost(java.awt.event.FocusEvent evt) {
txtProxyPortFocusLost(evt);
}
});
lblProxyUserName.setText(C.i18n("proxy.username")); // NOI18N
txtProxyUsername.addFocusListener(new java.awt.event.FocusAdapter() {
public void focusLost(java.awt.event.FocusEvent evt) {
txtProxyUsernameFocusLost(evt);
}
});
lblProxyPassword.setText(C.i18n("proxy.password")); // NOI18N
txtProxyPassword.addFocusListener(new java.awt.event.FocusAdapter() {
public void focusLost(java.awt.event.FocusEvent evt) {
txtProxyPasswordFocusLost(evt);
}
});
cboDownloadSource.addItemListener(new java.awt.event.ItemListener() {
public void itemStateChanged(java.awt.event.ItemEvent evt) {
cboDownloadSourceItemStateChanged(evt);
}
});
lblDownloadSource.setText(C.i18n("launcher.download_source")); // NOI18N
lblCommonPath.setText(C.i18n("launcher.common_location")); // NOI18N
txtCommonPath.setToolTipText(C.i18n("launcher.commpath_tooltip")); // NOI18N
txtCommonPath.addFocusListener(new java.awt.event.FocusAdapter() {
public void focusLost(java.awt.event.FocusEvent evt) {
txtCommonPathFocusLost(evt);
}
});
btnSetCommonPath.setText(C.i18n("ui.button.explore")); // NOI18N
btnSetCommonPath.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
btnSetCommonPathActionPerformed(evt);
}
});
btnCheckUpdate.setText(C.i18n("launcher.update_launcher")); // NOI18N
btnCheckUpdate.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
btnCheckUpdateActionPerformed(evt);
}
});
btnMCBBS.setText("MCBBS");
btnMCBBS.setToolTipText("");
btnMCBBS.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
btnMCBBSActionPerformed(evt);
}
});
cboLang.setModel(new DefaultComboBoxModel(new String[]{C.i18n("color.blue"),C.i18n("color.green"),C.i18n("color.purple"),C.i18n("color.dark_blue"),C.i18n("color.orange"),C.i18n("color.red")}));
cboLang.addItemListener(new java.awt.event.ItemListener() {
public void itemStateChanged(java.awt.event.ItemEvent evt) {
cboLangItemStateChanged(evt);
}
});
lblLang.setText(C.i18n("launcher.lang")); // NOI18N
cboProxyType.setModel(new javax.swing.DefaultComboBoxModel<>(new String[] { "Direct", "HTTP", "Socks" }));
cboProxyType.addItemListener(new java.awt.event.ItemListener() {
public void itemStateChanged(java.awt.event.ItemEvent evt) {
cboProxyTypeItemStateChanged(evt);
}
});
javax.swing.GroupLayout pnlGeneralLayout = new javax.swing.GroupLayout(pnlGeneral);
pnlGeneral.setLayout(pnlGeneralLayout);
pnlGeneralLayout.setHorizontalGroup(
pnlGeneralLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(pnlGeneralLayout.createSequentialGroup()
.addContainerGap()
.addGroup(pnlGeneralLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(pnlGeneralLayout.createSequentialGroup()
.addComponent(btnCheckUpdate)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(btnMCBBS)
.addGap(0, 0, Short.MAX_VALUE))
.addGroup(pnlGeneralLayout.createSequentialGroup()
.addGroup(pnlGeneralLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(lblDownloadSource)
.addComponent(lblCommonPath)
.addComponent(lblLang)
.addComponent(lblProxy))
.addGap(28, 28, 28)
.addGroup(pnlGeneralLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(pnlGeneralLayout.createSequentialGroup()
.addComponent(cboProxyType, 0, 156, Short.MAX_VALUE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(lblProxyHost)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(txtProxyHost, javax.swing.GroupLayout.PREFERRED_SIZE, 80, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(lblProxyPort)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(txtProxyPort, javax.swing.GroupLayout.PREFERRED_SIZE, 80, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(lblProxyUserName)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(txtProxyUsername, javax.swing.GroupLayout.PREFERRED_SIZE, 80, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(lblProxyPassword)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(txtProxyPassword, javax.swing.GroupLayout.PREFERRED_SIZE, 80, javax.swing.GroupLayout.PREFERRED_SIZE))
.addComponent(cboLang, javax.swing.GroupLayout.Alignment.TRAILING, 0, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addGroup(pnlGeneralLayout.createSequentialGroup()
.addComponent(txtCommonPath)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(btnSetCommonPath))
.addComponent(cboDownloadSource, javax.swing.GroupLayout.Alignment.TRAILING, 0, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))))
.addContainerGap())
);
pnlGeneralLayout.setVerticalGroup(
pnlGeneralLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(pnlGeneralLayout.createSequentialGroup()
.addContainerGap()
.addGroup(pnlGeneralLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(lblCommonPath)
.addComponent(txtCommonPath, javax.swing.GroupLayout.PREFERRED_SIZE, 26, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(btnSetCommonPath, javax.swing.GroupLayout.PREFERRED_SIZE, 26, javax.swing.GroupLayout.PREFERRED_SIZE))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(pnlGeneralLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(lblDownloadSource)
.addComponent(cboDownloadSource, javax.swing.GroupLayout.PREFERRED_SIZE, 26, javax.swing.GroupLayout.PREFERRED_SIZE))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(pnlGeneralLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(cboLang, javax.swing.GroupLayout.PREFERRED_SIZE, 26, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(lblLang))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(pnlGeneralLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(txtProxyHost, javax.swing.GroupLayout.PREFERRED_SIZE, 26, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(lblProxy)
.addComponent(lblProxyHost)
.addComponent(txtProxyPort, javax.swing.GroupLayout.PREFERRED_SIZE, 26, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(lblProxyPort)
.addComponent(txtProxyUsername, javax.swing.GroupLayout.PREFERRED_SIZE, 26, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(lblProxyUserName)
.addComponent(txtProxyPassword, javax.swing.GroupLayout.PREFERRED_SIZE, 26, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(lblProxyPassword)
.addComponent(cboProxyType, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 69, Short.MAX_VALUE)
.addGroup(pnlGeneralLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(btnCheckUpdate, javax.swing.GroupLayout.PREFERRED_SIZE, 26, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(btnMCBBS, javax.swing.GroupLayout.PREFERRED_SIZE, 26, javax.swing.GroupLayout.PREFERRED_SIZE))
.addContainerGap())
);
tabLauncherSettings.addTab(C.i18n("launcher.tab.general"), pnlGeneral); // NOI18N
lblTheme.setText(C.i18n("launcher.theme")); // NOI18N
cboTheme.addItemListener(new java.awt.event.ItemListener() {
public void itemStateChanged(java.awt.event.ItemEvent evt) {
cboThemeItemStateChanged(evt);
}
});
lblBackground.setText(C.i18n("launcher.background_location")); // NOI18N
lblBackground.setToolTipText("");
txtBackgroundPath.setToolTipText(C.i18n("launcher.background_tooltip")); // NOI18N
txtBackgroundPath.addFocusListener(new java.awt.event.FocusAdapter() {
public void focusLost(java.awt.event.FocusEvent evt) {
txtBackgroundPathFocusLost(evt);
}
});
chkEnableShadow.setText(C.i18n("launcher.enable_shadow")); // NOI18N
chkEnableShadow.addItemListener(new java.awt.event.ItemListener() {
public void itemStateChanged(java.awt.event.ItemEvent evt) {
chkEnableShadowItemStateChanged(evt);
}
});
chkEnableBlur.setText(C.i18n("launcher.enable_blur")); // NOI18N
chkEnableBlur.addItemListener(new java.awt.event.ItemListener() {
public void itemStateChanged(java.awt.event.ItemEvent evt) {
chkEnableBlurItemStateChanged(evt);
}
});
chkEnableAnimation.setText(C.i18n("launcher.enable_animation")); // NOI18N
chkEnableAnimation.addItemListener(new java.awt.event.ItemListener() {
public void itemStateChanged(java.awt.event.ItemEvent evt) {
chkEnableAnimationItemStateChanged(evt);
}
});
chkDecorated.setText(C.i18n("launcher.decorated")); // NOI18N
chkDecorated.addItemListener(new java.awt.event.ItemListener() {
public void itemStateChanged(java.awt.event.ItemEvent evt) {
chkDecoratedItemStateChanged(evt);
}
});
btnSelBackgroundPath.setText(C.i18n("ui.button.explore")); // NOI18N
btnSelBackgroundPath.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
btnSelBackgroundPathActionPerformed(evt);
}
});
cboFontFamily.addItemListener(new java.awt.event.ItemListener() {
public void itemStateChanged(java.awt.event.ItemEvent evt) {
cboFontFamilyItemStateChanged(evt);
}
});
lblFont.setText(C.i18n("launcher.log_font")); // NOI18N
spinnerFontSize.addChangeListener(new javax.swing.event.ChangeListener() {
public void stateChanged(javax.swing.event.ChangeEvent evt) {
spinnerFontSizeStateChanged(evt);
}
});
lblExample.setText("19:10:10 [Client Thread/INFO]: Example");
javax.swing.GroupLayout pnlUILayout = new javax.swing.GroupLayout(pnlUI);
pnlUI.setLayout(pnlUILayout);
pnlUILayout.setHorizontalGroup(
pnlUILayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(pnlUILayout.createSequentialGroup()
.addContainerGap()
.addGroup(pnlUILayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(pnlUILayout.createSequentialGroup()
.addGroup(pnlUILayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(chkDecorated)
.addGroup(pnlUILayout.createSequentialGroup()
.addComponent(chkEnableShadow)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(chkEnableBlur)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(chkEnableAnimation)))
.addGap(0, 163, Short.MAX_VALUE))
.addGroup(pnlUILayout.createSequentialGroup()
.addGroup(pnlUILayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(lblBackground)
.addComponent(lblFont)
.addComponent(lblTheme))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(pnlUILayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(cboTheme, 0, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addGroup(pnlUILayout.createSequentialGroup()
.addGroup(pnlUILayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(txtBackgroundPath)
.addComponent(cboFontFamily, 0, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(pnlUILayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
.addComponent(btnSelBackgroundPath, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(spinnerFontSize)))
.addGroup(pnlUILayout.createSequentialGroup()
.addComponent(lblExample)
.addGap(0, 0, Short.MAX_VALUE)))))
.addContainerGap())
);
pnlUILayout.setVerticalGroup(
pnlUILayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(pnlUILayout.createSequentialGroup()
.addContainerGap()
.addGroup(pnlUILayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(lblBackground)
.addComponent(txtBackgroundPath, javax.swing.GroupLayout.PREFERRED_SIZE, 26, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(btnSelBackgroundPath, javax.swing.GroupLayout.PREFERRED_SIZE, 26, javax.swing.GroupLayout.PREFERRED_SIZE))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(pnlUILayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(cboFontFamily, javax.swing.GroupLayout.PREFERRED_SIZE, 26, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(lblFont)
.addComponent(spinnerFontSize, javax.swing.GroupLayout.PREFERRED_SIZE, 26, javax.swing.GroupLayout.PREFERRED_SIZE))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(lblExample)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(pnlUILayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(cboTheme, javax.swing.GroupLayout.PREFERRED_SIZE, 26, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(lblTheme))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 63, Short.MAX_VALUE)
.addGroup(pnlUILayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(chkEnableShadow)
.addComponent(chkEnableBlur)
.addComponent(chkEnableAnimation))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(chkDecorated)
.addContainerGap())
);
tabLauncherSettings.addTab(C.i18n("launcher.tab.ui"), pnlUI); // NOI18N
lblAbout.setText(C.i18n("launcher.about")); // NOI18N
lblAbout.setCursor(new java.awt.Cursor(java.awt.Cursor.DEFAULT_CURSOR));
javax.swing.GroupLayout pnlAboutLayout = new javax.swing.GroupLayout(pnlAbout);
pnlAbout.setLayout(pnlAboutLayout);
pnlAboutLayout.setHorizontalGroup(
pnlAboutLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(pnlAboutLayout.createSequentialGroup()
.addContainerGap()
.addComponent(lblAbout, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addContainerGap(252, Short.MAX_VALUE))
);
pnlAboutLayout.setVerticalGroup(
pnlAboutLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(pnlAboutLayout.createSequentialGroup()
.addContainerGap()
.addComponent(lblAbout, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
);
tabLauncherSettings.addTab(C.i18n("launcher.tab.about"), pnlAbout); // NOI18N
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
this.setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addGap(10, 10, 10)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(lblModpack, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(lblRestart))
.addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
.addComponent(tabLauncherSettings)
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addComponent(tabLauncherSettings)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(lblModpack, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(lblRestart)
.addContainerGap())
);
tabLauncherSettings.getAccessibleContext().setAccessibleName("");
}// </editor-fold>//GEN-END:initComponents
private void cboDownloadSourceItemStateChanged(java.awt.event.ItemEvent evt) {//GEN-FIRST:event_cboDownloadSourceItemStateChanged
Settings.getInstance().setDownloadType(cboDownloadSource.getSelectedIndex());
}//GEN-LAST:event_cboDownloadSourceItemStateChanged
private void btnSelBackgroundPathActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnSelBackgroundPathActionPerformed
JSystemFileChooser fc = new JSystemFileChooser();
fc.setFileSelectionMode(JSystemFileChooser.FILES_ONLY);
fc.setDialogTitle(C.i18n("launcher.choose_bgpath"));
fc.setMultiSelectionEnabled(false);
fc.setFileFilter(new FileNameExtensionFilter("*.png", "png"));
fc.addChoosableFileFilter(new FileNameExtensionFilter("*.jpg", "jpg"));
if (fc.showOpenDialog(this) != JSystemFileChooser.APPROVE_OPTION || fc.getSelectedFile() == null)
return;
try {
String path = fc.getSelectedFile().getCanonicalPath();
path = IOUtils.removeLastSeparator(path);
txtBackgroundPath.setText(path);
Settings.getInstance().setBgpath(path);
MainFrame.INSTANCE.loadBackground();
} catch (IOException e) {
HMCLog.warn("Failed to set background path.", e);
MessageBox.show(C.i18n("ui.label.failed_set") + e.getMessage());
}
}//GEN-LAST:event_btnSelBackgroundPathActionPerformed
private void txtBackgroundPathFocusLost(java.awt.event.FocusEvent evt) {//GEN-FIRST:event_txtBackgroundPathFocusLost
Settings.getInstance().setBgpath(txtBackgroundPath.getText());
MainFrame.INSTANCE.loadBackground();
}//GEN-LAST:event_txtBackgroundPathFocusLost
private void btnCheckUpdateActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnCheckUpdateActionPerformed
Settings.UPDATE_CHECKER.process(true);
Settings.UPDATE_CHECKER.checkOutdate();
}//GEN-LAST:event_btnCheckUpdateActionPerformed
private void cboThemeItemStateChanged(java.awt.event.ItemEvent evt) {//GEN-FIRST:event_cboThemeItemStateChanged
Settings.getInstance().setTheme(((Theme) cboTheme.getSelectedItem()).id);
}//GEN-LAST:event_cboThemeItemStateChanged
private void lblModpackMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_lblModpackMouseClicked
SwingUtils.openLink("http://huangyuhui.duapp.com/link.php?type=modpack");
}//GEN-LAST:event_lblModpackMouseClicked
private void cboLangItemStateChanged(java.awt.event.ItemEvent evt) {//GEN-FIRST:event_cboLangItemStateChanged
Settings.getInstance().setLocalization(SupportedLocales.values()[cboLang.getSelectedIndex()].name());
}//GEN-LAST:event_cboLangItemStateChanged
private void chkEnableShadowItemStateChanged(java.awt.event.ItemEvent evt) {//GEN-FIRST:event_chkEnableShadowItemStateChanged
Settings.getInstance().setEnableShadow(chkEnableShadow.isSelected());
}//GEN-LAST:event_chkEnableShadowItemStateChanged
private void chkDecoratedItemStateChanged(java.awt.event.ItemEvent evt) {//GEN-FIRST:event_chkDecoratedItemStateChanged
Settings.getInstance().setDecorated(chkDecorated.isSelected());
}//GEN-LAST:event_chkDecoratedItemStateChanged
private void txtProxyHostFocusLost(java.awt.event.FocusEvent evt) {//GEN-FIRST:event_txtProxyHostFocusLost
Settings.getInstance().setProxyHost(txtProxyHost.getText());
}//GEN-LAST:event_txtProxyHostFocusLost
private void txtProxyPortFocusLost(java.awt.event.FocusEvent evt) {//GEN-FIRST:event_txtProxyPortFocusLost
Settings.getInstance().setProxyPort(txtProxyPort.getText());
}//GEN-LAST:event_txtProxyPortFocusLost
private void txtProxyUsernameFocusLost(java.awt.event.FocusEvent evt) {//GEN-FIRST:event_txtProxyUsernameFocusLost
Settings.getInstance().setProxyUserName(txtProxyUsername.getText());
}//GEN-LAST:event_txtProxyUsernameFocusLost
private void txtProxyPasswordFocusLost(java.awt.event.FocusEvent evt) {//GEN-FIRST:event_txtProxyPasswordFocusLost
Settings.getInstance().setProxyPassword(txtProxyPassword.getText());
}//GEN-LAST:event_txtProxyPasswordFocusLost
private void btnMCBBSActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnMCBBSActionPerformed
SwingUtils.openLink(C.URL_PUBLISH);
}//GEN-LAST:event_btnMCBBSActionPerformed
private void chkEnableBlurItemStateChanged(java.awt.event.ItemEvent evt) {//GEN-FIRST:event_chkEnableBlurItemStateChanged
Settings.getInstance().setEnableBlur(chkEnableBlur.isSelected());
}//GEN-LAST:event_chkEnableBlurItemStateChanged
private void chkEnableAnimationItemStateChanged(java.awt.event.ItemEvent evt) {//GEN-FIRST:event_chkEnableAnimationItemStateChanged
Settings.getInstance().setEnableAnimation(chkEnableAnimation.isSelected());
}//GEN-LAST:event_chkEnableAnimationItemStateChanged
private void btnSetCommonPathActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnSetCommonPathActionPerformed
JSystemFileChooser fc = new JSystemFileChooser();
fc.setFileSelectionMode(JSystemFileChooser.DIRECTORIES_ONLY);
fc.setDialogTitle(C.i18n("launcher.choose_commonpath"));
fc.setMultiSelectionEnabled(false);
if (fc.showOpenDialog(this) != JSystemFileChooser.APPROVE_OPTION || fc.getSelectedFile() == null)
return;
try {
String path = fc.getSelectedFile().getCanonicalPath();
txtCommonPath.setText(path);
Settings.getInstance().setCommonpath(path);
} catch (IOException e) {
HMCLog.warn("Failed to set common path.", e);
MessageBox.show(C.i18n("ui.label.failed_set") + e.getMessage());
}
}//GEN-LAST:event_btnSetCommonPathActionPerformed
private void txtCommonPathFocusLost(java.awt.event.FocusEvent evt) {//GEN-FIRST:event_txtCommonPathFocusLost
Settings.getInstance().setCommonpath(txtCommonPath.getText());
}//GEN-LAST:event_txtCommonPathFocusLost
private void cboFontFamilyItemStateChanged(java.awt.event.ItemEvent evt) {//GEN-FIRST:event_cboFontFamilyItemStateChanged
Settings.getInstance().setFontFamily(evt.getItem().toString());
lblExample.setFont(Settings.getInstance().getConsoleFont());
}//GEN-LAST:event_cboFontFamilyItemStateChanged
private void spinnerFontSizeStateChanged(javax.swing.event.ChangeEvent evt) {//GEN-FIRST:event_spinnerFontSizeStateChanged
Settings.getInstance().setFontSize(MathUtils.parseInt(spinnerFontSize.getValue().toString(), 12));
lblExample.setFont(Settings.getInstance().getConsoleFont());
}//GEN-LAST:event_spinnerFontSizeStateChanged
private void cboProxyTypeItemStateChanged(java.awt.event.ItemEvent evt) {//GEN-FIRST:event_cboProxyTypeItemStateChanged
Settings.getInstance().setProxyType(Proxy.Type.values()[cboProxyType.getSelectedIndex()]);
}//GEN-LAST:event_cboProxyTypeItemStateChanged
// Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.JButton btnCheckUpdate;
private javax.swing.JButton btnMCBBS;
private javax.swing.JButton btnSelBackgroundPath;
private javax.swing.JButton btnSetCommonPath;
private javax.swing.JComboBox cboDownloadSource;
private javax.swing.JComboBox cboFontFamily;
private javax.swing.JComboBox cboLang;
private javax.swing.JComboBox<String> cboProxyType;
private javax.swing.JComboBox cboTheme;
private javax.swing.JCheckBox chkDecorated;
private javax.swing.JCheckBox chkEnableAnimation;
private javax.swing.JCheckBox chkEnableBlur;
private javax.swing.JCheckBox chkEnableShadow;
private javax.swing.JLabel lblAbout;
private javax.swing.JLabel lblBackground;
private javax.swing.JLabel lblCommonPath;
private javax.swing.JLabel lblDownloadSource;
private javax.swing.JLabel lblExample;
private javax.swing.JLabel lblFont;
private javax.swing.JLabel lblLang;
private javax.swing.JLabel lblModpack;
private javax.swing.JLabel lblProxy;
private javax.swing.JLabel lblProxyHost;
private javax.swing.JLabel lblProxyPassword;
private javax.swing.JLabel lblProxyPort;
private javax.swing.JLabel lblProxyUserName;
private javax.swing.JLabel lblRestart;
private javax.swing.JLabel lblTheme;
private javax.swing.JPanel pnlAbout;
private javax.swing.JPanel pnlGeneral;
private javax.swing.JPanel pnlUI;
private javax.swing.JSpinner spinnerFontSize;
private javax.swing.JTabbedPane tabLauncherSettings;
private javax.swing.JTextField txtBackgroundPath;
private javax.swing.JTextField txtCommonPath;
private javax.swing.JTextField txtProxyHost;
private javax.swing.JTextField txtProxyPassword;
private javax.swing.JTextField txtProxyPort;
private javax.swing.JTextField txtProxyUsername;
// End of variables declaration//GEN-END:variables
}
@@ -1,254 +0,0 @@
/*
* Hello Minecraft! Launcher.
* Copyright (C) 2013 huangyuhui <huanghongxun2008@126.com>
*
* 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 3 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. If not, see {http://www.gnu.org/licenses/}.
*/
package org.jackhuang.hmcl.ui;
import java.io.File;
import java.io.IOException;
import java.io.PipedOutputStream;
import javax.swing.SwingUtilities;
import org.jackhuang.hmcl.api.HMCLApi;
import org.jackhuang.hmcl.api.event.process.JVMLaunchFailedEvent;
import org.jackhuang.hmcl.api.event.process.JavaProcessExitedAbnormallyEvent;
import org.jackhuang.hmcl.api.event.process.JavaProcessStoppedEvent;
import org.jackhuang.hmcl.api.event.launch.LaunchEvent;
import org.jackhuang.hmcl.api.event.launch.LaunchSucceededEvent;
import org.jackhuang.hmcl.api.event.launch.LaunchingStateChangedEvent;
import org.jackhuang.hmcl.util.LauncherVisibility;
import org.jackhuang.hmcl.core.launch.GameLauncher;
import org.jackhuang.hmcl.setting.Profile;
import org.jackhuang.hmcl.setting.Settings;
import org.jackhuang.hmcl.util.HMCLGameLauncher;
import org.jackhuang.hmcl.util.MinecraftCrashAdvicer;
import org.jackhuang.hmcl.util.C;
import org.jackhuang.hmcl.util.ui.MessageBox;
import org.jackhuang.hmcl.api.func.Consumer;
import org.jackhuang.hmcl.api.HMCLog;
import org.jackhuang.hmcl.api.event.launch.LaunchingState;
import org.jackhuang.hmcl.util.DefaultPlugin;
import org.jackhuang.hmcl.util.Log4jHandler;
import org.jackhuang.hmcl.util.StrUtils;
import org.jackhuang.hmcl.util.sys.FileUtils;
import org.jackhuang.hmcl.util.sys.PrintlnEvent;
import org.jackhuang.hmcl.util.sys.ProcessMonitor;
import org.xml.sax.XMLReader;
/**
*
* @author huangyuhui
*/
public class LaunchingUIDaemon {
XMLReader reader;
Log4jHandler logHandler;
public LaunchingUIDaemon() {
HMCLApi.EVENT_BUS.channel(LaunchingStateChangedEvent.class).register(LAUNCHING_STATE_CHANGED);
HMCLApi.EVENT_BUS.channel(LaunchEvent.class).register(p -> {
GameLauncher obj = (GameLauncher) p.getSource();
HMCLGameLauncher.GameLauncherTag tag = (HMCLGameLauncher.GameLauncherTag) obj.getTag();
if (tag.launcherVisibility == LauncherVisibility.CLOSE && !LogWindow.INSTANCE.isVisible()) {
HMCLog.log("Without the option of keeping the launcher visible, this application will exit and will NOT catch game logs, but you can turn on \"Debug Mode\".");
System.exit(0);
} else if (tag.launcherVisibility == LauncherVisibility.KEEP)
MainFrame.INSTANCE.closeMessage();
else {
if (LogWindow.INSTANCE.isVisible())
LogWindow.INSTANCE.setExit(() -> true);
HMCLApi.EVENT_BUS.fireChannel(new LaunchingStateChangedEvent(obj, LaunchingState.WaitingForGameLaunching));
}
// We promise that JavaProcessMonitor.tag is LauncherVisibility
// See events below.
ProcessMonitor monitor = new ProcessMonitor(p.getValue());
PipedOutputStream os = new PipedOutputStream();
monitor.setTag(obj);
try {
logHandler = new Log4jHandler(monitor, os, false);
logHandler.addForbiddenToken(obj.getLoginResult().getAccessToken(), "<access token>");
logHandler.addForbiddenToken(obj.getLoginResult().getSession(), "<session>");
logHandler.addForbiddenToken(obj.getLoginResult().getUserId(), "<uuid>");
logHandler.addForbiddenToken("Setting user: " + obj.getLoginResult().getUserName(), "<player>");
logHandler.start();
} catch(Exception e) {
HMCLog.err("", e);
}
monitor.registerPrintlnEvent(new PrintlnProcessor(obj, os));
monitor.start();
});
HMCLApi.EVENT_BUS.channel(LaunchSucceededEvent.class).register(p -> {
int state = ((HMCLGameLauncher.GameLauncherTag) ((GameLauncher) p.getSource()).getTag()).state;
if (state == 1)
LAUNCH_FINISHER.accept(p);
else if (state == 2)
LAUNCH_SCRIPT_FINISHER.accept(p);
});
HMCLApi.EVENT_BUS.channel(JavaProcessStoppedEvent.class).register(event -> {
GameLauncher launcher = ((GameLauncher) ((ProcessMonitor) event.getSource()).getTag());
HMCLApi.EVENT_BUS.fireChannel(new LaunchingStateChangedEvent(launcher, LaunchingState.Done));
checkExit(unpackProcessMonitor(event.getSource()));
});
HMCLApi.EVENT_BUS.channel(JavaProcessExitedAbnormallyEvent.class).register(event -> {
ProcessMonitor monitor = (ProcessMonitor) event.getSource();
int exitCode = event.getValue().getExitCode();
HMCLog.err("The game exited abnormally, exit code: " + exitCode);
monitor.waitForCommandLineCompletion();
String[] logs = event.getValue().getStdOutLines().toArray(new String[0]);
String errorText = null;
for (String s : logs) {
int pos = s.lastIndexOf("#@!@#");
if (pos >= 0 && pos < s.length() - "#@!@#".length() - 1) {
errorText = s.substring(pos + "#@!@#".length()).trim();
break;
}
}
String msg = C.i18n("launch.exited_abnormally") + " exit code: " + exitCode;
if (errorText != null)
msg += ", advice: " + MinecraftCrashAdvicer.getAdvice(FileUtils.readQuietly(new File(errorText)));
HMCLog.err(msg);
SwingUtilities.invokeLater(() -> LogWindow.INSTANCE.setVisible(true));
noExitThisTime = true;
});
HMCLApi.EVENT_BUS.channel(JVMLaunchFailedEvent.class).register(event -> {
int exitCode = event.getValue().getExitCode();
HMCLog.err("Cannot create jvm, exit code: " + exitCode);
SwingUtilities.invokeLater(() -> LogWindow.INSTANCE.setVisible(true));
noExitThisTime = true;
});
}
static LauncherVisibility unpackProcessMonitor(Object obj) {
GameLauncher launcher = ((GameLauncher) ((ProcessMonitor) obj).getTag());
HMCLGameLauncher.GameLauncherTag tag = (HMCLGameLauncher.GameLauncherTag) launcher.getTag();
return tag.launcherVisibility;
}
boolean noExitThisTime = false;
void runGame(Profile profile) {
MainFrame.INSTANCE.showMessage(C.i18n("ui.message.launching"));
profile.launcher().genLaunchCode(value -> {
DefaultPlugin.INSTANCE.saveAuthenticatorConfig();
((HMCLGameLauncher.GameLauncherTag) value.getTag()).state = 1;
}, MainFrame.INSTANCE::failed, Settings.getInstance().getAuthenticator().getPassword());
}
void testGame(Profile profile) {
MainFrame.INSTANCE.showMessage(C.i18n("ui.message.launching"));
profile.launcher().genLaunchCode(value -> {
DefaultPlugin.INSTANCE.saveAuthenticatorConfig();
((HMCLGameLauncher.GameLauncherTag) value.getTag()).state = 1;
((HMCLGameLauncher.GameLauncherTag) value.getTag()).launcherVisibility = LauncherVisibility.KEEP;
}, MainFrame.INSTANCE::failed, Settings.getInstance().getAuthenticator().getPassword());
}
void makeLaunchScript(Profile profile) {
MainFrame.INSTANCE.showMessage(C.i18n("ui.message.launching"));
profile.launcher().genLaunchCode(value -> {
DefaultPlugin.INSTANCE.saveAuthenticatorConfig();
((HMCLGameLauncher.GameLauncherTag) value.getTag()).state = 2;
}, MainFrame.INSTANCE::failed, Settings.getInstance().getAuthenticator().getPassword());
}
class PrintlnProcessor implements Consumer<PrintlnEvent> {
GameLauncher launcher;
PipedOutputStream os;
public PrintlnProcessor(GameLauncher launcher, PipedOutputStream os) {
this.launcher = launcher;
this.os = os;
}
@Override
public void accept(PrintlnEvent t) {
String log = t.getLine();
if (!t.isError() && logHandler != null) {
logHandler.newLogLine(log + C.LINE_SEPARATOR);
}
else System.err.println(t.getLine());
HMCLGameLauncher.GameLauncherTag tag = (HMCLGameLauncher.GameLauncherTag) launcher.getTag();
LauncherVisibility l = tag.launcherVisibility;
if (t.getLine().contains("LWJGL Version: ") && l != LauncherVisibility.KEEP)
SwingUtilities.invokeLater(() -> {
if (l != LauncherVisibility.HIDE_AND_REOPEN)
MainFrame.INSTANCE.dispose();
else { // If current state is 'hide and reopen', closes the main window and reset the state to normal.
MainFrame.INSTANCE.setVisible(false);
HMCLApi.EVENT_BUS.fireChannel(new LaunchingStateChangedEvent(launcher, LaunchingState.Done));
}
});
}
}
private static final Consumer<LaunchingStateChangedEvent> LAUNCHING_STATE_CHANGED = t -> {
String message = null;
switch (t.getValue()) {
case LoggingIn:
message = "launch.state.logging_in";
break;
case GeneratingLaunchingCodes:
message = "launch.state.generating_launching_codes";
break;
case DownloadingLibraries:
message = "launch.state.downloading_libraries";
break;
case DecompressingNatives:
message = "launch.state.decompressing_natives";
break;
case WaitingForGameLaunching:
message = "launch.state.waiting_launching";
break;
case Done:
MainFrame.INSTANCE.closeMessage();
return;
}
MainFrame.INSTANCE.showMessage(C.i18n(message));
};
private static final Consumer<LaunchSucceededEvent> LAUNCH_FINISHER = event -> {
try {
((GameLauncher) event.getSource()).launch(event.getValue());
} catch (IOException e) {
MainFrame.INSTANCE.failed(C.i18n("launch.failed_creating_process") + "\n" + e.getMessage());
HMCLog.err("Failed to launch when creating a new process.", e);
}
};
private void checkExit(LauncherVisibility v) {
if (v == LauncherVisibility.HIDE_AND_REOPEN) {
MainFrame.INSTANCE.setVisible(true);
} else if (v != LauncherVisibility.KEEP && !LogWindow.INSTANCE.isVisible() && !noExitThisTime) {
System.exit(0);
} else {
noExitThisTime = false;
}
}
private static final Consumer<LaunchSucceededEvent> LAUNCH_SCRIPT_FINISHER = event -> {
try {
String s = MessageBox.showInputDialog(C.i18n("mainwindow.enter_script_name"));
if (StrUtils.isNotBlank(s))
MessageBox.show(C.i18n("mainwindow.make_launch_succeed") + " " + ((GameLauncher) event.getSource()).makeLauncher(s, event.getValue()).getAbsolutePath());
} catch (IOException ex) {
MessageBox.show(C.i18n("mainwindow.make_launch_script_failed"));
HMCLog.err("Failed to create script file.", ex);
}
MainFrame.INSTANCE.closeMessage();
};
}
@@ -1,245 +0,0 @@
<?xml version="1.0" encoding="UTF-8" ?>
<Form version="1.3" maxVersion="1.8" type="org.netbeans.modules.form.forminfo.JFrameFormInfo">
<Properties>
<Property name="defaultCloseOperation" type="int" value="2"/>
<Property name="title" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/jackhuang/hmcl/I18N.properties" key="logwindow.title" replaceFormat="C.i18n(&quot;{key}&quot;)"/>
</Property>
</Properties>
<SyntheticProperties>
<SyntheticProperty name="formSizePolicy" type="int" value="1"/>
<SyntheticProperty name="generateCenter" type="boolean" value="false"/>
</SyntheticProperties>
<Events>
<EventHandler event="windowClosing" listener="java.awt.event.WindowListener" parameters="java.awt.event.WindowEvent" handler="formWindowClosing"/>
</Events>
<AuxValues>
<AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="0"/>
<AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/>
<AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/>
<AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="false"/>
<AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="false"/>
<AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="1"/>
<AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
<AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
<AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
</AuxValues>
<Layout>
<DimensionLayout dim="0">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" attributes="0">
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="1" attributes="0">
<Component id="btnContact" min="-2" max="-2" attributes="0"/>
<EmptySpace pref="144" max="32767" attributes="0"/>
<Component id="btnTerminateGame" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="btnCopy" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="btnClear" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="btnClose" min="-2" max="-2" attributes="0"/>
</Group>
<Component id="lblCrash" alignment="0" max="32767" attributes="0"/>
<Group type="102" alignment="0" attributes="0">
<Component id="lblShowLines" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="cboShowLines" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="lblSearch" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="txtSearch" max="32767" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="btnFatal" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="btnError" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="btnWarn" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="btnInfo" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="btnDebug" min="-2" max="-2" attributes="0"/>
</Group>
<Component id="pnlLog" alignment="0" max="32767" attributes="0"/>
</Group>
<EmptySpace max="-2" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
<DimensionLayout dim="1">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0">
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="3" attributes="0">
<Component id="lblShowLines" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="cboShowLines" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="btnDebug" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="btnInfo" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="btnWarn" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="btnError" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="btnFatal" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="txtSearch" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="lblSearch" alignment="3" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace max="-2" attributes="0"/>
<Component id="lblCrash" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="pnlLog" pref="281" max="32767" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="3" attributes="0">
<Component id="btnClear" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="btnClose" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="btnCopy" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="btnContact" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="btnTerminateGame" alignment="3" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace max="-2" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
</Layout>
<SubComponents>
<Component class="javax.swing.JButton" name="btnClear">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/jackhuang/hmcl/I18N.properties" key="ui.button.clear" replaceFormat="C.i18n(&quot;{key}&quot;)"/>
</Property>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="btnClearActionPerformed"/>
</Events>
</Component>
<Component class="javax.swing.JButton" name="btnClose">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/jackhuang/hmcl/I18N.properties" key="ui.button.close" replaceFormat="C.i18n(&quot;{key}&quot;)"/>
</Property>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="btnCloseActionPerformed"/>
</Events>
</Component>
<Component class="javax.swing.JButton" name="btnCopy">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/jackhuang/hmcl/I18N.properties" key="ui.button.copy" replaceFormat="C.i18n(&quot;{key}&quot;)"/>
</Property>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="btnCopyActionPerformed"/>
</Events>
</Component>
<Component class="javax.swing.JLabel" name="lblCrash">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/jackhuang/hmcl/I18N.properties" key="ui.label.crashing" replaceFormat="C.i18n(&quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JButton" name="btnContact">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/jackhuang/hmcl/lang/I18N.properties" key="logwindow.contact" replaceFormat="C.i18n(&quot;{key}&quot;)"/>
</Property>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="btnContactActionPerformed"/>
</Events>
</Component>
<Component class="javax.swing.JButton" name="btnTerminateGame">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/jackhuang/hmcl/I18N.properties" key="logwindow.terminate_game" replaceFormat="C.i18n(&quot;{key}&quot;)"/>
</Property>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="btnTerminateGameActionPerformed"/>
</Events>
</Component>
<Container class="javax.swing.JScrollPane" name="pnlLog">
<AuxValues>
<AuxValue name="autoScrollPane" type="java.lang.Boolean" value="true"/>
</AuxValues>
<Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/>
<SubComponents>
<Component class="javax.swing.JTextPane" name="txtLog">
<Properties>
<Property name="editable" type="boolean" value="false"/>
</Properties>
<AuxValues>
<AuxValue name="JavaCodeGenerator_CreateCodeCustom" type="java.lang.String" value="new JLineWrapTextPane()"/>
</AuxValues>
</Component>
</SubComponents>
</Container>
<Component class="javax.swing.JLabel" name="lblShowLines">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/jackhuang/hmcl/lang/I18N.properties" key="logwindow.show_lines" replaceFormat="C.i18n(&quot;{key}&quot;)"/>
</Property>
<Property name="toolTipText" type="java.lang.String" value=""/>
</Properties>
</Component>
<Component class="javax.swing.JComboBox" name="cboShowLines">
<Properties>
<Property name="model" type="javax.swing.ComboBoxModel" editor="org.netbeans.modules.form.editors2.ComboBoxModelEditor">
<StringArray count="3">
<StringItem index="0" value="100"/>
<StringItem index="1" value="1000"/>
<StringItem index="2" value="5000"/>
</StringArray>
</Property>
</Properties>
<Events>
<EventHandler event="itemStateChanged" listener="java.awt.event.ItemListener" parameters="java.awt.event.ItemEvent" handler="cboShowLinesItemStateChanged"/>
</Events>
<AuxValues>
<AuxValue name="JavaCodeGenerator_TypeParameters" type="java.lang.String" value="&lt;String&gt;"/>
</AuxValues>
</Component>
<Component class="javax.swing.JToggleButton" name="btnDebug">
<Properties>
<Property name="text" type="java.lang.String" value="0 debug"/>
</Properties>
</Component>
<Component class="javax.swing.JToggleButton" name="btnInfo">
<Properties>
<Property name="text" type="java.lang.String" value="0 info"/>
</Properties>
</Component>
<Component class="javax.swing.JToggleButton" name="btnWarn">
<Properties>
<Property name="text" type="java.lang.String" value="0 warn"/>
</Properties>
</Component>
<Component class="javax.swing.JButton" name="btnError">
<Properties>
<Property name="text" type="java.lang.String" value="0 error"/>
</Properties>
</Component>
<Component class="javax.swing.JButton" name="btnFatal">
<Properties>
<Property name="text" type="java.lang.String" value="0 fatal"/>
</Properties>
</Component>
<Component class="javax.swing.JTextField" name="txtSearch">
<Properties>
<Property name="toolTipText" type="java.lang.String" value=""/>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="txtSearchActionPerformed"/>
</Events>
</Component>
<Component class="javax.swing.JLabel" name="lblSearch">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/jackhuang/hmcl/lang/I18N.properties" key="logwindow.search" replaceFormat="C.i18n(&quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
</SubComponents>
</Form>
@@ -1,425 +0,0 @@
/*
* Hello Minecraft!.
* Copyright (C) 2013 huangyuhui <huanghongxun2008@126.com>
*
* 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 3 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. If not, see {http://www.gnu.org/licenses/}.
*/
package org.jackhuang.hmcl.ui;
import java.io.PrintStream;
import java.util.Deque;
import java.util.LinkedList;
import javax.swing.SwingUtilities;
import javax.swing.text.BadLocationException;
import javax.swing.text.Document;
import javax.swing.text.SimpleAttributeSet;
import javax.swing.text.StyleConstants;
import javax.swing.text.StyledDocument;
import org.jackhuang.hmcl.util.C;
import org.jackhuang.hmcl.api.HMCLog;
import org.jackhuang.hmcl.util.log.Level;
import org.jackhuang.hmcl.api.func.NonFunction;
import org.jackhuang.hmcl.setting.Settings;
import org.jackhuang.hmcl.util.DoubleOutputStream;
import org.jackhuang.hmcl.util.Utils;
import org.jackhuang.hmcl.util.sys.ProcessMonitor;
import org.jackhuang.hmcl.util.ui.SwingUtils;
/**
*
* @author huangyuhui
*/
public class LogWindow extends javax.swing.JFrame {
public static LogWindowOutputStream outputStream;
NonFunction<Boolean> listener;
/**
* Creates new form LogWindow
*/
public LogWindow() {
initComponents();
DoubleOutputStream out = new DoubleOutputStream(outputStream = new LogWindowOutputStream(this, Level.INFO), System.out);
System.setOut(new PrintStream(out));
DoubleOutputStream err = new DoubleOutputStream(new LogWindowOutputStream(this, Level.ERROR), System.err);
System.setErr(new PrintStream(err));
SwingUtilities.invokeLater(() -> {
setLocationRelativeTo(null);
//txtLog.setEditable(false);
txtLog.setFont(Settings.getInstance().getConsoleFont());
cboShowLines.setSelectedItem(String.valueOf(Settings.getInstance().getLogLines()));
});
}
public static final LogWindow INSTANCE = new LogWindow();
/**
* This method is called from within the constructor to initialize the form.
* WARNING: Do NOT modify this code. The content of this method is always
* regenerated by the Form Editor.
*/
@SuppressWarnings("unchecked")
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
private void initComponents() {
btnClear = new javax.swing.JButton();
btnClose = new javax.swing.JButton();
btnCopy = new javax.swing.JButton();
lblCrash = new javax.swing.JLabel();
btnContact = new javax.swing.JButton();
btnTerminateGame = new javax.swing.JButton();
pnlLog = new javax.swing.JScrollPane();
txtLog = new JLineWrapTextPane();
lblShowLines = new javax.swing.JLabel();
cboShowLines = new javax.swing.JComboBox<>();
btnDebug = new javax.swing.JToggleButton();
btnInfo = new javax.swing.JToggleButton();
btnWarn = new javax.swing.JToggleButton();
btnError = new javax.swing.JButton();
btnFatal = new javax.swing.JButton();
txtSearch = new javax.swing.JTextField();
lblSearch = new javax.swing.JLabel();
setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE);
setTitle(C.i18n("logwindow.title")); // NOI18N
addWindowListener(new java.awt.event.WindowAdapter() {
public void windowClosing(java.awt.event.WindowEvent evt) {
formWindowClosing(evt);
}
});
btnClear.setText(C.i18n("ui.button.clear")); // NOI18N
btnClear.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
btnClearActionPerformed(evt);
}
});
btnClose.setText(C.i18n("ui.button.close")); // NOI18N
btnClose.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
btnCloseActionPerformed(evt);
}
});
btnCopy.setText(C.i18n("ui.button.copy")); // NOI18N
btnCopy.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
btnCopyActionPerformed(evt);
}
});
lblCrash.setText(C.i18n("ui.label.crashing")); // NOI18N
btnContact.setText(C.i18n("logwindow.contact")); // NOI18N
btnContact.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
btnContactActionPerformed(evt);
}
});
btnTerminateGame.setText(C.i18n("logwindow.terminate_game")); // NOI18N
btnTerminateGame.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
btnTerminateGameActionPerformed(evt);
}
});
txtLog.setEditable(false);
pnlLog.setViewportView(txtLog);
lblShowLines.setText(C.i18n("logwindow.show_lines")); // NOI18N
lblShowLines.setToolTipText("");
cboShowLines.setModel(new javax.swing.DefaultComboBoxModel<>(new String[] { "100", "1000", "5000" }));
cboShowLines.addItemListener(new java.awt.event.ItemListener() {
public void itemStateChanged(java.awt.event.ItemEvent evt) {
cboShowLinesItemStateChanged(evt);
}
});
btnDebug.setText("0 debug");
btnInfo.setText("0 info");
btnWarn.setText("0 warn");
btnError.setText("0 error");
btnFatal.setText("0 fatal");
txtSearch.setToolTipText("");
txtSearch.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
txtSearchActionPerformed(evt);
}
});
lblSearch.setText(C.i18n("logwindow.search")); // NOI18N
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
getContentPane().setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addContainerGap()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
.addComponent(btnContact)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 144, Short.MAX_VALUE)
.addComponent(btnTerminateGame)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(btnCopy)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(btnClear)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(btnClose))
.addComponent(lblCrash, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addGroup(layout.createSequentialGroup()
.addComponent(lblShowLines)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(cboShowLines, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(lblSearch)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(txtSearch)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(btnFatal)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(btnError)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(btnWarn)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(btnInfo)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(btnDebug))
.addComponent(pnlLog))
.addContainerGap())
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addContainerGap()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(lblShowLines)
.addComponent(cboShowLines, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(btnDebug)
.addComponent(btnInfo)
.addComponent(btnWarn)
.addComponent(btnError)
.addComponent(btnFatal)
.addComponent(txtSearch, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(lblSearch))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(lblCrash)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(pnlLog, javax.swing.GroupLayout.DEFAULT_SIZE, 281, Short.MAX_VALUE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(btnClear)
.addComponent(btnClose)
.addComponent(btnCopy)
.addComponent(btnContact)
.addComponent(btnTerminateGame))
.addContainerGap())
);
pack();
}// </editor-fold>//GEN-END:initComponents
private void btnCloseActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnCloseActionPerformed
if (listener != null && listener.apply())
terminateGames();
SwingUtils.exitIfNoWindow(this, true);
}//GEN-LAST:event_btnCloseActionPerformed
private void btnClearActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnClearActionPerformed
clean();
}//GEN-LAST:event_btnClearActionPerformed
private void btnCopyActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnCopyActionPerformed
Utils.setClipboard(this.txtLog.getText());
}//GEN-LAST:event_btnCopyActionPerformed
private void btnContactActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnContactActionPerformed
SwingUtils.openLink(C.URL_CONTACT);
}//GEN-LAST:event_btnContactActionPerformed
private void btnTerminateGameActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnTerminateGameActionPerformed
terminateGames();
}//GEN-LAST:event_btnTerminateGameActionPerformed
private void formWindowClosing(java.awt.event.WindowEvent evt) {//GEN-FIRST:event_formWindowClosing
if (listener != null && listener.apply())
terminateGames();
SwingUtils.exitIfNoWindow(this);
}//GEN-LAST:event_formWindowClosing
private void cboShowLinesItemStateChanged(java.awt.event.ItemEvent evt) {//GEN-FIRST:event_cboShowLinesItemStateChanged
Settings.getInstance().setLogLines(Integer.parseInt(cboShowLines.getSelectedItem().toString()));
}//GEN-LAST:event_cboShowLinesItemStateChanged
private void txtSearchActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_txtSearchActionPerformed
if (evt.getSource() != txtSearch || txtSearch.getText().isEmpty())
return;
try {
if (!s.equals(txtSearch.getText()))
pos = 0;
StyledDocument d = txtLog.getStyledDocument();
s = txtSearch.getText();
String content = d.getText(0, d.getLength());
int x = content.indexOf(s, pos);
if (x == -1) {
pos = 0;
x = content.indexOf(s, pos);
}
if (x == -1)
return;
int len = s.length();
pos = x + len;
SimpleAttributeSet set = new SimpleAttributeSet(d.getLogicalStyle(x).copyAttributes());
StyleConstants.setBackground(set, txtLog.getSelectionColor());
StyleConstants.setForeground(set, txtLog.getSelectedTextColor());
d.setCharacterAttributes(x, len, set, true);
set = new SimpleAttributeSet(d.getLogicalStyle(lastX).copyAttributes());
StyleConstants.setBackground(set, txtLog.getBackground());
StyleConstants.setForeground(set, txtLog.getForeground());
d.setCharacterAttributes(lastX, lastLen, set, true);
txtLog.select(x, pos);
lastX = x;
lastLen = len;
} catch (BadLocationException e) {
}
}//GEN-LAST:event_txtSearchActionPerformed
String s = "";
int pos = 0, lastX = 0, lastLen = 0;
void terminateGames() {
ProcessMonitor.stopAll();
}
int removedLength = 0;
Deque<Integer> offsets = new LinkedList<>();
int fatals = 0, errors = 0, warns = 0, infos = 0, debugs = 0;
public void log(final String status, final Level c) {
if (!isVisible())
return;
SwingUtilities.invokeLater(() -> {
Document d = txtLog.getStyledDocument();
try { // prevent too much memory used.
if (Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory() > 1l * 1024 * 1024 * 256) {
d.remove(0, d.getLength());
offsets.clear();
removedLength = 0;
}
} catch (Exception ex) {
HMCLog.err("Failed to clear the text component", ex);
}
String newStatus = status.replace("\t", " ");
SimpleAttributeSet sas = new SimpleAttributeSet();
StyleConstants.setForeground(sas, c.COLOR);
try {
offsets.add(d.getLength() + removedLength);
d.insertString(d.getLength(), newStatus, sas);
} catch (Exception ex) {
HMCLog.err("Failed to insert \"" + newStatus + "\" to " + d.getLength(), ex);
}
switch (c) {
case FATAL:
btnFatal.setText(++fatals + " fatals");
break;
case ERROR:
btnError.setText(++errors + " errors");
break;
case WARN:
btnWarn.setText(++warns + " warns");
break;
case INFO:
btnInfo.setText(++infos + " infos");
break;
case DEBUG:
btnDebug.setText(++debugs + " debugs");
break;
}
int maxLines = Integer.parseInt(cboShowLines.getSelectedItem().toString());
while (offsets.size() > maxLines) {
int start = offsets.pollFirst();
int end = offsets.peekFirst();
try {
d.remove(start - removedLength, end - start); // start - removedLength must become 0
removedLength = end;
} catch (Exception ignore) {
}
}
});
}
public void setExit(NonFunction<Boolean> exit) {
this.listener = exit;
}
public void clean() {
txtLog.setText("");
}
@Override
public void setVisible(boolean b) {
txtLog.setFont(Settings.getInstance().getConsoleFont());
lblCrash.setVisible(false);
btnContact.setVisible(false);
super.setVisible(b);
}
public void showAsCrashWindow(boolean out_date) {
txtLog.setFont(Settings.getInstance().getConsoleFont());
if (out_date) {
lblCrash.setVisible(false);
btnContact.setVisible(false);
lblCrash.setText(C.i18n("ui.label.crashing_out_dated"));
} else {
lblCrash.setVisible(true);
btnContact.setVisible(true);
lblCrash.setText(C.i18n("ui.label.crashing"));
}
super.setVisible(true);
}
// Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.JButton btnClear;
private javax.swing.JButton btnClose;
private javax.swing.JButton btnContact;
private javax.swing.JButton btnCopy;
private javax.swing.JToggleButton btnDebug;
private javax.swing.JButton btnError;
private javax.swing.JButton btnFatal;
private javax.swing.JToggleButton btnInfo;
private javax.swing.JButton btnTerminateGame;
private javax.swing.JToggleButton btnWarn;
private javax.swing.JComboBox<String> cboShowLines;
private javax.swing.JLabel lblCrash;
private javax.swing.JLabel lblSearch;
private javax.swing.JLabel lblShowLines;
private javax.swing.JScrollPane pnlLog;
private javax.swing.JTextPane txtLog;
private javax.swing.JTextField txtSearch;
// End of variables declaration//GEN-END:variables
}
@@ -1,83 +0,0 @@
/*
* Hello Minecraft!.
* Copyright (C) 2013 huangyuhui <huanghongxun2008@126.com>
*
* 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 3 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. If not, see {http://www.gnu.org/licenses/}.
*/
package org.jackhuang.hmcl.ui;
import java.io.OutputStream;
import java.util.Objects;
import javax.swing.SwingUtilities;
import org.jackhuang.hmcl.util.log.Level;
/**
*
* @author huangyuhui
*/
public class LogWindowOutputStream extends OutputStream {
private final LogWindow txt;
private final Level sas;
public LogWindowOutputStream(LogWindow logWindow, Level l) {
txt = Objects.requireNonNull(logWindow);
sas = Objects.requireNonNull(l);
}
@Override
public final void write(byte[] arr) {
write(arr, 0, arr.length);
}
@Override
public final void write(byte[] arr, int off, int len) {
append(new String(arr, off, len));
}
final Object obj = new Object();
Level lastLevel = null;
private void append(final String str) {
synchronized(this) {
if (manual) return;
}
SwingUtilities.invokeLater(() -> {
Level level = Level.guessLevel(str);
if (level == null) level = lastLevel;
else lastLevel = level;
txt.log(str, Level.mergeLevel(sas, level));
});
}
@Override
public final void write(int i) {
append(new String(new byte[] { (byte) i }));
}
boolean manual = false;
public void log(String s, Level l) {
synchronized(this) {
manual = true;
System.out.print(s);
manual = false;
}
if (l == null) append(s);
else
SwingUtilities.invokeLater(() -> {
txt.log(s, l);
});
}
}
@@ -1,504 +0,0 @@
/*
* Hello Minecraft! Launcher.
* Copyright (C) 2013 huangyuhui <huanghongxun2008@126.com>
*
* 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 3 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. If not, see {http://www.gnu.org/licenses/}.
*/
package org.jackhuang.hmcl.ui;
import org.jackhuang.hmcl.util.ui.GaussionPanel;
import org.jackhuang.hmcl.util.ui.IRepaint;
import java.awt.BorderLayout;
import java.awt.CardLayout;
import java.awt.Color;
import java.awt.Cursor;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridLayout;
import java.awt.Rectangle;
import java.awt.Transparency;
import java.awt.Window;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;
import java.awt.image.BufferedImage;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import javax.swing.BorderFactory;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import org.jackhuang.hmcl.api.HMCLApi;
import org.jackhuang.hmcl.Main;
import org.jackhuang.hmcl.api.PluginManager;
import org.jackhuang.hmcl.api.event.config.ThemeChangedEvent;
import org.jackhuang.hmcl.setting.Settings;
import org.jackhuang.hmcl.util.C;
import org.jackhuang.hmcl.util.ui.MessageBox;
import org.jackhuang.hmcl.util.StrUtils;
import org.jackhuang.hmcl.api.HMCLog;
import org.jackhuang.hmcl.util.ui.BasicColors;
import org.jackhuang.hmcl.util.ui.DropShadowBorder;
import org.jackhuang.hmcl.util.ui.GraphicsUtils;
import org.jackhuang.hmcl.util.ui.SwingUtils;
import org.jackhuang.hmcl.util.ui.TintablePanel;
import org.jackhuang.hmcl.api.auth.IAuthenticator;
import org.jackhuang.hmcl.api.ui.Theme;
import org.jackhuang.hmcl.api.ui.TopTabPage;
/**
*
* @author huangyuhui
*/
public final class MainFrame extends DraggableFrame implements IRepaint {
public static final MainFrame INSTANCE = new MainFrame();
TintablePanel centralPanel;
JPanel header, infoSwap, realPanel;
CardLayout infoLayout;
JLabel windowTitle;
GaussionPanel backgroundLabel;
DropShadowBorder border;
boolean enableShadow;
String defaultTitle;
private int tempW, tempH;
void setContentSize(int w, int h) {
setSize(w, h);
tempW = w;
tempH = h;
}
MainFrame() {
setUndecorated(!Settings.getInstance().isDecorated());
defaultTitle = isUndecorated() ? Main.makeTitle() : "";
enableShadow = Settings.getInstance().isEnableShadow() && isUndecorated();
if (enableShadow)
setContentSize(834, 542);
else
setContentSize(802, 511);
setDefaultCloseOperation(EXIT_ON_CLOSE);
setTitle(Main.makeTitle());
initComponents();
loadBackground();
setLocationRelativeTo(null);
if (MainFrame.this.isUndecorated())
setResizable(false);
this.addWindowListener(new WindowListener() {
@Override
public void windowOpened(WindowEvent e) {
}
@Override
public void windowClosing(WindowEvent e) {
closing();
}
@Override
public void windowClosed(WindowEvent e) {
}
@Override
public void windowIconified(WindowEvent e) {
}
@Override
public void windowDeiconified(WindowEvent e) {
}
@Override
public void windowActivated(WindowEvent e) {
if (!MainFrame.this.isUndecorated()) {
int w = tempW + getWidth() - getContentPane().getWidth(), h = tempH + getHeight() - getContentPane().getHeight();
setSize(w, h);
setResizable(false);
setLocationRelativeTo(null);
}
}
@Override
public void windowDeactivated(WindowEvent e) {
}
});
if (enableShadow)
try {
setBackground(new Color(0, 0, 0, 0));
getRootPane().setBorder(border = new DropShadowBorder(borderColor, 4));
} catch (Throwable ex) {
HMCLog.err("Failed to set window transparent.", ex);
Settings.getInstance().setEnableShadow(false);
setSize(802, 511);
}
((JPanel) getContentPane()).setOpaque(true);
HMCLApi.EVENT_BUS.channel(ThemeChangedEvent.class).register(x -> reloadColor(x.getValue()));
SwingUtilities.invokeLater(() -> selectTab("main"));
}
private void initComponents() {
setLayout(null);
realPanel = new JPanel();
realPanel.setLayout(null);
header = new JPanel();
header.setBounds(0, 0, 800, 30);
realPanel.add(header);
header.setOpaque(true);
header.setLayout(new BoxLayout(header, BoxLayout.LINE_AXIS));
header.setBorder(BorderFactory.createEmptyBorder(0, 2, 0, 5));
header.setBackground(borderColor);
header.setForeground(BasicColors.COLOR_WHITE_TEXT);
ImageIcon headerIcon = Main.getIcon("icon.png");
this.setIconImage(headerIcon.getImage());
headerIcon = SwingUtils.scaleImage(headerIcon, 16, 16);
JLabel headerLabel = new JLabel(headerIcon);
headerLabel.setBorder(BorderFactory.createEmptyBorder(0, 8, 0, 0));
header.add(headerLabel);
header.add(Box.createRigidArea(new Dimension(8, 0)));
PluginManager.fireAddTab(this, this::initializeTab);
header.add(Box.createHorizontalGlue());
JPanel rightHeaderPanel = new JPanel();
rightHeaderPanel.setOpaque(false);
rightHeaderPanel.setLayout(new BoxLayout(rightHeaderPanel, BoxLayout.PAGE_AXIS));
rightHeaderPanel.setBorder(BorderFactory.createEmptyBorder(2, 0, 2, 0));
JPanel windowGadgetPanel = new JPanel();
windowGadgetPanel.setOpaque(false);
windowGadgetPanel.setLayout(new BoxLayout(windowGadgetPanel, BoxLayout.LINE_AXIS));
windowGadgetPanel.setAlignmentX(1.0F);
if (!Settings.getInstance().isDecorated()) {
ImageIcon minimizeIcon = Main.getIcon("minimize.png");
JButton minimizeButton = new JButton(minimizeIcon);
minimizeButton.setBorder(BorderFactory.createEmptyBorder());
minimizeButton.setContentAreaFilled(false);
minimizeButton.setCursor(new Cursor(12));
minimizeButton.setFocusable(false);
minimizeButton.addActionListener((e) -> MainFrame.this.minimizeWindow());
windowGadgetPanel.add(minimizeButton);
ImageIcon closeIcon = Main.getIcon("close.png");
JButton closeButton = new JButton(closeIcon);
closeButton.setBorder(BorderFactory.createEmptyBorder());
closeButton.setContentAreaFilled(false);
closeButton.addActionListener((e) -> MainFrame.this.closeWindow());
closeButton.setCursor(new Cursor(12));
closeButton.setFocusable(false);
windowGadgetPanel.add(closeButton);
}
rightHeaderPanel.add(windowGadgetPanel);
windowTitle = new JLabel(defaultTitle);
windowTitle.setForeground(BasicColors.COLOR_WHITE_TEXT);
header.add(windowTitle);
header.add(Box.createHorizontalGlue());
header.add(rightHeaderPanel);
this.centralPanel = new TintablePanel();
this.centralPanel.setTintColor(BasicColors.COLOR_CENTRAL_BACK);
realPanel.add(this.centralPanel);
JPanel truePanel = new JPanel();
truePanel.setLayout(new BorderLayout());
this.infoSwap = new JPanel();
this.infoLayout = new CardLayout();
this.infoSwap.setLayout(infoLayout);
this.infoSwap.setOpaque(false);
tabWrapper = new JPanel[tabHeader.size()];
for (int i = 0; i < tabHeader.size(); i++) {
tabWrapper[i] = new JPanel();
tabWrapper[i].setLayout(new GridLayout());
infoSwap.add(tabWrapper[i], tabHeader.get(i).getActionCommand());
}
truePanel.add(this.infoSwap, "Center");
centralPanel.setLayout(null);
centralPanel.add(truePanel);
truePanel.setBounds(0, 0, 800, 480);
centralPanel.setBounds(0, 30, 800, 480);
realPanel.setBounds(1, 0, 800, 511);
add(realPanel);
reloadColor(Settings.getInstance().getTheme());
}
private transient final ActionListener tabListener = e -> MainFrame.this.selectTab(e.getActionCommand());
private void initializeTab(TopTabPage inst, String cmd, String title) {
HeaderTab tab = new HeaderTab(title);
tab.setActionCommand(cmd);
tab.setForeground(BasicColors.COLOR_WHITE_TEXT);
tab.setBackground(borderColorDarker);
tab.setLayout(null);
tab.addActionListener(tabListener);
header.add(tab);
tabHeader.add(tab);
tabContent.add(inst);
}
private final List<HeaderTab> tabHeader = new ArrayList<>();
private JPanel tabWrapper[];
private final List<TopTabPage> tabContent = new ArrayList<>();
public void selectTab(String tabName) {
int chosen = -1;
TopTabPage onCreate = null, onSelect = null, lastPage = null;
for (int i = 0; i < tabHeader.size(); i++)
if (tabName.equalsIgnoreCase(tabHeader.get(i).getActionCommand())) {
if (!tabContent.get(i).isCreated()) {
onCreate = tabContent.get(i);
onCreate.setId(i);
tabWrapper[i].add(tabContent.get(i));
} else if (tabContent.get(i).isSelected())
continue;
chosen = i;
break;
}
if (chosen != -1) {
for (int i = 0; i < tabHeader.size(); i++)
if (i != chosen && tabContent.get(i) != null && tabContent.get(i).isSelected()) {
lastPage = tabContent.get(i);
lastPage.onLeave();
}
for (int i = 0; i < tabHeader.size(); i++)
if (i == chosen) {
for (int j = 0; j < tabHeader.size(); j++)
if (j != i)
tabHeader.get(j).setIsActive(false);
tabHeader.get(i).setIsActive(true);
onSelect = tabContent.get(i);
}
this.infoLayout.show(this.infoSwap, tabName);
if (onCreate != null)
onCreate.onCreate();
if (onSelect != null)
onSelect.onSelect(lastPage);
}
}
protected void closing() {
for (int i = 0; i < tabHeader.size(); i++)
if (tabContent.get(i) != null && tabContent.get(i).isSelected())
tabContent.get(i).onLeave();
}
protected void closeWindow() {
closing();
System.exit(0);
}
protected void minimizeWindow() {
setState(1);
}
ImageIcon background;
public void loadBackground() {
background = SwingUtils.searchBackgroundImage(Main.getIcon(Settings.getInstance().getTheme().settings.get("Customized.MainFrame.background_image")), Settings.getInstance().getBgpath(), 800, 480);
if (background != null) {
if (backgroundLabel == null) {
backgroundLabel = new GaussionPanel();
backgroundLabel.setDrawBackgroundLayer(true);
backgroundLabel.addAeroObject(backgroundLabel);
backgroundLabel.setBounds(0, 0, 800, 480);
centralPanel.add(backgroundLabel, -1);
}
backgroundLabel.setBackgroundImage(background.getImage());
} else
HMCLog.warn("No background image here! The background will be empty!");
}
public JPanel getTitleBar() {
return header;
}
boolean isShowedMessage = false;
public void closeMessage() {
if (isShowedMessage) {
isShowedMessage = false;
reloadColor(Settings.getInstance().getTheme());
windowTitle.setText(defaultTitle);
windowTitle.setForeground(Settings.UPDATE_CHECKER.isOutOfDate() ? Color.red : Color.white);
}
}
public void showMessage(String message) {
isShowedMessage = true;
borderColor = BasicColors.COLOR_RED;
borderColorDarker = BasicColors.COLOR_RED_DARKER;
header.setBackground(borderColor);
for (HeaderTab tab : tabHeader)
tab.setBackground(borderColorDarker);
if (border != null)
border.setColor(borderColor);
repaint();
windowTitle.setText(message);
windowTitle.setForeground(Color.white);
}
public static void showMainFrame() {
IAuthenticator l = Settings.getInstance().getAuthenticator();
if (StrUtils.isBlank(l.getUserName()))
SwingUtilities.invokeLater(() -> MainFrame.INSTANCE.showMessage(C.i18n("ui.message.first_load")));
if (l.hasPassword() && !l.isLoggedIn())
SwingUtilities.invokeLater(() -> MainFrame.INSTANCE.showMessage(C.i18n("ui.message.enter_password")));
INSTANCE.setVisible(true);
}
Color borderColor;
Color borderColorDarker;
private void initBorderColor() {
borderColor = UIManager.getColor("Customized.MainFrame.background");
borderColorDarker = UIManager.getColor("Customized.MainFrame.selected_background");
}
public void reloadColor(Theme t) {
if (isShowedMessage)
return;
for (Map.Entry<String, String> entry : t.settings.entrySet())
if (entry.getValue().startsWith("#"))
UIManager.put(entry.getKey(), GraphicsUtils.getWebColor(entry.getValue()));
initBorderColor();
if (border != null)
border.setColor(borderColor);
header.setBackground(borderColor);
for (HeaderTab tab : tabHeader)
tab.setBackground(borderColorDarker);
repaint();
}
private void paintImpl(Graphics g) {
int off = enableShadow ? 16 : 0, yoff = getInsets().top + off, xoff = getInsets().left + off;
int width = 800;
int height = header.getHeight() + 480 - 1;
super.paint(g);
g.setColor(borderColor);
g.drawLine(xoff, yoff, xoff, height + yoff + 1);
g.drawLine(xoff + width + 1, yoff, xoff + width + 1, height + yoff + 1);
g.drawLine(xoff, height + yoff + 1, xoff + width + 1, height + yoff + 1);
}
@Override
public void paint(Graphics g) {
int off = enableShadow ? 16 : 0;
int width = this.getWidth();
int height = this.getHeight();
int contentWidth = width - off - off;
int contentHeight = height - off - off;
if (!enableShadow || contentWidth <= 0 || contentHeight <= 0)
paintImpl(g);
else {
BufferedImage contentImage = new BufferedImage(contentWidth,
contentHeight, Transparency.OPAQUE);
Graphics2D contentG2d = contentImage.createGraphics();
contentG2d.translate(-off, -off);
paintImpl(g);
paintImpl(contentG2d);
contentG2d.dispose();
g.drawImage(contentImage, off, off, this);
}
}
public void invokeUpdate() {
defaultTitle = Main.makeTitle() + C.i18n("update.found");
windowTitle.addMouseListener(MouseListenerImpl.INSTANCE);
if (!isShowedMessage) {
windowTitle.setText(defaultTitle);
windowTitle.setForeground(Color.red);
}
}
@Override
public JComponent getRepaintComponent() {
return null;
}
@Override
public Window getRepaintWindow() {
return this;
}
@Override
public Collection<Rectangle> getRepaintRects() {
int off = MainFrame.INSTANCE.enableShadow ? 16 : 0, yoff = MainFrame.INSTANCE.getInsets().top + off, xoff = MainFrame.INSTANCE.getInsets().left + off;
int width = 800, height = MainFrame.INSTANCE.header.getHeight() + 480 - 1;
return Arrays.asList(new Rectangle(xoff, yoff, xoff, height + yoff + 1),
new Rectangle(xoff + width + 1, yoff, xoff + width + 1, height + yoff + 1),
new Rectangle(xoff, height + yoff + 1, xoff + width + 1, height + yoff + 1));
}
private static class MouseListenerImpl implements MouseListener {
public static final MouseListenerImpl INSTANCE = new MouseListenerImpl();
@Override
public void mouseClicked(MouseEvent e) {
Settings.UPDATE_CHECKER.checkOutdate();
}
@Override
public void mousePressed(MouseEvent e) {
}
@Override
public void mouseReleased(MouseEvent e) {
}
@Override
public void mouseEntered(MouseEvent e) {
}
@Override
public void mouseExited(MouseEvent e) {
}
}
public void failed(String s) {
if (s != null)
MessageBox.show(s);
closeMessage();
}
transient LaunchingUIDaemon daemon = new LaunchingUIDaemon();
}
@@ -1,304 +0,0 @@
<?xml version="1.0" encoding="UTF-8" ?>
<Form version="1.5" maxVersion="1.9" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
<AuxValues>
<AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="0"/>
<AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/>
<AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/>
<AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="false"/>
<AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="false"/>
<AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="1"/>
<AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
<AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
<AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
<AuxValue name="designerSize" type="java.awt.Dimension" value="-84,-19,0,5,115,114,0,18,106,97,118,97,46,97,119,116,46,68,105,109,101,110,115,105,111,110,65,-114,-39,-41,-84,95,68,20,2,0,2,73,0,6,104,101,105,103,104,116,73,0,5,119,105,100,116,104,120,112,0,0,1,-32,0,0,3,32"/>
</AuxValues>
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignAbsoluteLayout">
<Property name="useNullLayout" type="boolean" value="true"/>
</Layout>
<SubComponents>
<Container class="javax.swing.JPanel" name="pnlRoot">
<AuxValues>
<AuxValue name="JavaCodeGenerator_CreateCodeCustom" type="java.lang.String" value="new org.jackhuang.hmcl.launcher.ui.GaussionPanel()"/>
</AuxValues>
<Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignAbsoluteLayout" value="org.netbeans.modules.form.compat2.layouts.DesignAbsoluteLayout$AbsoluteConstraintsDescription">
<AbsoluteConstraints x="0" y="0" width="800" height="480"/>
</Constraint>
</Constraints>
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignAbsoluteLayout">
<Property name="useNullLayout" type="boolean" value="true"/>
</Layout>
<SubComponents>
<Container class="javax.swing.JPanel" name="pnlMore">
<Properties>
<Property name="background" type="java.awt.Color" editor="org.netbeans.beaninfo.editors.ColorEditor">
<Color blue="cc" green="cc" red="cc" type="rgb"/>
</Property>
<Property name="opaque" type="boolean" value="false"/>
</Properties>
<AuxValues>
<AuxValue name="JavaCodeGenerator_CreateCodeCustom" type="java.lang.String" value="new org.jackhuang.hmcl.launcher.ui.RepaintPage()"/>
<AuxValue name="JavaCodeGenerator_SerializeTo" type="java.lang.String" value="MainPagePanel_pnlMore"/>
</AuxValues>
<Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignAbsoluteLayout" value="org.netbeans.modules.form.compat2.layouts.DesignAbsoluteLayout$AbsoluteConstraintsDescription">
<AbsoluteConstraints x="0" y="0" width="190" height="480"/>
</Constraint>
</Constraints>
<Layout>
<DimensionLayout dim="0">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" attributes="0">
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Component id="pnlPassword" alignment="1" max="32767" attributes="0"/>
<Group type="102" alignment="0" attributes="0">
<Group type="103" groupAlignment="0" attributes="0">
<Component id="lblProfile" alignment="1" min="-2" max="-2" attributes="0"/>
<Component id="lblVersion" alignment="1" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Component id="cboProfiles" alignment="0" max="32767" attributes="0"/>
<Component id="cboVersions" alignment="0" max="32767" attributes="0"/>
</Group>
</Group>
<Group type="102" alignment="0" attributes="0">
<Group type="103" groupAlignment="0" attributes="0">
<Component id="lblUserName" alignment="0" min="-2" max="-2" attributes="0"/>
<Component id="lblLogin" alignment="0" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Component id="cboLoginMode" max="32767" attributes="0"/>
<Component id="txtPlayerName" max="32767" attributes="0"/>
</Group>
</Group>
<Component id="btnExportModpack" alignment="0" max="32767" attributes="0"/>
<Component id="btnImportModpack" alignment="0" max="32767" attributes="0"/>
</Group>
<EmptySpace max="-2" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
<DimensionLayout dim="1">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="1" attributes="0">
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="3" attributes="0">
<Component id="lblProfile" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="cboProfiles" alignment="3" min="-2" pref="26" max="-2" attributes="0"/>
</Group>
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="3" attributes="0">
<Component id="cboVersions" alignment="3" min="-2" pref="26" max="-2" attributes="0"/>
<Component id="lblVersion" alignment="3" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="3" attributes="0">
<Component id="lblLogin" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="cboLoginMode" alignment="3" min="-2" pref="26" max="-2" attributes="0"/>
</Group>
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="3" attributes="0">
<Component id="lblUserName" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="txtPlayerName" alignment="3" min="-2" pref="26" max="-2" attributes="0"/>
</Group>
<EmptySpace max="-2" attributes="0"/>
<Component id="pnlPassword" min="-2" pref="26" max="-2" attributes="0"/>
<EmptySpace pref="254" max="32767" attributes="0"/>
<Component id="btnImportModpack" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="btnExportModpack" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
</Layout>
<SubComponents>
<Component class="javax.swing.JTextField" name="txtPlayerName">
<Events>
<EventHandler event="focusGained" listener="java.awt.event.FocusListener" parameters="java.awt.event.FocusEvent" handler="txtPlayerNameFocusGained"/>
<EventHandler event="focusLost" listener="java.awt.event.FocusListener" parameters="java.awt.event.FocusEvent" handler="txtPlayerNameFocusLost"/>
<EventHandler event="keyPressed" listener="java.awt.event.KeyListener" parameters="java.awt.event.KeyEvent" handler="txtPlayerNameKeyPressed"/>
</Events>
</Component>
<Component class="javax.swing.JLabel" name="lblLogin">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/jackhuang/hmcl/lang/I18N.properties" key="login.type" replaceFormat="C.i18n(&quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JComboBox" name="cboLoginMode">
<Properties>
<Property name="model" type="javax.swing.ComboBoxModel" editor="org.netbeans.modules.form.editors2.ComboBoxModelEditor">
<StringArray count="0"/>
</Property>
</Properties>
<Events>
<EventHandler event="itemStateChanged" listener="java.awt.event.ItemListener" parameters="java.awt.event.ItemEvent" handler="cboLoginModeItemStateChanged"/>
</Events>
</Component>
<Component class="javax.swing.JLabel" name="lblUserName">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/jackhuang/hmcl/lang/I18N.properties" key="login.username" replaceFormat="C.i18n(&quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JLabel" name="lblProfile">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/jackhuang/hmcl/lang/I18N.properties" key="ui.label.profile" replaceFormat="C.i18n(&quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JComboBox" name="cboProfiles">
<Properties>
<Property name="model" type="javax.swing.ComboBoxModel" editor="org.netbeans.modules.form.editors2.ComboBoxModelEditor">
<StringArray count="0"/>
</Property>
</Properties>
<Events>
<EventHandler event="itemStateChanged" listener="java.awt.event.ItemListener" parameters="java.awt.event.ItemEvent" handler="cboProfilesItemStateChanged"/>
</Events>
</Component>
<Component class="javax.swing.JLabel" name="lblVersion">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/jackhuang/hmcl/lang/I18N.properties" key="ui.label.version" replaceFormat="C.i18n(&quot;{key}&quot;)"/>
</Property>
<Property name="toolTipText" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/jackhuang/hmcl/lang/I18N.properties" key="ui.label.version" replaceFormat="C.i18n(&quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JComboBox" name="cboVersions">
<Properties>
<Property name="model" type="javax.swing.ComboBoxModel" editor="org.netbeans.modules.form.editors2.ComboBoxModelEditor">
<StringArray count="0"/>
</Property>
</Properties>
<Events>
<EventHandler event="itemStateChanged" listener="java.awt.event.ItemListener" parameters="java.awt.event.ItemEvent" handler="cboVersionsItemStateChanged"/>
</Events>
<AuxValues>
<AuxValue name="JavaCodeGenerator_CreateCodeCustom" type="java.lang.String" value="new WideComboBox()"/>
</AuxValues>
</Component>
<Container class="javax.swing.JPanel" name="pnlPassword">
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignCardLayout"/>
<SubComponents>
<Container class="javax.swing.JPanel" name="pnlLogIn">
<Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignCardLayout" value="org.netbeans.modules.form.compat2.layouts.DesignCardLayout$CardConstraintsDescription">
<CardConstraints cardName="card2"/>
</Constraint>
</Constraints>
<Layout>
<DimensionLayout dim="0">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0">
<Component id="lblPassword" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="txtPassword" max="32767" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
<DimensionLayout dim="1">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="1" attributes="0">
<EmptySpace min="0" pref="0" max="32767" attributes="0"/>
<Group type="103" groupAlignment="3" attributes="0">
<Component id="lblPassword" alignment="3" min="-2" pref="22" max="-2" attributes="0"/>
<Component id="txtPassword" alignment="3" min="-2" pref="26" max="-2" attributes="0"/>
</Group>
</Group>
</Group>
</DimensionLayout>
</Layout>
<SubComponents>
<Component class="javax.swing.JLabel" name="lblPassword">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/jackhuang/hmcl/lang/I18N.properties" key="ui.label.password" replaceFormat="C.i18n(&quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JPasswordField" name="txtPassword">
<Events>
<EventHandler event="caretUpdate" listener="javax.swing.event.CaretListener" parameters="javax.swing.event.CaretEvent" handler="txtPasswordCaretUpdate"/>
<EventHandler event="focusGained" listener="java.awt.event.FocusListener" parameters="java.awt.event.FocusEvent" handler="txtPasswordFocusGained"/>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="txtPasswordActionPerformed"/>
<EventHandler event="keyPressed" listener="java.awt.event.KeyListener" parameters="java.awt.event.KeyEvent" handler="txtPasswordKeyPressed"/>
</Events>
</Component>
</SubComponents>
</Container>
<Container class="javax.swing.JPanel" name="pnlLogOut">
<Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignCardLayout" value="org.netbeans.modules.form.compat2.layouts.DesignCardLayout$CardConstraintsDescription">
<CardConstraints cardName="card3"/>
</Constraint>
</Constraints>
<Layout>
<DimensionLayout dim="0">
<Group type="103" groupAlignment="0" attributes="0">
<Component id="btnLogout" alignment="0" pref="170" max="32767" attributes="0"/>
</Group>
</DimensionLayout>
<DimensionLayout dim="1">
<Group type="103" groupAlignment="0" attributes="0">
<Component id="btnLogout" alignment="0" max="32767" attributes="0"/>
</Group>
</DimensionLayout>
</Layout>
<SubComponents>
<Component class="javax.swing.JButton" name="btnLogout">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/jackhuang/hmcl/lang/I18N.properties" key="ui.button.logout" replaceFormat="C.i18n(&quot;{key}&quot;)"/>
</Property>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="btnLogoutActionPerformed"/>
</Events>
</Component>
</SubComponents>
</Container>
</SubComponents>
</Container>
<Component class="javax.swing.JButton" name="btnImportModpack">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/jackhuang/hmcl/lang/I18N.properties" key="modpack.task.install" replaceFormat="C.i18n(&quot;{key}&quot;)"/>
</Property>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="btnImportModpackActionPerformed"/>
</Events>
</Component>
<Component class="javax.swing.JButton" name="btnExportModpack">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/jackhuang/hmcl/lang/I18N.properties" key="modpack.task.save" replaceFormat="C.i18n(&quot;{key}&quot;)"/>
</Property>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="btnExportModpackActionPerformed"/>
</Events>
</Component>
</SubComponents>
</Container>
</SubComponents>
</Container>
</SubComponents>
</Form>
@@ -1,553 +0,0 @@
/*
* Hello Minecraft! Launcher.
* Copyright (C) 2013 huangyuhui <huanghongxun2008@126.com>
*
* 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 3 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. If not, see {http://www.gnu.org/licenses/}.
*/
package org.jackhuang.hmcl.ui;
import org.jackhuang.hmcl.util.ui.Page;
import org.jackhuang.hmcl.util.ui.WideComboBox;
import org.jackhuang.hmcl.util.ui.GaussionPanel;
import java.awt.CardLayout;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.event.ItemEvent;
import java.awt.event.KeyEvent;
import javax.swing.DefaultComboBoxModel;
import javax.swing.SwingUtilities;
import javax.swing.filechooser.FileNameExtensionFilter;
import org.jackhuang.hmcl.api.HMCLApi;
import org.jackhuang.hmcl.api.event.config.AuthenticatorChangedEvent;
import org.jackhuang.hmcl.api.event.config.ProfileChangedEvent;
import org.jackhuang.hmcl.api.event.config.ProfileLoadingEvent;
import org.jackhuang.hmcl.api.event.launch.LaunchSucceededEvent;
import org.jackhuang.hmcl.api.event.launch.LaunchingState;
import org.jackhuang.hmcl.api.event.launch.LaunchingStateChangedEvent;
import org.jackhuang.hmcl.api.event.version.RefreshedVersionsEvent;
import org.jackhuang.hmcl.util.C;
import org.jackhuang.hmcl.core.auth.AbstractAuthenticator;
import org.jackhuang.hmcl.setting.Profile;
import org.jackhuang.hmcl.util.StrUtils;
import org.jackhuang.hmcl.core.version.MinecraftVersion;
import org.jackhuang.hmcl.setting.Settings;
import org.jackhuang.hmcl.core.mod.ModpackManager;
import org.jackhuang.hmcl.ui.modpack.ModpackWizard;
import org.jackhuang.hmcl.laf.button.CustomButton;
import org.jackhuang.hmcl.api.func.Consumer;
import org.jackhuang.hmcl.util.sys.FileUtils;
import org.jackhuang.hmcl.util.task.TaskWindow;
import org.jackhuang.hmcl.util.ui.GraphicsUtils;
import org.jackhuang.hmcl.util.ui.JSystemFileChooser;
import org.jackhuang.hmcl.util.ui.SwingUtils;
import org.jackhuang.hmcl.util.ui.wizard.api.WizardDisplayer;
import org.jackhuang.hmcl.api.auth.IAuthenticator;
import org.jackhuang.hmcl.laf.button.CustomButtonUI;
import org.jackhuang.hmcl.util.ui.MessageBox;
/**
*
* @author huangyuhui
*/
public class MainPagePanel extends Page {
public MainPagePanel() {
}
void initGui() {
initComponents();
animationEnabled = Settings.getInstance().isEnableAnimation();
pnlButtons = new javax.swing.JPanel();
pnlButtons.setLayout(null);
int w = 150, h = 50;
btnRun = new CustomButton();
btnRun.setBounds(0, 0, w, h);
Font font = btnRun.getFont();
Font newFont = new Font(font.getName(), font.getStyle(), 15);
pnlButtons.add(btnRun);
btnRun.setText(C.i18n("ui.button.run"));
btnRun.setFont(newFont);
btnRun.addActionListener(e -> MainFrame.INSTANCE.daemon.runGame(Settings.getLastProfile()));
btnRun.setUI(new CustomButtonUI());
pnlRoot.add(pnlButtons);
pnlButtons.setBounds(0, 0, w, h);
this.setSize(new Dimension(DEFAULT_WIDTH, DEFAULT_HEIGHT));
this.pnlButtons.setLocation(DEFAULT_WIDTH - pnlButtons.getWidth() - 25, DEFAULT_HEIGHT - pnlButtons.getHeight() - 25);
pnlMore.setBounds(0, 0, pnlMore.getWidth(), DEFAULT_HEIGHT);
pnlMore.setBackground(GraphicsUtils.getWebColorWithAlpha("FFFFFF7F"));
pnlMore.setOpaque(true);
if (Settings.getInstance().isEnableBlur())
((GaussionPanel) pnlRoot).addAeroObject(pnlMore);
((GaussionPanel) pnlRoot).setBackgroundImage(MainFrame.INSTANCE.background.getImage());
((RepaintPage) pnlMore).setRepainter(pnlRoot);
HMCLApi.EVENT_BUS.channel(AuthenticatorChangedEvent.class).register(onAuthChanged);
HMCLApi.EVENT_BUS.channel(ProfileLoadingEvent.class).register(onLoadingProfiles);
HMCLApi.EVENT_BUS.channel(ProfileChangedEvent.class).register(onSelectedProfilesChanged);
HMCLApi.EVENT_BUS.channel(RefreshedVersionsEvent.class).register(onRefreshedVersions);
HMCLApi.EVENT_BUS.channel(LaunchingStateChangedEvent.class).register(launchingStateChanged);
HMCLApi.EVENT_BUS.channel(LaunchSucceededEvent.class).register(this::prepareAuths);
prepareAuths();
}
/**
* This method is called from within the constructor to initialize the form.
* WARNING: Do NOT modify this code. The content of this method is always
* regenerated by the Form Editor.
*/
@SuppressWarnings("unchecked")
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
private void initComponents() {
pnlRoot = new GaussionPanel();
pnlMore = new org.jackhuang.hmcl.ui.RepaintPage();
txtPlayerName = new javax.swing.JTextField();
lblLogin = new javax.swing.JLabel();
cboLoginMode = new javax.swing.JComboBox();
lblUserName = new javax.swing.JLabel();
lblProfile = new javax.swing.JLabel();
cboProfiles = new javax.swing.JComboBox();
lblVersion = new javax.swing.JLabel();
cboVersions = new WideComboBox();
pnlPassword = new javax.swing.JPanel();
pnlLogIn = new javax.swing.JPanel();
lblPassword = new javax.swing.JLabel();
txtPassword = new javax.swing.JPasswordField();
pnlLogOut = new javax.swing.JPanel();
btnLogout = new javax.swing.JButton();
btnImportModpack = new javax.swing.JButton();
btnExportModpack = new javax.swing.JButton();
setLayout(null);
pnlRoot.setLayout(null);
pnlMore.setBackground(new java.awt.Color(204, 204, 204));
pnlMore.setOpaque(false);
txtPlayerName.addFocusListener(new java.awt.event.FocusAdapter() {
public void focusGained(java.awt.event.FocusEvent evt) {
txtPlayerNameFocusGained(evt);
}
public void focusLost(java.awt.event.FocusEvent evt) {
txtPlayerNameFocusLost(evt);
}
});
txtPlayerName.addKeyListener(new java.awt.event.KeyAdapter() {
public void keyPressed(java.awt.event.KeyEvent evt) {
txtPlayerNameKeyPressed(evt);
}
});
lblLogin.setText(C.i18n("login.type")); // NOI18N
cboLoginMode.addItemListener(new java.awt.event.ItemListener() {
public void itemStateChanged(java.awt.event.ItemEvent evt) {
cboLoginModeItemStateChanged(evt);
}
});
lblUserName.setText(C.i18n("login.username")); // NOI18N
lblProfile.setText(C.i18n("ui.label.profile")); // NOI18N
cboProfiles.addItemListener(new java.awt.event.ItemListener() {
public void itemStateChanged(java.awt.event.ItemEvent evt) {
cboProfilesItemStateChanged(evt);
}
});
lblVersion.setText(C.i18n("ui.label.version")); // NOI18N
lblVersion.setToolTipText(C.i18n("ui.label.version")); // NOI18N
cboVersions.addItemListener(new java.awt.event.ItemListener() {
public void itemStateChanged(java.awt.event.ItemEvent evt) {
cboVersionsItemStateChanged(evt);
}
});
pnlPassword.setLayout(new java.awt.CardLayout());
lblPassword.setText(C.i18n("ui.label.password")); // NOI18N
txtPassword.addCaretListener(new javax.swing.event.CaretListener() {
public void caretUpdate(javax.swing.event.CaretEvent evt) {
txtPasswordCaretUpdate(evt);
}
});
txtPassword.addFocusListener(new java.awt.event.FocusAdapter() {
public void focusGained(java.awt.event.FocusEvent evt) {
txtPasswordFocusGained(evt);
}
});
txtPassword.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
txtPasswordActionPerformed(evt);
}
});
txtPassword.addKeyListener(new java.awt.event.KeyAdapter() {
public void keyPressed(java.awt.event.KeyEvent evt) {
txtPasswordKeyPressed(evt);
}
});
javax.swing.GroupLayout pnlLogInLayout = new javax.swing.GroupLayout(pnlLogIn);
pnlLogIn.setLayout(pnlLogInLayout);
pnlLogInLayout.setHorizontalGroup(
pnlLogInLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(pnlLogInLayout.createSequentialGroup()
.addComponent(lblPassword)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(txtPassword))
);
pnlLogInLayout.setVerticalGroup(
pnlLogInLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, pnlLogInLayout.createSequentialGroup()
.addGap(0, 0, Short.MAX_VALUE)
.addGroup(pnlLogInLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(lblPassword, javax.swing.GroupLayout.PREFERRED_SIZE, 22, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(txtPassword, javax.swing.GroupLayout.PREFERRED_SIZE, 26, javax.swing.GroupLayout.PREFERRED_SIZE)))
);
pnlPassword.add(pnlLogIn, "card2");
btnLogout.setText(C.i18n("ui.button.logout")); // NOI18N
btnLogout.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
btnLogoutActionPerformed(evt);
}
});
javax.swing.GroupLayout pnlLogOutLayout = new javax.swing.GroupLayout(pnlLogOut);
pnlLogOut.setLayout(pnlLogOutLayout);
pnlLogOutLayout.setHorizontalGroup(
pnlLogOutLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(btnLogout, javax.swing.GroupLayout.DEFAULT_SIZE, 170, Short.MAX_VALUE)
);
pnlLogOutLayout.setVerticalGroup(
pnlLogOutLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(btnLogout, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
);
pnlPassword.add(pnlLogOut, "card3");
btnImportModpack.setText(C.i18n("modpack.task.install")); // NOI18N
btnImportModpack.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
btnImportModpackActionPerformed(evt);
}
});
btnExportModpack.setText(C.i18n("modpack.task.save")); // NOI18N
btnExportModpack.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
btnExportModpackActionPerformed(evt);
}
});
javax.swing.GroupLayout pnlMoreLayout = new javax.swing.GroupLayout(pnlMore);
pnlMore.setLayout(pnlMoreLayout);
pnlMoreLayout.setHorizontalGroup(
pnlMoreLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(pnlMoreLayout.createSequentialGroup()
.addContainerGap()
.addGroup(pnlMoreLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(pnlPassword, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addGroup(pnlMoreLayout.createSequentialGroup()
.addGroup(pnlMoreLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(lblProfile, javax.swing.GroupLayout.Alignment.TRAILING)
.addComponent(lblVersion, javax.swing.GroupLayout.Alignment.TRAILING))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(pnlMoreLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(cboProfiles, 0, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(cboVersions, 0, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)))
.addGroup(pnlMoreLayout.createSequentialGroup()
.addGroup(pnlMoreLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(lblUserName)
.addComponent(lblLogin))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(pnlMoreLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(cboLoginMode, 0, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(txtPlayerName)))
.addComponent(btnExportModpack, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(btnImportModpack, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
.addContainerGap())
);
pnlMoreLayout.setVerticalGroup(
pnlMoreLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, pnlMoreLayout.createSequentialGroup()
.addContainerGap()
.addGroup(pnlMoreLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(lblProfile)
.addComponent(cboProfiles, javax.swing.GroupLayout.PREFERRED_SIZE, 26, javax.swing.GroupLayout.PREFERRED_SIZE))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(pnlMoreLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(cboVersions, javax.swing.GroupLayout.PREFERRED_SIZE, 26, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(lblVersion))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(pnlMoreLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(lblLogin)
.addComponent(cboLoginMode, javax.swing.GroupLayout.PREFERRED_SIZE, 26, javax.swing.GroupLayout.PREFERRED_SIZE))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(pnlMoreLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(lblUserName)
.addComponent(txtPlayerName, javax.swing.GroupLayout.PREFERRED_SIZE, 26, javax.swing.GroupLayout.PREFERRED_SIZE))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(pnlPassword, javax.swing.GroupLayout.PREFERRED_SIZE, 26, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 254, Short.MAX_VALUE)
.addComponent(btnImportModpack)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(btnExportModpack)
.addContainerGap())
);
pnlRoot.add(pnlMore);
pnlMore.setBounds(0, 0, 190, 480);
add(pnlRoot);
pnlRoot.setBounds(0, 0, 800, 480);
}// </editor-fold>//GEN-END:initComponents
private void txtPlayerNameFocusGained(java.awt.event.FocusEvent evt) {//GEN-FIRST:event_txtPlayerNameFocusGained
MainFrame.INSTANCE.closeMessage();
}//GEN-LAST:event_txtPlayerNameFocusGained
private void txtPlayerNameFocusLost(java.awt.event.FocusEvent evt) {//GEN-FIRST:event_txtPlayerNameFocusLost
IAuthenticator l = Settings.getInstance().getAuthenticator();
l.setUserName(txtPlayerName.getText());
}//GEN-LAST:event_txtPlayerNameFocusLost
private void cboLoginModeItemStateChanged(java.awt.event.ItemEvent evt) {//GEN-FIRST:event_cboLoginModeItemStateChanged
if (evt.getStateChange() != ItemEvent.SELECTED)
return;
if (preparingAuth)
return;
Settings.getInstance().setLoginType(cboLoginMode.getSelectedIndex());
}//GEN-LAST:event_cboLoginModeItemStateChanged
private void cboProfilesItemStateChanged(java.awt.event.ItemEvent evt) {//GEN-FIRST:event_cboProfilesItemStateChanged
if (!isLoading && cboProfiles.getSelectedIndex() != -1 && !StrUtils.isBlank((String) cboProfiles.getSelectedItem()))
Settings.getInstance().setLast((String) cboProfiles.getSelectedItem());
}//GEN-LAST:event_cboProfilesItemStateChanged
private void cboVersionsItemStateChanged(java.awt.event.ItemEvent evt) {//GEN-FIRST:event_cboVersionsItemStateChanged
if (isLoading || evt.getStateChange() != ItemEvent.SELECTED || cboVersions.getSelectedIndex() < 0 || StrUtils.isBlank((String) cboVersions.getSelectedItem()))
return;
String mcv = (String) cboVersions.getSelectedItem();
Settings.getLastProfile().setSelectedVersion(mcv);
}//GEN-LAST:event_cboVersionsItemStateChanged
private void txtPasswordFocusGained(java.awt.event.FocusEvent evt) {//GEN-FIRST:event_txtPasswordFocusGained
MainFrame.INSTANCE.closeMessage();
}//GEN-LAST:event_txtPasswordFocusGained
private void txtPasswordActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_txtPasswordActionPerformed
MainFrame.INSTANCE.daemon.runGame(Settings.getLastProfile());
}//GEN-LAST:event_txtPasswordActionPerformed
private void btnLogoutActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnLogoutActionPerformed
if (preparingAuth)
return;
IAuthenticator l = Settings.getInstance().getAuthenticator();
CardLayout cl = (CardLayout) pnlPassword.getLayout();
if (l.isLoggedIn())
l.logOut();
cl.first(pnlPassword);
SwingUtilities.invokeLater(this::repaint);
}//GEN-LAST:event_btnLogoutActionPerformed
private void txtPlayerNameKeyPressed(java.awt.event.KeyEvent evt) {//GEN-FIRST:event_txtPlayerNameKeyPressed
if (evt.getKeyCode() == KeyEvent.VK_ENTER) {
IAuthenticator l = Settings.getInstance().getAuthenticator();
l.setUserName(txtPlayerName.getText());
if (!l.hasPassword())
MainFrame.INSTANCE.daemon.runGame(Settings.getLastProfile());
else if (!l.isLoggedIn())
txtPassword.requestFocus();
}
}//GEN-LAST:event_txtPlayerNameKeyPressed
private void txtPasswordKeyPressed(java.awt.event.KeyEvent evt) {//GEN-FIRST:event_txtPasswordKeyPressed
if (evt.getKeyCode() == KeyEvent.VK_ENTER)
MainFrame.INSTANCE.daemon.runGame(Settings.getLastProfile());
}//GEN-LAST:event_txtPasswordKeyPressed
private void btnImportModpackActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnImportModpackActionPerformed
JSystemFileChooser fc = new JSystemFileChooser();
fc.setFileSelectionMode(JSystemFileChooser.FILES_ONLY);
fc.setDialogTitle(C.i18n("modpack.choose"));
fc.setMultiSelectionEnabled(false);
fc.setFileFilter(new FileNameExtensionFilter(C.i18n("modpack"), "zip"));
fc.showOpenDialog(this);
if (fc.getSelectedFile() == null)
return;
String suggestedModpackId = MessageBox.showInputDialog(C.i18n("modpack.enter_name"), FileUtils.getBaseName(fc.getSelectedFile().getName()));
if (StrUtils.isBlank(suggestedModpackId))
return;
TaskWindow.factory().append(ModpackManager.install(MainFrame.INSTANCE, fc.getSelectedFile(), Settings.getLastProfile().service(), suggestedModpackId)).execute();
Settings.getLastProfile().service().version().refreshVersions();
}//GEN-LAST:event_btnImportModpackActionPerformed
private void btnExportModpackActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnExportModpackActionPerformed
if (Settings.getLastProfile().service().version().getVersionCount() <= 0)
return;
WizardDisplayer.showWizard(new ModpackWizard(Settings.getLastProfile()).createWizard());
}//GEN-LAST:event_btnExportModpackActionPerformed
private void txtPasswordCaretUpdate(javax.swing.event.CaretEvent evt) {//GEN-FIRST:event_txtPasswordCaretUpdate
Settings.getInstance().getAuthenticator().setPassword(txtPassword.getText());
}//GEN-LAST:event_txtPasswordCaretUpdate
// <editor-fold defaultstate="collapsed" desc="Loads">
private void prepareAuths() {
preparingAuth = true;
cboLoginMode.removeAllItems();
for (IAuthenticator str : AbstractAuthenticator.LOGINS)
cboLoginMode.addItem(str.getName());
preparingAuth = false;
int loginType = Settings.getInstance().getLoginType();
if (0 <= loginType && loginType < cboLoginMode.getItemCount()) {
cboLoginMode.setSelectedIndex(loginType);
Settings.getInstance().setLoginType(loginType);
}
}
//</editor-fold>
// <editor-fold defaultstate="collapsed" desc="Private Variables">
boolean preparingAuth = true;
private boolean isLoading = false;
private javax.swing.JPanel pnlButtons;
private CustomButton btnRun;
private static final int DEFAULT_WIDTH = 800, DEFAULT_HEIGHT = 480;
//</editor-fold>
@Override
public void onCreate() {
initGui();
super.onCreate();
Settings.onProfileLoading();
}
// Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.JButton btnExportModpack;
private javax.swing.JButton btnImportModpack;
private javax.swing.JButton btnLogout;
private javax.swing.JComboBox cboLoginMode;
private javax.swing.JComboBox cboProfiles;
private javax.swing.JComboBox cboVersions;
private javax.swing.JLabel lblLogin;
private javax.swing.JLabel lblPassword;
private javax.swing.JLabel lblProfile;
private javax.swing.JLabel lblUserName;
private javax.swing.JLabel lblVersion;
private javax.swing.JPanel pnlLogIn;
private javax.swing.JPanel pnlLogOut;
private javax.swing.JPanel pnlMore;
private javax.swing.JPanel pnlPassword;
private javax.swing.JPanel pnlRoot;
private javax.swing.JPasswordField txtPassword;
private javax.swing.JTextField txtPlayerName;
// End of variables declaration//GEN-END:variables
final Consumer<AuthenticatorChangedEvent> onAuthChanged = (x) -> {
if (x.getValue().hasPassword()) {
pnlPassword.setVisible(true);
lblUserName.setText(C.i18n("login.account"));
} else {
pnlPassword.setVisible(false);
lblUserName.setText(C.i18n("login.username"));
}
CardLayout cl = (CardLayout) pnlPassword.getLayout();
if (x.getValue().isLoggedIn())
cl.last(pnlPassword);
else
cl.first(pnlPassword);
String username = x.getValue().getUserName();
if (username == null)
username = "";
txtPlayerName.setText(username);
};
final Runnable onLoadingProfiles = () -> {
isLoading = true;
DefaultComboBoxModel<String> model = new DefaultComboBoxModel<>();
for (Profile s : Settings.getProfilesFiltered())
model.addElement(s.getName());
cboProfiles.setModel(model);
isLoading = false;
};
final Consumer<RefreshedVersionsEvent> onRefreshedVersions = t -> {
if (Settings.getLastProfile().service().version() == t.getSource())
loadVersions();
};
boolean showedNoVersion = false;
void loadVersions() {
isLoading = true;
cboVersions.removeAllItems();
String selVersion = Settings.getLastProfile().getSelectedVersion();
if (!Settings.getLastProfile().service().version().getVersions().isEmpty()) {
for (MinecraftVersion mcVersion : Settings.getLastProfile().service().version().getVersions()) {
if (mcVersion.hidden)
continue;
cboVersions.addItem(mcVersion.id);
}
versionChanged(selVersion);
}
isLoading = false;
}
final Consumer<LaunchingStateChangedEvent> launchingStateChanged = t -> SwingUtilities.invokeLater(() -> SwingUtils.setEnabled(MainFrame.INSTANCE.getRootPane(), t.getValue() == LaunchingState.Done));
void versionChanged(String selectedVersion) {
isLoading = true;
DefaultComboBoxModel<String> model = (DefaultComboBoxModel<String>) cboVersions.getModel();
for (int i = 0; i < model.getSize(); ++i)
if (model.getElementAt(i).equals(selectedVersion)) {
model.setSelectedItem(selectedVersion);
break;
}
isLoading = false;
}
final Consumer<ProfileChangedEvent> onSelectedProfilesChanged = event -> {
Profile t = event.getValue();
t.propertyChanged.register(e -> {
if ("selectedVersion".equals(e.getPropertyName()))
versionChanged(e.getNewValue());
});
isLoading = true;
DefaultComboBoxModel<String> model = (DefaultComboBoxModel<String>) cboProfiles.getModel();
for (int i = 0; i < model.getSize(); ++i)
if (model.getElementAt(i).equals(t.getName())) {
model.setSelectedItem(t.getName());
break;
}
isLoading = false;
};
}
@@ -1,164 +0,0 @@
/*
* Hello Minecraft! Launcher.
* Copyright (C) 2013 huangyuhui <huanghongxun2008@126.com>
*
* 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 3 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. If not, see {http://www.gnu.org/licenses/}.
*/
package org.jackhuang.hmcl.ui;
import org.jackhuang.hmcl.util.C;
import org.jackhuang.hmcl.setting.Profile;
import org.jackhuang.hmcl.setting.Settings;
import org.jackhuang.hmcl.util.StrUtils;
/**
*
* @author huangyuhui
*/
public final class NewProfileWindow extends javax.swing.JDialog {
public NewProfileWindow(java.awt.Frame parent) {
super(parent, true);
initComponents();
setLocationRelativeTo(null);
for (Profile s : Settings.getProfilesFiltered())
cboProfiles.addItem(s.getName());
}
/**
* This method is called from within the constructor to initialize the form.
* WARNING: Do NOT modify this code. The content of this method is always
* regenerated by the Form Editor.
*/
@SuppressWarnings("unchecked")
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
private void initComponents() {
jLabel1 = new javax.swing.JLabel();
txtNewProfileName = new javax.swing.JTextField();
jLabel2 = new javax.swing.JLabel();
cboProfiles = new javax.swing.JComboBox();
btnCancel = new javax.swing.JButton();
btnOK = new javax.swing.JButton();
setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE);
setTitle(C.i18n("ui.newProfileWindow.title")); // NOI18N
jLabel1.setText(C.i18n("ui.label.newProfileWindow.new_profile_name")); // NOI18N
txtNewProfileName.addKeyListener(new java.awt.event.KeyAdapter() {
public void keyTyped(java.awt.event.KeyEvent evt) {
txtNewProfileNameKeyTyped(evt);
}
});
jLabel2.setText(C.i18n("ui.label.newProfileWindow.copy_from")); // NOI18N
btnCancel.setText(C.i18n("button.cancel")); // NOI18N
btnCancel.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
btnCancelActionPerformed(evt);
}
});
btnOK.setText(C.i18n("ui.button.ok")); // NOI18N
btnOK.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
btnOKActionPerformed(evt);
}
});
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
getContentPane().setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addContainerGap()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addComponent(jLabel1)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(txtNewProfileName))
.addGroup(layout.createSequentialGroup()
.addComponent(jLabel2)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(cboProfiles, 0, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
.addGap(0, 262, Short.MAX_VALUE)
.addComponent(btnOK)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(btnCancel)))
.addContainerGap())
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addContainerGap()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(jLabel1)
.addComponent(txtNewProfileName, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(jLabel2)
.addComponent(cboProfiles, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(btnCancel)
.addComponent(btnOK))
.addContainerGap())
);
pack();
}// </editor-fold>//GEN-END:initComponents
private void txtNewProfileNameKeyTyped(java.awt.event.KeyEvent evt) {//GEN-FIRST:event_txtNewProfileNameKeyTyped
switch (evt.getKeyCode()) {
case 13:
act();
break;
case 27:
this.dispose();
break;
default:
break;
}
}//GEN-LAST:event_txtNewProfileNameKeyTyped
private void btnOKActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnOKActionPerformed
act();
}//GEN-LAST:event_btnOKActionPerformed
void act() {
if (!StrUtils.isBlank(txtNewProfileName.getText())) {
Profile newProfile = new Profile(txtNewProfileName.getText(), Settings.getProfile(cboProfiles.getSelectedItem().toString()));
Settings.putProfile(newProfile);
}
this.dispose();
}
private void btnCancelActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnCancelActionPerformed
this.dispose();
}//GEN-LAST:event_btnCancelActionPerformed
// Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.JButton btnCancel;
private javax.swing.JButton btnOK;
private javax.swing.JComboBox cboProfiles;
private javax.swing.JLabel jLabel1;
private javax.swing.JLabel jLabel2;
private javax.swing.JTextField txtNewProfileName;
// End of variables declaration//GEN-END:variables
}
@@ -1,59 +0,0 @@
/*
* Hello Minecraft! Launcher.
* Copyright (C) 2013 huangyuhui <huanghongxun2008@126.com>
*
* 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 3 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. If not, see {http://www.gnu.org/licenses/}.
*/
package org.jackhuang.hmcl.ui;
import javax.swing.JTabbedPane;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import org.jackhuang.hmcl.api.ui.TopTabPage;
/**
*
* @author huangyuhui
*/
public class NewTabPane extends JTabbedPane implements ChangeListener {
public NewTabPane() {
super();
addChangeListener(this);
}
public boolean initializing;
@Override
public void stateChanged(ChangeEvent e) {
if (initializing)
return;
for (int i = 0; i < getComponentCount(); ++i)
if (getComponent(i) instanceof TopTabPage) {
TopTabPage comp = (TopTabPage) getComponent(i);
comp.setId(i);
if (getSelectedIndex() != i)
((TopTabPage) getComponent(i)).onLeave();
}
if (getSelectedComponent() instanceof TopTabPage) {
if (page == null && getComponentCount() > 0 && getComponent(0) instanceof TopTabPage)
page = (TopTabPage) getComponent(0);
((TopTabPage) getSelectedComponent()).onSelect(page);
page = (TopTabPage) getSelectedComponent();
}
}
TopTabPage page = null;
}
@@ -1,58 +0,0 @@
/*
* Hello Minecraft! Launcher.
* Copyright (C) 2013 huangyuhui <huanghongxun2008@126.com>
*
* 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 3 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. If not, see {http://www.gnu.org/licenses/}.
*/
package org.jackhuang.hmcl.ui;
import org.jackhuang.hmcl.util.ui.Page;
import org.jackhuang.hmcl.util.ui.IRepaint;
import java.awt.Rectangle;
import java.awt.Window;
import java.util.Arrays;
import java.util.Collection;
import javax.swing.JComponent;
/**
*
* @author huang
*/
public class RepaintPage extends Page implements IRepaint {
public RepaintPage() {
super();
}
JComponent repainter;
@Override
public JComponent getRepaintComponent() {
return repainter;
}
public void setRepainter(JComponent repainter) {
this.repainter = repainter;
}
@Override
public Collection<Rectangle> getRepaintRects() {
return Arrays.asList(this.getBounds());
}
@Override
public Window getRepaintWindow() {
return null;
}
}
@@ -1,75 +0,0 @@
<?xml version="1.0" encoding="UTF-8" ?>
<Form version="1.3" maxVersion="1.9" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
<AuxValues>
<AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="0"/>
<AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/>
<AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/>
<AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="false"/>
<AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="false"/>
<AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="1"/>
<AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
<AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
<AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
</AuxValues>
<Layout>
<DimensionLayout dim="0">
<Group type="103" groupAlignment="0" attributes="0">
<Component id="jScrollPane1" max="32767" attributes="0"/>
<Group type="102" attributes="0">
<EmptySpace min="0" pref="0" max="32767" attributes="0"/>
<Component id="jButton1" min="-2" max="-2" attributes="0"/>
</Group>
<Group type="102" alignment="0" attributes="0">
<Component id="lblTitle" min="-2" max="-2" attributes="0"/>
<EmptySpace min="0" pref="0" max="32767" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
<DimensionLayout dim="1">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0">
<Component id="lblTitle" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="jScrollPane1" pref="250" max="32767" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="jButton1" min="-2" max="-2" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
</Layout>
<SubComponents>
<Container class="javax.swing.JScrollPane" name="jScrollPane1">
<AuxValues>
<AuxValue name="autoScrollPane" type="java.lang.Boolean" value="true"/>
</AuxValues>
<Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/>
<SubComponents>
<Component class="javax.swing.JTextPane" name="txtDescription">
<Events>
<EventHandler event="caretUpdate" listener="javax.swing.event.CaretListener" parameters="javax.swing.event.CaretEvent" handler="txtDescriptionCaretUpdate"/>
</Events>
</Component>
</SubComponents>
</Container>
<Component class="javax.swing.JButton" name="jButton1">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/jackhuang/hellominecraft/lang/I18N.properties" key="ui.button.preview" replaceFormat="C.i18n(&quot;{key}&quot;)"/>
</Property>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="jButton1ActionPerformed"/>
</Events>
</Component>
<Component class="javax.swing.JLabel" name="lblTitle">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/jackhuang/hellominecraft/lang/I18N.properties" key="modpack.desc" replaceFormat="C.i18n(&quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
</SubComponents>
</Form>
@@ -1,129 +0,0 @@
/*
* Hello Minecraft! Launcher.
* Copyright (C) 2013 huangyuhui <huanghongxun2008@126.com>
*
* 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 3 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. If not, see {http://www.gnu.org/licenses/}.
*/
package org.jackhuang.hmcl.ui.modpack;
import java.awt.Dimension;
import java.awt.HeadlessException;
import java.io.IOException;
import java.util.Map;
import javax.swing.JOptionPane;
import org.jackhuang.hmcl.util.C;
import org.jackhuang.hmcl.util.ui.MessageBox;
import org.jackhuang.hmcl.util.StrUtils;
import org.jackhuang.hmcl.util.net.WebPage;
import org.jackhuang.hmcl.util.ui.wizard.spi.WizardController;
import org.markdown4j.Markdown4jProcessor;
/**
*
* @author huangyuhui
*/
public class ModpackDescriptionPanel extends javax.swing.JPanel {
public static final String KEY_MODPACK_DESCRITION = "modpackDescription";
private final transient WizardController controller;
private final Map wizardData;
/**
* Creates new form ModpackDescriptionPanel
*/
public ModpackDescriptionPanel(WizardController controller, Map wizardData) {
initComponents();
this.controller = controller;
this.wizardData = wizardData;
}
/**
* This method is called from within the constructor to
* initialize the form.
* WARNING: Do NOT modify this code. The content of this method is
* always regenerated by the Form Editor.
*/
@SuppressWarnings("unchecked")
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
private void initComponents() {
jScrollPane1 = new javax.swing.JScrollPane();
txtDescription = new javax.swing.JTextPane();
jButton1 = new javax.swing.JButton();
lblTitle = new javax.swing.JLabel();
txtDescription.addCaretListener(new javax.swing.event.CaretListener() {
public void caretUpdate(javax.swing.event.CaretEvent evt) {
txtDescriptionCaretUpdate(evt);
}
});
jScrollPane1.setViewportView(txtDescription);
jButton1.setText(C.i18n("ui.button.preview")); // NOI18N
jButton1.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
jButton1ActionPerformed(evt);
}
});
lblTitle.setText(C.i18n("modpack.desc")); // NOI18N
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
this.setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(jScrollPane1)
.addGroup(layout.createSequentialGroup()
.addGap(0, 0, Short.MAX_VALUE)
.addComponent(jButton1))
.addGroup(layout.createSequentialGroup()
.addComponent(lblTitle)
.addGap(0, 0, Short.MAX_VALUE))
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addComponent(lblTitle)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 250, Short.MAX_VALUE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(jButton1))
);
}// </editor-fold>//GEN-END:initComponents
private void txtDescriptionCaretUpdate(javax.swing.event.CaretEvent evt) {//GEN-FIRST:event_txtDescriptionCaretUpdate
wizardData.put(KEY_MODPACK_DESCRITION, txtDescription.getText());
}//GEN-LAST:event_txtDescriptionCaretUpdate
private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton1ActionPerformed
try {
Object msgs[] = new Object[2];
msgs[0] = C.i18n("ui.button.preview");
msgs[1] = new WebPage(new Markdown4jProcessor().process(txtDescription.getText()));
((WebPage) msgs[1]).setPreferredSize(new Dimension(800, 350));
JOptionPane.showOptionDialog(null, msgs, (String) msgs[0], JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE, null, null, null);
} catch (HeadlessException | IOException e) {
MessageBox.show(StrUtils.getStackTrace(e), C.i18n("message.error"), MessageBox.WARNING_MESSAGE);
}
}//GEN-LAST:event_jButton1ActionPerformed
// Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.JButton jButton1;
private javax.swing.JScrollPane jScrollPane1;
private javax.swing.JLabel lblTitle;
private javax.swing.JTextPane txtDescription;
// End of variables declaration//GEN-END:variables
}
@@ -1,41 +0,0 @@
<?xml version="1.0" encoding="UTF-8" ?>
<Form version="1.3" maxVersion="1.9" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
<AuxValues>
<AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="0"/>
<AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/>
<AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/>
<AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="false"/>
<AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="false"/>
<AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="1"/>
<AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
<AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
<AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
</AuxValues>
<Layout>
<DimensionLayout dim="0">
<Group type="103" groupAlignment="0" attributes="0">
<Component id="jScrollPane1" alignment="0" pref="400" max="32767" attributes="0"/>
</Group>
</DimensionLayout>
<DimensionLayout dim="1">
<Group type="103" groupAlignment="0" attributes="0">
<Component id="jScrollPane1" alignment="1" pref="300" max="32767" attributes="0"/>
</Group>
</DimensionLayout>
</Layout>
<SubComponents>
<Container class="javax.swing.JScrollPane" name="jScrollPane1">
<AuxValues>
<AuxValue name="autoScrollPane" type="java.lang.Boolean" value="true"/>
</AuxValues>
<Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/>
<SubComponents>
<Component class="javax.swing.JTree" name="jTree1">
</Component>
</SubComponents>
</Container>
</SubComponents>
</Form>
@@ -1,141 +0,0 @@
/*
* Hello Minecraft! Launcher.
* Copyright (C) 2013 huangyuhui <huanghongxun2008@126.com>
*
* 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 3 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. If not, see {http://www.gnu.org/licenses/}.
*/
package org.jackhuang.hmcl.ui.modpack;
import java.io.File;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import javax.swing.tree.DefaultTreeModel;
import org.jackhuang.hmcl.core.mod.ModAdviser;
import org.jackhuang.hmcl.util.C;
import org.jackhuang.hmcl.util.Pair;
import org.jackhuang.hmcl.util.sys.FileUtils;
import org.jackhuang.hmcl.util.ui.checktree.CheckBoxTreeCellRenderer;
import org.jackhuang.hmcl.util.ui.checktree.CheckBoxTreeNode;
import org.jackhuang.hmcl.util.ui.checktree.CheckBoxTreeNodeSelectionListener;
import org.jackhuang.hmcl.util.ui.wizard.spi.WizardController;
/**
*
* @author huangyuhui
*/
public class ModpackFileSelectionPanel extends javax.swing.JPanel {
private transient final WizardController controller;
private final Map wizardData;
private transient final ModAdviser blackList;
private final Set<String> bannedFiles = new HashSet<>();
/**
* Creates new form ModpackFileSelectionPanel
*
* @param blackList Return 0: non blocked, 1: non shown, 2: suggested,
* checked
*/
public ModpackFileSelectionPanel(WizardController controller, Map wizardData, File gameDir, ModAdviser blackList) {
initComponents();
this.controller = controller;
this.wizardData = wizardData;
this.blackList = blackList;
CheckBoxTreeNode root = create(gameDir, "minecraft");
jTree1.setModel(new DefaultTreeModel(root));
jTree1.setCellRenderer(new CheckBoxTreeCellRenderer());
jTree1.addMouseListener(new CheckBoxTreeNodeSelectionListener());
wizardData.put("blackList", root);
}
private static final HashMap<String, String> TRANSLATION = new HashMap<String, String>() {
{
put("minecraft/servers.dat", C.i18n("modpack.files.servers_dat"));
put("minecraft/saves", C.i18n("modpack.files.saves"));
put("minecraft/mods", C.i18n("modpack.files.mods"));
put("minecraft/config", C.i18n("modpack.files.config"));
put("minecraft/liteconfig", C.i18n("modpack.files.liteconfig"));
put("minecraft/resourcepacks", C.i18n("modpack.files.resourcepacks"));
put("minecraft/options.txt", C.i18n("modpack.files.options_txt"));
put("minecraft/optionsshaders.txt", C.i18n("modpack.files.optionsshaders_txt"));
put("minecraft/mods/VoxelMods", C.i18n("modpack.files.mods.voxelmods"));
put("minecraft/dumps", C.i18n("modpack.files.dumps"));
put("minecraft/blueprints", C.i18n("modpack.files.blueprints"));
put("minecraft/scripts", C.i18n("modpack.files.scripts"));
}
};
CheckBoxTreeNode create(File file, String basePath) {
ModAdviser.ModSuggestion state = ModAdviser.ModSuggestion.NORMAL;
if (basePath.length() > "minecraft/".length())
if ((state = blackList.advise(basePath.substring("minecraft/".length()) + (file.isDirectory() ? "/" : ""), file.isDirectory())) == ModAdviser.ModSuggestion.HIDDEN)
return null;
CheckBoxTreeNode node = new CheckBoxTreeNode(TRANSLATION.containsKey(basePath) ? new Pair<>(FileUtils.getName(basePath), TRANSLATION.get(basePath)) : FileUtils.getName(basePath));
if (state == ModAdviser.ModSuggestion.SUGGESTED)
node.setSelected(true);
if (file.isDirectory()) {
File[] f = file.listFiles();
for (File subFile : f) {
CheckBoxTreeNode subNode = create(subFile, basePath + "/" + subFile.getName());
if (subNode != null) {
subNode.setSelected(subNode.isSelected() | node.isSelected());
node.add(subNode);
}
}
if (!node.children().hasMoreElements())
return null;
}
return node;
}
/**
* This method is called from within the constructor to
* initialize the form.
* WARNING: Do NOT modify this code. The content of this method is
* always regenerated by the Form Editor.
*/
@SuppressWarnings("unchecked")
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
private void initComponents() {
jScrollPane1 = new javax.swing.JScrollPane();
jTree1 = new javax.swing.JTree();
jScrollPane1.setViewportView(jTree1);
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
this.setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 400, Short.MAX_VALUE)
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(jScrollPane1, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, 300, Short.MAX_VALUE)
);
}// </editor-fold>//GEN-END:initComponents
// Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.JScrollPane jScrollPane1;
private javax.swing.JTree jTree1;
// End of variables declaration//GEN-END:variables
}
@@ -1,145 +0,0 @@
<?xml version="1.0" encoding="UTF-8" ?>
<Form version="1.3" maxVersion="1.9" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
<AuxValues>
<AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="0"/>
<AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/>
<AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/>
<AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="false"/>
<AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="false"/>
<AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="1"/>
<AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
<AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
<AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
</AuxValues>
<Layout>
<DimensionLayout dim="0">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" attributes="0">
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Component id="txtModpackName" max="32767" attributes="0"/>
<Group type="102" alignment="0" attributes="0">
<Component id="lblModpackLocation" min="-2" max="-2" attributes="0"/>
<EmptySpace pref="353" max="32767" attributes="0"/>
<Component id="cboModpackLocation" min="-2" max="-2" attributes="0"/>
</Group>
<Component id="txtModpackLocation" max="32767" attributes="0"/>
<Component id="cboGameVersion" max="32767" attributes="0"/>
<Group type="102" attributes="0">
<Group type="103" groupAlignment="0" attributes="0">
<Component id="lblGameVersion" min="-2" max="-2" attributes="0"/>
<Component id="jLabel1" alignment="0" min="-2" max="-2" attributes="0"/>
<Component id="jLabel2" alignment="0" min="-2" max="-2" attributes="0"/>
<Component id="chkIncludeLauncher" alignment="0" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace min="0" pref="0" max="32767" attributes="0"/>
</Group>
</Group>
<EmptySpace max="-2" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
<DimensionLayout dim="1">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0">
<EmptySpace max="-2" attributes="0"/>
<Component id="jLabel1" min="-2" max="-2" attributes="0"/>
<EmptySpace pref="19" max="32767" attributes="0"/>
<Component id="jLabel2" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="txtModpackName" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="3" attributes="0">
<Component id="lblModpackLocation" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="cboModpackLocation" alignment="3" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace max="-2" attributes="0"/>
<Component id="txtModpackLocation" min="-2" max="-2" attributes="0"/>
<EmptySpace min="-2" max="-2" attributes="0"/>
<Component id="lblGameVersion" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="cboGameVersion" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="chkIncludeLauncher" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
</Layout>
<SubComponents>
<Component class="javax.swing.JLabel" name="lblModpackLocation">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/jackhuang/hellominecraft/lang/I18N.properties" key="modpack.wizard.step.initialization.save" replaceFormat="C.i18n(&quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JTextField" name="txtModpackLocation">
<Events>
<EventHandler event="caretUpdate" listener="javax.swing.event.CaretListener" parameters="javax.swing.event.CaretEvent" handler="txtModpackLocationCaretUpdate"/>
</Events>
</Component>
<Component class="javax.swing.JButton" name="cboModpackLocation">
<Properties>
<Property name="text" type="java.lang.String" value="..."/>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="cboModpackLocationActionPerformed"/>
</Events>
</Component>
<Component class="javax.swing.JLabel" name="lblGameVersion">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/jackhuang/hellominecraft/lang/I18N.properties" key="modpack.wizard.step.initialization.exported_version" replaceFormat="C.i18n(&quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JComboBox" name="cboGameVersion">
<Properties>
<Property name="model" type="javax.swing.ComboBoxModel" editor="org.netbeans.modules.form.editors2.ComboBoxModelEditor">
<StringArray count="0"/>
</Property>
</Properties>
<Events>
<EventHandler event="itemStateChanged" listener="java.awt.event.ItemListener" parameters="java.awt.event.ItemEvent" handler="cboGameVersionItemStateChanged"/>
</Events>
<AuxValues>
<AuxValue name="JavaCodeGenerator_TypeParameters" type="java.lang.String" value="&lt;String&gt;"/>
</AuxValues>
</Component>
<Component class="javax.swing.JLabel" name="jLabel1">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/jackhuang/hellominecraft/lang/I18N.properties" key="modpack.wizard.step.initialization.warning" replaceFormat="C.i18n(&quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JLabel" name="jLabel2">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/jackhuang/hellominecraft/lang/I18N.properties" key="modpack.name" replaceFormat="C.i18n(&quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JTextField" name="txtModpackName">
<Properties>
<Property name="toolTipText" type="java.lang.String" value=""/>
</Properties>
<Events>
<EventHandler event="caretUpdate" listener="javax.swing.event.CaretListener" parameters="javax.swing.event.CaretEvent" handler="txtModpackNameCaretUpdate"/>
</Events>
</Component>
<Component class="javax.swing.JCheckBox" name="chkIncludeLauncher">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/jackhuang/hellominecraft/lang/I18N.properties" key="modpack.wizard.step.initialization.include_launcher" replaceFormat="C.i18n(&quot;{key}&quot;)"/>
</Property>
</Properties>
<Events>
<EventHandler event="itemStateChanged" listener="java.awt.event.ItemListener" parameters="java.awt.event.ItemEvent" handler="chkIncludeLauncherItemStateChanged"/>
</Events>
</Component>
</SubComponents>
</Form>
@@ -1,230 +0,0 @@
/*
* Hello Minecraft! Launcher.
* Copyright (C) 2013 huangyuhui <huanghongxun2008@126.com>
*
* 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 3 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. If not, see {http://www.gnu.org/licenses/}.
*/
package org.jackhuang.hmcl.ui.modpack;
import java.util.Map;
import java.util.Vector;
import java.util.regex.Pattern;
import javax.swing.DefaultComboBoxModel;
import javax.swing.filechooser.FileNameExtensionFilter;
import org.jackhuang.hmcl.util.C;
import org.jackhuang.hmcl.util.ui.JSystemFileChooser;
import org.jackhuang.hmcl.util.ui.wizard.spi.WizardController;
/**
*
* @author huangyuhui
*/
public class ModpackInitializationPanel extends javax.swing.JPanel {
public static final String KEY_GAME_VERSION = "gameVersion";
public static final String KEY_MODPACK_LOCATION = "modpackLocation";
public static final String KEY_MODPACK_NAME = "modpackName";
public static final String KEY_INCLUDING_LAUNCHER = "launcher";
private final transient WizardController controller;
private final Map<String, Object> wizardData;
/**
* Creates new form ModpackInitializationPanel
*/
public ModpackInitializationPanel(WizardController controller, Map<String, Object> wizardData, Vector<String> versions, String selVersion) {
initComponents();
this.controller = controller;
this.wizardData = wizardData;
wizardData.put(KEY_GAME_VERSION, versions);
wizardData.put("selVersion", selVersion);
wizardData.put(KEY_INCLUDING_LAUNCHER, false);
configureComboContents();
checkProblem();
}
private void configureComboContents() {
Vector<String> versions = (Vector<String>) wizardData.get(KEY_GAME_VERSION);
cboGameVersion.setModel(new DefaultComboBoxModel<>(versions));
wizardData.put(KEY_GAME_VERSION, wizardData.get("selVersion"));
}
/**
* This method is called from within the constructor to
* initialize the form.
* WARNING: Do NOT modify this code. The content of this method is
* always regenerated by the Form Editor.
*/
@SuppressWarnings("unchecked")
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
private void initComponents() {
lblModpackLocation = new javax.swing.JLabel();
txtModpackLocation = new javax.swing.JTextField();
cboModpackLocation = new javax.swing.JButton();
lblGameVersion = new javax.swing.JLabel();
cboGameVersion = new javax.swing.JComboBox<>();
jLabel1 = new javax.swing.JLabel();
jLabel2 = new javax.swing.JLabel();
txtModpackName = new javax.swing.JTextField();
chkIncludeLauncher = new javax.swing.JCheckBox();
lblModpackLocation.setText(C.i18n("modpack.wizard.step.initialization.save")); // NOI18N
txtModpackLocation.addCaretListener(new javax.swing.event.CaretListener() {
public void caretUpdate(javax.swing.event.CaretEvent evt) {
txtModpackLocationCaretUpdate(evt);
}
});
cboModpackLocation.setText("...");
cboModpackLocation.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
cboModpackLocationActionPerformed(evt);
}
});
lblGameVersion.setText(C.i18n("modpack.wizard.step.initialization.exported_version")); // NOI18N
cboGameVersion.addItemListener(new java.awt.event.ItemListener() {
public void itemStateChanged(java.awt.event.ItemEvent evt) {
cboGameVersionItemStateChanged(evt);
}
});
jLabel1.setText(C.i18n("modpack.wizard.step.initialization.warning")); // NOI18N
jLabel2.setText(C.i18n("modpack.name")); // NOI18N
txtModpackName.setToolTipText("");
txtModpackName.addCaretListener(new javax.swing.event.CaretListener() {
public void caretUpdate(javax.swing.event.CaretEvent evt) {
txtModpackNameCaretUpdate(evt);
}
});
chkIncludeLauncher.setText(C.i18n("modpack.wizard.step.initialization.include_launcher")); // NOI18N
chkIncludeLauncher.addItemListener(new java.awt.event.ItemListener() {
public void itemStateChanged(java.awt.event.ItemEvent evt) {
chkIncludeLauncherItemStateChanged(evt);
}
});
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
this.setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addContainerGap()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(txtModpackName)
.addGroup(layout.createSequentialGroup()
.addComponent(lblModpackLocation)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 353, Short.MAX_VALUE)
.addComponent(cboModpackLocation))
.addComponent(txtModpackLocation)
.addComponent(cboGameVersion, 0, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addGroup(layout.createSequentialGroup()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(lblGameVersion)
.addComponent(jLabel1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(jLabel2)
.addComponent(chkIncludeLauncher))
.addGap(0, 0, Short.MAX_VALUE)))
.addContainerGap())
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addContainerGap()
.addComponent(jLabel1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 19, Short.MAX_VALUE)
.addComponent(jLabel2)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(txtModpackName, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(lblModpackLocation)
.addComponent(cboModpackLocation))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(txtModpackLocation, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(lblGameVersion)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(cboGameVersion, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(chkIncludeLauncher)
.addContainerGap())
);
}// </editor-fold>//GEN-END:initComponents
private void cboModpackLocationActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_cboModpackLocationActionPerformed
JSystemFileChooser fc = new JSystemFileChooser();
fc.setFileSelectionMode(JSystemFileChooser.FILES_ONLY);
fc.setDialogTitle(C.i18n("modpack.wizard.step.initialization.save"));
fc.setMultiSelectionEnabled(false);
fc.setFileFilter(new FileNameExtensionFilter(C.i18n("modpack") + "(*.zip)", "zip"));
fc.showSaveDialog(this);
if (fc.getSelectedFile() != null) {
String path = fc.getSelectedFile().getAbsolutePath();
if (!path.endsWith(".zip"))
path += ".zip";
txtModpackLocation.setText(path);
}
}//GEN-LAST:event_cboModpackLocationActionPerformed
private void txtModpackLocationCaretUpdate(javax.swing.event.CaretEvent evt) {//GEN-FIRST:event_txtModpackLocationCaretUpdate
wizardData.put(KEY_MODPACK_LOCATION, txtModpackLocation.getText());
checkProblem();
}//GEN-LAST:event_txtModpackLocationCaretUpdate
private void cboGameVersionItemStateChanged(java.awt.event.ItemEvent evt) {//GEN-FIRST:event_cboGameVersionItemStateChanged
wizardData.put(KEY_GAME_VERSION, cboGameVersion.getSelectedItem());
}//GEN-LAST:event_cboGameVersionItemStateChanged
private void txtModpackNameCaretUpdate(javax.swing.event.CaretEvent evt) {//GEN-FIRST:event_txtModpackNameCaretUpdate
wizardData.put(KEY_MODPACK_NAME, txtModpackName.getText());
checkProblem();
}//GEN-LAST:event_txtModpackNameCaretUpdate
private void chkIncludeLauncherItemStateChanged(java.awt.event.ItemEvent evt) {//GEN-FIRST:event_chkIncludeLauncherItemStateChanged
wizardData.put(KEY_INCLUDING_LAUNCHER, chkIncludeLauncher.isSelected());
}//GEN-LAST:event_chkIncludeLauncherItemStateChanged
static final Pattern PATTERN = Pattern.compile("[-a-zA-Z0-9_\\.\\(\\)\\[\\]\\{\\}\\<\\>\"\'\u4E00-\u9FA5]+$");
void checkProblem() {
controller.setProblem(null);
if (txtModpackLocation.getText().trim().isEmpty())
controller.setProblem(C.i18n("modpack.not_a_valid_location"));
if (!PATTERN.matcher(txtModpackName.getText()).matches())
controller.setProblem(C.i18n("modpack.not_a_valid_name"));
}
// Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.JComboBox<String> cboGameVersion;
private javax.swing.JButton cboModpackLocation;
private javax.swing.JCheckBox chkIncludeLauncher;
private javax.swing.JLabel jLabel1;
private javax.swing.JLabel jLabel2;
private javax.swing.JLabel lblGameVersion;
private javax.swing.JLabel lblModpackLocation;
private javax.swing.JTextField txtModpackLocation;
private javax.swing.JTextField txtModpackName;
// End of variables declaration//GEN-END:variables
}
@@ -1,193 +0,0 @@
/*
* Hello Minecraft! Launcher.
* Copyright (C) 2013 huangyuhui <huanghongxun2008@126.com>
*
* 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 3 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. If not, see {http://www.gnu.org/licenses/}.
*/
package org.jackhuang.hmcl.ui.modpack;
import java.io.File;
import java.io.IOException;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Vector;
import javax.swing.JComponent;
import org.jackhuang.hmcl.core.GameException;
import org.jackhuang.hmcl.core.mod.ModpackManager;
import org.jackhuang.hmcl.core.version.MinecraftVersion;
import org.jackhuang.hmcl.setting.Config;
import org.jackhuang.hmcl.setting.Profile;
import org.jackhuang.hmcl.setting.Settings;
import org.jackhuang.hmcl.util.HMCLMinecraftService;
import org.jackhuang.hmcl.util.C;
import org.jackhuang.hmcl.util.Pair;
import org.jackhuang.hmcl.util.StrUtils;
import org.jackhuang.hmcl.util.Utils;
import org.jackhuang.hmcl.api.HMCLog;
import org.jackhuang.hmcl.util.sys.IOUtils;
import org.jackhuang.hmcl.util.sys.ZipEngine;
import org.jackhuang.hmcl.util.net.WebPage;
import org.jackhuang.hmcl.util.ui.checktree.CheckBoxTreeNode;
import org.jackhuang.hmcl.util.ui.wizard.spi.DeferredWizardResult;
import org.jackhuang.hmcl.util.ui.wizard.spi.ResultProgressHandle;
import org.jackhuang.hmcl.util.ui.wizard.spi.Summary;
import org.jackhuang.hmcl.util.ui.wizard.spi.WizardBranchController;
import org.jackhuang.hmcl.util.ui.wizard.spi.WizardController;
import org.jackhuang.hmcl.util.ui.wizard.spi.WizardException;
import org.jackhuang.hmcl.util.ui.wizard.spi.WizardPanelProvider;
/**
*
* @author huangyuhui
*/
public class ModpackWizard extends WizardBranchController {
static void process(CheckBoxTreeNode node, String basePath, List<String> list) {
if (node == null)
return;
if (node.isSelected()) {
if (basePath.length() > "minecraft/".length())
list.add(basePath.substring("minecraft/".length()));
return;
}
Enumeration<CheckBoxTreeNode> e = node.children();
for (; e.hasMoreElements();) {
CheckBoxTreeNode n = e.nextElement();
String s;
if (n.getUserObject() instanceof Pair)
s = ((Pair<String, String>) n.getUserObject()).key;
else
s = n.getUserObject().toString();
process(n, basePath + "/" + s, list);
}
}
public ModpackWizard(Profile profile) {
super(new WizardPanelProvider(C.i18n("modpack.wizard"), new String[] { C.i18n("modpack.wizard.step.1"), C.i18n("modpack.wizard.step.2"), C.i18n("modpack.wizard.step.3") }, new String[] { C.i18n("modpack.wizard.step.1.title"), C.i18n("modpack.wizard.step.2.title"), C.i18n("modpack.wizard.step.3.title") }) {
@Override
protected Object finish(Map settings) throws WizardException {
return new DeferredWizardResult(false) {
@Override
public void start(Map settings, ResultProgressHandle progress) {
progress.setBusy("Processing modpack");
ArrayList<String> blackList = new ArrayList<>(ModpackManager.MODPACK_BLACK_LIST);
CheckBoxTreeNode root = (CheckBoxTreeNode) settings.get("blackList");
process(root, "minecraft", blackList);
HashMap map = new HashMap();
map.put("name", (String) settings.get(ModpackInitializationPanel.KEY_MODPACK_NAME));
if (settings.containsKey(ModpackDescriptionPanel.KEY_MODPACK_DESCRITION))
try {
map.put("description", new org.markdown4j.Markdown4jProcessor().process((String) settings.get(ModpackDescriptionPanel.KEY_MODPACK_DESCRITION)));
} catch (IOException ex) {
progress.failed(C.i18n("modpack.export_error") + ": " + StrUtils.getStackTrace(ex), true);
}
try {
String gameVersion = (String) settings.get(ModpackInitializationPanel.KEY_GAME_VERSION);
String strLocation = (String) settings.get(ModpackInitializationPanel.KEY_MODPACK_LOCATION);
if (!strLocation.endsWith(".zip"))
strLocation += ".zip";
File loc = new File(strLocation);
File modpack = loc;
if ((Boolean) settings.get(ModpackInitializationPanel.KEY_INCLUDING_LAUNCHER))
modpack = new File(loc.getAbsolutePath() + ".temp");
ModpackManager.export(modpack, profile.service().version(), gameVersion, blackList, map,
t -> t.putTextFile(C.GSON.toJson(((HMCLMinecraftService) profile.service()).getVersionSetting(gameVersion)), "minecraft/hmclversion.cfg"));
String summary = "<html>" + C.i18n("modpack.export_finished") + ": " + loc.getAbsolutePath();
boolean including = false;
if ((Boolean) settings.get(ModpackInitializationPanel.KEY_INCLUDING_LAUNCHER)) {
boolean flag = true;
try (ZipEngine engine = new ZipEngine(loc)) {
Config s = new Config();
if (!IOUtils.isAbsolutePath(Settings.getInstance().getBgpath()))
s.setBgpath(Settings.getInstance().getBgpath());
s.setDownloadType(Settings.getInstance().getDownloadType());
engine.putTextFile(C.GSON.toJson(s), "hmcl.json");
engine.putFile(modpack, "modpack.zip");
File bg = new File("bg").getAbsoluteFile();
if (bg.isDirectory())
engine.putDirectory(bg);
bg = new File("background.png").getAbsoluteFile();
if (bg.isFile())
engine.putFile(bg, "background.png");
bg = new File("background.jpg").getAbsoluteFile();
if (bg.isFile())
engine.putFile(bg, "background.jpg");
for (URL u : Utils.getURL())
try {
File f = new File(u.toURI());
if (f.getName().endsWith(".exe") || f.getName().endsWith(".jar"))
engine.putFile(f, f.getName());
} catch (IOException | URISyntaxException e) {
HMCLog.err("Failed to add launcher files.", e);
flag = false;
break;
}
}
if (flag) {
including = true;
if (!modpack.delete())
HMCLog.warn("Failed to delete modpack.zip.temp, maybe the file is in using.");
}
}
summary += "<br/>" + C.i18n(including ? "modpack.included_launcher" : "modpack.not_included_launcher") + "</html>";
progress.finished(new Summary(new WebPage(summary), null));
} catch (IOException | GameException ex) {
HMCLog.err("Failed to export modpack", ex);
progress.failed(C.i18n("modpack.export_error") + ": " + StrUtils.getStackTrace(ex), true);
}
}
};
}
@Override
protected JComponent createPanel(WizardController controller, String id, Map settings) {
switch (indexOfStep(id)) {
case 0:
Vector<String> s = new Vector<>(profile.service().version().getVersionCount());
for (MinecraftVersion v : profile.service().version().getVersions())
if (!v.hidden)
s.add(v.id);
controller.setForwardNavigationMode(WizardController.MODE_CAN_CONTINUE);
return new ModpackInitializationPanel(controller, settings, s, profile.getSelectedVersion());
case 1:
controller.setForwardNavigationMode(WizardController.MODE_CAN_CONTINUE_OR_FINISH);
return new ModpackFileSelectionPanel(controller, settings, profile.service().baseDirectory(), ModpackManager.MODPACK_PREDICATE);
case 2:
controller.setForwardNavigationMode(WizardController.MODE_CAN_FINISH);
return new ModpackDescriptionPanel(controller, settings);
default:
throw new IllegalArgumentException(id);
}
}
});
}
@Override
protected WizardPanelProvider getPanelProviderForStep(String step, Map settings) {
return null;
}
}
@@ -1,151 +0,0 @@
/*
* Hello Minecraft! Launcher.
* Copyright (C) 2013 huangyuhui <huanghongxun2008@126.com>
*
* 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 3 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. If not, see {http://www.gnu.org/licenses/}.
*/
package org.jackhuang.hmcl.util;
import org.jackhuang.hmcl.util.C;
import org.jackhuang.hmcl.util.StrUtils;
import org.jackhuang.hmcl.util.ui.MessageBox;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.SwingUtilities;
import org.jackhuang.hmcl.api.HMCLog;
import static org.jackhuang.hmcl.Main.LAUNCHER_VERSION;
import org.jackhuang.hmcl.setting.Settings;
import org.jackhuang.hmcl.util.net.NetUtils;
import org.jackhuang.hmcl.util.sys.OS;
import org.jackhuang.hmcl.ui.LogWindow;
/**
*
* @author huangyuhui
*/
public class CrashReporter implements Thread.UncaughtExceptionHandler {
private static final Logger LOGGER = Logger.getLogger(CrashReporter.class.getName());
private static final HashMap<String, String> SOURCE = new HashMap<String, String>() {
{
put("MessageBox", "");
put("AWTError", "");
put("JFileChooser", "Has your operating system been installed completely or is a ghost system?");
put("JSystemFileChooser", "Has your operating system been installed completely or is a ghost system?");
put("Jce", "Has your operating system been installed completely or is a ghost system?");
put("couldn't create component peer", "Fucking computer!");
put("sun.awt.shell.Win32ShellFolder2", "crash.user_fault");
put("UnsatisfiedLinkError", "crash.user_fault");
put("java.awt.HeadlessException", "crash.headless");
put("java.lang.NoClassDefFoundError", "crash.NoClassDefFound");
put("java.lang.VerifyError", "crash.NoClassDefFound");
put("java.lang.NoSuchMethodError", "crash.NoClassDefFound");
put("java.lang.IncompatibleClassChangeError", "crash.NoClassDefFound");
put("java.lang.ClassFormatError", "crash.NoClassDefFound");
put("java.lang.OutOfMemoryError", "FUCKING MEMORY LIMIT!");
put("Trampoline", "ui.message.update_java");
put("NoSuchAlgorithmException", "Has your operating system been installed completely or is a ghost system?");
}
};
boolean enableLogger = false;
public CrashReporter(boolean enableLogger) {
this.enableLogger = enableLogger;
}
public boolean checkThrowable(Throwable e) {
String s = StrUtils.getStackTrace(e);
for (HashMap.Entry<String, String> entry : SOURCE.entrySet())
if (s.contains(entry.getKey())) {
if (StrUtils.isNotBlank(entry.getValue())) {
String info = C.i18n(entry.getKey());
LOGGER.severe(info);
try {
showMessage(info);
} catch (Throwable t) {
LOGGER.log(Level.SEVERE, "Failed to show message", t);
}
}
return false;
}
return true;
}
@Override
public void uncaughtException(Thread t, Throwable e) {
String s = StrUtils.getStackTrace(e);
if (!s.contains("org.jackhuang"))
return;
try {
String text = "\n---- Hello Minecraft! Crash Report ----\n";
text += " Version: " + LAUNCHER_VERSION + "\n";
text += " Time: " + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()) + "\n";
text += " Thread: " + t.toString() + "\n";
text += "\n Content: \n ";
text += s + "\n\n";
text += "-- System Details --\n";
text += " Operating System: " + OS.getSystemVersion() + "\n";
text += " Java Version: " + System.getProperty("java.version") + ", " + System.getProperty("java.vendor") + "\n";
text += " Java VM Version: " + System.getProperty("java.vm.name") + " (" + System.getProperty("java.vm.info") + "), " + System.getProperty("java.vm.vendor") + "\n";
if (enableLogger)
HMCLog.err(text);
else
System.out.println(text);
if (checkThrowable(e) && !System.getProperty("java.vm.name").contains("OpenJDK")) {
SwingUtilities.invokeLater(() -> LogWindow.INSTANCE.showAsCrashWindow(Settings.UPDATE_CHECKER.isOutOfDate()));
if (!Settings.UPDATE_CHECKER.isOutOfDate())
reportToServer(text, s);
}
} catch (Throwable ex) {
LOGGER.log(Level.SEVERE, "Failed to caught exception", ex);
LOGGER.log(Level.SEVERE, "There is the original exception", e);
}
}
void showMessage(String s) {
try {
MessageBox.show(s, "ERROR", MessageBox.ERROR_MESSAGE);
} catch (Throwable e) {
LOGGER.log(Level.SEVERE, "ERROR", e);
}
}
private static final HashSet<String> THROWABLE_SET = new HashSet<>();
void reportToServer(final String text, String stacktrace) {
if (THROWABLE_SET.contains(stacktrace) || stacktrace.contains("Font") || stacktrace.contains("InternalError"))
return;
THROWABLE_SET.add(stacktrace);
Thread t = new Thread(() -> {
HashMap<String, String> map = new HashMap<>();
map.put("CrashReport", text);
try {
NetUtils.post(NetUtils.constantURL("http://huangyuhui.duapp.com/crash.php"), map);
} catch (IOException ex) {
LOGGER.log(Level.SEVERE, "Failed to post HMCL server.", ex);
}
});
t.setDaemon(true);
t.start();
}
}
@@ -1,78 +0,0 @@
/*
* Hello Minecraft! Launcher.
* Copyright (C) 2013 huangyuhui <huanghongxun2008@126.com>
*
* 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 3 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. If not, see {http://www.gnu.org/licenses/}.
*/
package org.jackhuang.hmcl.util;
import java.util.ArrayList;
import javax.swing.JFrame;
import org.jackhuang.hmcl.api.ui.AddTabCallback;
import org.jackhuang.hmcl.api.IPlugin;
import org.jackhuang.hmcl.core.auth.OfflineAuthenticator;
import org.jackhuang.hmcl.core.auth.YggdrasilAuthenticator;
import org.jackhuang.hmcl.setting.Settings;
import org.jackhuang.hmcl.ui.GameSettingsPanel;
import org.jackhuang.hmcl.ui.LauncherSettingsPanel;
import org.jackhuang.hmcl.ui.MainPagePanel;
import org.jackhuang.hmcl.api.auth.IAuthenticator;
import org.jackhuang.hmcl.api.func.Consumer;
import org.jackhuang.hmcl.api.ui.Theme;
import org.jackhuang.hmcl.laf.LAFTheme;
/**
*
* @author huangyuhui
*/
public class DefaultPlugin implements IPlugin {
public static DefaultPlugin INSTANCE;
public DefaultPlugin() {
INSTANCE = this;
for (Theme t : LAFTheme.THEMES)
Theme.THEMES.put(t.getId(), t);
}
ArrayList<IAuthenticator> auths = new ArrayList<>();
@Override
public void onRegisterAuthenticators(Consumer<IAuthenticator> apply) {
String clientToken = Settings.getInstance().getClientToken();
auths.add(new OfflineAuthenticator(clientToken));
auths.add(new YggdrasilAuthenticator(clientToken));
try {
Runtime.getRuntime().addShutdownHook(new Thread(this::saveAuthenticatorConfig));
} catch (IllegalStateException ignore) { // Shutdown in progress
}
for (IAuthenticator i : auths) {
i.onLoadSettings(Settings.getInstance().getAuthenticatorConfig(i.id()));
apply.accept(i);
}
}
public void saveAuthenticatorConfig() {
for (IAuthenticator i : auths)
Settings.getInstance().setAuthenticatorConfig(i.id(), i.onSaveSettings());
}
@Override
public void onAddTab(JFrame frame, AddTabCallback callback) {
callback.addTab(new MainPagePanel(), "main", C.i18n("launcher.title.main"));
callback.addTab(new GameSettingsPanel(), "game", C.i18n("launcher.title.game"));
callback.addTab(new LauncherSettingsPanel(), "launcher", C.i18n("launcher.title.launcher"));
}
}
@@ -1,45 +0,0 @@
/*
* Hello Minecraft! Launcher.
* Copyright (C) 2013 huangyuhui <huanghongxun2008@126.com>
*
* 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 3 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. If not, see {http://www.gnu.org/licenses/}.
*/
package org.jackhuang.hmcl.util;
import java.io.File;
import javax.swing.filechooser.FileFilter;
import org.jackhuang.hmcl.util.sys.FileUtils;
/**
*
* @author huangyuhui
*/
public class FileNameFilter extends FileFilter {
String acceptedName;
public FileNameFilter(String acceptedName) {
this.acceptedName = acceptedName;
}
@Override
public boolean accept(File f) {
return f.isDirectory() || f.getName().equals(acceptedName) && !FileUtils.getExtension(f.getName()).equals("lnk");
}
@Override
public String getDescription() {
return acceptedName;
}
}
@@ -1,47 +0,0 @@
/*
* Hello Minecraft! Launcher.
* Copyright (C) 2013 huangyuhui <huanghongxun2008@126.com>
*
* 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 3 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. If not, see {http://www.gnu.org/licenses/}.
*/
package org.jackhuang.hmcl.util;
import java.io.File;
import org.jackhuang.hmcl.core.asset.MinecraftAssetService;
import org.jackhuang.hmcl.core.service.IMinecraftService;
import org.jackhuang.hmcl.setting.Settings;
/**
*
* @author huang
*/
public class HMCLAssetService extends MinecraftAssetService {
public HMCLAssetService(IMinecraftService service) {
super(service);
}
private boolean useSelf(String assetId) {
return new File(service.baseDirectory(), "assets/indexes/" + assetId + ".json").exists() || ((HMCLMinecraftService) service).getProfile().isNoCommon();
}
@Override
public File getAssets(String assetId) {
if (useSelf(assetId))
return new File(service.baseDirectory(), "assets");
else
return new File(Settings.getInstance().getCommonpath(), "assets");
}
}
@@ -1,112 +0,0 @@
/*
* Hello Minecraft! Launcher.
* Copyright (C) 2013 huangyuhui <huanghongxun2008@126.com>
*
* 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 3 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. If not, see {http://www.gnu.org/licenses/}.
*/
package org.jackhuang.hmcl.util;
import org.jackhuang.hmcl.core.GameException;
import org.jackhuang.hmcl.api.auth.AuthenticationException;
import org.jackhuang.hmcl.core.auth.AbstractAuthenticator;
import org.jackhuang.hmcl.api.auth.LoginInfo;
import org.jackhuang.hmcl.core.launch.DefaultGameLauncher;
import org.jackhuang.hmcl.core.launch.GameLauncher;
import org.jackhuang.hmcl.api.game.LaunchOptions;
import org.jackhuang.hmcl.setting.Profile;
import org.jackhuang.hmcl.setting.Settings;
import org.jackhuang.hmcl.api.HMCLApi;
import org.jackhuang.hmcl.api.event.launch.LaunchSucceededEvent;
import org.jackhuang.hmcl.api.event.launch.LaunchingState;
import org.jackhuang.hmcl.api.event.launch.LaunchingStateChangedEvent;
import org.jackhuang.hmcl.api.event.launch.ProcessingLaunchOptionsEvent;
import org.jackhuang.hmcl.core.RuntimeGameException;
import org.jackhuang.hmcl.api.func.Consumer;
import org.jackhuang.hmcl.api.HMCLog;
import org.jackhuang.hmcl.api.Wrapper;
import org.jackhuang.hmcl.util.sys.JavaProcess;
import org.jackhuang.hmcl.api.auth.IAuthenticator;
/**
*
* @author huangyuhui
*/
public class HMCLGameLauncher {
Profile profile;
boolean isLaunching = false;
public HMCLGameLauncher(Profile p) {
this.profile = p;
HMCLApi.EVENT_BUS.channel(LaunchSucceededEvent.class).register(() -> setLaunching(false));
}
void setLaunching(boolean isLaunching) {
if (isLaunching != this.isLaunching)
HMCLApi.EVENT_BUS.fireChannel(new LaunchingStateChangedEvent(this, isLaunching ? LaunchingState.Starting : LaunchingState.Done));
this.isLaunching = isLaunching;
}
public void genLaunchCode(final Consumer<GameLauncher> listener, final Consumer<String> failed, String passwordIfNeeded) {
if (isLaunching || profile == null)
return;
setLaunching(true);
HMCLog.log("Start generating launching command...");
if (!profile.getGameDir().exists()) {
failed.accept(C.i18n("minecraft.wrong_path"));
setLaunching(false);
return;
}
if (profile.getSelectedVersion() == null) {
failed.accept(C.i18n("minecraft.no_selected_version"));
setLaunching(false);
return;
}
final IAuthenticator l = AbstractAuthenticator.LOGINS.get(Settings.getInstance().getLoginType());
final LoginInfo li = new LoginInfo(l.getUserName(), l.isLoggedIn() || !l.hasPassword() ? null : passwordIfNeeded);
Thread t = new Thread() {
@Override
public void run() {
Thread.currentThread().setName("Game Launcher");
try {
Wrapper<LaunchOptions> options = new Wrapper<>(profile.getSelectedVersionSetting().createLaunchOptions(profile.getGameDir()));
HMCLApi.EVENT_BUS.fireChannel(new ProcessingLaunchOptionsEvent(this, options));
DefaultGameLauncher gl = new DefaultGameLauncher(options.getValue(), profile.service(), li, l);
GameLauncherTag tag = new GameLauncherTag();
tag.launcherVisibility = profile.getSelectedVersionSetting().getLauncherVisibility();
gl.setTag(tag);
listener.accept(gl);
gl.makeLaunchCommand();
} catch (GameException | RuntimeGameException e) {
failed.accept(C.i18n("launch.failed") + ", " + e.getMessage());
setLaunching(false);
} catch (AuthenticationException e) {
failed.accept(C.i18n("login.failed") + ", " + e.getMessage());
setLaunching(false);
}
}
};
t.setDaemon(true);
t.start();
}
public static class GameLauncherTag {
public LauncherVisibility launcherVisibility;
public JavaProcess process;
public int state; // 0 - unknown; 1 - launch; 2 - make launch script.
}
}
@@ -1,58 +0,0 @@
/*
* Hello Minecraft! Launcher.
* Copyright (C) 2013 huangyuhui <huanghongxun2008@126.com>
*
* 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 3 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. If not, see {http://www.gnu.org/licenses/}.
*/
package org.jackhuang.hmcl.util;
import java.io.File;
import org.jackhuang.hmcl.api.game.GameDirType;
import org.jackhuang.hmcl.api.game.IMinecraftLibrary;
import org.jackhuang.hmcl.core.version.MinecraftVersion;
import org.jackhuang.hmcl.core.version.MinecraftVersionManager;
import org.jackhuang.hmcl.setting.Settings;
import org.jackhuang.hmcl.setting.VersionSetting;
/**
*
* @author huangyuhui
*/
public class HMCLGameProvider extends MinecraftVersionManager<HMCLMinecraftService> {
public HMCLGameProvider(HMCLMinecraftService p) {
super(p);
}
@Override
public File getLibraryFile(MinecraftVersion version, IMinecraftLibrary lib) {
VersionSetting vs = service.getProfile().getVersionSetting(version.id);
File self = super.getLibraryFile(version, lib);
if (self == null || self.exists() || (vs != null && service.getProfile().isNoCommon()))
return self;
else
return lib.getFilePath(new File(Settings.getInstance().getCommonpath()));
}
@Override
public File getRunDirectory(String id) {
VersionSetting vs = service.getProfile().getVersionSetting(id);
if (vs == null)
return super.getRunDirectory(id);
else
return vs.getGameDirType() == GameDirType.VERSION_FOLDER
? service.version().versionRoot(id)
: super.getRunDirectory(id);
}
}
@@ -1,46 +0,0 @@
/*
* Hello Minecraft! Launcher.
* Copyright (C) 2013 huangyuhui <huanghongxun2008@126.com>
*
* 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 3 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. If not, see {http://www.gnu.org/licenses/}.
*/
package org.jackhuang.hmcl.util;
import java.util.List;
import java.util.Map;
import org.jackhuang.hmcl.Main;
import org.jackhuang.hmcl.api.auth.UserProfileProvider;
import org.jackhuang.hmcl.api.game.LaunchOptions;
import org.jackhuang.hmcl.core.GameException;
import org.jackhuang.hmcl.core.launch.MinecraftLoader;
import org.jackhuang.hmcl.core.service.IMinecraftService;
/**
*
* @author huang
*/
public class HMCLMinecraftLoader extends MinecraftLoader {
public HMCLMinecraftLoader(LaunchOptions p, IMinecraftService provider, UserProfileProvider lr) throws GameException {
super(p, provider, lr);
}
@Override
protected Map<String, String> getConfigurations() {
Map<String, String> map = super.getConfigurations();
map.put("${launcher_version}", Main.LAUNCHER_VERSION);
map.put("${launcher_name}", Main.LAUNCHER_NAME);
return map;
}
}
@@ -1,187 +0,0 @@
/*
* Hello Minecraft! Launcher.
* Copyright (C) 2013 huangyuhui <huanghongxun2008@126.com>
*
* 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 3 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. If not, see {http://www.gnu.org/licenses/}.
*/
package org.jackhuang.hmcl.util;
import org.jackhuang.hmcl.core.service.IMinecraftService;
import org.jackhuang.hmcl.core.service.IMinecraftLoader;
import org.jackhuang.hmcl.core.service.IMinecraftModService;
import com.google.gson.JsonSyntaxException;
import java.io.File;
import java.util.HashMap;
import java.util.Map;
import javax.swing.SwingUtilities;
import org.jackhuang.hmcl.api.HMCLApi;
import org.jackhuang.hmcl.api.event.version.LoadedOneVersionEvent;
import org.jackhuang.hmcl.api.event.version.RefreshedVersionsEvent;
import org.jackhuang.hmcl.api.event.version.RefreshingVersionsEvent;
import org.jackhuang.hmcl.core.GameException;
import org.jackhuang.hmcl.core.install.MinecraftInstallerService;
import org.jackhuang.hmcl.api.auth.UserProfileProvider;
import org.jackhuang.hmcl.core.download.MinecraftDownloadService;
import org.jackhuang.hmcl.api.game.LaunchOptions;
import org.jackhuang.hmcl.core.launch.MinecraftLoader;
import org.jackhuang.hmcl.core.mod.MinecraftModService;
import org.jackhuang.hmcl.core.mod.ModpackManager;
import org.jackhuang.hmcl.setting.Profile;
import org.jackhuang.hmcl.setting.VersionSetting;
import org.jackhuang.hmcl.ui.MainFrame;
import org.jackhuang.hmcl.api.HMCLog;
import org.jackhuang.hmcl.util.sys.FileUtils;
import org.jackhuang.hmcl.util.task.TaskWindow;
/**
*
* @author huangyuhui
*/
public class HMCLMinecraftService extends IMinecraftService {
private Profile p;
final Map<String, VersionSetting> versionSettings = new HashMap<>();
public HMCLMinecraftService(Profile p) {
this.p = p;
this.provider = new HMCLGameProvider(this);
provider.initializeMinecraft();
HMCLApi.EVENT_BUS.channel(RefreshingVersionsEvent.class).register(versionSettings::clear);
HMCLApi.EVENT_BUS.channel(RefreshedVersionsEvent.class).registerFirst(() -> {
if (!checkingModpack) {
checkingModpack = true;
if (version().getVersionCount() == 0) {
File modpack = new File("modpack.zip").getAbsoluteFile();
if (modpack.exists())
SwingUtilities.invokeLater(() -> {
if (TaskWindow.factory().execute(ModpackManager.install(MainFrame.INSTANCE, modpack, this, null)))
version().refreshVersions();
checkedModpack = true;
});
}
}
});
HMCLApi.EVENT_BUS.channel(LoadedOneVersionEvent.class).register(e -> loadVersionSetting(e.getValue()));
this.mms = new MinecraftModService(this);
this.mds = new MinecraftDownloadService(this);
this.mas = new HMCLAssetService(this);
this.mis = new MinecraftInstallerService(this);
}
public boolean checkedModpack = false, checkingModpack = false;
private void loadVersionSetting(String id) {
if (provider.getVersionById(id) == null)
return;
VersionSetting vs = null;
File f = new File(provider.versionRoot(id), "hmclversion.cfg");
if (f.exists()) {
String s = FileUtils.readQuietly(f);
if (s != null)
try {
vs = C.GSON.fromJson(s, VersionSetting.class);
} catch (JsonSyntaxException ex) {
HMCLog.warn("Failed to load version setting: " + id, ex);
vs = null;
}
}
if (vs == null)
return;
initVersionSetting(id, vs);
}
public void createVersionSetting(String id) {
if (provider.getVersionById(id) == null || versionSettings.containsKey(id))
return;
initVersionSetting(id, new VersionSetting());
}
private void initVersionSetting(String id, VersionSetting vs) {
vs.id = id;
vs.propertyChanged.register(event -> saveVersionSetting(((VersionSetting) event.getSource()).id));
versionSettings.put(id, vs);
}
/**
* Get the version setting for version id.
*
* @param id version id
*
* @return may return null if the id not exists
*/
public VersionSetting getVersionSetting(String id) {
if (!versionSettings.containsKey(id))
loadVersionSetting(id);
return versionSettings.get(id);
}
public void saveVersionSetting(String id) {
if (!versionSettings.containsKey(id))
return;
File f = new File(provider.versionRoot(id), "hmclversion.cfg");
FileUtils.writeQuietly(f, C.GSON.toJson(versionSettings.get(id)));
}
@Override
public File baseDirectory() {
return p.getGameDir();
}
protected HMCLGameProvider provider;
@Override
public HMCLGameProvider version() {
return provider;
}
protected MinecraftModService mms;
@Override
public IMinecraftModService mod() {
return mms;
}
protected MinecraftDownloadService mds;
@Override
public MinecraftDownloadService download() {
return mds;
}
final HMCLAssetService mas;
@Override
public HMCLAssetService asset() {
return mas;
}
protected MinecraftInstallerService mis;
@Override
public MinecraftInstallerService install() {
return mis;
}
@Override
public IMinecraftLoader launch(LaunchOptions options, UserProfileProvider p) throws GameException {
MinecraftLoader l = new HMCLMinecraftLoader(options, this, p);
l.setAssetProvider(mas.ASSET_PROVIDER_IMPL);
return l;
}
public Profile getProfile() {
return p;
}
}
@@ -1,44 +0,0 @@
/*
* Hello Minecraft! Launcher.
* Copyright (C) 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 3 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. If not, see {http://www.gnu.org/licenses/}.
*/
package org.jackhuang.hmcl.util;
/**
*
* @author huangyuhui
*/
public enum LauncherVisibility {
/**
* Close the launcher anyway when the game process created even if failed to
* launch game.
*/
CLOSE,
/**
* Hide the launcher when the game process created, if failed to launch
* game, will show the log window.
*/
HIDE,
/**
* Keep the launcher visible even if the game launched successfully.
*/
KEEP,
/**
* Hide the launcher and reopen it when game closes.
*/
HIDE_AND_REOPEN
}
@@ -1,149 +0,0 @@
/*
* Hello Minecraft! Launcher.
* Copyright (C) 2013 huangyuhui <huanghongxun2008@126.com>
*
* 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 3 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. If not, see {http://www.gnu.org/licenses/}.
*/
package org.jackhuang.hmcl.util;
import java.io.PipedOutputStream;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicBoolean;
import org.jackhuang.hmcl.api.HMCLApi;
import org.jackhuang.hmcl.api.event.process.JavaProcessStoppedEvent;
import org.jackhuang.hmcl.api.func.Consumer;
import org.jackhuang.hmcl.ui.LogWindow;
import org.jackhuang.hmcl.util.log.Level;
import org.jackhuang.hmcl.util.sys.ProcessMonitor;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
/**
*
* @author huang
*/
public class Log4jHandler extends Thread implements Consumer<JavaProcessStoppedEvent> {
ProcessMonitor monitor;
List<Pair<String, String>> forbiddenTokens = new LinkedList<>();
AtomicBoolean interrupted = new AtomicBoolean(false);
boolean enabled = true;
public Log4jHandler(ProcessMonitor monitor, PipedOutputStream outputStream, boolean enabled) {
this.monitor = monitor;
this.enabled = enabled;
HMCLApi.EVENT_BUS.channel(JavaProcessStoppedEvent.class).register((Consumer<JavaProcessStoppedEvent>) this);
}
public void addForbiddenToken(String token, String replacement) {
forbiddenTokens.add(new Pair<>(token, replacement));
}
@Override
public void run() {
}
@Override
public void accept(JavaProcessStoppedEvent t) {
}
/**
* Always use this instance method to write to the log,
* to make sure only this Thread writes to the PipedOutputStream.
*
* It will also flush the buffer, directly after write.
*
* This prevents java.io.IOException: Read end dead
* See also https://techtavern.wordpress.com/2008/07/16/whats-this-ioexception-write-end-dead/
*
* @param content The content to be written to the log
*/
public Future newLogLine(String content) {
printlnImpl(content, Level.guessLevel(content));
return null;
}
class Log4jHandlerImpl extends DefaultHandler {
private final SimpleDateFormat df = new SimpleDateFormat("HH:mm:ss");
String date = "", thread = "", logger = "";
StringBuilder message = null;
Level l = null;
boolean readingMessage = false;
@Override
public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
switch (localName) {
case "log4j_Event":
message = new StringBuilder();
Date d = new Date(Long.valueOf(attributes.getValue("timestamp")));
date = df.format(d);
try {
l = Level.valueOf(attributes.getValue("level"));
} catch (IllegalArgumentException e) {
l = Level.INFO;
}
thread = attributes.getValue("thread");
logger = attributes.getValue("logger");
if ("STDERR".equals(logger))
l = Level.ERROR;
break;
case "log4j_Message":
readingMessage = true;
break;
}
}
@Override
public void endElement(String uri, String localName, String qName) throws SAXException {
switch (localName) {
case "log4j_Event":
println("[" + date + "] [" + thread + "/" + l.name() + "] [" + logger + "] " + message.toString(), l);
break;
case "log4j_Message":
readingMessage = false;
break;
}
}
@Override
public void characters(char[] ch, int start, int length) throws SAXException {
String line = new String(ch, start, length);
if (line.trim().isEmpty())
return;
if (readingMessage)
message.append(line).append(C.LINE_SEPARATOR);
else
println(line, Level.guessLevel(line));
}
public void println(String message, Level l) {
printlnImpl(message, l);
}
}
private void printlnImpl(String message, Level l) {
for (Pair<String, String> entry : forbiddenTokens)
message = message.replace(entry.key, entry.value);
if (LogWindow.outputStream != null)
LogWindow.outputStream.log(message, l);
}
}
@@ -1,58 +0,0 @@
/*
* Hello Minecraft! Launcher.
* Copyright (C) 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 3 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. If not, see {http://www.gnu.org/licenses/}.
*/
package org.jackhuang.hmcl.util;
import org.jackhuang.hmcl.util.lang.SupportedLocales;
/**
* Give the advice to solve the Minecraft crashing.
*
* @author huangyuhui
*/
public final class MinecraftCrashAdvicer {
public static String getAdvice(String trace) {
return getAdvice(trace, false);
}
public static String getAdvice(String trace, boolean selfCrash) {
if (trace == null)
return C.i18n("crash.advice.no");
trace = trace.toLowerCase(SupportedLocales.getNowLocale().self);
if (trace.contains("pixel format not accelerated"))
return C.i18n("crash.advice.LWJGLException");
else if (trace.contains("unsupportedclassversionrrror"))
return C.i18n("crash.advice.UnsupportedClassVersionError");
else if (trace.contains("concurrentmodificationexception"))
return C.i18n("crash.advice.ConcurrentModificationException");
else if (trace.contains("securityexception"))
return C.i18n("crash.advice.SecurityException");
else if (trace.contains("nosuchfieldexception") || trace.contains("nosuchmethodexception") || trace.contains("nosuchfielderror") || trace.contains("nosuchmethoderror"))
return C.i18n("crash.advice.NoSuchFieldError");
else if (trace.contains("outofmemory") || trace.contains("out of memory"))
return C.i18n("crash.advice.OutOfMemoryError");
else if (trace.contains("noclassdeffounderror") || trace.contains("classnotfoundexception"))
return C.i18n("crash.advice.ClassNotFoundException");
else if (trace.contains("no lwjgl in java.library.path"))
return C.i18n("crash.advice.no_lwjgl");
else if (trace.contains("opengl") || trace.contains("openal"))
return C.i18n("crash.advice.OpenGL");
return C.i18n(selfCrash ? "crash.advice.no" : "crash.advice.otherwise");
}
}
@@ -1,279 +0,0 @@
/*
* Hello Minecraft! Launcher.
* Copyright (C) 2013 huangyuhui <huanghongxun2008@126.com>
*
* 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 3 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. If not, see {http://www.gnu.org/licenses/}.
*/
package org.jackhuang.hmcl.util.upgrade;
import com.google.gson.JsonParseException;
import com.google.gson.reflect.TypeToken;
import java.io.File;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.jar.JarFile;
import java.util.jar.JarOutputStream;
import java.util.jar.Pack200;
import java.util.logging.Level;
import java.util.zip.GZIPInputStream;
import org.jackhuang.hmcl.Main;
import org.jackhuang.hmcl.api.HMCLog;
import org.jackhuang.hmcl.api.event.SimpleEvent;
import org.jackhuang.hmcl.util.C;
import org.jackhuang.hmcl.core.MCUtils;
import org.jackhuang.hmcl.util.task.Task;
import org.jackhuang.hmcl.util.task.TaskWindow;
import org.jackhuang.hmcl.util.net.FileDownloadTask;
import org.jackhuang.hmcl.util.ui.MessageBox;
import org.jackhuang.hmcl.util.Utils;
import org.jackhuang.hmcl.api.VersionNumber;
import org.jackhuang.hmcl.util.StrUtils;
import org.jackhuang.hmcl.util.sys.FileUtils;
import org.jackhuang.hmcl.util.sys.IOUtils;
import org.jackhuang.hmcl.util.sys.Java;
import org.jackhuang.hmcl.util.sys.OS;
/**
*
* @author huangyuhui
*/
public class AppDataUpgrader extends IUpgrader {
private void launchNewerVersion(List<String> args, File jar) throws IOException, ReflectiveOperationException {
try (JarFile jarFile = new JarFile(jar)) {
String mainClass = jarFile.getManifest().getMainAttributes().getValue("Main-Class");
if (mainClass == null)
throw new ClassNotFoundException("Main-Class not found in manifest");
ArrayList<String> al = new ArrayList<>(args);
al.add("--noupdate");
ClassLoader pre = Thread.currentThread().getContextClassLoader();
try {
ClassLoader now = new URLClassLoader(new URL[] { jar.toURI().toURL() }, ClassLoader.getSystemClassLoader().getParent());
Thread.currentThread().setContextClassLoader(now);
now.loadClass(mainClass).getMethod("main", String[].class).invoke(null, new Object[] { al.toArray(new String[0]) });
} finally {
Thread.currentThread().setContextClassLoader(pre);
}
}
}
@Override
public void parseArguments(VersionNumber nowVersion, List<String> args) {
File f = AppDataUpgraderPackGzTask.HMCL_VER_FILE;
if (!args.contains("--noupdate"))
try {
if (f.exists()) {
Map<String, String> m = C.GSON.fromJson(FileUtils.read(f), new TypeToken<Map<String, String>>() {
}.getType());
String s = m.get("ver");
if (s != null && VersionNumber.asVersion(s).compareTo(nowVersion) > 0) {
String j = m.get("loc");
if (j != null) {
File jar = new File(j);
if (jar.exists()) {
launchNewerVersion(args, jar);
System.exit(0);
}
}
}
}
} catch (JsonParseException ex) {
f.delete();
} catch (IOException | ReflectiveOperationException t) {
HMCLog.err("Unable to execute newer version application", t);
AppDataUpgraderPackGzTask.HMCL_VER_FILE.delete(); // delete version json, let HMCL re-download the newer version.
}
}
@Override
public void accept(SimpleEvent<VersionNumber> event) {
final VersionNumber version = event.getValue();
((UpdateChecker) event.getSource()).requestDownloadLink().reg(map -> {
boolean flag = false;
for (Java java : Java.JAVA)
if (java.getName().startsWith("1.8") || java.getName().startsWith("9") || java.getName().startsWith("10")) {
flag = true;
break;
}
if (!flag) {
MessageBox.show("请安装 Java 8");
try {
java.awt.Desktop.getDesktop().browse(new URI("https://java.com"));
} catch (URISyntaxException | IOException e) {
Utils.setClipboard("https://java.com");
MessageBox.show(C.i18n("update.no_browser"));
}
}
if (MessageBox.show(C.i18n("update.newest_version") + version.toString() + "\n"
+ C.i18n("update.should_open_link"),
MessageBox.YES_NO_OPTION) == MessageBox.YES_OPTION)
if (map != null && map.containsKey("pack") && !StrUtils.isBlank(map.get("pack")))
try {
String hash = null;
if (map.containsKey("packsha1"))
hash = map.get("packsha1");
if (TaskWindow.factory().append(new AppDataUpgraderPackGzTask(map.get("pack"), version.toString(), hash)).execute()) {
new ProcessBuilder(new String[] { IOUtils.getJavaDir(), "-jar", AppDataUpgraderPackGzTask.getSelf(version.toString()).getAbsolutePath() }).directory(new File("").getAbsoluteFile()).start();
System.exit(0);
}
} catch (IOException ex) {
HMCLog.err("Failed to create upgrader", ex);
}
else if (map != null && map.containsKey("jar") && !StrUtils.isBlank(map.get("jar")))
try {
String hash = null;
if (map.containsKey("jarsha1"))
hash = map.get("jarsha1");
if (TaskWindow.factory().append(new AppDataUpgraderJarTask(map.get("jar"), version.toString(), hash)).execute()) {
new ProcessBuilder(new String[] { IOUtils.getJavaDir(), "-jar", AppDataUpgraderJarTask.getSelf(version.toString()).getAbsolutePath() }).directory(new File("").getAbsoluteFile()).start();
System.exit(0);
}
} catch (IOException ex) {
Main.LOGGER.log(Level.SEVERE, "Failed to create upgrader", ex);
}
else {
String url = C.URL_PUBLISH;
if (map != null)
if (map.containsKey(OS.os().checkedName))
url = map.get(OS.os().checkedName);
else if (map.containsKey(OS.UNKNOWN.checkedName))
url = map.get(OS.UNKNOWN.checkedName);
if (url == null)
url = C.URL_PUBLISH;
try {
java.awt.Desktop.getDesktop().browse(new URI(url));
} catch (URISyntaxException | IOException e) {
HMCLog.err("Failed to browse uri: " + url, e);
Utils.setClipboard(url);
MessageBox.show(C.i18n("update.no_browser"));
}
}
}).execute();
}
;
public static class AppDataUpgraderPackGzTask extends Task {
public static final File BASE_FOLDER = MCUtils.getWorkingDirectory("hmcl");
public static final File HMCL_VER_FILE = new File(BASE_FOLDER, "hmclver.json");
public static File getSelf(String ver) {
return new File(BASE_FOLDER, "HMCL-" + ver + ".jar");
}
private final String downloadLink, newestVersion, expectedHash;
File tempFile;
public AppDataUpgraderPackGzTask(String downloadLink, String newestVersion, String hash) throws IOException {
this.downloadLink = downloadLink;
this.newestVersion = newestVersion;
this.expectedHash = hash;
tempFile = File.createTempFile("hmcl", ".pack.gz");
}
@Override
public Collection<Task> getDependTasks() {
return Collections.singleton(new FileDownloadTask(downloadLink, tempFile, expectedHash));
}
@Override
public void executeTask(boolean areDependTasksSucceeded) throws Exception {
if (!areDependTasksSucceeded) {
tempFile.delete();
return;
}
HashMap<String, String> json = new HashMap<>();
File f = getSelf(newestVersion);
if (!FileUtils.makeDirectory(f.getParentFile()))
throw new IOException("Failed to make directories: " + f.getParent());
for (int i = 0; f.exists(); i++)
f = new File(BASE_FOLDER, "HMCL-" + newestVersion + (i > 0 ? "-" + i : "") + ".jar");
if (!f.createNewFile())
throw new IOException("Failed to create new file: " + f);
try (GZIPInputStream in = new GZIPInputStream(FileUtils.openInputStream(tempFile));
JarOutputStream jos = new JarOutputStream(FileUtils.openOutputStream(f))) {
Pack200.newUnpacker().unpack(in, jos);
}
json.put("ver", newestVersion);
json.put("loc", f.getAbsolutePath());
String result = C.GSON.toJson(json);
FileUtils.write(HMCL_VER_FILE, result);
}
@Override
public String getInfo() {
return "Upgrade";
}
}
public static class AppDataUpgraderJarTask extends Task {
public static final File BASE_FOLDER = MCUtils.getWorkingDirectory("hmcl");
public static final File HMCL_VER_FILE = new File(BASE_FOLDER, "hmclver.json");
public static File getSelf(String ver) {
return new File(BASE_FOLDER, "HMCL-" + ver + ".jar");
}
private final String downloadLink, newestVersion, expectedHash;
File tempFile;
public AppDataUpgraderJarTask(String downloadLink, String newestVersion, String hash) throws IOException {
this.downloadLink = downloadLink;
this.newestVersion = newestVersion;
this.expectedHash = hash;
tempFile = File.createTempFile("hmcl", ".jar");
}
@Override
public Collection<Task> getDependTasks() {
return Collections.singleton(new FileDownloadTask(downloadLink, tempFile, expectedHash));
}
@Override
public void executeTask(boolean areDependTasksSucceeded) throws Exception {
if (!areDependTasksSucceeded) {
tempFile.delete();
return;
}
HashMap<String, String> json = new HashMap<>();
File f = getSelf(newestVersion);
FileUtils.copyFile(tempFile, f);
json.put("ver", newestVersion);
json.put("loc", f.getAbsolutePath());
String result = C.GSON.toJson(json);
FileUtils.write(HMCL_VER_FILE, result);
}
@Override
public String getInfo() {
return "Upgrade";
}
}
}
@@ -1,51 +0,0 @@
/*
* Hello Minecraft! Launcher.
* Copyright (C) 2013 huangyuhui <huanghongxun2008@126.com>
*
* 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 3 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. If not, see {http://www.gnu.org/licenses/}.
*/
package org.jackhuang.hmcl.util.upgrade;
import java.util.List;
import org.jackhuang.hmcl.api.event.SimpleEvent;
import org.jackhuang.hmcl.api.VersionNumber;
import org.jackhuang.hmcl.api.func.Consumer;
/**
*
* @author huangyuhui
*/
public abstract class IUpgrader implements Consumer<SimpleEvent<VersionNumber>> {
public static final IUpgrader NOW_UPGRADER = new AppDataUpgrader();
/**
* Paring arguments to decide on whether the upgrade is needed.
*
* @param nowVersion now launcher version
* @param args Application CommandLine Arguments
*/
public abstract void parseArguments(VersionNumber nowVersion, List<String> args);
/**
* Just download the new app.
*
* @param sender Should be VersionChecker
* @param number the newest version
*
* @return should return true
*/
@Override
public abstract void accept(SimpleEvent<VersionNumber> event);
}
@@ -1,110 +0,0 @@
/*
* Hello Minecraft!.
* Copyright (C) 2013 huangyuhui <huanghongxun2008@126.com>
*
* 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 3 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. If not, see {http://www.gnu.org/licenses/}.
*/
package org.jackhuang.hmcl.util.upgrade;
import org.jackhuang.hmcl.util.ui.MessageBox;
import org.jackhuang.hmcl.api.VersionNumber;
import org.jackhuang.hmcl.api.event.EventHandler;
import org.jackhuang.hmcl.util.net.NetUtils;
import com.google.gson.JsonSyntaxException;
import java.io.IOException;
import org.jackhuang.hmcl.api.HMCLog;
import java.util.Map;
import org.jackhuang.hmcl.Main;
import org.jackhuang.hmcl.api.HMCLApi;
import org.jackhuang.hmcl.api.event.SimpleEvent;
import org.jackhuang.hmcl.api.event.OutOfDateEvent;
import org.jackhuang.hmcl.util.AbstractSwingWorker;
import org.jackhuang.hmcl.util.C;
import org.jackhuang.hmcl.util.IUpdateChecker;
/**
*
* @author huangyuhui
*/
public final class UpdateChecker implements IUpdateChecker {
private volatile boolean outOfDate = false;
public VersionNumber base;
public String versionString;
public String type;
private Map<String, String> download_link = null;
public UpdateChecker(VersionNumber base, String type) {
this.base = base;
this.type = type;
}
VersionNumber value;
public boolean isOutOfDate() {
return outOfDate;
}
@Override
public AbstractSwingWorker<VersionNumber> process(final boolean showMessage) {
return new AbstractSwingWorker<VersionNumber>() {
@Override
protected void work() throws Exception {
if (value == null) {
versionString = NetUtils.get("http://hmcl.huangyuhui.net/api/update?version=" + Main.LAUNCHER_VERSION);
value = VersionNumber.asVersion(versionString);
}
if (value == null) {
HMCLog.warn("Failed to check update...");
if (showMessage)
MessageBox.show(C.i18n("update.failed"));
} else if (base.compareTo(value) < 0)
outOfDate = true;
if (outOfDate)
publish(value);
}
};
}
@Override
public VersionNumber getNewVersion() {
return value;
}
@Override
public synchronized AbstractSwingWorker<Map<String, String>> requestDownloadLink() {
return new AbstractSwingWorker<Map<String, String>>() {
@Override
protected void work() throws Exception {
if (download_link == null)
try {
download_link = C.GSON.<Map<String, String>>fromJson(NetUtils.get("http://hmcl.huangyuhui.net/api/update_link?version=" + Main.LAUNCHER_VERSION), Map.class);
} catch (JsonSyntaxException | IOException e) {
HMCLog.warn("Failed to get update link.", e);
}
publish(download_link);
}
};
}
public final EventHandler<SimpleEvent<VersionNumber>> upgrade = new EventHandler<>();
@Override
public void checkOutdate() {
if (outOfDate)
if (HMCLApi.EVENT_BUS.fireChannelResulted(new OutOfDateEvent(this, getNewVersion())))
upgrade.fire(new SimpleEvent<>(this, getNewVersion()));
}
}
Binary file not shown.

Before

Width:  |  Height:  |  Size: 81 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 382 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 232 B

@@ -0,0 +1,305 @@
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package org.jackhuang.hellominecraftlauncher;
import org.jackhuang.hellominecraftlauncher.apis.LogUtils;
import org.jackhuang.hellominecraftlauncher.apis.DoneListener;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.jackhuang.hellominecraftlauncher.apis.handlers.Login;
import org.jackhuang.hellominecraftlauncher.apis.handlers.LoginInfo;
import org.jackhuang.hellominecraftlauncher.apis.handlers.LoginResult;
import org.jackhuang.hellominecraftlauncher.apis.PluginHandlerType;
import org.jackhuang.hellominecraftlauncher.apis.version.MinecraftLibrary;
import org.jackhuang.hellominecraftlauncher.loaders.MinecraftLoader;
import org.jackhuang.hellominecraftlauncher.loaders.MinecraftOldLoader;
import org.jackhuang.hellominecraftlauncher.plugin.PluginHandler;
import org.jackhuang.hellominecraftlauncher.utilities.SettingsManager;
import org.jackhuang.hellominecraftlauncher.settings.Version;
import org.jackhuang.hellominecraftlauncher.utilities.C;
import org.jackhuang.hellominecraftlauncher.apis.utils.MessageBox;
import org.jackhuang.hellominecraftlauncher.apis.utils.OperatingSystems;
import org.jackhuang.hellominecraftlauncher.apis.utils.Utils;
import org.jackhuang.hellominecraftlauncher.apis.utils.Compressor;
import org.jackhuang.hellominecraftlauncher.apis.version.MinecraftVersion;
/**
*
* @author hyh
*/
public class GameLauncher {
private static String makeCommand(List<String> cmd) {
StringBuilder cmdbuf = new StringBuilder(120);
for (int i = 0; i < cmd.size(); i++) {
if (i > 0) {
cmdbuf.append(' ');
}
String s = cmd.get(i);
if (s.indexOf(' ') >= 0 || s.indexOf('\t') >= 0) {
if (s.charAt(0) != '"') {
cmdbuf.append('"');
cmdbuf.append(s);
if (s.endsWith("\\")) {
cmdbuf.append("\\");
}
cmdbuf.append('"');
} else if (s.endsWith("\"")) {
/* The argument has already been quoted. */
cmdbuf.append(s);
} else {
/* Unmatched quote for the argument. */
throw new IllegalArgumentException();
}
} else {
cmdbuf.append(s);
}
}
String str = cmdbuf.toString();
return str;
}
Version get;
LoginInfo info;
Login login;
ArrayList<ArrayList<DoneListener<List, GameLauncher>>> listeners;
public GameLauncher(Version version, LoginInfo info, int loginType) {
this.get = version;
this.info = info;
listeners = new ArrayList<ArrayList<DoneListener<List, GameLauncher>>>(101);
for (int i = 0; i < 101; i++) {
listeners.add(new ArrayList<DoneListener<List, GameLauncher>>());
}
this.login = (Login)PluginHandler.getPluginHandlers(PluginHandlerType.getType("LOGIN")).get(loginType);
}
private void executeEvent(int eventType, List p) {
for (DoneListener<List, GameLauncher> dl : listeners.get(eventType)) {
dl.onDone(p, this);
}
}
public void addListener(int eventType, DoneListener<List, GameLauncher> dl) {
listeners.get(eventType).add(dl);
}
public void makeLaunchCommand() {
ArrayList al = new ArrayList();
LoginResult result;
if(info != null)
result = login.login(info);
else
result = login.loginBySettings();
if (result == null || result.success == false) {
String error;
if (result == null || result.error == null) {
error = C.I18N.getString("登录失败:") + C.I18N.getString("插件错误");
} else {
error = C.I18N.getString("登录失败:") + result.error;
}
al.add(error);
executeEvent(0, al);
return;
}
String name = get.name;
final String realpa = Utils.addSeparator(Utils.getGameDir(get, SettingsManager.settings.publicSettings.gameDir));
if (get.isVer16) {
String minecraftJar = realpa
+ "versions" + File.separator + name + File.separator + name
+ ".jar";
String minecraftJarTo = realpa
+ "versions" + File.separator + name + File.separator + name
+ "-HMCL-MERGE-TEMP.jar";
if (get.minecraftJar != null && !get.minecraftJar.isEmpty()) {
String unzipDir = Utils.addSeparator(Utils.currentDir())
+ "HMCL-MERGE-TEMP" + File.separator;
Compressor.unzip(minecraftJar, unzipDir);
for (int i = 0; i < get.minecraftJar.size(); i++) {
if (get.minecraftJarIsActive == null || get.minecraftJarIsActive.get(i)) {
Compressor.unzip(get.minecraftJar.get(i), unzipDir);
}
}
Compressor.zip(unzipDir, minecraftJarTo);
Utils.deleteAll(new File(unzipDir));
minecraftJar = minecraftJarTo;
}
MinecraftVersion mv = Utils.getMinecraftVersion(get, SettingsManager.settings.publicSettings.gameDir);
if (mv.minimumLauncherVersion > Main.minimumLauncherVersion) {
MessageBox.Show("对不起,本启动器现在可能不能启动这个版本的Minecraft,但启动器还是会尝试启动");
}
final MinecraftLoader ml = new MinecraftLoader(mv,
SettingsManager.settings.publicSettings, get, result,
minecraftJar);
//Find assets
//Find, download & unzip libraries
MinecraftVersion v = (ml).getVersion();
File file = new File(realpa + "versions" + File.separator + name + File.separator + name + "-natives");
Utils.deleteAll(file);
file.mkdirs();
ArrayList<String[]> unzippings = new ArrayList<String[]>();
ArrayList<String[]> downloadLibraries = new ArrayList<String[]>();
for (int i = 0; i < v.libraries.size(); i++) {
MinecraftLibrary l = v.libraries.get(i);
if (l.allow()) {
File ff = new File(realpa + "libraries" + File.separator
+ l.formatted);
if (!ff.exists()) {
new File(ff.getParent()).mkdirs();
final String location = l.formatted.replace('\\', '/');
String[] lib = new String[3];
lib[0] = location;
lib[1] = C.URL_LIBRARIES[SettingsManager.settings.downloadtype] + location;
lib[2] = ff.getPath();
downloadLibraries.add(lib);
}
}
if (l.natives != null && l.allow()) {
String[] unzip = new String[2];
unzip[0] = realpa + "libraries" + File.separator + l.formatted;
unzip[1] = realpa + "versions" + File.separator
+ name + File.separator + name + "-natives";
unzippings.add(unzip);
}
}
executeEvent(2, downloadLibraries);
executeEvent(3, unzippings);
executeEvent(100, ml.makeLaunchingCommand());
} else {
String minecraftJar = realpa + "bin" + File.separator + "minecraft.jar";
String minecraftJarTo = realpa + "bin" + File.separator + "minecraft-HMCL-MERGE-TEMP.jar";
if (get.minecraftJar != null && !get.minecraftJar.isEmpty()) {
String unzipDir = Utils.addSeparator(Utils.currentDir())
+ "HMCL-MERGE-TEMP" + File.separator;
Compressor.unzip(minecraftJar, unzipDir);
for (int i = 0; i < get.minecraftJar.size(); i++) {
if (get.minecraftJarIsActive == null || get.minecraftJarIsActive.get(i)) {
Compressor.unzip(get.minecraftJar.get(i), unzipDir);
}
}
Compressor.zip(unzipDir, minecraftJarTo);
Utils.deleteAll(new File(unzipDir));
minecraftJar = minecraftJarTo;
}
String command;
MinecraftOldLoader loader = new MinecraftOldLoader(
SettingsManager.settings.publicSettings, get, result,
minecraftJar);
command = makeCommand(loader.makeLaunchingCommand());
al.add(command);
executeEvent(100, al);
}
}
/**
* Launch the game "as soon as possible".
* @param str launch command
*/
public void launch(List str) {
try {
Process p;
File dir = new File(Utils.getGameDir(get, SettingsManager.settings.publicSettings.gameDir));
String appdata = dir.getParent();
LogUtils.info("APPDATA: " + appdata);
ProcessBuilder builder = new ProcessBuilder(str);
builder.environment().put("APPDATA", appdata);
builder.directory(dir);
p = builder.start();
ArrayList<JavaProcess> al = new ArrayList<JavaProcess>();
al.add(new JavaProcess(str, p));
executeEvent(4, al);
} catch (IOException e) {
e.printStackTrace();
MessageBox.Show(C.I18N.getString("启动失败"));
}
}
/**
* According to the name...
*
* @param launcherName the name of launch bat/sh
* @param str launch command
*/
public void makeLauncher(String launcherName, List str) {
OperatingSystems os = Utils.os();
String gameDir = Utils.getGameDir(get, SettingsManager.settings.publicSettings.gameDir);
File f;
boolean isWin = os == OperatingSystems.WINDOWS;
if (isWin) {
f = new File(launcherName + ".bat");
} else {
f = new File(launcherName + ".sh");
}
if (!f.exists()) {
try {
f.createNewFile();
} catch (IOException ex) {
throw new RuntimeException(ex);
}
}
BufferedWriter writer = null;
try {
writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(f), System.getProperty("sun.jnu.encoding", "gbk")));
} catch (FileNotFoundException ex) {
throw new RuntimeException(ex);
} catch (UnsupportedEncodingException ex) {
Logger.getLogger(GameLauncher.class.getName()).log(Level.SEVERE, null, ex);
try {
writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(f)));
} catch (FileNotFoundException ex1) {
throw new RuntimeException(ex1);
}
}
if (isWin) {
File dir = new File(gameDir);
String appdata = dir.getParent();
if (appdata != null) {
try {
writer.write("set appdata=" + appdata);
writer.newLine();
} catch (IOException ex) {
System.err.println("Failed to write.");
ex.printStackTrace();
}
}
}
try {
writer.write(makeCommand(str));
writer.close();
} catch (IOException ex) {
Logger.getLogger(GameLauncher.class.getName()).log(Level.SEVERE, null, ex);
}
if (!isWin) {
try {
Runtime.getRuntime().exec("chmod +x launch.sh");
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
@@ -0,0 +1,19 @@
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package org.jackhuang.hellominecraftlauncher;
/**
*
* @author hyh
*/
public enum GameLauncherRequest {
ERROR,
DOWNLOAD_ASSETS,
DOWNLOAD_LIBRARIES,
UNZIP_LIBRARIES,
PROCESS_STARTED,
SUCCEED
}
@@ -0,0 +1,238 @@
# To change this template, choose Tools | Templates
# and open the template in the editor.
\u6e38\u620f\u7248\u672c=\u6e38\u620f\u7248\u672c
\u8fd9\u4e2aMINECRAFT\u6587\u4ef6\u5939\u65e2\u4e0d\u662f1.6\u7248\u4e5f\u4e0d\u662f\u65e7\u7248\u7684\u600e\u4e48\u5bfc\u5165\u561b0V0\u3002=\u8fd9\u4e2aminecraft\u6587\u4ef6\u5939\u65e2\u4e0d\u662f1.6\u7248\u4e5f\u4e0d\u662f\u65e7\u7248\u7684\u600e\u4e48\u5bfc\u5165\u561b0v0\u3002
\u672a\u9009\u4e2d\u4efb\u4f55\u4e00\u4e2a\u7248\u672c=\u672a\u9009\u4e2d\u4efb\u4f55\u4e00\u4e2a\u7248\u672c
\u5bfc\u5165\u5931\u8d25\:\ {0}=\u5bfc\u5165\u5931\u8d25: {0}
\u627e\u5230\u540c\u540d\u7684MINECRAFT\u7248\u672c\uff0c\u8bf7\u6362\u7528\u53e6\u4e00\u4e2a\u540d\u79f0=\u627e\u5230\u540c\u540d\u7684Minecraft\u7248\u672c\uff0c\u8bf7\u6362\u7528\u53e6\u4e00\u4e2a\u540d\u79f0
\u8bf7\u8f93\u5165\u8be5\u65e7\u7248\u672c\u7684\u540d\u79f0=\u8bf7\u8f93\u5165\u8be5\u65e7\u7248\u672c\u7684\u540d\u79f0
\u627e\u4e0d\u5230MINECRAFT.JAR=\u627e\u4e0d\u5230minecraft.jar
\u9009\u62e9MINECRAFT\u8def\u5f84=\u9009\u62e9Minecraft\u8def\u5f84
\u542f\u52a8\u5931\u8d25=\u542f\u52a8\u5931\u8d25
\u590d\u5236\u914d\u7f6e\u6587\u4ef6\u5931\u8d25\:\ =\u590d\u5236\u914d\u7f6e\u6587\u4ef6\u5931\u8d25:
\u590d\u5236\u6838\u5fc3\u6a21\u7ec4\u5931\u8d25\:\ =\u590d\u5236\u6838\u5fc3\u6a21\u7ec4\u5931\u8d25:
\u590d\u5236\u666e\u901a\u6a21\u7ec4\u5931\u8d25\:\ =\u590d\u5236\u666e\u901a\u6a21\u7ec4\u5931\u8d25:
\u4e0b\u8f7d\u7f3a\u5931\u5e93\uff1a{0}=\u4e0b\u8f7d\u7f3a\u5931\u5e93\uff1a{0}
\u6ca1\u6709\u9009\u62e9\u4efb\u4f55\u4e00\u4e2aMINECRAFT\u7248\u672c=\u6ca1\u6709\u9009\u62e9\u4efb\u4f55\u4e00\u4e2aMinecraft\u7248\u672c
\u9519\u8bef\u7684MINECRAFT\u8def\u5f84=\u9519\u8bef\u7684Minecraft\u8def\u5f84
\u5173\u4e8e=\u5173\u4e8e
\u4e0b\u8f7d=\u4e0b\u8f7d
\u5bc6\u7801=\u5bc6\u7801
\u624b\u52a8\u8bbe\u7f6e=\u624b\u52a8\u8bbe\u7f6e
\u4e0d\u9650\u5236=\u4e0d\u9650\u5236
32\u4f4d=32\u4f4d
64\u4f4d=64\u4f4d
\u542f\u52a8\u6a21\u5f0f=\u542f\u52a8\u6a21\u5f0f
\u6700\u5927\u5185\u5b58=\u6700\u5927\u5185\u5b58
\u6e38\u620f\u540d\u79f0=\u540d\u5b57
\u6e38\u620f\u8def\u5f84=\u6e38\u620f\u8def\u5f84
\u5bfc\u5165\u6587\u4ef6\u5939=\u5bfc\u5165\u6587\u4ef6\u5939
\u65b0\u5efa=\u65b0\u5efa
\u5220\u9664=\u5220\u9664
\u7f16\u8f91=\u7f16\u8f91
\u590d\u5236=\u590d\u5236
\u5bfc\u5165\u65e7\u7248\u672c=\u5bfc\u5165\u65e7\u7248\u672c
\u5236\u4f5c\u4e00\u952e\u542f\u52a8=\u5236\u4f5c\u4e00\u952e\u542f\u52a8
\u51c6\u5907\u4e2d=\u51c6\u5907\u4e2d
\u5f00\u59cbMINECRAFT\u4e4b\u65c5!=\u542f\u52a8\u6e38\u620f
\u5237\u65b0=\u5237\u65b0
public_settings=\u5168\u5c40\u8bbe\u7f6e
game_download=\u6e38\u620f\u4e0b\u8f7d
\u66f4\u65b0\u4fe1\u606f=\u66f4\u65b0\u4fe1\u606f
\u8bbe\u7f6e\u5931\u8d25\uff1a=\u8bbe\u7f6e\u5931\u8d25\uff1a
\u7f3a\u5931\u5e93\u4e0b\u8f7d=\u7f3a\u5931\u5e93\u4e0b\u8f7d
\u9009\u62e9\u80cc\u666f\u8def\u5f84=\u9009\u62e9\u80cc\u666f\u8def\u5f84
MineLogin0=\u7f51\u7edc\u9519\u8bef
MineLogin1=\u7528\u6237\u540d\u6216\u5bc6\u7801\u4e0d\u5408\u6cd5
MineLogin2=\u5185\u90e8\u9519\u8bef
MineLogin3=\u7528\u6237\u4e0d\u5b58\u5728
MineLogin4=\u9700\u8981\u9a8c\u8bc1
MineLogin5=\u5bc6\u7801\u9519\u8bef
ForgeMod=Forge mod
ModLoaderMod=ModLoader mod
Forge=Forge
ModLoader=ModLoader
Unknown=\u672a\u77e5
Mods\u6587\u4ef6\u5939=Mods\u6587\u4ef6\u5939
Coremods\u6587\u4ef6\u5939=Coremods\u6587\u4ef6\u5939
Mod\u72ec\u7acb\u6587\u4ef6\u5939=Mod\u72ec\u7acb\u6587\u4ef6\u5939
\u914d\u7f6e\u6587\u4ef6\u5939=\u914d\u7f6e\u6587\u4ef6\u5939
\u767b\u5f55\u5931\u8d25\uff1a=\u767b\u5f55\u5931\u8d25\uff1a
\u9009\u62e9\u5931\u8d25=\u9009\u62e9\u5931\u8d25
\u63d2\u4ef6\u9519\u8bef\uff1a=\u63d2\u4ef6\u9519\u8bef\uff1a
\u767b\u5f55\u5931\u8d25\uff1a=\u767b\u5f55\u5931\u8d25\uff1a
\u6ca1\u6709\u767b\u5165\u65b9\u5f0f...=\u6ca1\u6709\u767b\u5165\u65b9\u5f0f...
\u4fdd\u5b58=\u4fdd\u5b58
\u767b\u5f55\u6a21\u5f0f=\u767b\u5f55\u6a21\u5f0f
\u7248\u672c\u7f16\u8f91=\u7248\u672c\u7f16\u8f91
\u7248\u672c\u53f7=\u7248\u672c\u53f7
\u5bfc\u5165=\u5bfc\u5165
\u64cd\u4f5c=\u64cd\u4f5c
\u4e0b\u8f7d\u4fe1\u606f=\u4e0b\u8f7d\u4fe1\u606f
\u5b89\u88c5=\u5b89\u88c5
\u6dfb\u52a0=\u6dfb\u52a0
\u5168\u90e8\u4e0b\u8f7d=\u5168\u90e8\u4e0b\u8f7d
\u52a0\u5165MINECRAFT.JAR=\u52a0\u5165minecraft.jar
\u7ba1\u7406=\u7ba1\u7406
\u52a8\u6001\u52a0\u8f7d\u6a21\u7ec4=\u52a8\u6001\u52a0\u8f7d\u6a21\u7ec4
\u5e93=\u5e93
AdvancedSettings=\u9ad8\u7ea7\u8bbe\u7f6e
\u6700\u5927\u5316=\u6700\u5927\u5316
\u68c0\u67e5\u66f4\u65b0=\u68c0\u67e5\u66f4\u65b0
\u67e5\u770b\u65e5\u5fd7=\u67e5\u770b\u65e5\u5fd7
\u80cc\u666f\u5730\u5740=\u80cc\u666f\u5730\u5740
UNEXPECTED\ EXCEPTION\ LOADING\ =Unexpected exception loading
\u5f53\u524d\u662f\u6700\u65b0\u7248\u672c=\u5f53\u524d\u662f\u6700\u65b0\u7248\u672c
\u65e0\u6cd5\u6253\u5f00\u6d4f\u89c8\u5668\uff0c\u7f51\u5740\u5df2\u7ecf\u590d\u5236\u5230\u526a\u8d34\u677f\u4e86\uff0c\u60a8\u53ef\u4ee5\u624b\u52a8\u7c98\u8d34\u7f51\u5740\u6253\u5f00\u9875\u9762=\u65e0\u6cd5\u6253\u5f00\u6d4f\u89c8\u5668\uff0c\u7f51\u5740\u5df2\u7ecf\u590d\u5236\u5230\u526a\u8d34\u677f\u4e86\uff0c\u60a8\u53ef\u4ee5\u624b\u52a8\u7c98\u8d34\u7f51\u5740\u6253\u5f00\u9875\u9762
\u662f\u5426\u524d\u5f80\u53d1\u5e03\u9875\u9762\u66f4\u65b0\uff1f=\u662f\u5426\u524d\u5f80\u53d1\u5e03\u9875\u9762\u66f4\u65b0\uff1f
\u66f4\u65b0\u4fe1\u606f\u4e3a\:\ =\u66f4\u65b0\u4fe1\u606f\u4e3a:
\u6700\u65b0\u7248\u672c\u4e3a\uff1a=\u6700\u65b0\u7248\u672c\u4e3a\uff1a
\u68c0\u67e5\u66f4\u65b0\u5931\u8d25=\u68c0\u67e5\u66f4\u65b0\u5931\u8d25
\u8fde\u63a5\u4e2d=\u8fde\u63a5\u4e2d
\u83b7\u53d6\u5217\u8868\u5931\u8d25\uff0c\u8bf7\u5237\u65b0\u91cd\u8bd5=\u83b7\u53d6\u5217\u8868\u5931\u8d25\uff0c\u8bf7\u5237\u65b0\u91cd\u8bd5
INVALID\ PLUGIN=Invalid plugin
\u65e0\u6cd5\u8fde\u63a5=\u65e0\u6cd5\u8fde\u63a5
\ \u5dee\ ORANGERED=\ \u5dee orangered
\ \u8f83\u5dee\ ORANGE=\ \u8f83\u5dee orange
\ \u4e2d\ YELLOGREEN=\ \u4e2d yellogreen
\ \u8f83\u597d\ BLUE=\ \u8f83\u597d blue
\ \u597d\ GREEN=\ \u597d green
\u670d\u52a1\u5668{0}\u7684\u56de\u590d\u65e0\u6548=\u670d\u52a1\u5668{0}\u7684\u56de\u590d\u65e0\u6548
ForgeInstall=\u63a5\u4e0b\u6765\u5f39\u51fa\u6765\u7684\u7a97\u53e3\u91cc\u8bf7\u9009\u62e9\u8def\u5f84\u4e3a\u6e38\u620f\u8def\u5f84\u3002\u7a0b\u5e8f\u5df2\u7ecf\u5c06\u76ee\u5f55\u590d\u5236\u5230\u4e86\u526a\u8d34\u677f\uff0c\u76f4\u63a5\u5728\u7a97\u53e3\u91cc\u9009\u62e9"..."\u6309\u94ae\uff0c\u7c98\u8d34\u8def\u5f84\uff0c\u786e\u5b9a\u5373\u53ef
\u65e0\u6cd5\u6253\u5f00\u8d44\u6e90\u7ba1\u7406\u5668\:\ =\u65e0\u6cd5\u6253\u5f00\u8d44\u6e90\u7ba1\u7406\u5668:
\u63d0\u793a=\u63d0\u793a
\u8f93\u5165\u65b0\u7248\u672c\u540d\u79f0=\u8f93\u5165\u65b0\u7248\u672c\u540d\u79f0
\u540d\u79f0=\u540d\u79f0
\u4fdd\u5b58\u5931\u8d25=\u4fdd\u5b58\u5931\u8d25
\u4fdd\u5b58\u538b\u7f29\u5305\u5230=\u4fdd\u5b58\u538b\u7f29\u5305\u5230
\u9009\u62e9\u6750\u8d28\u5305=\u9009\u62e9\u6750\u8d28\u5305
\u9009\u62e9\u8d44\u6e90\u5305=\u9009\u62e9\u8d44\u6e90\u5305
\u9009\u62e9\u5e93/\u6a21\u7ec4=\u9009\u62e9\u5e93/\u6a21\u7ec4
\u6ca1\u6709\u9009\u4e2d\u4efb\u4f55\u4e00\u4e2a\u5e93/\u6a21\u7ec4\u3002=\u6ca1\u6709\u9009\u4e2d\u4efb\u4f55\u4e00\u4e2a\u5e93/\u6a21\u7ec4\u3002
\u5220\u9664\u5931\u8d25=\u5220\u9664\u5931\u8d25
\u6dfb\u52a0\u5931\u8d25=\u6dfb\u52a0\u5931\u8d25
\u9009\u62e9\u6a21\u7ec4=\u9009\u62e9\u6a21\u7ec4
\u7248\u672c\u540d\u79f0\u4e0d\u80fd\u4e3a\u7a7a=\u7248\u672c\u540d\u79f0\u4e0d\u80fd\u4e3a\u7a7a
\u5907\u4efd\u5230=\u5907\u4efd\u5230
\u662fCOREODS\u6587\u4ef6\u5939\u5185\u7684\u6240\u6709\u6838\u5fc3\u6a21\u7ec4=\u662fCoremods\u6587\u4ef6\u5939\u5185\u7684\u6240\u6709\u6838\u5fc3\u6a21\u7ec4
\u662fMODS\u6587\u4ef6\u5939\u5185\u7684\u6240\u6709\u6a21\u7ec4=\u662fMods\u6587\u4ef6\u5939\u5185\u7684\u6240\u6709\u6a21\u7ec4
\u901a\u5e38\u662f\u6a21\u7ec4=\u901a\u5e38\u662f\u6a21\u7ec4
\u4e0b\u79fb=\u4e0b\u79fb
\u4e0a\u79fb=\u4e0a\u79fb
\u5220\u9664=\u5220\u9664
\u589e\u52a0=\u589e\u52a0
\u901a\u5e38\u662fFORGE,MODLOADER\u4ee5\u53caMINECRAFT\u6240\u4f9d\u8d56\u7684\u5e93=\u901a\u5e38\u662fForge,Modloader\u4ee5\u53caMinecraft\u6240\u4f9d\u8d56\u7684\u5e93
\u9644\u52a0\u542f\u52a8\u53c2\u6570=\u9644\u52a0\u542f\u52a8\u53c2\u6570
\u81ea\u5b9a\u4e49\u5e93\u6587\u4ef6\u5939(LIBRARIES\u6587\u4ef6\u5939)=\u81ea\u5b9a\u4e49\u5e93\u6587\u4ef6\u5939(libraries\u6587\u4ef6\u5939)
\u4e3b\u7c7b=\u4e3b\u7c7b
\u81ea\u5b9a\u4e49\u8d44\u6e90\u6587\u4ef6\u5939(ASSETS\u6587\u4ef6\u5939)=\u81ea\u5b9a\u4e49\u8d44\u6e90\u6587\u4ef6\u5939(assets\u6587\u4ef6\u5939)
\u624b\u52a8\u8bbe\u7f6e=\u624b\u52a8\u8bbe\u7f6e
\u4e0d\u5f3a\u5236=\u4e0d\u5f3a\u5236
32\u4f4d=32\u4f4d
64\u4f4d=64\u4f4d
\u542f\u52a8\u6a21\u5f0f=\u542f\u52a8\u6a21\u5f0f
\u73a9\u5bb6\u540d=\u73a9\u5bb6\u540d
1.6\u53ca\u4ee5\u4e0a\u7248\u672c\u4ee5\u53ca\u5bfc\u5165\u7684\u65e7\u7248\u672c=1.6\u53ca\u4ee5\u4e0a\u7248\u672c\u4ee5\u53ca\u5bfc\u5165\u7684\u65e7\u7248\u672c
\u6700\u5927\u5185\u5b58=\u6700\u5927\u5185\u5b58\uff08MB\uff09
JAVA\u865a\u62df\u673a\u53c2\u6570=Java\u865a\u62df\u673a\u53c2\u6570
JAVA\u8def\u5f84=Java\u8def\u5f84
\u5168\u5c4f=\u5168\u5c4f
\u5206\u8fa8\u7387=\u5206\u8fa8\u7387
\u6e38\u620f\u8def\u5f84=\u6e38\u620f\u8def\u5f84
\u4ee5\u4e0b\u8bbe\u7f6e\u5b57\u6bb5\u4e3a\u7a7a\u4ee3\u8868\u7740\u4f7f\u7528\u9ed8\u8ba4\u8bbe\u7f6e=\u9664\u540d\u79f0\u4ee5\u4e0b\u5b57\u6bb5\u53ef\u4ee5\u4e0d\u586b
\u53d6\u6d88=\u53d6\u6d88
\u786e\u5b9a=\u786e\u5b9a
game_download=\u6e38\u620f\u4e0b\u8f7d
public_settings=\u5168\u5c40\u8bbe\u7f6e
invalid=\u65e0\u6548\u7684
invalid_jar=\u65e0\u6548\u7684jar\u5305
not_a_file=\u4e0d\u662f\u6587\u4ef6
not_found=\u627e\u4e0d\u5230minecraft.jar
not_readable=minecraft.jar\u4e0d\u53ef\u8bfb
modified=(\u4fee\u6539\u7684!)
\u83b7\u53d6\u4e2d=\u83b7\u53d6\u4e2d
\u63d2\u4ef6\u9519\u8bef=\u63d2\u4ef6\u9519\u8bef
CannotLoadPluginsBecauseOfAnError=\u65e0\u6cd5\u52a0\u8f7d\u63d2\u4ef6\uff0c\u56e0\u4e3a\u53d1\u751f\u4e86\u4e00\u4e2a\u9519\u8bef\u3002
CRASH\ REPORT\ DETECTED,\ BUT\ UNKNOWN\ FORMAT\:=Crash report detected, but unknown format:
COULDN'T\ OPEN\ CRASH\ REPORT=Couldn't open crash report
CRASH\ REPORT\ DETECTED,\ OPENING\:=Crash report detected, opening:
MinecraftCrashed=Minecraft\u5d29\u6e83\u4e86\uff01(\u9519\u8bef\u4ee3\u7801:{0})
RememberMe=\u8bb0\u4f4f\u6211
Logout=\u767b\u51fa
ShowIfIsLoaded=\u663e\u793a\u63d2\u4ef6\u662f\u5426\u52a0\u8f7d\uff0c\u70b9\u51fb\u67e5\u770b\u9519\u8bef
IsLoaded=\u662f\u5426\u52a0\u8f7d
PluginSettings=\u63d2\u4ef6\u8bbe\u7f6e
Details=\u4fe1\u606f
Authors=\u4f5c\u8005
Version=\u7248\u672c
Name=\u540d\u79f0
CheckUpdate=\u68c0\u67e5\u672c\u542f\u52a8\u5668\u7684\u66f4\u65b0
DownloadSource=\u4e0b\u8f7d\u6e90
DisableMoveMods=\u7981\u6b62\u7248\u672c\u81ea\u6709\u6a21\u7ec4\uff08\u79fb\u52a8\u6a21\u7ec4\uff09\u529f\u80fd
ShowConsoleOutput=\u5c31\u662fMinecraft\u7684\u63a7\u5236\u53f0\u8f93\u51fa
MinecraftLocation=Minecraft\u8def\u5f84\uff08\u5373.minecraft\u6587\u4ef6\u5939\uff09
MaxMemoryTooltip=\u5141\u8bb8Minecraft\u6700\u591a\u5141\u8bb8\u4f7f\u7528\u7684\u5185\u5b58\uff08\u770b\u4e0d\u61c2\u5c31\u4f7f\u7528\u9ed8\u8ba4\u76841024\u5427\uff09
FailedToLoad=\u52a0\u8f7d\u5931\u8d25
Loaded=\u5df2\u52a0\u8f7d
NoCharacter=\u8be5\u5e10\u53f7\u6ca1\u6709\u89d2\u8272
LegacyLogin=\u65e7\u7248\u6b63\u7248\u767b\u5f55
YggdrasilLogin=\u65b0\u7248\u6b63\u7248\u767b\u5f55
PleaseChooseCharacter=\u8bf7\u9009\u62e9\u60a8\u8981\u4f7f\u7528\u7684\u89d2\u8272
WrongPassword=\u53ef\u80fd\u662f\u60a8\u7684\u7528\u6237\u540d\u6216\u5bc6\u7801\u9519\u8bef
OfflineLogin=\u79bb\u7ebf\u6a21\u5f0f
GameDownload=\u6e38\u620f\u4e0b\u8f7d
IntegrateDownload=\u6574\u5408\u5305\u4e0b\u8f7d
AssetsDownload=\u8d44\u6e90\u4e0b\u8f7d
Installers=\u81ea\u52a8\u5b89\u88c5
WorldSaving=\u5907\u4efd\u5730\u56fe
ServerEditor=\u670d\u52a1\u5668\u7f16\u8f91
TexturepackEditor=\u6750\u8d28\u5305\u7ba1\u7406
Refresh=\u5237\u65b0\u5217\u8868
Install=\u5b89\u88c5
AssetsType=\u8d44\u6e90\u7c7b\u578b
InstallOptifine=\u5b89\u88c5\u9009\u4e2d\u7684Optifine
Changelog=\u66f4\u65b0\u4fe1\u606f
InstallForge=\u5b89\u88c5\u9009\u4e2d\u7684Forge
ModManaging=\u6a21\u7ec4\u7ba1\u7406
PluginCenter=\u63d2\u4ef6\u4e2d\u5fc3
ExtMods=\u5916\u90e8\u6a21\u7ec4
CoreMods=\u6838\u5fc3\u6a21\u7ec4
NormalSettings=\u666e\u901a\u8bbe\u7f6e
1.6AndAbove=1.6\u53ca\u4ee5\u4e0a
1.5AndBelow=1.5\u53ca\u4ee5\u4e0b
IsActive=\u6d3b\u52a8
Location=\u8def\u5f84
Type=\u7c7b\u578b
ReleaseTime=\u91ca\u653e\u65f6\u95f4
Time=\u53d1\u5e03\u65f6\u95f4
Version=\u7248\u672c
MCVersion=MC\u7248\u672c
IntegrateName=\u6574\u5408\u5305\u540d\u79f0
IntegrateVersion=\u6574\u5408\u5305\u7248\u672c
ServerName=\u670d\u52a1\u5668\u540d\u79f0
HideAddress=\u9690\u85cf\u5730\u5740
Address=\u5730\u5740
Introduction=\u4ecb\u7ecd
Online=\u5728\u7ebf
Delay=\u5ef6\u8fdf
Clear=\u6e05\u9664
Close=\u5173\u95ed
Save=\u4fdd\u5b58
JoinMinecraftJar=\u52a0\u5165minecraft.jar
ExternalMods=\u5916\u90e8\u6a21\u7ec4
DynamicLoadingMods=\u52a8\u6001\u52a0\u8f7d\u6a21\u7ec4
Libraries=\u5e93
TagArguments=\u9644\u52a0\u7ed9\u4e88Minecraft\u7684\u53c2\u6570
MainClass=Minecraft\u7684\u4e3b\u7c7b\uff08\u4e0d\u77e5\u9053\u4ec0\u4e48\u610f\u601d\u7684\u8bdd\u4e5f\u5c31\u7528\u4e0d\u4e0a\u4e86\uff09
DefaultLibrariesFolder=\u9ed8\u8ba4\u4e3a.minecraft/libraries\u6587\u4ef6\u5939
DefaultAssetsFolder=\u9ed8\u8ba4\u4e3a.minecraft/assets\u6587\u4ef6\u5939
MakeMCMaximum=\u4f7fMinecraft\u7a97\u53e3\u6700\u5927\u5316
MCFolderFormat=\u5c31\u662fMinecraft\u6587\u4ef6\u5939\u683c\u5f0f
MakeMCFullscreen=\u4f7fMinecraft\u7a97\u53e3\u5168\u5c4f
MCHeight=Minecraft\u7a97\u53e3\u9ad8
MCWidth=Minecraft\u7a97\u53e3\u5bbd
Personalization=\u4e2a\u6027\u5316
MaxPermGen=\u6700\u5927\u6c38\u4e45\u4fdd\u5b58\u533a\u57df\uff08MB\uff09
Options=\u8bbe\u7f6e
Setup=\u8bbe\u7f6e
@@ -0,0 +1,230 @@
\u6e38\u620f\u7248\u672c=Game versions
\u8fd9\u4e2aMINECRAFT\u6587\u4ef6\u5939\u65e2\u4e0d\u662f1.6\u7248\u4e5f\u4e0d\u662f\u65e7\u7248\u7684\u600e\u4e48\u5bfc\u5165\u561b0V0\u3002=This chosen minecraft folder is not a format of version 1.6 above or 1.5 below, so the launcher cannot import it.
\u672a\u9009\u4e2d\u4efb\u4f55\u4e00\u4e2a\u7248\u672c=Not version selected.
\u5bfc\u5165\u5931\u8d25\:\ {0}=Failed to include: {0}
\u627e\u5230\u540c\u540d\u7684MINECRAFT\u7248\u672c\uff0c\u8bf7\u6362\u7528\u53e6\u4e00\u4e2a\u540d\u79f0=Already existed a Minecraft version which has same name, please use another name.
\u8bf7\u8f93\u5165\u8be5\u65e7\u7248\u672c\u7684\u540d\u79f0=Please enter the name of this old version
\u627e\u4e0d\u5230MINECRAFT.JAR=Cannot find minecraft.jar
\u9009\u62e9MINECRAFT\u8def\u5f84=Choose Minecraft path
\u542f\u52a8\u5931\u8d25=Failed to launch
\u590d\u5236\u914d\u7f6e\u6587\u4ef6\u5931\u8d25\:\ =Failed to copy config folder:
\u590d\u5236\u6838\u5fc3\u6a21\u7ec4\u5931\u8d25\:\ =Failed to copy coremods folder:
\u590d\u5236\u666e\u901a\u6a21\u7ec4\u5931\u8d25\:\ =Failed to copy mods foler:
\u4e0b\u8f7d\u7f3a\u5931\u5e93\uff1a{0}=Download missing libraries\uff1a{0}
\u6ca1\u6709\u9009\u62e9\u4efb\u4f55\u4e00\u4e2aMINECRAFT\u7248\u672c=Not version selected.
\u9519\u8bef\u7684MINECRAFT\u8def\u5f84=An erroneous Minecraft path.
\u5173\u4e8e=About
\u4e0b\u8f7d=Download
\u5bc6\u7801=Password
\u624b\u52a8\u8bbe\u7f6e=Select
\u4e0d\u9650\u5236=Default
32\u4f4d=32 bit
64\u4f4d=64 bit
\u542f\u52a8\u6a21\u5f0f=Launch mode
\u6700\u5927\u5185\u5b58=Max memory(MB)
\u6e38\u620f\u540d\u79f0=User name
\u6e38\u620f\u8def\u5f84=Game location
\u5bfc\u5165\u6587\u4ef6\u5939=Import folder
\u65b0\u5efa=New
\u5220\u9664=Delete
\u7f16\u8f91=Edit
\u590d\u5236=Copy
\u5bfc\u5165\u65e7\u7248\u672c=Import old version
\u5236\u4f5c\u4e00\u952e\u542f\u52a8=Make bat/sh launcher
\u51c6\u5907\u4e2d=Preparing
\u5f00\u59cbMINECRAFT\u4e4b\u65c5!=Enjoy Minecraft now!
\u5237\u65b0=Refresh
game_download=Game downloads
public_settings=Public settings
\u8bbe\u7f6e\u5931\u8d25\uff1a=Failed to set\uff1a
\u7f3a\u5931\u5e93\u4e0b\u8f7d=Download missing libraries
\u9009\u62e9\u80cc\u666f\u8def\u5f84=Choose background image path
MineLogin0=Network error
MineLogin1=User name or password is incorrect
MineLogin2=Internal error
MineLogin3=User does not exist
MineLogin4=Need to verify
MineLogin5=Wrong password
ForgeMod=Forge mod
ModLoaderMod=ModLoader mod
Forge=Forge
ModLoader=ModLoader
Unknown=Unknown
Mods\u6587\u4ef6\u5939=Mods folder
Coremods\u6587\u4ef6\u5939=Coremods folder
Mod\u72ec\u7acb\u6587\u4ef6\u5939=Moddir folder
\u914d\u7f6e\u6587\u4ef6\u5939=Config folder
\u767b\u5f55\u5931\u8d25\uff1a=Failed to login
\u9009\u62e9\u5931\u8d25=Failed to select
\u63d2\u4ef6\u9519\u8bef\uff1a=Plugin error\uff1a
\u767b\u5f55\u5931\u8d25\uff1a=Failed to login\uff1a
\u6ca1\u6709\u767b\u5165\u65b9\u5f0f...=No sign...
\u4fdd\u5b58=Save
\u767b\u5f55\u6a21\u5f0f=Log-In mode
\u7248\u672c\u7f16\u8f91=Preferences
\u7248\u672c\u53f7=Version
\u5bfc\u5165=Import
\u64cd\u4f5c=Operations
\u4e0b\u8f7d\u4fe1\u606f=Download Info
\u5b89\u88c5=Install
\u6dfb\u52a0=Add
\u5168\u90e8\u4e0b\u8f7d=Download all
\u52a0\u5165MINECRAFT.JAR=Join minecraft.jar
\u7ba1\u7406=Managings
\u52a8\u6001\u52a0\u8f7d\u6a21\u7ec4=Dynamic Loading Mods
\u5e93=Libraries
AdvancedSettings=Advanced
\u6700\u5927\u5316=Maximized
\u68c0\u67e5\u66f4\u65b0=Check for updates
\u67e5\u770b\u65e5\u5fd7=View Log
\u80cc\u666f\u5730\u5740=Background Location
UNEXPECTED\ EXCEPTION\ LOADING\ =Unexpected exception loading
\u5f53\u524d\u662f\u6700\u65b0\u7248\u672c=This is the latest version
\u65e0\u6cd5\u6253\u5f00\u6d4f\u89c8\u5668\uff0c\u7f51\u5740\u5df2\u7ecf\u590d\u5236\u5230\u526a\u8d34\u677f\u4e86\uff0c\u60a8\u53ef\u4ee5\u624b\u52a8\u7c98\u8d34\u7f51\u5740\u6253\u5f00\u9875\u9762=Unable to open the browser, the URL has been copied to the clipboard, you can paste the URL manually open the page
\u662f\u5426\u524d\u5f80\u53d1\u5e03\u9875\u9762\u66f4\u65b0\uff1f=Do you wish to go to the publishing page to update?
\u66f4\u65b0\u4fe1\u606f\u4e3a\:\ =Update notes:
\u6700\u65b0\u7248\u672c\u4e3a\uff1a=Latest version\uff1a
\u68c0\u67e5\u66f4\u65b0\u5931\u8d25=Failed to check update
\u8fde\u63a5\u4e2d=Connecting
\u83b7\u53d6\u5217\u8868\u5931\u8d25\uff0c\u8bf7\u5237\u65b0\u91cd\u8bd5=Failed to get the list, please retry to refresh
INVALID\ PLUGIN=Invalid plugin
\u65e0\u6cd5\u8fde\u63a5=Unable to connect
\ \u5dee\ ORANGERED=\ Bad orangered
\ \u8f83\u5dee\ ORANGE=\ Not good orange
\ \u4e2d\ YELLOGREEN=\ So-so yellogreen
\ \u8f83\u597d\ BLUE=\ OK blue
\ \u597d\ GREEN=\ Good green
\u670d\u52a1\u5668{0}\u7684\u56de\u590d\u65e0\u6548=The reply of the server {0} is invalid
\u63a5\u4e0b\u6765\u5f39\u51fa\u6765\u7684\u7a97\u53e3\u91cc\u8bf7\u9009\u62e9\u8def\u5f84\u4e3a\u6e38\u620f\u8def\u5f84\u3002\u7a0b\u5e8f\u5df2\u7ecf\u5c06\u76ee\u5f55\u590d\u5236\u5230\u4e86\u526a\u8d34\u677f\uff0c\u76f4\u63a5\u5728\u7a97\u53e3\u91cc\u9009\u62e9\\"...\\"\u6309\u94ae\uff0c\u7c98\u8d34\u8def\u5f84\uff0c\u786e\u5b9a\u5373\u53ef=In the next pop-up window, select the path as the game paths. Launcher has been copied the directory to the clipboard. In the window, choose \\"...\\" button, paste the path, and click OK. It can be determined.
\u65e0\u6cd5\u6253\u5f00\u8d44\u6e90\u7ba1\u7406\u5668\:\ =Can not open Explorer:
\u63d0\u793a=Notice
\u8f93\u5165\u65b0\u7248\u672c\u540d\u79f0=Enter the name of the new version
\u540d\u79f0=Name
\u4fdd\u5b58\u5931\u8d25=Failed to save
\u4fdd\u5b58\u538b\u7f29\u5305\u5230=Save zip file to
\u9009\u62e9\u6750\u8d28\u5305=Choose texture pack
\u9009\u62e9\u8d44\u6e90\u5305=Choose resource pack
\u9009\u62e9\u5e93/\u6a21\u7ec4=Choose library/mod
\u6ca1\u6709\u9009\u4e2d\u4efb\u4f55\u4e00\u4e2a\u5e93/\u6a21\u7ec4\u3002=Not selected any library/mod.
\u5220\u9664\u5931\u8d25=Failed to delete
\u6dfb\u52a0\u5931\u8d25=Failed to add
\u9009\u62e9\u6a21\u7ec4=Choose mod
\u7248\u672c\u540d\u79f0\u4e0d\u80fd\u4e3a\u7a7a=Version name cannot be empty.
\u5907\u4efd\u5230=Backup to
\u662fCOREODS\u6587\u4ef6\u5939\u5185\u7684\u6240\u6709\u6838\u5fc3\u6a21\u7ec4=They're all the core mods in coremods folder.
\u662fMODS\u6587\u4ef6\u5939\u5185\u7684\u6240\u6709\u6a21\u7ec4=They're all the mods in mods folder.
\u901a\u5e38\u662f\u6a21\u7ec4=Usually mods.
\u4e0b\u79fb=Down
\u4e0a\u79fb=Up
\u5220\u9664=Delete
\u589e\u52a0=Add
\u901a\u5e38\u662fFORGE,MODLOADER\u4ee5\u53caMINECRAFT\u6240\u4f9d\u8d56\u7684\u5e93=They're usually Forge, Modloader and libraries.
\u9644\u52a0\u542f\u52a8\u53c2\u6570=Addition arguments
\u81ea\u5b9a\u4e49\u5e93\u6587\u4ef6\u5939(LIBRARIES\u6587\u4ef6\u5939)=Customize libraries folder
\u4e3b\u7c7b=Main class
\u81ea\u5b9a\u4e49\u8d44\u6e90\u6587\u4ef6\u5939(ASSETS\u6587\u4ef6\u5939)=Customize assets folder
\u624b\u52a8\u8bbe\u7f6e=Manually set
\u4e0d\u5f3a\u5236=Default
32\u4f4d=32 bit
64\u4f4d=64 bit
\u542f\u52a8\u6a21\u5f0f=Launch mode
\u73a9\u5bb6\u540d=Player name
1.6\u53ca\u4ee5\u4e0a\u7248\u672c\u4ee5\u53ca\u5bfc\u5165\u7684\u65e7\u7248\u672c=Version 1.6 and above, and imported the old version
\u6700\u5927\u5185\u5b58=Max memory
JAVA\u865a\u62df\u673a\u53c2\u6570=JVM arguments
JAVA\u8def\u5f84=Java path
\u5168\u5c4f=Fullscreen
\u5206\u8fa8\u7387=Resolution
\u6e38\u620f\u8def\u5f84=Game dir
\u4ee5\u4e0b\u8bbe\u7f6e\u5b57\u6bb5\u4e3a\u7a7a\u4ee3\u8868\u7740\u4f7f\u7528\u9ed8\u8ba4\u8bbe\u7f6e=These field could not fill except the name field.
\u53d6\u6d88=Cancel
\u786e\u5b9a=Ok
invalid=invalid
invalid_jar=invalid jar
not_a_file=not a file
not_found=not found
not_readable=not readable
modified=(modified!)
\u83b7\u53d6\u4e2d=Loading
\u63d2\u4ef6\u9519\u8bef=Plugin error
CannotLoadPluginsBecauseOfAnError=Cannot load plugins because an error occurred.
CRASH\ REPORT\ DETECTED,\ BUT\ UNKNOWN\ FORMAT\:=Crash report detected, but unknown format:
COULDN'T\ OPEN\ CRASH\ REPORT=Couldn't open crash report
CRASH\ REPORT\ DETECTED,\ OPENING\:=Crash report detected, opening:
MinecraftCrashed=Minecraft crashed! (Error code: {0})
RememberMe=Remember me
Logout=Log out
ShowIfIsLoaded=To show if plugins are loaded.
IsLoaded=Is loaded
PluginSettings=Plugin settings
Details=Details
Authors=Authors
Version=Version
Name=Name
CheckUpdate=Check for update
DownloadSource=Download source
DisableMoveMods=Disable moving mods.
ShowConsoleOutput=To show Minecraft console output.
MinecraftLocation=Minecraft location
MaxMemoryTooltip=Maximum memory(default 1024)
FailedToLoad=Failed to load
Loaded=Loaded
NoCharacter=No characters
LegacyLogin=Legacy
YggdrasilLogin=Yggdrasil
PleaseChooseCharacter=Please choose the character you want to use.
WrongPassword=Maybe your user name or password is wrong.
OfflineLogin=Offline
GameDownload=Downloads
IntegrateDownload=Integrate Packs
AssetsDownload=Assets
Installers=Installers
WorldSaving=World Backups
ServerEditor=Server List
TexturepackEditor=Texturepacks
Refresh=Refresh
AssetsType=Type
Install=Install
InstallOptifine=Install selected Optifine
Changelog=Changelog
InstallForge=Install selected Forge
ModManaging=Mods
PluginCenter=Plugins
ExtMods=External Mods
CoreMods=Core Mods
NormalSettings=Normal
1.6AndAbove=1.6 And Above
1.5AndBelow=1.5 And Below
IsActive=Active
Location=Location
Type=Type
ReleaseTime=Release Time
Time=Time
Version=Version
MCVersion=MC Version
IntegrateName=Pack Name
IntegrateVersion=Pack Version
ServerName=Server Name
HideAddress=Hide Address
Address=Address
Introduction=Introduction
Online=Online
Delay=Delay
Clear=Clear
Close=Close
Save=Save
JoinMinecraftJar=Join minecraft.jar
ExternalMods=External Mods
DynamicLoadingMods=Dynamic Loading Mods
Libraries=Libraries
TagArguments=Tag Args
MainClass=Minecraft Main Class
DefaultLibrariesFolder=Default: .minecraft/libraries
DefaultAssetsFolder=Default: .minecraft/assets
MakeMCMaximum=Make Minecraft Maximum
MCFolderFormat=Minecraft Folder format
MakeMCFullscreen=Make Minecraft fullscreen
MCHeight=Minecraft window height
MCWidth=Minecraft window width
Personalization=Personalization
MaxPermGen=Max PermGen Size(MB)
@@ -0,0 +1,236 @@
# To change this template, choose Tools | Templates
# and open the template in the editor.
\u6e38\u620f\u7248\u672c=\u6e38\u620f\u7248\u672c
\u8fd9\u4e2aMINECRAFT\u6587\u4ef6\u5939\u65e2\u4e0d\u662f1.6\u7248\u4e5f\u4e0d\u662f\u65e7\u7248\u7684\u600e\u4e48\u5bfc\u5165\u561b0V0\u3002=\u8fd9\u4e2aminecraft\u6587\u4ef6\u5939\u65e2\u4e0d\u662f1.6\u7248\u4e5f\u4e0d\u662f\u65e7\u7248\u7684\u600e\u4e48\u5bfc\u5165\u561b0v0\u3002
\u672a\u9009\u4e2d\u4efb\u4f55\u4e00\u4e2a\u7248\u672c=\u672a\u9009\u4e2d\u4efb\u4f55\u4e00\u4e2a\u7248\u672c
\u5bfc\u5165\u5931\u8d25\:\ {0}=\u5bfc\u5165\u5931\u8d25: {0}
\u627e\u5230\u540c\u540d\u7684MINECRAFT\u7248\u672c\uff0c\u8bf7\u6362\u7528\u53e6\u4e00\u4e2a\u540d\u79f0=\u627e\u5230\u540c\u540d\u7684Minecraft\u7248\u672c\uff0c\u8bf7\u6362\u7528\u53e6\u4e00\u4e2a\u540d\u79f0
\u8bf7\u8f93\u5165\u8be5\u65e7\u7248\u672c\u7684\u540d\u79f0=\u8bf7\u8f93\u5165\u8be5\u65e7\u7248\u672c\u7684\u540d\u79f0
\u627e\u4e0d\u5230MINECRAFT.JAR=\u627e\u4e0d\u5230minecraft.jar
\u9009\u62e9MINECRAFT\u8def\u5f84=\u9009\u62e9Minecraft\u8def\u5f84
\u542f\u52a8\u5931\u8d25=\u542f\u52a8\u5931\u8d25
\u590d\u5236\u914d\u7f6e\u6587\u4ef6\u5931\u8d25\:\ =\u590d\u5236\u914d\u7f6e\u6587\u4ef6\u5931\u8d25:
\u590d\u5236\u6838\u5fc3\u6a21\u7ec4\u5931\u8d25\:\ =\u590d\u5236\u6838\u5fc3\u6a21\u7ec4\u5931\u8d25:
\u590d\u5236\u666e\u901a\u6a21\u7ec4\u5931\u8d25\:\ =\u590d\u5236\u666e\u901a\u6a21\u7ec4\u5931\u8d25:
\u4e0b\u8f7d\u7f3a\u5931\u5e93\uff1a{0}=\u4e0b\u8f7d\u7f3a\u5931\u5e93\uff1a{0}
\u6ca1\u6709\u9009\u62e9\u4efb\u4f55\u4e00\u4e2aMINECRAFT\u7248\u672c=\u6ca1\u6709\u9009\u62e9\u4efb\u4f55\u4e00\u4e2aMinecraft\u7248\u672c
\u9519\u8bef\u7684MINECRAFT\u8def\u5f84=\u9519\u8bef\u7684Minecraft\u8def\u5f84
\u5173\u4e8e=\u5173\u4e8e
\u4e0b\u8f7d=\u4e0b\u8f7d
\u5bc6\u7801=\u5bc6\u7801
\u624b\u52a8\u8bbe\u7f6e=\u624b\u52a8\u8bbe\u7f6e
\u4e0d\u9650\u5236=\u4e0d\u9650\u5236
32\u4f4d=32\u4f4d
64\u4f4d=64\u4f4d
\u542f\u52a8\u6a21\u5f0f=\u542f\u52a8\u6a21\u5f0f
\u6700\u5927\u5185\u5b58=\u6700\u5927\u5185\u5b58
\u6e38\u620f\u540d\u79f0=\u540d\u5b57
\u6e38\u620f\u8def\u5f84=\u6e38\u620f\u8def\u5f84
\u5bfc\u5165\u6587\u4ef6\u5939=\u5bfc\u5165\u6587\u4ef6\u5939
\u65b0\u5efa=\u65b0\u5efa
\u5220\u9664=\u5220\u9664
\u7f16\u8f91=\u7f16\u8f91
\u590d\u5236=\u590d\u5236
\u5bfc\u5165\u65e7\u7248\u672c=\u5bfc\u5165\u65e7\u7248\u672c
\u5236\u4f5c\u4e00\u952e\u542f\u52a8=\u5236\u4f5c\u4e00\u952e\u542f\u52a8
\u51c6\u5907\u4e2d=\u51c6\u5907\u4e2d
\u5f00\u59cbMINECRAFT\u4e4b\u65c5!=\u5f00\u59cbMinecraft\u4e4b\u65c5!
\u5237\u65b0=\u5237\u65b0
public_settings=\u5168\u5c40\u8bbe\u7f6e
game_download=\u6e38\u620f\u4e0b\u8f7d
\u8bbe\u7f6e\u5931\u8d25\uff1a=\u8bbe\u7f6e\u5931\u8d25\uff1a
\u7f3a\u5931\u5e93\u4e0b\u8f7d=\u7f3a\u5931\u5e93\u4e0b\u8f7d
\u9009\u62e9\u80cc\u666f\u8def\u5f84=\u9009\u62e9\u80cc\u666f\u8def\u5f84
MineLogin0=\u7f51\u7edc\u9519\u8bef
MineLogin1=\u7528\u6237\u540d\u6216\u5bc6\u7801\u4e0d\u5408\u6cd5
MineLogin2=\u5185\u90e8\u9519\u8bef
MineLogin3=\u7528\u6237\u4e0d\u5b58\u5728
MineLogin4=\u9700\u8981\u9a8c\u8bc1
MineLogin5=\u5bc6\u7801\u9519\u8bef
ForgeMod=Forge mod
ModLoaderMod=ModLoader mod
Forge=Forge
ModLoader=ModLoader
Unknown=\u672a\u77e5
Mods\u6587\u4ef6\u5939=Mods\u6587\u4ef6\u5939
Coremods\u6587\u4ef6\u5939=Coremods\u6587\u4ef6\u5939
Mod\u72ec\u7acb\u6587\u4ef6\u5939=Mod\u72ec\u7acb\u6587\u4ef6\u5939
\u914d\u7f6e\u6587\u4ef6\u5939=\u914d\u7f6e\u6587\u4ef6\u5939
\u767b\u5f55\u5931\u8d25\uff1a=\u767b\u5f55\u5931\u8d25\uff1a
\u9009\u62e9\u5931\u8d25=\u9009\u62e9\u5931\u8d25
\u63d2\u4ef6\u9519\u8bef\uff1a=\u63d2\u4ef6\u9519\u8bef\uff1a
\u767b\u5f55\u5931\u8d25\uff1a=\u767b\u5f55\u5931\u8d25\uff1a
\u6ca1\u6709\u767b\u5165\u65b9\u5f0f...=\u6ca1\u6709\u767b\u5165\u65b9\u5f0f...
\u4fdd\u5b58=\u4fdd\u5b58
\u767b\u5f55\u6a21\u5f0f=\u767b\u5f55\u6a21\u5f0f
\u7248\u672c\u7f16\u8f91=\u7248\u672c\u7f16\u8f91
\u7248\u672c\u53f7=\u7248\u672c\u53f7
\u5bfc\u5165=\u5bfc\u5165
\u64cd\u4f5c=\u64cd\u4f5c
\u4e0b\u8f7d\u4fe1\u606f=\u4e0b\u8f7d\u4fe1\u606f
\u5b89\u88c5=\u5b89\u88c5
\u6dfb\u52a0=\u6dfb\u52a0
\u5168\u90e8\u4e0b\u8f7d=\u5168\u90e8\u4e0b\u8f7d
\u52a0\u5165MINECRAFT.JAR=\u52a0\u5165minecraft.jar
\u7ba1\u7406=\u7ba1\u7406
\u52a8\u6001\u52a0\u8f7d\u6a21\u7ec4=\u52a8\u6001\u52a0\u8f7d\u6a21\u7ec4
\u5e93=\u5e93
AdvancedSettings=\u9ad8\u7ea7\u8bbe\u7f6e
\u6700\u5927\u5316=\u6700\u5927\u5316
\u68c0\u67e5\u66f4\u65b0=\u68c0\u67e5\u66f4\u65b0
\u67e5\u770b\u65e5\u5fd7=\u67e5\u770b\u65e5\u5fd7
\u80cc\u666f\u5730\u5740=\u80cc\u666f\u5730\u5740
UNEXPECTED\ EXCEPTION\ LOADING\ =Unexpected exception loading
\u5f53\u524d\u662f\u6700\u65b0\u7248\u672c=\u5f53\u524d\u662f\u6700\u65b0\u7248\u672c
\u65e0\u6cd5\u6253\u5f00\u6d4f\u89c8\u5668\uff0c\u7f51\u5740\u5df2\u7ecf\u590d\u5236\u5230\u526a\u8d34\u677f\u4e86\uff0c\u60a8\u53ef\u4ee5\u624b\u52a8\u7c98\u8d34\u7f51\u5740\u6253\u5f00\u9875\u9762=\u65e0\u6cd5\u6253\u5f00\u6d4f\u89c8\u5668\uff0c\u7f51\u5740\u5df2\u7ecf\u590d\u5236\u5230\u526a\u8d34\u677f\u4e86\uff0c\u60a8\u53ef\u4ee5\u624b\u52a8\u7c98\u8d34\u7f51\u5740\u6253\u5f00\u9875\u9762
\u662f\u5426\u524d\u5f80\u53d1\u5e03\u9875\u9762\u66f4\u65b0\uff1f=\u662f\u5426\u524d\u5f80\u53d1\u5e03\u9875\u9762\u66f4\u65b0\uff1f
\u66f4\u65b0\u4fe1\u606f\u4e3a\:\ =\u66f4\u65b0\u4fe1\u606f\u4e3a:
\u6700\u65b0\u7248\u672c\u4e3a\uff1a=\u6700\u65b0\u7248\u672c\u4e3a\uff1a
\u68c0\u67e5\u66f4\u65b0\u5931\u8d25=\u68c0\u67e5\u66f4\u65b0\u5931\u8d25
\u8fde\u63a5\u4e2d=\u8fde\u63a5\u4e2d
\u83b7\u53d6\u5217\u8868\u5931\u8d25\uff0c\u8bf7\u5237\u65b0\u91cd\u8bd5=\u83b7\u53d6\u5217\u8868\u5931\u8d25\uff0c\u8bf7\u5237\u65b0\u91cd\u8bd5
INVALID\ PLUGIN=Invalid plugin
\u65e0\u6cd5\u8fde\u63a5=\u65e0\u6cd5\u8fde\u63a5
\ \u5dee\ ORANGERED=\ \u5dee orangered
\ \u8f83\u5dee\ ORANGE=\ \u8f83\u5dee orange
\ \u4e2d\ YELLOGREEN=\ \u4e2d yellogreen
\ \u8f83\u597d\ BLUE=\ \u8f83\u597d blue
\ \u597d\ GREEN=\ \u597d green
\u670d\u52a1\u5668{0}\u7684\u56de\u590d\u65e0\u6548=\u670d\u52a1\u5668{0}\u7684\u56de\u590d\u65e0\u6548
\u63a5\u4e0b\u6765\u5f39\u51fa\u6765\u7684\u7a97\u53e3\u91cc\u8bf7\u9009\u62e9\u8def\u5f84\u4e3a\u6e38\u620f\u8def\u5f84\u3002\u7a0b\u5e8f\u5df2\u7ecf\u5c06\u76ee\u5f55\u590d\u5236\u5230\u4e86\u526a\u8d34\u677f\uff0c\u76f4\u63a5\u5728\u7a97\u53e3\u91cc\u9009\u62e9\\"...\\"\u6309\u94ae\uff0c\u7c98\u8d34\u8def\u5f84\uff0c\u786e\u5b9a\u5373\u53ef=\u63a5\u4e0b\u6765\u5f39\u51fa\u6765\u7684\u7a97\u53e3\u91cc\u8bf7\u9009\u62e9\u8def\u5f84\u4e3a\u6e38\u620f\u8def\u5f84\u3002\u7a0b\u5e8f\u5df2\u7ecf\u5c06\u76ee\u5f55\u590d\u5236\u5230\u4e86\u526a\u8d34\u677f\uff0c\u76f4\u63a5\u5728\u7a97\u53e3\u91cc\u9009\u62e9\\"...\\"\u6309\u94ae\uff0c\u7c98\u8d34\u8def\u5f84\uff0c\u786e\u5b9a\u5373\u53ef
\u65e0\u6cd5\u6253\u5f00\u8d44\u6e90\u7ba1\u7406\u5668\:\ =\u65e0\u6cd5\u6253\u5f00\u8d44\u6e90\u7ba1\u7406\u5668:
\u63d0\u793a=\u63d0\u793a
\u8f93\u5165\u65b0\u7248\u672c\u540d\u79f0=\u8f93\u5165\u65b0\u7248\u672c\u540d\u79f0
\u540d\u79f0=\u540d\u79f0
\u4fdd\u5b58\u5931\u8d25=\u4fdd\u5b58\u5931\u8d25
\u4fdd\u5b58\u538b\u7f29\u5305\u5230=\u4fdd\u5b58\u538b\u7f29\u5305\u5230
\u9009\u62e9\u6750\u8d28\u5305=\u9009\u62e9\u6750\u8d28\u5305
\u9009\u62e9\u8d44\u6e90\u5305=\u9009\u62e9\u8d44\u6e90\u5305
\u9009\u62e9\u5e93/\u6a21\u7ec4=\u9009\u62e9\u5e93/\u6a21\u7ec4
\u6ca1\u6709\u9009\u4e2d\u4efb\u4f55\u4e00\u4e2a\u5e93/\u6a21\u7ec4\u3002=\u6ca1\u6709\u9009\u4e2d\u4efb\u4f55\u4e00\u4e2a\u5e93/\u6a21\u7ec4\u3002
\u5220\u9664\u5931\u8d25=\u5220\u9664\u5931\u8d25
\u6dfb\u52a0\u5931\u8d25=\u6dfb\u52a0\u5931\u8d25
\u9009\u62e9\u6a21\u7ec4=\u9009\u62e9\u6a21\u7ec4
\u7248\u672c\u540d\u79f0\u4e0d\u80fd\u4e3a\u7a7a=\u7248\u672c\u540d\u79f0\u4e0d\u80fd\u4e3a\u7a7a
\u5907\u4efd\u5230=\u5907\u4efd\u5230
\u662fCOREODS\u6587\u4ef6\u5939\u5185\u7684\u6240\u6709\u6838\u5fc3\u6a21\u7ec4=\u662fCoremods\u6587\u4ef6\u5939\u5185\u7684\u6240\u6709\u6838\u5fc3\u6a21\u7ec4
\u662fMODS\u6587\u4ef6\u5939\u5185\u7684\u6240\u6709\u6a21\u7ec4=\u662fMods\u6587\u4ef6\u5939\u5185\u7684\u6240\u6709\u6a21\u7ec4
\u901a\u5e38\u662f\u6a21\u7ec4=\u901a\u5e38\u662f\u6a21\u7ec4
\u4e0b\u79fb=\u4e0b\u79fb
\u4e0a\u79fb=\u4e0a\u79fb
\u5220\u9664=\u5220\u9664
\u589e\u52a0=\u589e\u52a0
\u901a\u5e38\u662fFORGE,MODLOADER\u4ee5\u53caMINECRAFT\u6240\u4f9d\u8d56\u7684\u5e93=\u901a\u5e38\u662fForge,Modloader\u4ee5\u53caMinecraft\u6240\u4f9d\u8d56\u7684\u5e93
\u9644\u52a0\u542f\u52a8\u53c2\u6570=\u9644\u52a0\u542f\u52a8\u53c2\u6570
\u81ea\u5b9a\u4e49\u5e93\u6587\u4ef6\u5939(LIBRARIES\u6587\u4ef6\u5939)=\u81ea\u5b9a\u4e49\u5e93\u6587\u4ef6\u5939(libraries\u6587\u4ef6\u5939)
\u4e3b\u7c7b=\u4e3b\u7c7b
\u81ea\u5b9a\u4e49\u8d44\u6e90\u6587\u4ef6\u5939(ASSETS\u6587\u4ef6\u5939)=\u81ea\u5b9a\u4e49\u8d44\u6e90\u6587\u4ef6\u5939(assets\u6587\u4ef6\u5939)
\u624b\u52a8\u8bbe\u7f6e=\u624b\u52a8\u8bbe\u7f6e
\u4e0d\u5f3a\u5236=\u4e0d\u5f3a\u5236
32\u4f4d=32\u4f4d
64\u4f4d=64\u4f4d
\u542f\u52a8\u6a21\u5f0f=\u542f\u52a8\u6a21\u5f0f
\u73a9\u5bb6\u540d=\u73a9\u5bb6\u540d
1.6\u53ca\u4ee5\u4e0a\u7248\u672c\u4ee5\u53ca\u5bfc\u5165\u7684\u65e7\u7248\u672c=1.6\u53ca\u4ee5\u4e0a\u7248\u672c\u4ee5\u53ca\u5bfc\u5165\u7684\u65e7\u7248\u672c
\u6700\u5927\u5185\u5b58=\u6700\u5927\u5185\u5b58
JAVA\u865a\u62df\u673a\u53c2\u6570=Java\u865a\u62df\u673a\u53c2\u6570
JAVA\u8def\u5f84=Java\u8def\u5f84
\u5168\u5c4f=\u5168\u5c4f
\u5206\u8fa8\u7387=\u5206\u8fa8\u7387
\u6e38\u620f\u8def\u5f84=\u6e38\u620f\u8def\u5f84
\u4ee5\u4e0b\u8bbe\u7f6e\u5b57\u6bb5\u4e3a\u7a7a\u4ee3\u8868\u7740\u4f7f\u7528\u9ed8\u8ba4\u8bbe\u7f6e=\u9664\u540d\u79f0\u4ee5\u4e0b\u5b57\u6bb5\u53ef\u4ee5\u4e0d\u586b
\u53d6\u6d88=\u53d6\u6d88
\u786e\u5b9a=\u786e\u5b9a
game_download=\u6e38\u620f\u4e0b\u8f7d
public_settings=\u5168\u5c40\u8bbe\u7f6e
invalid=\u65e0\u6548\u7684
invalid_jar=\u65e0\u6548\u7684jar\u5305
not_a_file=\u4e0d\u662f\u6587\u4ef6
not_found=\u627e\u4e0d\u5230minecraft.jar
not_readable=minecraft.jar\u4e0d\u53ef\u8bfb
modified=(\u4fee\u6539\u7684!)
\u83b7\u53d6\u4e2d=\u83b7\u53d6\u4e2d
\u63d2\u4ef6\u9519\u8bef=\u63d2\u4ef6\u9519\u8bef
CannotLoadPluginsBecauseOfAnError=\u65e0\u6cd5\u52a0\u8f7d\u63d2\u4ef6\uff0c\u56e0\u4e3a\u53d1\u751f\u4e86\u4e00\u4e2a\u9519\u8bef\u3002
CRASH\ REPORT\ DETECTED,\ BUT\ UNKNOWN\ FORMAT\:=Crash report detected, but unknown format:
COULDN'T\ OPEN\ CRASH\ REPORT=Couldn't open crash report
CRASH\ REPORT\ DETECTED,\ OPENING\:=Crash report detected, opening:
MinecraftCrashed=Minecraft\u5d29\u6e83\u4e86\uff01(\u9519\u8bef\u4ee3\u7801:{0})
RememberMe=\u8bb0\u4f4f\u6211
Logout=\u767b\u51fa
ShowIfIsLoaded=\u663e\u793a\u63d2\u4ef6\u662f\u5426\u52a0\u8f7d\uff0c\u70b9\u51fb\u67e5\u770b\u9519\u8bef
IsLoaded=\u662f\u5426\u52a0\u8f7d
PluginSettings=\u63d2\u4ef6\u8bbe\u7f6e
Details=\u4fe1\u606f
Authors=\u4f5c\u8005
Version=\u7248\u672c
Name=\u540d\u79f0
CheckUpdate=\u68c0\u67e5\u672c\u542f\u52a8\u5668\u7684\u66f4\u65b0
DownloadSource=\u4e0b\u8f7d\u6e90
DisableMoveMods=\u7981\u6b62\u7248\u672c\u81ea\u6709\u6a21\u7ec4\uff08\u79fb\u52a8\u6a21\u7ec4\uff09\u529f\u80fd
ShowConsoleOutput=\u5c31\u662fMinecraft\u7684\u63a7\u5236\u53f0\u8f93\u51fa
MinecraftLocation=Minecraft\u8def\u5f84\uff08\u5373.minecraft\u6587\u4ef6\u5939\uff09
MaxMemoryTooltip=\u5141\u8bb8Minecraft\u6700\u591a\u5141\u8bb8\u4f7f\u7528\u7684\u5185\u5b58\uff08\u770b\u4e0d\u61c2\u5c31\u4f7f\u7528\u9ed8\u8ba4\u76841024\u5427\uff09
FailedToLoad=\u52a0\u8f7d\u5931\u8d25
Loaded=\u5df2\u52a0\u8f7d
NoCharacter=\u8be5\u5e10\u53f7\u6ca1\u6709\u89d2\u8272
LegacyLogin=\u65e7\u7248\u6b63\u7248\u767b\u5f55
YggdrasilLogin=\u65b0\u7248\u6b63\u7248\u767b\u5f55
PleaseChooseCharacter=\u8bf7\u9009\u62e9\u60a8\u8981\u4f7f\u7528\u7684\u89d2\u8272
WrongPassword=\u53ef\u80fd\u662f\u60a8\u7684\u7528\u6237\u540d\u6216\u5bc6\u7801\u9519\u8bef
OfflineLogin=\u79bb\u7ebf\u6a21\u5f0f
GameDownload=\u6e38\u620f\u4e0b\u8f7d
IntegrateDownload=\u6574\u5408\u5305\u4e0b\u8f7d
AssetsDownload=\u8d44\u6e90\u4e0b\u8f7d
Installers=\u81ea\u52a8\u5b89\u88c5
WorldSaving=\u5907\u4efd\u5730\u56fe
ServerEditor=\u670d\u52a1\u5668\u7f16\u8f91
TexturepackEditor=\u6750\u8d28\u5305\u7ba1\u7406
Refresh=\u5237\u65b0\u5217\u8868
Install=\u5b89\u88c5
AssetsType=\u8d44\u6e90\u7c7b\u578b
InstallOptifine=\u5b89\u88c5\u9009\u4e2d\u7684Optifine
Changelog=\u66f4\u65b0\u4fe1\u606f
InstallForge=\u5b89\u88c5\u9009\u4e2d\u7684Forge
ModManaging=\u6a21\u7ec4\u7ba1\u7406
PluginCenter=\u63d2\u4ef6\u4e2d\u5fc3
ExtMods=\u5916\u90e8\u6a21\u7ec4
CoreMods=\u6838\u5fc3\u6a21\u7ec4
NormalSettings=\u666e\u901a\u8bbe\u7f6e
1.6AndAbove=1.6\u53ca\u4ee5\u4e0a
1.5AndBelow=1.5\u53ca\u4ee5\u4e0b
IsActive=\u6d3b\u52a8
Location=\u8def\u5f84
Type=\u7c7b\u578b
ReleaseTime=\u91ca\u653e\u65f6\u95f4
Time=\u53d1\u5e03\u65f6\u95f4
Version=\u7248\u672c
MCVersion=MC\u7248\u672c
IntegrateName=\u6574\u5408\u5305\u540d\u79f0
IntegrateVersion=\u6574\u5408\u5305\u7248\u672c
ServerName=\u670d\u52a1\u5668\u540d\u79f0
HideAddress=\u9690\u85cf\u5730\u5740
Address=\u5730\u5740
Introduction=\u4ecb\u7ecd
Online=\u5728\u7ebf
Delay=\u5ef6\u8fdf
Clear=\u6e05\u9664
Close=\u5173\u95ed
Save=\u4fdd\u5b58
JoinMinecraftJar=\u52a0\u5165minecraft.jar
ExternalMods=\u5916\u90e8\u6a21\u7ec4
DynamicLoadingMods=\u52a8\u6001\u52a0\u8f7d\u6a21\u7ec4
Libraries=\u5e93
TagArguments=\u9644\u52a0\u7ed9\u4e88Minecraft\u7684\u53c2\u6570
MainClass=Minecraft\u7684\u4e3b\u7c7b\uff08\u4e0d\u77e5\u9053\u4ec0\u4e48\u610f\u601d\u7684\u8bdd\u4e5f\u5c31\u7528\u4e0d\u4e0a\u4e86\uff09
DefaultLibrariesFolder=\u9ed8\u8ba4\u4e3a.minecraft/libraries\u6587\u4ef6\u5939
DefaultAssetsFolder=\u9ed8\u8ba4\u4e3a.minecraft/assets\u6587\u4ef6\u5939
MakeMCMaximum=\u4f7fMinecraft\u7a97\u53e3\u6700\u5927\u5316
MCFolderFormat=\u5c31\u662fMinecraft\u6587\u4ef6\u5939\u683c\u5f0f
MakeMCFullscreen=\u4f7fMinecraft\u7a97\u53e3\u5168\u5c4f
MCHeight=Minecraft\u7a97\u53e3\u9ad8
MCWidth=Minecraft\u7a97\u53e3\u5bbd
Personalization=\u4e2a\u6027\u5316
MaxPermGen=\u6700\u5927\u6c38\u4e45\u4fdd\u5b58\u533a\u57df\uff08MB\uff09
@@ -0,0 +1,236 @@
# To change this template, choose Tools | Templates
# and open the template in the editor.
\u6e38\u620f\u7248\u672c=\u904a\u6232\u7248\u672c
\u8fd9\u4e2aMINECRAFT\u6587\u4ef6\u5939\u65e2\u4e0d\u662f1.6\u7248\u4e5f\u4e0d\u662f\u65e7\u7248\u7684\u600e\u4e48\u5bfc\u5165\u561b0V0\u3002=\u9019\u500bminecraft\u8cc7\u6599\u593e\u65e2\u4e0d\u662f1.6\u7248\u4e5f\u4e0d\u662f\u820a\u7248\u7684\u600e\u9ebc\u5c0e\u5165\u561b0v0\u3002
\u672a\u9009\u4e2d\u4efb\u4f55\u4e00\u4e2a\u7248\u672c=\u672a\u9078\u4e2d\u4efb\u4f55\u4e00\u500b\u7248\u672c
\u5bfc\u5165\u5931\u8d25\:\ {0}=\u5c0e\u5165\u5931\u6557: {0}
\u627e\u5230\u540c\u540d\u7684MINECRAFT\u7248\u672c\uff0c\u8bf7\u6362\u7528\u53e6\u4e00\u4e2a\u540d\u79f0=\u627e\u5230\u540c\u540d\u7684Minecraft\u7248\u672c\uff0c\u8acb\u63db\u7528\u53e6\u4e00\u500b\u540d\u7a31
\u8bf7\u8f93\u5165\u8be5\u65e7\u7248\u672c\u7684\u540d\u79f0=\u8acb\u8f38\u5165\u8a72\u820a\u7248\u672c\u7684\u540d\u7a31
\u627e\u4e0d\u5230MINECRAFT.JAR=\u627e\u4e0d\u5230minecraft.jar
\u9009\u62e9MINECRAFT\u8def\u5f84=\u9078\u64c7Minecraft\u8def\u5f91
\u542f\u52a8\u5931\u8d25=\u555f\u52d5\u5931\u6557
\u590d\u5236\u914d\u7f6e\u6587\u4ef6\u5931\u8d25\:\ =\u8907\u88fd\u914d\u7f6e\u6587\u4ef6\u5931\u6557:
\u590d\u5236\u6838\u5fc3\u6a21\u7ec4\u5931\u8d25\:\ =\u8907\u88fd\u6838\u5fc3\u6a21\u7d44\u5931\u6557:
\u590d\u5236\u666e\u901a\u6a21\u7ec4\u5931\u8d25\:\ =\u8907\u88fd\u666e\u901a\u6a21\u7d44\u5931\u6557:
\u4e0b\u8f7d\u7f3a\u5931\u5e93\uff1a{0}=\u4e0b\u8f09\u7f3a\u5931\u5eab\uff1a{0}
\u6ca1\u6709\u9009\u62e9\u4efb\u4f55\u4e00\u4e2aMINECRAFT\u7248\u672c=\u6c92\u6709\u9078\u64c7\u4efb\u4f55\u4e00\u500bMinecraft\u7248\u672c
\u9519\u8bef\u7684MINECRAFT\u8def\u5f84=\u932f\u8aa4\u7684Minecraft\u8def\u5f91
\u5173\u4e8e=\u5173\u4e8e
\u4e0b\u8f7d=\u4e0b\u8f09
\u5bc6\u7801=\u5bc6\u78bc
\u624b\u52a8\u8bbe\u7f6e=\u624b\u52d5\u8a2d\u5b9a
\u4e0d\u9650\u5236=\u4e0d\u9650\u5236
32\u4f4d=32\u4f4d
64\u4f4d=64\u4f4d
\u542f\u52a8\u6a21\u5f0f=\u555f\u52d5\u6a21\u5f0f
\u6700\u5927\u5185\u5b58=\u6700\u5927\u5167\u5b58
\u6e38\u620f\u540d\u79f0=\u904a\u6232\u540d\u7a31
\u6e38\u620f\u8def\u5f84=\u904a\u6232\u8def\u5f91
\u5bfc\u5165\u6587\u4ef6\u5939=\u5c0e\u5165\u8cc7\u6599\u593e
\u65b0\u5efa=\u65b0\u5efa
\u5220\u9664=\u522a\u9664
\u7f16\u8f91=\u7de8\u8f2f
\u590d\u5236=\u8907\u88fd
\u5bfc\u5165\u65e7\u7248\u672c=\u5c0e\u5165\u820a\u7248\u672c
\u5236\u4f5c\u4e00\u952e\u542f\u52a8=\u88fd\u4f5c\u4e00\u9375\u555f\u52d5
\u51c6\u5907\u4e2d=\u51c6\u5907\u4e2d
\u5f00\u59cbMINECRAFT\u4e4b\u65c5!=\u958b\u59cbMinecraft\u4e4b\u65c5!
\u5237\u65b0=\u5237\u65b0
public_settings=\u5168\u5c40\u8a2d\u5b9a
game_download=\u904a\u6232\u4e0b\u8f09
\u8bbe\u7f6e\u5931\u8d25\uff1a=\u8a2d\u5b9a\u5931\u6557\uff1a
\u7f3a\u5931\u5e93\u4e0b\u8f7d=\u7f3a\u5931\u5eab\u4e0b\u8f09
\u9009\u62e9\u80cc\u666f\u8def\u5f84=\u9078\u64c7\u80cc\u666f\u8def\u5f91
MineLogin0=\u7db2\u7d61\u932f\u8aa4
MineLogin1=\u7528\u6236\u540d\u6216\u5bc6\u78bc\u4e0d\u5408\u6cd5
MineLogin2=\u5167\u90e8\u932f\u8aa4
MineLogin3=\u7528\u6236\u4e0d\u5b58\u5728
MineLogin4=\u9700\u8981\u9a57\u8b49
MineLogin5=\u5bc6\u78bc\u932f\u8aa4
ForgeMod=Forge mod
ModLoaderMod=ModLoader mod
Forge=Forge
ModLoader=ModLoader
Unknown=\u672a\u77e5
Mods\u6587\u4ef6\u5939=Mods\u8cc7\u6599\u593e
Coremods\u6587\u4ef6\u5939=Coremods\u8cc7\u6599\u593e
Mod\u72ec\u7acb\u6587\u4ef6\u5939=Mod\u72ec\u7acb\u8cc7\u6599\u593e
\u914d\u7f6e\u6587\u4ef6\u5939=\u914d\u7f6e\u8cc7\u6599\u593e
\u767b\u5f55\u5931\u8d25\uff1a=\u767b\u5165\u5931\u6557\uff1a
\u9009\u62e9\u5931\u8d25=\u9078\u64c7\u5931\u6557
\u63d2\u4ef6\u9519\u8bef\uff1a=\u63d2\u4ef6\u932f\u8aa4\uff1a
\u767b\u5f55\u5931\u8d25\uff1a=\u767b\u9304\u5931\u6557\uff1a
\u6ca1\u6709\u767b\u5165\u65b9\u5f0f...=\u6c92\u6709\u767b\u5165\u65b9\u5f0f...
\u4fdd\u5b58=\u4fdd\u5b58
\u767b\u5f55\u6a21\u5f0f=\u767b\u5165\u6a21\u5f0f
\u7248\u672c\u7f16\u8f91=\u7248\u672c\u7de8\u8f2f
\u7248\u672c\u53f7=\u7248\u672c\u865f
\u5bfc\u5165=\u5c0e\u5165
\u64cd\u4f5c=\u64cd\u4f5c
\u4e0b\u8f7d\u4fe1\u606f=\u4e0b\u8f09\u4fe1\u606f
\u5b89\u88c5=\u5b89\u88c5
\u6dfb\u52a0=\u6dfb\u52a0
\u5168\u90e8\u4e0b\u8f7d=\u5168\u90e8\u4e0b\u8f09
\u52a0\u5165MINECRAFT.JAR=\u52a0\u5165minecraft.jar
\u7ba1\u7406=\u7ba1\u7406
\u52a8\u6001\u52a0\u8f7d\u6a21\u7ec4=\u52d5\u614b\u52a0\u8f09\u6a21\u7d44
\u5e93=\u5eab
AdvancedSettings=\u9ad8\u7d1a\u8a2d\u7f6e
\u6700\u5927\u5316=\u6700\u5927\u5316
\u68c0\u67e5\u66f4\u65b0=\u6aa2\u67e5\u66f4\u65b0
\u67e5\u770b\u65e5\u5fd7=\u67e5\u770b\u65e5\u8a8c
\u80cc\u666f\u5730\u5740=\u80cc\u666f\u5730\u5740
UNEXPECTED\ EXCEPTION\ LOADING\ =\u610f\u5916\u7684\u7570\u5e38
\u5f53\u524d\u662f\u6700\u65b0\u7248\u672c=\u7576\u524d\u662f\u6700\u65b0\u7248\u672c
\u65e0\u6cd5\u6253\u5f00\u6d4f\u89c8\u5668\uff0c\u7f51\u5740\u5df2\u7ecf\u590d\u5236\u5230\u526a\u8d34\u677f\u4e86\uff0c\u60a8\u53ef\u4ee5\u624b\u52a8\u7c98\u8d34\u7f51\u5740\u6253\u5f00\u9875\u9762=\u7121\u6cd5\u6253\u958b\u700f\u89bd\u5668\uff0c\u7db2\u5740\u5df2\u7d93\u5fa9\u88fd\u5230\u526a\u8cbc\u677f\u4e86\uff0c\u60a8\u53ef\u4ee5\u624b\u52d5\u7c98\u8cbc\u7db2\u5740\u6253\u958b\u9801\u9762
\u662f\u5426\u524d\u5f80\u53d1\u5e03\u9875\u9762\u66f4\u65b0\uff1f=\u662f\u5426\u524d\u5f80\u767c\u5e03\u9801\u9762\u66f4\u65b0\uff1f
\u66f4\u65b0\u4fe1\u606f\u4e3a\:\ =\u66f4\u65b0\u4fe1\u606f\u70ba:
\u6700\u65b0\u7248\u672c\u4e3a\uff1a=\u6700\u65b0\u7248\u672c\u70ba\uff1a
\u68c0\u67e5\u66f4\u65b0\u5931\u8d25=\u6aa2\u67e5\u66f4\u65b0\u5931\u6557
\u8fde\u63a5\u4e2d=\u9023\u63a5\u4e2d
\u83b7\u53d6\u5217\u8868\u5931\u8d25\uff0c\u8bf7\u5237\u65b0\u91cd\u8bd5=\u7372\u53d6\u5217\u8868\u5931\u6557\uff0c\u8acb\u5237\u65b0\u91cd\u8a66
INVALID\ PLUGIN=\u7121\u6548\u63d2\u4ef6
\u65e0\u6cd5\u8fde\u63a5=\u7121\u6cd5\u9023\u63a5
\ \u5dee\ ORANGERED=\ \u5dee orangered
\ \u8f83\u5dee\ ORANGE=\ \u8f03\u5dee orange
\ \u4e2d\ YELLOGREEN=\ \u4e2d yellogreen
\ \u8f83\u597d\ BLUE=\ \u8f03\u597d blue
\ \u597d\ GREEN=\ \u597d green
\u670d\u52a1\u5668{0}\u7684\u56de\u590d\u65e0\u6548=\u670d\u52d9\u5668{0}\u7684\u56de\u590d\u7121\u6548
\u63a5\u4e0b\u6765\u5f39\u51fa\u6765\u7684\u7a97\u53e3\u91cc\u8bf7\u9009\u62e9\u8def\u5f84\u4e3a\u6e38\u620f\u8def\u5f84\u3002\u7a0b\u5e8f\u5df2\u7ecf\u5c06\u76ee\u5f55\u590d\u5236\u5230\u4e86\u526a\u8d34\u677f\uff0c\u76f4\u63a5\u5728\u7a97\u53e3\u91cc\u9009\u62e9\\"...\\"\u6309\u94ae\uff0c\u7c98\u8d34\u8def\u5f84\uff0c\u786e\u5b9a\u5373\u53ef=\u63a5\u4e0b\u4f86\u5f48\u51fa\u4f86\u7684\u7a97\u53e3\u88e1\u8acb\u9078\u64c7\u8def\u5f91\u70ba\u904a\u6232\u8def\u5f91\u3002\u7a0b\u5e8f\u5df2\u7d93\u5c07\u76ee\u9304\u8907\u88fd\u5230\u4e86\u526a\u8cbc\u677f\uff0c\u76f4\u63a5\u5728\u7a97\u53e3\u88e1\u9078\u64c7\\"...\\"\u6309\u9215\uff0c\u7c98\u8cbc\u8def\u5f91\uff0c\u78ba\u5b9a\u5373\u53ef
\u65e0\u6cd5\u6253\u5f00\u8d44\u6e90\u7ba1\u7406\u5668\:\ =\u7121\u6cd5\u6253\u958b\u8cc7\u6e90\u7ba1\u7406\u5668:
\u63d0\u793a=\u63d0\u793a
\u8f93\u5165\u65b0\u7248\u672c\u540d\u79f0=\u8f38\u5165\u65b0\u7248\u672c\u540d\u7a31
\u540d\u79f0=\u540d\u7a31
\u4fdd\u5b58\u5931\u8d25=\u4fdd\u5b58\u5931\u6557
\u4fdd\u5b58\u538b\u7f29\u5305\u5230=\u4fdd\u5b58\u58d3\u7e2e\u5305\u5230
\u9009\u62e9\u6750\u8d28\u5305=\u9078\u64c7\u6750\u8cea\u5305
\u9009\u62e9\u8d44\u6e90\u5305=\u9078\u64c7\u8cc7\u6e90\u5305
\u9009\u62e9\u5e93/\u6a21\u7ec4=\u9078\u64c7\u5eab/\u6a21\u7d44
\u6ca1\u6709\u9009\u4e2d\u4efb\u4f55\u4e00\u4e2a\u5e93/\u6a21\u7ec4\u3002=\u6c92\u6709\u9078\u4e2d\u4efb\u4f55\u4e00\u500b\u5eab/\u6a21\u7d44\u3002
\u5220\u9664\u5931\u8d25=\u522a\u9664\u5931\u6557
\u6dfb\u52a0\u5931\u8d25=\u6dfb\u52a0\u5931\u6557
\u9009\u62e9\u6a21\u7ec4=\u9078\u64c7\u6a21\u7d44
\u7248\u672c\u540d\u79f0\u4e0d\u80fd\u4e3a\u7a7a=\u7248\u672c\u540d\u7a31\u4e0d\u80fd\u70ba\u7a7a
\u5907\u4efd\u5230=\u5099\u4efd\u5230
\u662fCOREODS\u6587\u4ef6\u5939\u5185\u7684\u6240\u6709\u6838\u5fc3\u6a21\u7ec4=\u662fCoremods\u6587\u4ef6\u593e\u5167\u7684\u6240\u6709\u6838\u5fc3\u6a21\u7d44
\u662fMODS\u6587\u4ef6\u5939\u5185\u7684\u6240\u6709\u6a21\u7ec4=\u662fMods\u6587\u4ef6\u593e\u5167\u7684\u6240\u6709\u6a21\u7d44
\u901a\u5e38\u662f\u6a21\u7ec4=\u901a\u5e38\u662f\u6a21\u7d44
\u4e0b\u79fb=\u4e0b\u79fb
\u4e0a\u79fb=\u4e0a\u79fb
\u5220\u9664=\u522a\u9664
\u589e\u52a0=\u589e\u52a0
\u901a\u5e38\u662fFORGE,MODLOADER\u4ee5\u53caMINECRAFT\u6240\u4f9d\u8d56\u7684\u5e93=\u901a\u5e38\u662fForge,Modloader\u4ee5\u53caMinecraft\u6240\u4f9d\u8cf4\u7684\u5eab
\u9644\u52a0\u542f\u52a8\u53c2\u6570=\u9644\u52a0\u555f\u52d5\u53c3\u6578
\u81ea\u5b9a\u4e49\u5e93\u6587\u4ef6\u5939(LIBRARIES\u6587\u4ef6\u5939)=\u81ea\u5b9a\u7fa9\u5eab\u8cc7\u6599\u593e(libraries\u8cc7\u6599\u593e)
\u4e3b\u7c7b=\u4e3b\u7c7b
\u81ea\u5b9a\u4e49\u8d44\u6e90\u6587\u4ef6\u5939(ASSETS\u6587\u4ef6\u5939)=\u81ea\u5b9a\u7fa9\u8cc7\u6e90\u8cc7\u6599\u593e(assets\u8cc7\u6599\u593e)
\u624b\u52a8\u8bbe\u7f6e=\u624b\u52d5\u8a2d\u5b9a
\u4e0d\u5f3a\u5236=\u4e0d\u5f37\u5236
32\u4f4d=32\u4f4d
64\u4f4d=64\u4f4d
\u542f\u52a8\u6a21\u5f0f=\u555f\u52d5\u6a21\u5f0f
\u73a9\u5bb6\u540d=\u73a9\u5bb6\u540d
1.6\u53ca\u4ee5\u4e0a\u7248\u672c\u4ee5\u53ca\u5bfc\u5165\u7684\u65e7\u7248\u672c=1.6\u53ca\u4ee5\u4e0a\u7248\u672c\u4ee5\u53ca\u5c0e\u5165\u7684\u820a\u7248\u672c
\u6700\u5927\u5185\u5b58=\u6700\u5927\u5167\u5b58
JAVA\u865a\u62df\u673a\u53c2\u6570=Java\u865b\u64ec\u6a5f\u53c3\u6578
JAVA\u8def\u5f84=Java\u8def\u5f91
\u5168\u5c4f=\u5168\u5c4f
\u5206\u8fa8\u7387=\u5206\u8fa8\u7387
\u6e38\u620f\u8def\u5f84=\u904a\u6232\u8def\u5f91
\u4ee5\u4e0b\u8bbe\u7f6e\u5b57\u6bb5\u4e3a\u7a7a\u4ee3\u8868\u7740\u4f7f\u7528\u9ed8\u8ba4\u8bbe\u7f6e=\u9664\u540d\u7a31\u4ee5\u4e0b\u5b57\u6bb5\u53ef\u4ee5\u4e0d\u586b
\u53d6\u6d88=\u53d6\u6d88
\u786e\u5b9a=\u78ba\u5b9a
game_download=\u904a\u6232\u4e0b\u8f09
public_settings=\u5168\u5c40\u8a2d\u5b9a
invalid=\u7121\u6548\u7684
invalid_jar=\u7121\u6548\u7684jar\u5305
not_a_file=\u4e0d\u662f\u6587\u4ef6
not_found=\u627e\u4e0d\u5230minecraft.jar
not_readable=minecraft.jar\u4e0d\u53ef\u8b80
modified=(\u4fee\u6539\u7684!)
\u83b7\u53d6\u4e2d=\u83b7\u53d6\u4e2d
\u63d2\u4ef6\u9519\u8bef=\u63d2\u4ef6\u9519\u8bef
CannotLoadPluginsBecauseOfAnError=\u65e0\u6cd5\u52a0\u8f7d\u63d2\u4ef6\uff0c\u56e0\u4e3a\u53d1\u751f\u4e86\u4e00\u4e2a\u9519\u8bef\u3002
CRASH\ REPORT\ DETECTED,\ BUT\ UNKNOWN\ FORMAT\:=Crash report detected, but unknown format:
COULDN'T\ OPEN\ CRASH\ REPORT=Couldn't open crash report
CRASH\ REPORT\ DETECTED,\ OPENING\:=Crash report detected, opening:
MinecraftCrashed=Minecraft\u5d29\u6e83\u4e86\uff01(\u9519\u8bef\u4ee3\u7801:{0})
RememberMe=\u8bb0\u4f4f\u6211
Logout=\u767b\u51fa
ShowIfIsLoaded=\u663e\u793a\u63d2\u4ef6\u662f\u5426\u52a0\u8f7d\uff0c\u70b9\u51fb\u67e5\u770b\u9519\u8bef
IsLoaded=\u662f\u5426\u52a0\u8f7d
PluginSettings=\u63d2\u4ef6\u8bbe\u7f6e
Details=\u4fe1\u606f
Authors=\u4f5c\u8005
Version=\u7248\u672c
Name=\u540d\u79f0
CheckUpdate=\u68c0\u67e5\u672c\u542f\u52a8\u5668\u7684\u66f4\u65b0
DownloadSource=\u4e0b\u8f7d\u6e90
DisableMoveMods=\u7981\u6b62\u7248\u672c\u81ea\u6709\u6a21\u7ec4\uff08\u79fb\u52a8\u6a21\u7ec4\uff09\u529f\u80fd
ShowConsoleOutput=\u5c31\u662fMinecraft\u7684\u63a7\u5236\u53f0\u8f93\u51fa
MinecraftLocation=Minecraft\u8def\u5f84\uff08\u5373.minecraft\u6587\u4ef6\u5939\uff09
MaxMemoryTooltip=\u5141\u8bb8Minecraft\u6700\u591a\u5141\u8bb8\u4f7f\u7528\u7684\u5185\u5b58\uff08\u770b\u4e0d\u61c2\u5c31\u4f7f\u7528\u9ed8\u8ba4\u76841024\u5427\uff09
FailedToLoad=\u52a0\u8f7d\u5931\u8d25
Loaded=\u5df2\u52a0\u8f7d
NoCharacter=\u8be5\u5e10\u53f7\u6ca1\u6709\u89d2\u8272
LegacyLogin=\u65e7\u7248\u6b63\u7248\u767b\u5f55
YggdrasilLogin=\u65b0\u7248\u6b63\u7248\u767b\u5f55
PleaseChooseCharacter=\u8bf7\u9009\u62e9\u60a8\u8981\u4f7f\u7528\u7684\u89d2\u8272
WrongPassword=\u53ef\u80fd\u662f\u60a8\u7684\u7528\u6237\u540d\u6216\u5bc6\u7801\u9519\u8bef
OfflineLogin=\u79bb\u7ebf\u6a21\u5f0f
GameDownload=\u6e38\u620f\u4e0b\u8f7d
IntegrateDownload=\u6574\u5408\u5305\u4e0b\u8f7d
AssetsDownload=\u8d44\u6e90\u4e0b\u8f7d
Installers=\u81ea\u52a8\u5b89\u88c5
WorldSaving=\u5907\u4efd\u5730\u56fe
ServerEditor=\u670d\u52a1\u5668\u7f16\u8f91
TexturepackEditor=\u6750\u8d28\u5305\u7ba1\u7406
Refresh=\u5237\u65b0\u5217\u8868
Install=\u5b89\u88c5
AssetsType=\u8d44\u6e90\u7c7b\u578b
InstallOptifine=\u5b89\u88c5\u9009\u4e2d\u7684Optifine
Changelog=\u66f4\u65b0\u4fe1\u606f
InstallForge=\u5b89\u88c5\u9009\u4e2d\u7684Forge
ModManaging=\u6a21\u7ec4\u7ba1\u7406
PluginCenter=\u63d2\u4ef6\u4e2d\u5fc3
ExtMods=\u5916\u90e8\u6a21\u7ec4
CoreMods=\u6838\u5fc3\u6a21\u7ec4
NormalSettings=\u666e\u901a\u8bbe\u7f6e
1.6AndAbove=1.6\u53ca\u4ee5\u4e0a
1.5AndBelow=1.5\u53ca\u4ee5\u4e0b
IsActive=\u6d3b\u52a8
Location=\u8def\u5f84
Type=\u7c7b\u578b
ReleaseTime=\u91ca\u653e\u65f6\u95f4
Time=\u53d1\u5e03\u65f6\u95f4
Version=\u7248\u672c
MCVersion=MC\u7248\u672c
IntegrateName=\u6574\u5408\u5305\u540d\u79f0
IntegrateVersion=\u6574\u5408\u5305\u7248\u672c
ServerName=\u670d\u52a1\u5668\u540d\u79f0
HideAddress=\u9690\u85cf\u5730\u5740
Address=\u5730\u5740
Introduction=\u4ecb\u7ecd
Online=\u5728\u7ebf
Delay=\u5ef6\u8fdf
Clear=\u6e05\u9664
Close=\u5173\u95ed
Save=\u4fdd\u5b58
JoinMinecraftJar=\u52a0\u5165minecraft.jar
ExternalMods=\u5916\u90e8\u6a21\u7ec4
DynamicLoadingMods=\u52a8\u6001\u52a0\u8f7d\u6a21\u7ec4
Libraries=\u5e93
TagArguments=\u9644\u52a0\u7ed9\u4e88Minecraft\u7684\u53c2\u6570
MainClass=Minecraft\u7684\u4e3b\u7c7b\uff08\u4e0d\u77e5\u9053\u4ec0\u4e48\u610f\u601d\u7684\u8bdd\u4e5f\u5c31\u7528\u4e0d\u4e0a\u4e86\uff09
DefaultLibrariesFolder=\u9ed8\u8ba4\u4e3a.minecraft/libraries\u6587\u4ef6\u5939
DefaultAssetsFolder=\u9ed8\u8ba4\u4e3a.minecraft/assets\u6587\u4ef6\u5939
MakeMCMaximum=\u4f7fMinecraft\u7a97\u53e3\u6700\u5927\u5316
MCFolderFormat=\u5c31\u662fMinecraft\u6587\u4ef6\u5939\u683c\u5f0f
MakeMCFullscreen=\u4f7fMinecraft\u7a97\u53e3\u5168\u5c4f
MCHeight=Minecraft\u7a97\u53e3\u9ad8
MCWidth=Minecraft\u7a97\u53e3\u5bbd
Personalization=\u4e2a\u6027\u5316
MaxPermGen=\u6700\u5927\u6c38\u4e45\u4fdd\u5b58\u533a\u57df\uff08MB\uff09
@@ -0,0 +1,67 @@
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package org.jackhuang.hellominecraftlauncher;
import java.util.List;
import org.jackhuang.hellominecraftlauncher.utilities.LimitedCapacityList;
/**
*
* @author hyh
*/
public class JavaProcess {
private final List<String> commands;
private final Process process;
private final LimitedCapacityList<String> sysOutLines = new LimitedCapacityList<String>(String.class, 5);
public JavaProcess(List<String> commands, Process process) {
this.commands = commands;
this.process = process;
}
public Process getRawProcess() {
return this.process;
}
public List<String> getStartupCommands() {
return this.commands;
}
public String getStartupCommand() {
return this.process.toString();
}
public LimitedCapacityList<String> getSysOutLines() {
return this.sysOutLines;
}
public boolean isRunning() {
try {
this.process.exitValue();
} catch (IllegalThreadStateException ex) {
return true;
}
return false;
}
public int getExitCode() {
try {
return this.process.exitValue();
} catch (IllegalThreadStateException ex) {
ex.fillInStackTrace();
throw ex;
}
}
public String toString() {
return "JavaProcess[commands=" + this.commands + ", isRunning=" + isRunning() + "]";
}
public void stop() {
this.process.destroy();
}
}
@@ -0,0 +1,336 @@
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package org.jackhuang.hellominecraftlauncher;
import java.awt.Dimension;
import java.io.File;
import java.io.IOException;
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 java.util.logging.Level;
import java.util.logging.Logger;
import org.jackhuang.hellominecraftlauncher.apis.IPlugin;
import org.jackhuang.hellominecraftlauncher.utilities.C;
import org.jackhuang.hellominecraftlauncher.apis.utils.OperatingSystems;
import org.jackhuang.hellominecraftlauncher.apis.utils.Utils;
import org.jackhuang.hellominecraftlauncher.plugin.PluginManager;
/**
*
* @author hyh
*/
public class Launcher {
public static boolean disactivedMods = false;
public static File gameDir = null;
public static boolean ver16 = false, notMove = false;
public static String name = null;
public static void print(String s) {
System.out.println(s);
}
private static File getLocation() {
return gameDir == null ? gameDir = Utils.getLocation() : gameDir;
}
public static void main(String[] args) {
try {
print("*** " + Main.makeTitle() + " ***");
Dimension dimension = null;
boolean fullscreen = false;
String[] inactiveExtMods = null;
String[] inactiveCoreMods = null;
String classPath = "";
String mainClass = "net.minecraft.client.Minecraft";
ArrayList<String> cmdList = new ArrayList<String>();
int width = 854;
int height = 480;
getLocation();
for (int n = 0; n < args.length; n++) {
String s = args[n];
if (s.startsWith("-cp=")) {
classPath = s.substring("-cp=".length());
print(" ClassPath: " + classPath);
} else if (s.startsWith("-windowSize=")) {
String o = s.substring("-windowSize=".length());
dimension = Utils.parseDimension(o);
print(" WindowSize: " + (String) o);
if (dimension == null) {
continue;
}
width = dimension.width;
height = dimension.height;
} else if (s.equals("-windowFullscreen")) {
fullscreen = true;
print(" Fullscreen: " + true);
} else if (s.startsWith("-inactiveExtMods=")) {
s = s.substring("-inactiveExtMods=".length());
inactiveExtMods = Utils.tokenize(s, ";");
print(" InactiveExtMods: " + s);
} else if (s.startsWith("-inactiveCoreMods=")) {
s = s.substring("-inactiveCoreMods=".length());
inactiveCoreMods = Utils.tokenize(s, ";");
print(" InactiveCoreMods: " + s);
} else if (s.startsWith("-mainClass=")) {
mainClass = s.substring("-mainClass=".length());
print(" MainClass: " + mainClass);
} else if (s.equals("-ver16")) {
ver16 = true;
print(" Type: 1.6");
} else if (s.equals("-notMove")) {
notMove = true;
print(" Do not move mods: true");
} else if (s.startsWith("-name=")) {
name = s.substring("-name=".length());
print(" Name: " + name);
} else if (s.startsWith("-gameDir=")) {
gameDir = new File(s.substring("-gameDir=".length()));
print(" GameDir: " + gameDir.getPath());
} else {
cmdList.add(s);
}
}
if (fullscreen
? cmdList.add("--fullscreen")
: (width > 0) && (height > 0)) {
cmdList.add("--width=" + width);
cmdList.add("--height=" + height);
}
String[] cmds = (String[]) cmdList.toArray(new String[cmdList.size()]);
if (classPath == null) {
print("Invalid launcher classpath: " + classPath);
return;
}
String[] tokenized = Utils.tokenize(classPath, File.pathSeparator);
int len = tokenized.length;
File[] files = new File[len];
URL[] urls = new URL[len];
for (int j = 0; j < len; j++) {
files[j] = new File(tokenized[j]);
urls[j] = new File(tokenized[j]).toURI().toURL();
}
URLClassLoader loader = new URLClassLoader(urls);
Class minecraft = loader.loadClass(mainClass);
Method minecraftMain = minecraft.getMethod("main", new Class[]{String[].class});
moveMods();
moveModDir();
disactiveMods(inactiveExtMods, inactiveCoreMods);
addShutdownHook();
System.out.println("Invoking minecraft main()");
minecraftMain.invoke(null, new Object[]{cmds});
addForgeModLoaderHandler();
print("*** Main class main() finished ***");
} catch (Throwable throwable) {
throwable.printStackTrace();
}
}
private static void disactiveMods(String[] inactiveExtMods, String[] inactiveCoreMods) {
disactiveModsByType(inactiveExtMods, "mods");
disactiveModsByType(inactiveCoreMods, "coremods");
disactivedMods = true;
}
private static void addShutdownHook() {
ShutdownHook hook = new ShutdownHook();
Thread thread = new Thread(hook);
Runtime.getRuntime().addShutdownHook(thread);
}
private static void addForgeModLoaderHandler() {
MinecraftHandler handler = new MinecraftHandler();
Logger localLogger = Logger.getLogger("ForgeModLoader");
localLogger.addHandler(handler);
}
private static void disactiveModsByType(String[] paramArrayOfString, String paramString) {
restoreModsByType(paramString);
print("Disable inactive mods: " + paramString);
if ((paramArrayOfString == null) || (paramArrayOfString.length <= 0)) {
return;
}
List<String> al = Arrays.asList(paramArrayOfString);
File[] files = new File(getLocation(), paramString).listFiles();
if (files == null) {
print(" No mods: " + paramString);
return;
}
for (int i = 0; i < files.length; i++) {
File file = files[i];
if (!file.isDirectory()) {
String name = file.getName();
if ((!al.contains(name))
|| ((!name.toLowerCase().endsWith(".zip")) && (!name.toLowerCase().endsWith(".jar")))) {
continue;
}
String newName = name + "x";
File newFile = new File(file.getParentFile(), newName);
if (newFile.exists()) {
newFile.delete();
}
if (file.renameTo(newFile)) {
print(" Disabled: " + name + ", new name: " + newFile.getName());
} else {
print(" Can not disable: " + name);
}
}
}
}
private static void restoreModsByType(String paramString) {
print("Restoring disabled mods: " + paramString);
File[] files = new File(getLocation(), paramString).listFiles();
if (files == null) {
return;
}
for (int i = 0; i < files.length; i++) {
File file = files[i];
if (file.isDirectory()) {
continue;
}
String name = file.getName();
String lowName = name.toLowerCase();
if ((!lowName.endsWith(".zipx")) && (!lowName.endsWith(".jarx"))) {
continue;
}
String newName = name.substring(0, name.length() - 1);
File newFile = new File(file.getParentFile(), newName);
if (newFile.exists()) {
file.delete();
} else {
if (!file.renameTo(newFile)) {
print("Can not rename: " + file.getName() + " to: " + newFile.getName() + " in: " + file.getParent());
}
}
}
}
static void restoreMods() {
if (disactivedMods) {
restoreModsByType("mods");
restoreModsByType("coremods");
disactivedMods = false;
}
}
static void moveMods() {
if(notMove) return;
String realpa = Utils.addSeparator(gameDir.getPath());
java.util.ResourceBundle bundle = C.I18N;
moveModsByType(realpa, name, "mods", bundle.getString("复制普通模组失败: "));
moveModsByType(realpa, name, "coremods", bundle.getString("复制核心模组失败: "));
moveModsByType(realpa, name, "config", bundle.getString("复制配置文件失败: "));
}
static void moveModsByType(String realpa, String name, String type, String error) {
if(notMove) return;
File file = new File(realpa + "versions" + File.separator + name + File.separator + type);
print("Moving mods: " + type);
if (file.exists()) {
File mf = new File(realpa + type);
print("Deleting folder:" + mf.getAbsolutePath());
Utils.deleteAll(mf);
try {
Utils.copyDirectiory(file, mf);
print("Copying folder:" + file.getAbsolutePath());
} catch (IOException e) {
print(error + e.getMessage());
}
} else {
print("Folder doesn't exist: " + file.getAbsolutePath());
}
}
static void moveBackMods() {
if(notMove) return;
String realpa = Utils.addSeparator(gameDir.getPath());
moveBackModsByType(realpa, "mods");
moveBackModsByType(realpa, "coremods");
moveBackModsByType(realpa, "config");
}
static void moveBackModsByType(String realpa, String type) {
if(notMove) return;
if (ver16) {
File fmods = new File(realpa + type);
if (fmods.exists()) {
try {
Utils.copyDirectiory(fmods,
new File(realpa + "versions" + File.separator
+ name + File.separator + type));
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
static void moveModDir() {
if(notMove) return;
String realpa = Utils.addSeparator(gameDir.getPath());
try {
print("Moving mod directory");
Utils.copyDirectiory(realpa + "versions" + File.separator + name + File.separator + "moddir",
realpa);
} catch (IOException ex) {
print("Failed to move mod directory");
Logger.getLogger(Launcher.class.getName()).log(Level.SEVERE, null, ex);
}
}
static void moveBackModDir() {
if(notMove) return;
String realpa = Utils.addSeparator(gameDir.getPath());
File file = new File(realpa + "versions" + File.separator + name + File.separator + "moddir");
if (file.exists()) {
try {
ArrayList<String> al = Utils.findAllDir(file);
for (String s : al) {
File fileto = new File(file, s);
fileto.delete();
File moddir = new File(realpa + s);
Utils.copyDirectiory(moddir, fileto);
}
al = Utils.findAllFile(file);
for (String s : al) {
File fileto = new File(file, s);
fileto.delete();
File moddir = new File(realpa + s);
Utils.copyFile(moddir, fileto);
}
} catch (IOException ex) {
print("Failed to move back mod directory");
Logger.getLogger(Launcher.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
}
@@ -0,0 +1,85 @@
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package org.jackhuang.hellominecraftlauncher;
import java.io.IOException;
import java.io.OutputStream;
/**
*
* @author hyh
*/
public final class LauncherOutputStream extends OutputStream {
private OutputStream a = null;
private OutputStream b = null;
private boolean c = true;
public LauncherOutputStream(OutputStream paramOutputStream1, OutputStream paramOutputStream2) {
this(paramOutputStream1, paramOutputStream2, true);
}
private LauncherOutputStream(OutputStream paramOutputStream1, OutputStream paramOutputStream2, boolean paramBoolean) {
this.a = paramOutputStream1;
this.b = paramOutputStream2;
this.c = paramBoolean;
}
public final void write(byte[] paramArrayOfByte, int paramInt1, int paramInt2) throws IOException {
if (this.a != null) {
this.a.write(paramArrayOfByte, paramInt1, paramInt2);
}
if (this.b != null) {
this.b.write(paramArrayOfByte, paramInt1, paramInt2);
}
if (this.c) {
flush();
}
}
public final void write(byte[] paramArrayOfByte) throws IOException {
if (this.a != null) {
this.a.write(paramArrayOfByte);
}
if (this.b != null) {
this.b.write(paramArrayOfByte);
}
if (this.c) {
flush();
}
}
public final void write(int paramInt) throws IOException {
if (this.a != null) {
this.a.write(paramInt);
}
if (this.b != null) {
this.b.write(paramInt);
}
if (this.c) {
flush();
}
}
public final void close() throws IOException {
flush();
if (this.a != null) {
this.a.close();
}
if (this.b != null) {
this.b.close();
}
}
public final void flush() throws IOException {
if (this.a != null) {
this.a.flush();
}
if (this.b != null) {
this.b.flush();
}
}
}
@@ -0,0 +1,27 @@
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package org.jackhuang.hellominecraftlauncher;
import java.io.OutputStream;
import java.io.PrintStream;
import java.lang.reflect.Array;
/**
*
* @author hyh
*/
public final class LauncherPrintStream extends PrintStream {
private ModLoaderHandler handler = new ModLoaderHandler();
public LauncherPrintStream(OutputStream outputStream) {
super(outputStream);
}
public final void println(String line) {
super.println(line);
this.handler.check(line);
}
}
@@ -0,0 +1,165 @@
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package org.jackhuang.hellominecraftlauncher;
import com.seaglasslookandfeel.SeaGlassLookAndFeel;
import java.awt.Font;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintStream;
import java.net.URLEncoder;
import java.security.GeneralSecurityException;
import java.security.cert.X509Certificate;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import javax.net.ssl.X509TrustManager;
import javax.swing.UIManager;
import org.jackhuang.hellominecraftlauncher.apis.PluginHandlerType;
import org.jackhuang.hellominecraftlauncher.apis.handlers.Login;
import org.jackhuang.hellominecraftlauncher.apis.utils.MonitorInfoBean;
import org.jackhuang.hellominecraftlauncher.apis.utils.MonitorServiceImpl;
import org.jackhuang.hellominecraftlauncher.apis.utils.Utils;
import org.jackhuang.hellominecraftlauncher.download.URLGet;
import org.jackhuang.hellominecraftlauncher.installers.forge.BaseLauncherProfile;
import org.jackhuang.hellominecraftlauncher.plugin.PluginManager;
import org.jackhuang.hellominecraftlauncher.utilities.SettingsManager;
import org.jackhuang.hellominecraftlauncher.views.MainWindow;
import org.jackhuang.metro.MetroLookAndFeel;
/**
*
* @author hyh
*/
public class Main {
// Create an anonymous class to trust all certificates.
// This is bad style, you should create a separate class.
private static X509TrustManager xtm = new X509TrustManager() {
@Override
public void checkClientTrusted(X509Certificate[] chain, String authType) {
}
@Override
public void checkServerTrusted(X509Certificate[] chain, String authType) {
//System.out.println("---cert: " + chain[0].toString() + ", 认证方式: " + authType);
}
@Override
public X509Certificate[] getAcceptedIssuers() {
return null;
}
};
// Create an class to trust all hosts
private static HostnameVerifier hnv = new HostnameVerifier() {
@Override
public boolean verify(String hostname, SSLSession session) {
//System.out.println("hostname:111111111111111111111 " + hostname);
return true;
}
};
static {
// 初始化TLS协议SSLContext
// TrustManager
SSLContext sslContext = null;
try {
sslContext = SSLContext.getInstance("TLS");
X509TrustManager[] xtmArray = new X509TrustManager[]{xtm};
sslContext.init(null, xtmArray, new java.security.SecureRandom());
} catch (GeneralSecurityException gse) {
//打印出一些错误信息和处理这个异常
}
//设置默认的SocketFactory和HostnameVerifier
//为javax.net.ssl.HttpsURLConnection
if (sslContext != null) {
HttpsURLConnection.setDefaultSSLSocketFactory(sslContext.getSocketFactory());
}
HttpsURLConnection.setDefaultHostnameVerifier(hnv);
}
public static String launcherName = "Hello Minecraft! Launcher";
public static int firstVer = 1, secondVer = 9, thirdVer = 4;
public static int minimumLauncherVersion = 13;
public static int pluginVersion = 1;
public static String makeVersion() {
return "" + firstVer + '.' + secondVer + '.' + thirdVer;
}
public static String makeTitle() {
return launcherName + ' ' + makeVersion();
}
public static void main(String[] args) {
try {
PrintStream localPrintStream = System.out;
File file = new File(Utils.addSeparator(Utils.currentDir()) + "hmcl.log");
FileOutputStream fos = new FileOutputStream(file, false);
LauncherOutputStream los = new LauncherOutputStream(localPrintStream, fos);
System.setOut(new LauncherPrintStream(los));
System.setErr(new LauncherPrintStream(los));
} catch (FileNotFoundException ex) {
Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
}
try {
//UIManager.setLookAndFeel(new SeaGlassLookAndFeel());
UIManager.setLookAndFeel(new MetroLookAndFeel());
UIManager.getLookAndFeelDefaults().put("defaultFont", new Font("微软雅黑", Font.PLAIN, 12));
} catch (Exception ex) {
java.util.logging.Logger.getLogger(MainWindow.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
}
//</editor-fold>
Runtime.getRuntime().addShutdownHook(new Thread() {
@Override
public void run() {
PluginManager.unloadPlugin();
}
});
PluginHandlerType.registerPluginHandlerType("LOGIN", Login.class);
SettingsManager.load();
try {
PluginManager.preparePlugins();
PluginManager.loadPlugin();
} catch (IOException ex) {
Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
}
BaseLauncherProfile.tryWriteProfile(SettingsManager.settings.publicSettings.gameDir);
Thread t = new Thread() {
@Override
public void run() {
long m = 0;
try {
MonitorInfoBean bean = new MonitorServiceImpl().getMonitorInfoBean();
m = bean.getTotalMemorySize() / 1024;
} catch (Exception ex) {
Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
}
String url = "http://hellominecraftlauncher.duapp.com/count.php?os=" + URLEncoder.encode(System.getProperty("os.name")) + "&mac=" + Utils.getLocalMAC() +
"&memory=" + m + "&ver=" + makeVersion();
URLGet.get(url);
}
};
t.start();
MainWindow.show(args);
}
}
@@ -0,0 +1,50 @@
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package org.jackhuang.hellominecraftlauncher;
import java.util.logging.Handler;
import java.util.logging.Level;
import java.util.logging.LogRecord;
/**
*
* @author hyh
*/
public class MinecraftHandler extends Handler {
private boolean restore;
MinecraftHandler() {
restore = false;
}
@Override
public final void publish(LogRecord logrecord) {
if (restore) {
return;
}
String s = logrecord.getMessage();
if (s == null) {
return;
}
if (logrecord.getLevel().intValue() < Level.INFO.intValue()) {
return;
}
if (s.startsWith("Forge Mod Loader has successfully loaded") && s.endsWith("mods")) {
restore = true;
}
if (restore) {
Launcher.restoreMods();
}
}
@Override
public final void close() {
}
@Override
public final void flush() {
}
}
@@ -0,0 +1,39 @@
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package org.jackhuang.hellominecraftlauncher;
import java.io.File;
import java.net.URLClassLoader;
/**
*
* @author hyh
*/
public class ModLoaderHandler {
private boolean ended = false;
public void check(String line) {
if (this.ended) {
return;
}
if (line == null) {
return;
}
if ((!line.equals("Done.")
&& (!line.startsWith("Starting up SoundSystem"))
&& (!line.startsWith("Loading: net.java.games.input."))
&& (!line.startsWith("Found animation info for:"))
? 0 : 1) != 0) {
this.ended = true;
Launcher.restoreMods();
}
}
ModLoaderHandler() {
super();
ended = false;
}
}
@@ -0,0 +1,18 @@
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package org.jackhuang.hellominecraftlauncher;
/**
*
* @author jack
*/
public class Pair<K,T> {
public K key;
public T value;
public Pair(K key, T value) {
this.key = key;
this.value = value;
}
}
@@ -0,0 +1,30 @@
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package org.jackhuang.hellominecraftlauncher;
import org.jackhuang.hellominecraftlauncher.apis.IPlugin;
import org.jackhuang.hellominecraftlauncher.plugin.PluginManager;
/**
*
* @author hyh
*/
public final class ShutdownHook implements Runnable {
@Override
public final void run() {
Launcher.restoreMods();
Launcher.moveBackMods();
Launcher.moveBackModDir();
try {
for(IPlugin p : PluginManager.plugins) {
p.minecraftStopped();
}
} catch(Throwable t) {
}
}
}
@@ -0,0 +1,37 @@
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package org.jackhuang.hellominecraftlauncher.installers;
import java.io.File;
import java.util.ArrayList;
import org.jackhuang.hellominecraftlauncher.apis.utils.Utils;
import org.jackhuang.hellominecraftlauncher.apis.utils.Compressor;
/**
*
* @author hyh
*/
public class PackMinecraftInstaller {
String dest;
ArrayList<String> src;
public PackMinecraftInstaller(ArrayList<String> src, String dest) {
this.dest = dest;
this.src = src;
}
public void install() {
String path = Utils.addSeparator(Utils.currentDir())
+ "HMCL-MERGE-TEMP" + File.separator;
File file = new File(path);
file.mkdirs();
for (int i = 0; i < src.size(); i++) {
Compressor.unzip(src.get(i), path);
}
Compressor.zip(path, dest);
Utils.deleteAll(file);
}
}
@@ -0,0 +1,21 @@
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package org.jackhuang.hellominecraftlauncher.installers.forge;
import java.io.File;
import org.jackhuang.hellominecraftlauncher.apis.utils.Utils;
/**
*
* @author hyh
*/
public class BaseLauncherProfile {
public static String profile = "{\"selectedProfile\": \"(Default)\",\"profiles\": {\"(Default)\": {\"name\": \"(Default)\"}},\"clientToken\": \"88888888-8888-8888-8888-888888888888\"}";
public static void tryWriteProfile(String gameDir) {
File file = new File(Utils.addSeparator(gameDir) + "launcher_profiles.json");
if(!file.exists())
Utils.writeToFile(file, profile);
}
}
@@ -0,0 +1,185 @@
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package org.jackhuang.hellominecraftlauncher.installers.forge;
import com.google.gson.Gson;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.jackhuang.hellominecraftlauncher.apis.DoneListener;
import org.jackhuang.hellominecraftlauncher.download.URLGet;
import org.jackhuang.hellominecraftlauncher.utilities.C;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
/**
*
* @author hyh
*/
public class ForgeFormatThread extends Thread {
DoneListener<List<ForgeVersion>, Object> lis;
int type;
public ForgeFormatThread(DoneListener<List<ForgeVersion>, Object> lis, int type) {
this.lis = lis;
this.type = type;
}
public static List<ForgeVersion> formatNew() {
ArrayList<ForgeVersion> al = new ArrayList<ForgeVersion>();
try {
Document doc = Jsoup.connect("http://files.minecraftforge.net/").get();
Elements allbuilds = doc.getElementsByClass("builds");
Elements tables = new Elements();
for(Element build : allbuilds)
tables.addAll(build.getElementsByTag("table"));
Elements allforge = new Elements();
for(Element table : tables)
allforge.addAll(table.getElementsByTag("tr"));
tables = null;
for(Element e : allforge) {
Elements tds = e.getElementsByTag("td");
if(tds.isEmpty()) continue;
ForgeVersion v = new ForgeVersion();
v.ver = tds.get(0).text();
v.mcver = tds.get(1).text();
v.releasetime = tds.get(2).text();
v.installer = new String[2];
v.universal = new String[2];
v.javadoc = new String[2];
v.src = new String[2];
v.userdev = new String[2];
Elements a = tds.get(3).getElementsByTag("a");
String prev = null;
for(Element e2 : a) {
String href = e2.attributes().get("href").toLowerCase();
if(e2.text().toLowerCase().indexOf("changelog") != -1) {
v.changelog = href;
} else if(prev != null) {
int index;
if(href.indexOf("adf.ly") != -1) index = 0;
else index = 1;
if(prev.toLowerCase().indexOf("installer") != -1) {
v.installer[index] = href;
} else
if(prev.toLowerCase().indexOf("universal") != -1) {
v.universal[index] = href;
} else
if(prev.toLowerCase().indexOf("javadoc") != -1) {
v.javadoc[index] = href;
} else
if(prev.toLowerCase().indexOf("src") != -1) {
v.src[index] = href;
} else
if(prev.toLowerCase().indexOf("userdev") != -1) {
v.userdev[index] = href;
}
}
prev = e2.text();
}
al.add(v);
}
} catch (Exception ex) {
Logger.getLogger(ForgeFormatThread.class.getName()).log(Level.SEVERE, null, ex);
ForgeVersion v = new ForgeVersion();
v.ver = "获取失败";
al.add(v);
}
return al;
}
public static List<ForgeVersion> formatLegacy() {
ArrayList<ForgeVersion> al = new ArrayList<ForgeVersion>();
try {
Document doc = Jsoup.connect("http://files.minecraftforge.net/minecraftforge/index_legacy.html").get();
Element allbuilds = doc.getElementById("all_builds");
Elements mainTable = allbuilds.getElementsByTag("table");
Element table = mainTable.first();
Elements allforge = table.getElementsByTag("tr");
for(Element e : allforge) {
Elements tds = e.getElementsByTag("td");
if(tds.isEmpty()) continue;
ForgeVersion v = new ForgeVersion();
v.ver = tds.get(0).text();
v.mcver = tds.get(1).text();
v.releasetime = tds.get(2).text();
v.installer = new String[2];
v.universal = new String[2];
v.javadoc = new String[2];
Elements a = tds.get(3).getElementsByTag("a");
String prev = null;
for(Element e2 : a) {
String href = e2.attributes().get("href").toLowerCase();
if(e2.text().toLowerCase().indexOf("changelog") != -1) {
v.changelog = href;
} else if(prev != null) {
int index;
if(href.indexOf("adf.ly") != -1) index = 0;
else index = 1;
if(prev.toLowerCase().indexOf("installer") != -1) {
v.installer[index] = href;
} else
if(prev.toLowerCase().indexOf("universal") != -1) {
v.universal[index] = href;
} else
if(prev.toLowerCase().indexOf("javadoc") != -1) {
v.javadoc[index] = href;
} else
if(prev.toLowerCase().indexOf("src") != -1) {
v.src[index] = href;
}
}
prev = e2.text();
}
al.add(v);
}
} catch (Exception ex) {
//Logger.getLogger(ForgeFormatThread.class.getName()).log(Level.SEVERE, null, ex);
ForgeVersion v = new ForgeVersion();
v.ver = "获取失败";
al.add(v);
}
return al;
}
public static ForgeVersion[] formatBMCL(String url) {
String s = URLGet.get(url);
return new Gson().fromJson(s, ForgeVersion[].class);
}
@Override
public void run() {
List<ForgeVersion> al = null;
switch(type) {
case 0:
al = formatNew();
al.addAll(formatLegacy());
break;
case 1:
al = new ArrayList<ForgeVersion>();
for(ForgeVersion fv : formatBMCL(C.URL_FORGE_BMCL_NEW)) {
al.add(fv);
}
for(ForgeVersion fv : formatBMCL(C.URL_FORGE_BMCL_LEGACY)) {
al.add(fv);
}
break;
}
if(lis != null)
lis.onDone(al, null);
}
}
@@ -0,0 +1,23 @@
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package org.jackhuang.hellominecraftlauncher.installers.forge;
import java.util.ArrayList;
import org.jackhuang.hellominecraftlauncher.installers.PackMinecraftInstaller;
/**
*
* @author hyh
*/
public class ForgeOldInstaller {
public static void install(String destMinecraftJar, String srcMinecraftJar, String forgeUniversal) {
ArrayList<String> al = new ArrayList<String>();
al.add(srcMinecraftJar);
al.add(forgeUniversal);
new PackMinecraftInstaller(al, destMinecraftJar).install();
}
}
@@ -0,0 +1,15 @@
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package org.jackhuang.hellominecraftlauncher.installers.forge;
/**
*
* @author hyh
*/
public class ForgeVersion {
public String vername, ver, mcver, releasetime, changelog;
public String[] installer, javadoc, src, universal, userdev;
public int typeint;
}
@@ -0,0 +1,69 @@
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package org.jackhuang.hellominecraftlauncher.installers.optifine;
import java.net.URLEncoder;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.jackhuang.hellominecraftlauncher.apis.DoneListener;
import org.jackhuang.hellominecraftlauncher.download.URLGet;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
/**
*
* @author hyh
*/
public class OptifineFormatDownloadThread extends Thread {
DoneListener<String, Object> lis;
OptifineVersion source;
int type;
public OptifineFormatDownloadThread(DoneListener<String, Object> lis, OptifineVersion source, int type) {
this.lis = lis;
this.type = type;
this.source = source;
}
public static String format(String source) {
String url;
try {
Document doc = Jsoup.connect(source).get();
Element download = doc.getElementById("Download");
Element a = download.getElementsByTag("a").first();
url = "http://optifine.net/" + a.attributes().get("href");
} catch (Exception ex) {
Logger.getLogger(OptifineFormatThread.class.getName()).log(Level.SEVERE, null, ex);
OptifineVersion v = new OptifineVersion();
url = null;
}
return url;
}
public static String format_bmcl(String source) {
String url = "http://bmclapi.bangbang93.com/optifine/" + URLEncoder.encode(source);
return URLGet.get(url);
}
@Override
public void run() {
String url = null;
switch(type) {
case 0:
url = format(source.dl);
break;
case 1:
url = format_bmcl(source.ver);
break;
}
if(lis != null)
lis.onDone(url, null);
}
}
@@ -0,0 +1,98 @@
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package org.jackhuang.hellominecraftlauncher.installers.optifine;
import com.google.gson.Gson;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import org.jackhuang.hellominecraftlauncher.apis.DoneListener;
import org.jackhuang.hellominecraftlauncher.download.URLGet;
import org.jackhuang.hellominecraftlauncher.utilities.C;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
/**
*
* @author hyh
*/
public class OptifineFormatThread extends Thread {
DoneListener<List<OptifineVersion>, Object> lis;
int type;
public OptifineFormatThread(DoneListener<List<OptifineVersion>, Object> lis, int type) {
this.lis = lis;
this.type = type;
}
public static List<OptifineVersion> format(String source) {
List<OptifineVersion> al = new ArrayList<OptifineVersion>();
try {
Document doc = Jsoup.connect(source).get();
Elements downloads = doc.getElementsByClass("downloads");
Element table = downloads.first();
Elements tds = table.getElementsByTag("td");
Element td = tds.first();
Elements allopt = td.children();
String lasth2 = "", lasth3 = "";
for(int i = 0; i < allopt.size(); i++) {
Element e = allopt.get(i);
String tagName = e.tagName().toLowerCase();
if(tagName.indexOf("h3") != -1) {
lasth3 = e.text();
String[] s = lasth3.split(" ");
lasth3 = s[s.length - 1];
} else if(tagName.indexOf("h2") != -1) {
lasth2 = e.text().split(" ")[1];
} else
if(tagName.indexOf("table") != -1) {
Elements downloadLines = e.getElementsByTag("tr");
for(Element downloadLine : downloadLines) {
OptifineVersion v = new OptifineVersion();
v.type = lasth3;
String[] ver = downloadLine.child(0).text().split(" ");
if(ver.length < 1) continue;
v.ver = ver[ver.length - 1];
v.mcver = lasth2;
Element mirror = downloadLine.child(2).child(0);
v.dl = mirror.attributes().get("href");
v.date = downloadLine.child(3).text();
al.add(v);
}
}
}
} catch (Exception ex) {
System.err.println(ex.getMessage());
//Logger.getLogger(OptifineFormatThread.class.getName()).log(Level.SEVERE, null, ex);
OptifineVersion v = new OptifineVersion();
v.ver = "获取失败";
al.add(v);
}
return al;
}
public static List<OptifineVersion> format_bmcl(String source) {
Gson gson = new Gson();
return Arrays.asList(gson.fromJson(URLGet.get(source), OptifineVersion[].class));
}
@Override
public void run() {
List<OptifineVersion> al;
if(type == 0) {
al = format(C.URL_OPTIFINE[0]);
} else {
al = format_bmcl(C.URL_OPTIFINE[1]);
}
if(lis != null)
lis.onDone(al, null);
}
}
@@ -0,0 +1,13 @@
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package org.jackhuang.hellominecraftlauncher.installers.optifine;
/**
*
* @author hyh
*/
public class OptifineVersion {
public String dl, ver, mcver, date, type;
}
@@ -0,0 +1,153 @@
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package org.jackhuang.hellominecraftlauncher.loaders;
import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import org.jackhuang.hellominecraftlauncher.apis.handlers.LoginResult;
import org.jackhuang.hellominecraftlauncher.apis.utils.OperatingSystems;
import org.jackhuang.hellominecraftlauncher.apis.utils.Utils;
import org.jackhuang.hellominecraftlauncher.settings.Version;
import org.jackhuang.hellominecraftlauncher.utilities.SettingsManager;
/**
*
* @author hyh
*/
public abstract class IMinecraftLoader {
protected String minecraftJar;
protected Version v;
protected LoginResult lr;
public IMinecraftLoader(Version pub, Version ver, LoginResult lr, String minecraftJar) {
this.lr = lr;
this.minecraftJar = minecraftJar;
v = new Version(ver);
if(Utils.isEmpty(ver.gameDir)) v.gameDir = Utils.addSeparator(pub.gameDir);
if(Utils.isEmpty(ver.gameAssets)) v.gameAssets = pub.gameAssets;
if(Utils.isEmpty(v.gameAssets)) v.gameAssets = v.gameDir + "assets";
if(Utils.isEmpty(ver.gameLibraries)) v.gameLibraries = pub.gameLibraries;
if(Utils.isEmpty(ver.height)) v.height = pub.height;
if(Utils.isEmpty(ver.javaArgs)) v.javaArgs = pub.javaArgs;
if(Utils.isEmpty(ver.javaDir)) v.javaDir = pub.javaDir;
if(Utils.isEmpty(ver.mainClass)) v.mainClass = pub.mainClass;
if(Utils.isEmpty(ver.maxMemory)) v.maxMemory = pub.maxMemory;
if(Utils.isEmpty(ver.name)) v.name = pub.name;
if(Utils.isEmpty(ver.width)) v.width = pub.width;
if(Utils.isEmpty(ver.minecraftArguments)) v.minecraftArguments = pub.minecraftArguments;
}
public List<String> makeLaunchingCommand() {
System.out.println("*** Making Minecraft Launching Command ***");
ArrayList<String> res = new ArrayList<String>();
String java;
if(!Utils.isEmpty(v.javaDir.trim()))
{
if(Utils.os() == OperatingSystems.WINDOWS) {
File file = new File(Utils.addSeparator(v.javaDir) + "javaw.exe");
if(file.exists() && file.isFile())
java = "javaw.exe";
else
java = "java.exe";
} else {
java = "java";
}
java = Utils.addSeparator(v.javaDir) + java;
}
else
java = Utils.getJavaDir();
System.out.println("Java path: " + java);
res.add(java);
if(!Utils.isEmpty(v.javaArgs.trim()))
{
System.out.println("Java args: " + v.javaArgs);
res.add(v.javaArgs);
}
res.add("-Xincgc");
if(!Utils.isEmpty(v.maxMemory))
{
System.out.println("Memory: " + v.maxMemory);
res.add("-Xmx" + v.maxMemory + "m");
}
makeJavaLibraryPath(res);
res.add("-Dfml.ignoreInvalidMinecraftCertificates=true");
res.add("-Dfml.ignorePatchDiscrepancies=true");
res.add("-Dsun.java2d.noddraw=true");
res.add("-Dsun.java2d.pmoffscreen=false");
res.add("-Dsun.java2d.d3d=false");
res.add("-Dsun.java2d.opengl=false");
if(Utils.os() != OperatingSystems.WINDOWS)
{
String base = new File(v.gameDir).getParent();
System.out.println("Base folder: " + base);
res.add("-Duser.home=" + base);
}
res.add("-cp");
res.add(Utils.parseParams("", Utils.getURL(), File.pathSeparator));
res.add("org.jackhuang.hellominecraftlauncher.Launcher");
makeSelf(res);
if(!Utils.isEmpty(v.height) && !Utils.isEmpty(v.width))
{
res.add("-windowSize=" + v.width + "x" + v.height);
}
if(v.fullscreen)
res.add("-windowFullscreen");
if(v.inactiveCoreMods != null && !v.inactiveCoreMods.isEmpty()) {
String s = "-inactiveCoreMods=" + Utils.parseParams(
"",
v.inactiveCoreMods.toArray(), File.pathSeparator
);
res.add(s);
}
if(v.inactiveExtMods != null && !v.inactiveExtMods.isEmpty()) {
String s = "-inactiveExtMods=" + Utils.parseParams(
"",
v.inactiveExtMods.toArray(), File.pathSeparator);
res.add(s);
}
if(!Utils.isEmpty(v.minecraftArguments))
{
String[] splitted2 = Utils.tokenize(v.minecraftArguments);
res.addAll(Arrays.asList(splitted2));
}
res.add("-gameDir=" + v.gameDir);
if(SettingsManager.settings.disableMoveMods)
res.add("-notMove");
return res;
}
protected abstract void makeJavaLibraryPath(List<String> list);
/**
* You must do these things:<br />
* 1 minecraft class path<br />
* 2 main class<br />
* 3 minecraft arguments<br />
* @param list the command list you shoud edit.
*/
protected abstract void makeSelf(List<String> list);
public Version getUserVersion()
{
return v;
}
}
@@ -0,0 +1,15 @@
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package org.jackhuang.hellominecraftlauncher.loaders;
/**
*
* @author hyh
*/
public class Latest {
public String snapshot, release;
}
@@ -0,0 +1,25 @@
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package org.jackhuang.hellominecraftlauncher.loaders;
import java.util.List;
/**
*
* @author hyh
*/
public class LaunchRequest {
public boolean windowMaximized;
public boolean windowFullscreen;
public boolean showLog;
public int width, height;
public String classPath;
public String[] inactiveExtMods, inactiveCoreMods;
public List<String> minecraftArguments;
public List<String> launchStrings;
}
@@ -0,0 +1,133 @@
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package org.jackhuang.hellominecraftlauncher.loaders;
import org.jackhuang.hellominecraftlauncher.apis.utils.Utils;
import org.jackhuang.hellominecraftlauncher.apis.version.MinecraftLibrary;
import org.jackhuang.hellominecraftlauncher.apis.version.MinecraftVersion;
import org.jackhuang.hellominecraftlauncher.settings.Version;
import java.io.File;
import java.util.List;
import org.jackhuang.hellominecraftlauncher.apis.handlers.LoginResult;
/**
*
* @author hyh
*/
public class MinecraftLoader extends IMinecraftLoader {
private MinecraftVersion version;
String text;
public MinecraftLoader(MinecraftVersion mvt, Version pub, Version ver, LoginResult lr, String minecraftJar)
{
super(pub, ver, lr, minecraftJar);
version = mvt;
for(int i = 0; i < version.libraries.size(); i++)
{
MinecraftLibrary l = version.libraries.get(i);
String str = l.name;
String[] s = str.split(":");
str = s[0];
str = str.replace('.', File.separatorChar);
if(l.natives == null)
str += File.separator + s[1] + File.separator + s[2] +
File.separator + s[1] + '-' + s[2] + ".jar";
else
{
str += File.separator + s[1] + File.separator + s[2] +
File.separator + s[1] + '-' + s[2] + '-';
str += l.getNative();
str += ".jar";
}
l.formatted = str;
version.libraries.set(i, l);
}
}
@Override
protected void makeJavaLibraryPath(List<String> res) {
String library = "-Djava.library.path=";
library += Utils.addSeparator(v.gameDir) + "versions" +
File.separator + getVersion().id + File.separator + getVersion().id +
"-natives";
res.add(library);
}
@Override
protected void makeSelf(List<String> res)
{
String realpa = Utils.addSeparator(v.gameDir);
String library = "-cp=";
String librariespath = realpa + "libraries" + File.separator;
if(!v.gameLibraries.equals("")) librariespath = v.gameLibraries;
if(v.firstLoadLibraries != null)
for(int i = 0; i < v.firstLoadLibraries.size(); i++)
if(v.firstLoadLibrariesIsActive == null || v.firstLoadLibrariesIsActive.get(i))
library += v.firstLoadLibraries.get(i) + File.pathSeparator;
for(int i = 0; i < getVersion().libraries.size(); i++)
{
MinecraftLibrary l = getVersion().libraries.get(i);
if(l.allow())
{
library += librariespath + l.formatted + File.pathSeparator;
}
}
library += minecraftJar + File.pathSeparator;
if(v.lastLoadLibraries != null)
for(int i = 0; i < v.lastLoadLibraries.size(); i++)
if(v.lastLoadLibrariesIsActive == null || v.lastLoadLibrariesIsActive.get(i))
library += v.lastLoadLibraries.get(i) + File.pathSeparator;
library = library.substring(0, library.length() - File.pathSeparator.length());
res.add(library);
String mainClass;
if(Utils.isEmpty(v.mainClass))
mainClass = getVersion().mainClass;
else
mainClass = v.mainClass;
System.out.println("Main class: " + mainClass);
res.add("-mainClass=" + mainClass);
String arg = getVersion().minecraftArguments;
String[] splitted = Utils.tokenize(arg);
for(String t : splitted) {
t = t.replace("${auth_player_name}", lr.username);
t = t.replace("${auth_session}", lr.session);
t = t.replace("${auth_uuid}", lr.userId);
t = t.replace("${version_name}", getVersion().id);
t = t.replace("${game_directory}", v.gameDir);
t = t.replace("${game_assets}", v.gameAssets);
t = t.replace("${assets_root}", v.gameAssets);
t = t.replace("${auth_access_token}", lr.accessToken);
t = t.replace("${user_type}", lr.userType);
if(getVersion().assets != null)
t = t.replace("${assets_index_name}", getVersion().assets);
t = t.replace("${user_properties}", lr.userProperties);
res.add(t);
}
if(res.indexOf("--gameDir") != -1 && res.indexOf("--workDir") != -1) {
res.add("--workDir");
res.add(v.gameDir);
}
res.add("-ver16");
res.add("-name=" + v.name);
}
/**
* @return the version
*/
public MinecraftVersion getVersion() {
return version;
}
/**
* @param version the version to set
*/
public void setVersion(MinecraftVersion version) {
this.version = version;
}
}
@@ -0,0 +1,67 @@
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package org.jackhuang.hellominecraftlauncher.loaders;
import java.io.File;
import java.io.UnsupportedEncodingException;
import java.net.URL;
import java.net.URLClassLoader;
import java.net.URLDecoder;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.jackhuang.hellominecraftlauncher.apis.handlers.LoginResult;
import org.jackhuang.hellominecraftlauncher.apis.utils.Utils;
import org.jackhuang.hellominecraftlauncher.settings.Version;
/**
*
* @author hyh
*/
public class MinecraftOldLoader extends IMinecraftLoader {
public MinecraftOldLoader(Version pub, Version ver, LoginResult lr, String minecraftJar)
{
super(pub, ver, lr, minecraftJar);
}
@Override
protected void makeJavaLibraryPath(List<String> res) {
res.add("-Djava.library.path=" + v.gameDir + "bin" + File.separator + "natives");
}
@Override
protected void makeSelf(List<String> res)
{
String library = "-cp=";
if(v.firstLoadLibraries != null)
for(int i = 0; i < v.firstLoadLibraries.size(); i++)
if(v.firstLoadLibrariesIsActive == null || v.firstLoadLibrariesIsActive.get(i))
library += v.firstLoadLibraries.get(i) + File.pathSeparator;
library += v.gameDir + "bin" + File.separator + "jinput.jar" + File.pathSeparator +
v.gameDir + "bin" + File.separator + "lwjgl.jar" + File.pathSeparator +
v.gameDir + "bin" + File.separator + "lwjgl_util.jar" + File.pathSeparator;
library += minecraftJar + File.separator;
if(v.lastLoadLibraries != null)
for(int i = 0; i < v.lastLoadLibraries.size(); i++)
if(v.lastLoadLibrariesIsActive == null || v.lastLoadLibrariesIsActive.get(i))
library += v.lastLoadLibraries.get(i) + File.pathSeparator;
library = library.substring(0, library.length() - File.pathSeparator.length());
res.add(library);
String mainClass;
if(Utils.isEmpty(v.mainClass))
mainClass = "net.minecraft.client.Minecraft";
else
mainClass = v.mainClass;
System.out.println("Main class: " + mainClass);
res.add("-mainClass=" + mainClass);
res.add(lr.username);
res.add(lr.session);
res.add("--workDir");
res.add(v.gameDir);
}
}
@@ -0,0 +1,19 @@
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package org.jackhuang.hellominecraftlauncher.loaders;
import org.jackhuang.hellominecraftlauncher.apis.version.MinecraftVersion;
import java.util.ArrayList;
/**
*
* @author hyh
*/
public class MinecraftVersions {
public ArrayList<MinecraftVersion> versions;
public Latest latest;
}
@@ -0,0 +1,33 @@
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package org.jackhuang.hellominecraftlauncher.loaders;
import com.google.gson.Gson;
/**
*
* @author hyh
*/
public class MinecraftVersionsLoader {
String JSON;
Gson gson;
private MinecraftVersions versions;
public MinecraftVersionsLoader(String j) {
gson = new Gson();
JSON = j;
versions = gson.fromJson(JSON, MinecraftVersions.class);
}
/**
* @return the versions
*/
public MinecraftVersions getVersions() {
return versions;
}
}
@@ -0,0 +1,13 @@
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package org.jackhuang.hellominecraftlauncher.loaders.packages;
/**
*
* @author hyh
*/
public class Packages {
public String author, mcversion, version, name, type;
}
@@ -0,0 +1,14 @@
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package org.jackhuang.hellominecraftlauncher.loaders.serverlist;
/**
*
* @author hyh
*/
public class ServerInfo {
public String name, address;
public boolean isHide;
}
@@ -0,0 +1,151 @@
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package org.jackhuang.hellominecraftlauncher.loaders.serverlist;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.logging.Level;
import java.util.logging.Logger;
import sun.misc.BASE64Decoder;
/**
*
* @author hyh
*/
public class ServerList {
public static String address = "AmlwAA==";
public static String header = "CgAACQAHc2VydmVycwoAAA==";
public static String hideAddress = "AAtoaWRlQWRkcmVzcw==";
public static String name = "AARuYW1lAA==";
public ArrayList<ServerInfo> list;
public File file;
public ServerList(File file) {
this.file = file;
if(!file.exists())
try {
file.getParentFile().mkdirs();
file.createNewFile();
} catch (IOException ex) {
Logger.getLogger(ServerList.class.getName()).log(Level.SEVERE, null, ex);
}
this.list = new ArrayList<ServerInfo>();
try {
FileInputStream stream = new FileInputStream(file);
byte[] header = new byte[0x13];
stream.read(header, 0, header.length);
if(stream.available() < 5) {
stream.close();
return;
}
while(stream.available() > 0) {
byte[] hideAddress = new byte[13];
stream.read(hideAddress, 0, hideAddress.length);
boolean isHide = stream.read() == 1 ? true : false;
byte[] name = new byte[9];
stream.read(name, 0, name.length);
ArrayList<Byte> nameList = new ArrayList<Byte>(20);
byte ch = (byte) stream.read();
while(ch != 0) {
if(ch == -1) break;
nameList.add(ch);
ch = (byte) stream.read();
}
if(ch == -1) break;
byte[] names = new byte[nameList.size()];
for(int i = 0; i < nameList.size(); i++) {
names[i] = nameList.get(i);
}
String Name = new String(names);
byte[] address = new byte[5];
stream.read(address, 0, address.length);
ArrayList<Byte> AddRess = new ArrayList<Byte>(20);
ch = (byte) stream.read();
while(ch != 0) {
if(ch == -1) break;
AddRess.add(ch);
ch = (byte) stream.read();
}
if(ch == -1) break;
byte[] addresses = new byte[AddRess.size()];
for(int i = 0; i < AddRess.size(); i++) {
addresses[i] = AddRess.get(i);
}
String Address = new String(addresses);
ServerInfo info = new ServerInfo();
info.address = Address;
info.isHide = isHide;
info.name = Name;
list.add(info);
if(stream.read() == 0)
break;
}
} catch (FileNotFoundException ex) {
Logger.getLogger(ServerList.class.getName()).log(Level.SEVERE, null, ex);
} catch (IOException ex) {
Logger.getLogger(ServerList.class.getName()).log(Level.SEVERE, null, ex);
}
}
public void write() {
try {
FileOutputStream stream = new FileOutputStream(file);
BASE64Decoder decoder = new BASE64Decoder();
stream.write(decoder.decodeBuffer(header));
int p = 0;
stream.write(0);
stream.write(list.size());
stream.write(1);
for(ServerInfo info : list) {
p++;
stream.write(decoder.decodeBuffer(hideAddress));
if(info.isHide)
stream.write(1);
else
stream.write(0);
stream.write(8);
stream.write(decoder.decodeBuffer(name));
stream.write(info.name.length());
stream.write(info.name.getBytes());
stream.write(new byte[]{8, 0});
stream.write(decoder.decodeBuffer(address));
stream.write(info.address.length());
stream.write(info.address.getBytes());
stream.write(0);
if(p != list.size())
stream.write(1);
else
stream.write(0);
}
stream.close();
} catch (FileNotFoundException ex) {
Logger.getLogger(ServerList.class.getName()).log(Level.SEVERE, null, ex);
} catch (IOException ex) {
Logger.getLogger(ServerList.class.getName()).log(Level.SEVERE, null, ex);
}
}
public static void writeEmptyFile(File path) {
try {
FileOutputStream serverdat = new FileOutputStream(path);
BASE64Decoder decoder = new BASE64Decoder();
byte[] writes = decoder.decodeBuffer(header);
serverdat.write(writes, 0, writes.length);
serverdat.write(0);
serverdat.close();
} catch (IOException ex) {
Logger.getLogger(ServerList.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
@@ -0,0 +1,30 @@
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package org.jackhuang.hellominecraftlauncher.models;
/**
*
* @author hyh
*/
public class ControllerAction<T> {
/**
* -1 - NULL
* 1 - delete version<br />
* 2 - new version<br />
* 3 - copy version<br />
* 4 - import version<br />
* 5 - import folder<br />
* 6 - cannot find minecraft.jar<br />
* 7 - find the same name in the list<br />
*/
int action;
T content;
public ControllerAction(int action, T content) {
this.action = action;
this.content = content;
}
}
@@ -0,0 +1,54 @@
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package org.jackhuang.hellominecraftlauncher.models;
import org.jackhuang.hellominecraftlauncher.apis.version.MinecraftVersion;
import com.google.gson.Gson;
import java.io.File;
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.jackhuang.hellominecraftlauncher.apis.utils.Utils;
/**
*
* @author hyh
*/
public class VersionCopier {
public static boolean copy(String gameDir, String fromName, String toName) {
gameDir = Utils.addSeparator(gameDir);
File fromDir = new File(gameDir + fromName + File.separator);
if(!fromDir.exists()) return false;
File toDir = new File(gameDir + toName + File.separator);
toDir.mkdirs();
File fromMinecraftJar = new File(gameDir + fromName + File.separator + fromName + ".jar");
File toMinecraftJar = new File(gameDir + fromName + File.separator + toName + ".jar");
File fromMinecraftJson = new File(gameDir + fromName + File.separator + fromName + ".json");
File toMinecraftJson = new File(gameDir + fromName + File.separator + toName + ".json");
File fromMinecraftMods = new File(gameDir + fromName + File.separator + "mods" + File.separator);
File toMinecraftMods = new File(gameDir + fromName + File.separator + "mods" + File.separator);
File fromMinecraftCoreMods = new File(gameDir + fromName + File.separator + "coremods" + File.separator);
File toMinecraftCoreMods = new File(gameDir + fromName + File.separator + "coremods" + File.separator);
File fromMinecraftConfig = new File(gameDir + fromName + File.separator + "config" + File.separator);
File toMinecraftConfig = new File(gameDir + fromName + File.separator + "config" + File.separator);
try {
Utils.copyFile(fromMinecraftJar, toMinecraftJar);
String str = Utils.readToEnd(fromMinecraftJson);
Gson gson = new Gson();
MinecraftVersion v = gson.fromJson(str, MinecraftVersion.class);
v.id = toName;
Utils.writeToFile(toMinecraftJson, gson.toJson(v));
Utils.copyDirectiory(fromMinecraftMods, toMinecraftMods);
Utils.copyDirectiory(fromMinecraftCoreMods, toMinecraftCoreMods);
Utils.copyDirectiory(fromMinecraftConfig, toMinecraftConfig);
} catch (IOException ex) {
Logger.getLogger(VersionCopier.class.getName()).log(Level.SEVERE, null, ex);
return false;
}
return true;
}
}
@@ -0,0 +1,62 @@
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package org.jackhuang.hellominecraftlauncher.models;
import java.io.File;
import javax.swing.JFileChooser;
import javax.swing.JOptionPane;
import org.jackhuang.hellominecraftlauncher.apis.utils.Utils;
import org.jackhuang.hellominecraftlauncher.utilities.C;
import org.jackhuang.hellominecraftlauncher.utilities.MinecraftOldVersionIncluder;
import org.jackhuang.hellominecraftlauncher.utilities.SettingsManager;
/**
*
* @author hyh
*/
public class VersionManager {
/**
* 导入旧版本
* @param mcp
* @return Controller Action
*/
public ControllerAction<String> includeOldVersion() {
JFileChooser fc = new JFileChooser();
fc.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
fc.setDialogTitle(C.I18N.getString("选择MINECRAFT路径"));
fc.setMultiSelectionEnabled(false);
fc.showOpenDialog(null);
try {
String mcp = fc.getSelectedFile().getCanonicalPath();
if (mcp == null || mcp.trim().equals("")) {
return new ControllerAction<String>(-1, "");
}
File file = new File(mcp + File.separator + "bin" + File.separator + "minecraft.jar");
if (!file.exists()) {
//MessageBox.Show(C.I18N.getString("找不到MINECRAFT.JAR"));
return new ControllerAction<String>(6, "");
}
String name = JOptionPane.showInputDialog(C.I18N.getString("请输入该旧版本的名称"));
file = new File(Utils.addSeparator(SettingsManager.settings.publicSettings.gameDir)
+ "versions" + File.separator + name);
if (file.exists()) {
//MessageBox.Show(C.I18N.getString("找到同名的MINECRAFT版本,请换用另一个名称"));
return new ControllerAction<String>(7, "");
}
MinecraftOldVersionIncluder l = new MinecraftOldVersionIncluder(mcp, name);
l.include();
return new ControllerAction<String>(4, "");
} catch (Exception e) {
//MessageBox.Show(
// java.text.MessageFormat.format(
// C.I18N.getString("导入失败: {0}"), new Object[]{e.getMessage()}));
return new ControllerAction<String>(0, e.getMessage());
}
}
}
@@ -0,0 +1,155 @@
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package org.jackhuang.hellominecraftlauncher.plugin;
import org.jackhuang.hellominecraftlauncher.plugin.editpanels.SaveWorldPanel;
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.jackhuang.hellominecraftlauncher.apis.Configuration;
import org.jackhuang.hellominecraftlauncher.apis.IMinecraftEnvironment;
import org.jackhuang.hellominecraftlauncher.apis.IPlugin;
import org.jackhuang.hellominecraftlauncher.apis.Plugin;
import org.jackhuang.hellominecraftlauncher.apis.PluginHandlerType;
import org.jackhuang.hellominecraftlauncher.apis.events.HMCLPluginLoadEvent;
import org.jackhuang.hellominecraftlauncher.apis.events.HMCLPluginUnloadEvent;
import org.jackhuang.hellominecraftlauncher.apis.events.HMCLPluginVersionChangedEvent;
import org.jackhuang.hellominecraftlauncher.apis.handlers.IAssetsHandler;
import org.jackhuang.hellominecraftlauncher.apis.handlers.Login;
import org.jackhuang.hellominecraftlauncher.plugin.editpanels.AssetsPanel;
import org.jackhuang.hellominecraftlauncher.plugin.editpanels.InstallersPanel;
import org.jackhuang.hellominecraftlauncher.plugin.editpanels.ServerEditPanel;
import org.jackhuang.hellominecraftlauncher.plugin.editpanels.TexturepackEditPanel;
import org.jackhuang.hellominecraftlauncher.plugin.logins.LegacyLogin;
import org.jackhuang.hellominecraftlauncher.plugin.logins.LoginPluginSettings;
import org.jackhuang.hellominecraftlauncher.plugin.logins.MineLogin;
import org.jackhuang.hellominecraftlauncher.plugin.logins.OfflineLogin;
import org.jackhuang.hellominecraftlauncher.plugin.logins.SkinmeLogin;
import org.jackhuang.hellominecraftlauncher.plugin.logins.YggdrasilLogin;
import org.jackhuang.hellominecraftlauncher.plugin.mainpanels.GameDownloadPanel;
import org.jackhuang.hellominecraftlauncher.plugin.mainpanels.IntegrateDownloadPanel;
import org.jackhuang.hellominecraftlauncher.plugin.settings.AssetsMojangLoader;
import org.jackhuang.hellominecraftlauncher.plugin.settings.AssetsMojangOldLoader;
import org.jackhuang.hellominecraftlauncher.plugin.settings.AssetsZipHandler;
import org.jackhuang.hellominecraftlauncher.utilities.C;
/**
*
* @author hyh
*/
@Plugin(apiVer = 1, pluginVer = "1.9.4", pluginId = "hmcl", pluginName = "Hello Minecraft! Launcher",
authors = "huangyuhui", description = "Too many features.", requires = {})
public class HMCLPlugin extends IPlugin {
YggdrasilLogin yggdrasilLogin;
LegacyLogin legacyLogin;
OfflineLogin offlineLogin;
SkinmeLogin skinmeLogin;
MineLogin mineLogin;
Configuration<LoginPluginSettings> config;
public static IMinecraftEnvironment env;
//assets handlers
AssetsZipHandler assets17, assets174, assets173, assets16;
AssetsMojangLoader assetsMojang;
AssetsMojangLoader assetsBMCL;
AssetsMojangOldLoader assetsOldBMCL;
//Version edit panels
SaveWorldPanel saveWorldPanel;
ServerEditPanel serverEditPanel;
TexturepackEditPanel texturepackEditPanel;
InstallersPanel installersPanel;
AssetsPanel assetsPanel;
//Main panels
IntegrateDownloadPanel integrateDownloadPanel;
GameDownloadPanel gameDownloadPanel;
@Override
public void load(HMCLPluginLoadEvent event) {
PluginHandlerType.registerPluginHandlerType("ASSETS", IAssetsHandler.class);
PluginHandlerType.registerPluginHandlerType("LOGIN", Login.class);
String clientToken = event.getMinecraftEnvironment().clientToken();
PluginHandlerType login = PluginHandlerType.getType("LOGIN");
event.getPluginRegister().registerPluginHandler(login,
offlineLogin = new OfflineLogin(clientToken));
event.getPluginRegister().registerPluginHandler(login,
yggdrasilLogin = new YggdrasilLogin(clientToken));
event.getPluginRegister().registerPluginHandler(login,
legacyLogin = new LegacyLogin(clientToken));
event.getPluginRegister().registerPluginHandler(login,
skinmeLogin = new SkinmeLogin(clientToken));
event.getPluginRegister().registerPluginHandler(login,
mineLogin = new MineLogin(clientToken));
config = new Configuration<LoginPluginSettings>(event.getSuggestedConfigurationFile());
config.load(LoginPluginSettings.class);
if(config.get() != null) {
legacyLogin.onLoadSettings(config.get().legacy);
yggdrasilLogin.onLoadSettings(config.get().yggdrasil);
}
env = event.getMinecraftEnvironment();
assets174 = new AssetsZipHandler("1.7.4(googlecode)", "assets-175.zip", "http://hmcl.googlecode.com/svn/trunk/assets-175.zip");
assets173 = new AssetsZipHandler("1.7.3(googlecode)", "assets-174.zip", "http://hmcl.googlecode.com/svn/trunk/assets-174.zip");
assets17 = new AssetsZipHandler("1.7.2(googlecode)", "assets-173.zip", "http://hmcl.googlecode.com/svn/trunk/assets-173.zip");
assets16 = new AssetsZipHandler("1.6(googlecode)", "assets-164.zip", "http://hmcl.googlecode.com/svn/trunk/assets-164.zip");
assetsMojang = new AssetsMojangLoader(C.URL_ASSETS_MOJANG, "1.7.4(Mojang)");
assetsBMCL = new AssetsMojangLoader(C.URL_ASSETS_BMCL, "1.7.4(BMCL)");
assetsOldBMCL = new AssetsMojangOldLoader(C.URL_OLD_ASSETS_BMCL, "1.6(BMCL)");
PluginHandlerType assets = PluginHandlerType.getType("ASSETS");
event.getPluginRegister().registerPluginHandler(assets, assets174);
event.getPluginRegister().registerPluginHandler(assets, assets173);
event.getPluginRegister().registerPluginHandler(assets, assets17);
event.getPluginRegister().registerPluginHandler(assets, assets16);
event.getPluginRegister().registerPluginHandler(assets, assetsMojang);
event.getPluginRegister().registerPluginHandler(assets, assetsBMCL);
event.getPluginRegister().registerPluginHandler(assets, assetsOldBMCL);
saveWorldPanel = new SaveWorldPanel();
serverEditPanel = new ServerEditPanel();
texturepackEditPanel = new TexturepackEditPanel();
installersPanel = new InstallersPanel();
assetsPanel = new AssetsPanel();
assetsPanel.assetsType = config.get().assetsType;
assetsPanel.prepareAssets();
event.getUIRegister().addPanelToVersionEdit(saveWorldPanel);
event.getUIRegister().addPanelToVersionEdit(serverEditPanel);
event.getUIRegister().addPanelToVersionEdit(texturepackEditPanel);
event.getUIRegister().addPanelToVersionEdit(installersPanel);
event.getUIRegister().addPanelToVersionEdit(assetsPanel);
integrateDownloadPanel = new IntegrateDownloadPanel();
gameDownloadPanel = new GameDownloadPanel();
event.getUIRegister().addPanelToMain(gameDownloadPanel);
event.getUIRegister().addPanelToMain(integrateDownloadPanel);
}
@Override
public void unload(HMCLPluginUnloadEvent event) {
LoginPluginSettings s = new LoginPluginSettings();
s.legacy = legacyLogin.onSaveSettings();
s.yggdrasil = yggdrasilLogin.onSaveSettings();
s.assetsType = assetsPanel.assetsType;
config.set(s);
try {
config.save();
} catch (IOException ex) {
Logger.getLogger(HMCLPlugin.class.getName()).log(Level.SEVERE, null, ex);
}
}
@Override
public void versionChanged(HMCLPluginVersionChangedEvent event) {
saveWorldPanel.loadSaves();
serverEditPanel.loadServers();
texturepackEditPanel.loadPacks();
installersPanel.reloadForgeList();
installersPanel.reloadOptifineList();
}
}
@@ -0,0 +1,46 @@
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package org.jackhuang.hellominecraftlauncher.plugin;
import java.io.File;
import org.jackhuang.hellominecraftlauncher.apis.IMinecraftEnvironment;
import org.jackhuang.hellominecraftlauncher.apis.utils.MinecraftVersionRequest;
import org.jackhuang.hellominecraftlauncher.apis.utils.Utils;
import org.jackhuang.hellominecraftlauncher.utilities.SettingsManager;
import org.jackhuang.hellominecraftlauncher.settings.Version;
import org.jackhuang.hellominecraftlauncher.views.MainWindow;
/**
*
* @author hyh
*/
public class MinecraftEnvironment implements IMinecraftEnvironment {
@Override
public String clientToken() {
return SettingsManager.settings.clientToken;
}
@Override
public Version getVersion() {
return MainWindow.getInstance().getVersion();
}
@Override
public String getDefaultGameDir() {
return SettingsManager.settings.publicSettings.gameDir;
}
@Override
public MinecraftVersionRequest getMinecraftVersion() {
return Utils.minecraftVersion(new File(getVersion().getMinecraftJar()));
}
@Override
public int getSourceType() {
return SettingsManager.settings.downloadtype;
}
}
Loaded 100 of 873 files, more files were not shown because too many files have changed in this diff. Show more