2
0
mirror of https://github.com/HMCL-dev/HMCL.git synced 2025-04-24 18:50:52 +08:00

HMCL 2.3.2

This commit is contained in:
huanghongxun 2015-06-22 16:47:05 +08:00
parent 0693d12f6b
commit 0656227183
358 changed files with 35670 additions and 0 deletions
.gitignore.nb-gradle-properties
HMCL
build.gradleicon.ico
image
launch4j.xmlproguard.pro
src/main
icon.icns
java/org/jackhuang
hellominecraft/launcher
Launcher.javaMain.java
launch
utils
views
mojang/authlib

13
.gitignore vendored

@ -10,3 +10,16 @@
# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
hs_err_pid*
.gradle
.nb-gradle
*.map
*.bat
*.log
.mine*
HMCLAPI/build/
HMCL/build/
HMCSM/build/
MetroLookAndFeel/build/

46
.nb-gradle-properties Normal file

@ -0,0 +1,46 @@
<?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="no">launch4j</name>
</task-names>
<task-args/>
<task-jvm-args/>
</task>
<task>
<display-name>launch4jpack</display-name>
<non-blocking>no</non-blocking>
<task-names>
<name must-exist="no">launch4jpack</name>
</task-names>
<task-args/>
<task-jvm-args/>
</task>
<task>
<display-name>publish</display-name>
<non-blocking>no</non-blocking>
<task-names>
<name must-exist="no">clean</name>
<name must-exist="no">build</name>
<name must-exist="no">launch4j</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>
<property name="organization">huangyuhui</property>
</license-header>
</gradle-project-properties>

95
HMCL/build.gradle Normal file

@ -0,0 +1,95 @@
apply plugin: 'launch4j'
apply plugin: 'me.tatarka.retrolambda'
if (!hasProperty('mainClass')) {
ext.mainClass = 'org.jackhuang.hellominecraft.launcher.Main'
}
String mavenGroupId = 'HMCL'
String mavenVersion = '2.3.2'
String bundleName = "Hello Minecraft! Launcher"
group = mavenGroupId
version = mavenVersion
String mavenArtifactId = name
buildscript {
repositories {
mavenCentral();
dependencies {
classpath 'net.sf.proguard:proguard-gradle:4.10'
classpath 'edu.sc.seis.gradle:launch4j:1.0.6'
classpath 'me.tatarka:gradle-retrolambda:3.1.0'
}
}
}
configure(install.repositories.mavenInstaller) {
pom.project {
groupId = mavenGroupId
artifactId = mavenArtifactId
version = mavenVersion
}
}
dependencies {
compile project(":MetroLookAndFeel")
compile project(":HMCLAPI")
}
retrolambda {
javaVersion = JavaVersion.VERSION_1_7
}
jar {
jar.classifier = 'base'
from { configurations.compile.collect { it.isDirectory() ? it : zipTree(it) } }
manifest {
attributes 'Created-By' : 'Copyright(c) 2013-2014 huangyuhui.',
'Main-Class' : mainClass
}
}
task proguard(type: proguard.gradle.ProGuardTask, dependsOn: jar) {
ext {
def re = jar.classifier
injar = jar.archivePath
jar.classifier = ''
outjar = jar.archivePath
jar.classifier = re
}
injars injar
outjars outjar
printusage "shrinking_" + version + ".map"
printmapping "obfuscate_" + version + ".map"
configuration 'proguard.pro'
}
launch4j {
launch4jCmd = 'D:\\Develop\\Java\\Launch4j\\launch4j.exe'
supportUrl = 'http://www.mcbbs.net/thread-142335-1-1.html'
jreMinVersion = '1.6.0'
mainClassName = mainClass
icon = new File(project.buildDir, '../icon.ico').absolutePath
version = mavenVersion + '.0'
downloadUrl = 'http://java.com/download'
copyright = "Copyright(c) 2013-2014 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'
}
}
build.dependsOn proguard

BIN
HMCL/icon.ico Normal file

Binary file not shown.

After

(image error) Size: 4.2 KiB

Binary file not shown.

After

(image error) Size: 573 KiB

BIN
HMCL/image/A.jpg Normal file

Binary file not shown.

After

(image error) Size: 63 KiB

Binary file not shown.

After

(image error) Size: 309 KiB

Binary file not shown.

After

(image error) Size: 248 KiB

Binary file not shown.

After

(image error) Size: 657 KiB

BIN
HMCL/image/background.jpg Normal file

Binary file not shown.

After

(image error) Size: 78 KiB

41
HMCL/launch4j.xml Normal file

@ -0,0 +1,41 @@
<launch4jConfig>
<dontWrapJar>false</dontWrapJar>
<headerType>gui</headerType>
<jar>F:\Documents\NetBeansProjects\HMCL\HMCL\build\libs\HMCL-2.1.3.jar</jar>
<outfile>F:\Documents\NetBeansProjects\HMCL\HMCL\build\libs\HMCL-2.1.3-Launch4j.exe</outfile>
<errTitle></errTitle>
<cmdLine></cmdLine>
<chdir></chdir>
<priority>normal</priority>
<downloadUrl>http://java.com/download</downloadUrl>
<supportUrl></supportUrl>
<stayAlive>false</stayAlive>
<manifest></manifest>
<icon>F:\Documents\NetBeansProjects\HMCL\HMCL\icon.ico</icon>
<jre>
<path></path>
<bundledJre64Bit>false</bundledJre64Bit>
<minVersion>1.6.0</minVersion>
<maxVersion></maxVersion>
<jdkPreference>preferJre</jdkPreference>
</jre>
<versionInfo>
<fileVersion>2.1.3.0</fileVersion>
<txtFileVersion>2.1.3.0</txtFileVersion>
<fileDescription>Hello Minecraft! Launcher</fileDescription>
<copyright>Copyright(c) 2013~2014 huangyuhui</copyright>
<productVersion>2.1.3.0</productVersion>
<txtProductVersion>2.1.3.0</txtProductVersion>
<productName>Hello Minecraft! Launcher</productName>
<companyName></companyName>
<internalName>Hello Minecraft! Launcher</internalName>
<originalFilename>HMCL-2.1.3.exe</originalFilename>
</versionInfo>
<messages>
<startupErr>启动程序时出现错误</startupErr>
<bundledJreErr>未找到内置Java</bundledJreErr>
<jreVersionErr>此程序需要Java</jreVersionErr>
<launcherErr>未找到Java</launcherErr>
<instanceAlreadyExistsMsg>已存在一个程序实例</instanceAlreadyExistsMsg>
</messages>
</launch4jConfig>

77
HMCL/proguard.pro vendored Normal file

@ -0,0 +1,77 @@
-libraryjars D:\Develop\Java\jdk1.6.0_45\jre\lib\rt.jar
-libraryjars D:\Develop\Java\jdk1.6.0_45\jre\lib\jce.jar
-libraryjars D:\Develop\Java\jdk1.6.0_45\jre\lib\jsse.jar
-dontoptimize
-dontshrink
-dontwarn java.lang.invoke.*
-overloadaggressively
-repackageclasses 'org.jackhuang.hellominecraft.launcher'
-allowaccessmodification
-renamesourcefileattribute SourceFile
-keepattributes *Annotation*,SourceFile,LineNumberTable,Signature
-keep class com.** { *; }
-keep class org.jackhuang.hellominecraft.lookandfeel.* { *; }
-keep class org.jackhuang.hellominecraft.lookandfeel.painters.* { *; }
-keep class org.jackhuang.hellominecraft.lookandfeel.ui.* { *; }
-keepclassmembers class org.jackhuang.mojang.authlib.Agent { *; }
-keepclassmembers class org.jackhuang.mojang.authlib.UserType { *; }
-keepclassmembers class org.jackhuang.mojang.authlib.properties.Property { *; }
-keepclassmembers class org.jackhuang.mojang.authlib.minecraft.MinecraftProfileTexture$Type { *; }
-keepclassmembers class org.jackhuang.mojang.authlib.minecraft.MinecraftProfileTexture { *; }
-keepclassmembers class org.jackhuang.mojang.authlib.yggdrasil.request.AuthenticationRequest { *; }
-keepclassmembers class org.jackhuang.mojang.authlib.yggdrasil.request.InvalidateRequest { *; }
-keepclassmembers class org.jackhuang.mojang.authlib.yggdrasil.request.JoinMinecraftServerRequest { *; }
-keepclassmembers class org.jackhuang.mojang.authlib.yggdrasil.request.RefreshRequest { *; }
-keepclassmembers class org.jackhuang.mojang.authlib.yggdrasil.response.AuthenticationResponse { *; }
-keepclassmembers class org.jackhuang.mojang.authlib.yggdrasil.response.HasJoinedMinecraftServerResponse { *; }
-keepclassmembers class org.jackhuang.mojang.authlib.yggdrasil.response.MinecraftProfilePropertiesResponse { *; }
-keepclassmembers class org.jackhuang.mojang.authlib.yggdrasil.response.MinecraftTexturesPayload { *; }
-keepclassmembers class org.jackhuang.mojang.authlib.yggdrasil.response.ProfileSearchResultsResponse { *; }
-keepclassmembers class org.jackhuang.mojang.authlib.yggdrasil.response.RefreshResponse { *; }
-keepclassmembers class org.jackhuang.mojang.authlib.yggdrasil.response.Response { *; }
-keepclassmembers class org.jackhuang.mojang.authlib.yggdrasil.response.User { *; }
-keep class org.jackhuang.hellominecraft.launcher.Main { public static void main(java.lang.String[]); }
-keep class org.jackhuang.hellominecraft.launcher.Launcher { public static void main(java.lang.String[]); }
-keepclassmembers class org.jackhuang.hellominecraft.launcher.utils.settings.Profile { private <fields>; public <fields>; }
-keepclassmembers class org.jackhuang.hellominecraft.launcher.utils.settings.Config { public <fields>; }
-keepclassmembers class org.jackhuang.hellominecraft.launcher.utils.assets.AssetsObject { <fields>; }
-keepclassmembers class org.jackhuang.hellominecraft.launcher.utils.assets.AssetsIndex { <fields>; }
-keepclassmembers class org.jackhuang.hellominecraft.launcher.utils.version.MinecraftLibrary { public <fields>; }
-keepclassmembers class org.jackhuang.hellominecraft.launcher.utils.version.IMinecraftLibrary { public <fields>; }
-keepclassmembers class org.jackhuang.hellominecraft.launcher.utils.version.Natives { public <fields>; }
-keepclassmembers class org.jackhuang.hellominecraft.launcher.utils.version.OS { public <fields>; }
-keepclassmembers class org.jackhuang.hellominecraft.launcher.utils.version.Rules { public <fields>; }
-keepclassmembers class org.jackhuang.hellominecraft.launcher.utils.version.MinecraftVersion { public <fields>; }
-keepclassmembers class org.jackhuang.hellominecraft.launcher.utils.installers.forge.InstallProfile { public <fields>; }
-keepclassmembers class org.jackhuang.hellominecraft.launcher.utils.installers.forge.Install { public <fields>; }
-keepclassmembers class org.jackhuang.hellominecraft.launcher.utils.installers.forge.vanilla.MinecraftForgeVersionRoot { public <fields>; }
-keepclassmembers class org.jackhuang.hellominecraft.launcher.utils.installers.forge.vanilla.MinecraftForgeVersion { public <fields>; }
-keepclassmembers class org.jackhuang.hellominecraft.launcher.utils.installers.forge.bmcl.ForgeVersion { public <fields>; }
-keepclassmembers class org.jackhuang.hellominecraft.launcher.utils.installers.forge.bmcl.Downloads { public <fields>; }
-keepclassmembers class org.jackhuang.hellominecraft.launcher.utils.installers.optifine.OptiFineVersion { public <fields>; }
-keepclassmembers class org.jackhuang.hellominecraft.launcher.utils.installers.liteloader.LiteLoaderVersionsRoot { public <fields>; }
-keepclassmembers class org.jackhuang.hellominecraft.launcher.utils.installers.liteloader.LiteLoaderMCVersions { public <fields>; }
-keepclassmembers class org.jackhuang.hellominecraft.launcher.utils.installers.liteloader.LiteLoaderVersion { public <fields>; }
-keepclassmembers class org.jackhuang.hellominecraft.launcher.utils.installers.liteloader.LiteLoaderVersionsMeta { public <fields>; }
-keepclassmembers class org.jackhuang.hellominecraft.version.MinecraftRemoteLatestVersion { public <fields>; }
-keepclassmembers class org.jackhuang.hellominecraft.version.MinecraftRemoteVersion { public <fields>; }
-keepclassmembers class org.jackhuang.hellominecraft.version.MinecraftRemoteVersions { public <fields>; }

BIN
HMCL/src/main/icon.icns Normal file

Binary file not shown.

@ -0,0 +1,129 @@
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package org.jackhuang.hellominecraft.launcher;
import java.io.File;
import java.io.FileOutputStream;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.lang.reflect.Method;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;
import javax.swing.SwingUtilities;
import org.jackhuang.hellominecraft.C;
import org.jackhuang.hellominecraft.HMCLog;
import org.jackhuang.hellominecraft.utils.functions.TrueDoneListener;
import org.jackhuang.hellominecraft.utils.StrUtils;
import org.jackhuang.hellominecraft.views.LogWindow;
import org.jackhuang.hellominecraft.launcher.launch.MinecraftCrashAdvicer;
import org.jackhuang.hellominecraft.utils.DoubleOutputStream;
import org.jackhuang.hellominecraft.utils.JdkVersion;
import org.jackhuang.hellominecraft.utils.LauncherPrintStream;
import org.jackhuang.hellominecraft.utils.MessageBox;
import org.jackhuang.hellominecraft.utils.OS;
import org.jackhuang.hellominecraft.utils.Utils;
/**
*
* @author hyh
*/
public final class Launcher {
private static final Launcher instance = new Launcher();
public static void println(String s) {
System.out.println(s);
}
public static void main(String[] args) {
println("*** " + Main.makeTitle() + " ***");
Thread.currentThread().setName("launcher");
try {
File logFile = new File("hmclmc.log");
if (!logFile.exists()) logFile.createNewFile();
FileOutputStream tc = new FileOutputStream(logFile);
DoubleOutputStream out = new DoubleOutputStream(tc, System.out);
System.setOut(new LauncherPrintStream(out));
DoubleOutputStream err = new DoubleOutputStream(tc, System.err);
System.setErr(new LauncherPrintStream(err));
} catch (Exception e) {
println("Failed to add log file appender.");
e.printStackTrace();
}
LogWindow.instance.setTerminateGame(Utils::shutdownForcely);
boolean showInfo = false;
String classPath = "";
String mainClass = "net.minecraft.client.Minecraft";
ArrayList<String> cmdList = new ArrayList<>();
for (String s : args)
if (s.startsWith("-cp=")) classPath = classPath.concat(s.substring("-cp=".length()));
else if (s.startsWith("-mainClass=")) mainClass = s.substring("-mainClass=".length());
else if (s.equals("-debug")) showInfo = true;
else cmdList.add(s);
String[] cmds = (String[]) cmdList.toArray(new String[cmdList.size()]);
String[] tokenized = StrUtils.tokenize(classPath, File.pathSeparator);
int len = tokenized.length;
if (showInfo) {
println("Arguments: {\n" + StrUtils.parseParams(" ", args, "\n") + "\n}");
println("Main Class: " + mainClass);
println("Class Path: {\n" + StrUtils.parseParams(" ", tokenized, "\n") + "\n}");
SwingUtilities.invokeLater(() -> LogWindow.instance.setVisible(true));
}
URL[] urls = new URL[len];
try {
for (int j = 0; j < len; j++)
urls[j] = new File(tokenized[j]).toURI().toURL();
} catch (Throwable e) {
MessageBox.Show(C.i18n("crash.main_class_not_found"));
println("Failed to get classpath.");
e.printStackTrace();
return;
}
if (!JdkVersion.isJava64Bit() && OS.is64Bit())
MessageBox.Show(C.i18n("advice.os64butjdk32"));
Method minecraftMain;
try {
minecraftMain = new URLClassLoader(urls).loadClass(mainClass).getMethod("main", String[].class);
} catch (Throwable t) {
MessageBox.Show(C.i18n("crash.main_class_not_found"));
println("Minecraft main class not found.");
return;
}
println("*** Launching Game ***");
try {
minecraftMain.invoke(null, new Object[]{cmds});
} catch (Throwable throwable) {
HMCLog.err("Cought exception!");
final StringWriter trace = new StringWriter();
PrintWriter writer = new PrintWriter(trace);
throwable.printStackTrace(writer);
final String advice = MinecraftCrashAdvicer.getAdvice(throwable);
MessageBox.Show(C.i18n("crash.minecraft") + ": " + advice);
LogWindow.instance.log(C.i18n("crash.minecraft"));
LogWindow.instance.log(advice);
LogWindow.instance.log(trace.toString());
LogWindow.instance.setExit(TrueDoneListener.instance);
LogWindow.instance.setVisible(true);
}
println("*** Game Exited ***");
}
}

@ -0,0 +1,126 @@
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package org.jackhuang.hellominecraft.launcher;
import java.awt.Toolkit;
import java.awt.datatransfer.Clipboard;
import java.awt.datatransfer.StringSelection;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.URI;
import javax.swing.ImageIcon;
import javax.swing.UIManager;
import org.jackhuang.hellominecraft.C;
import org.jackhuang.hellominecraft.utils.functions.DoneListener0;
import org.jackhuang.hellominecraft.HMCLog;
import org.jackhuang.hellominecraft.launcher.launch.GameLauncher;
import org.jackhuang.hellominecraft.launcher.utils.CrashReport;
import org.jackhuang.hellominecraft.logging.Configuration;
import org.jackhuang.hellominecraft.logging.appender.ConsoleAppender;
import org.jackhuang.hellominecraft.logging.layout.DefaultLayout;
import org.jackhuang.hellominecraft.views.LogWindow;
import org.jackhuang.hellominecraft.launcher.utils.settings.Settings;
import org.jackhuang.hellominecraft.launcher.views.MainFrame;
import org.jackhuang.hellominecraft.lookandfeel.HelloMinecraftLookAndFeel;
import org.jackhuang.hellominecraft.utils.MessageBox;
/**
*
* @author hyh
*/
public final class Main implements DoneListener0 {
public static String launcherName = "Hello Minecraft! Launcher";
public static byte firstVer = 2, secondVer = 3, thirdVer = 2;
public static int minimumLauncherVersion = 16;
/**
* Make the version of HMCL.
*
* @return the version: firstVer.secondVer.thirdVer
*/
public static String makeVersion() {
return "" + firstVer + '.' + secondVer + '.' + thirdVer;
}
/**
* Make the main window title.
*
* @return the MainWindow title.
*/
public static String makeTitle() {
return launcherName + ' ' + makeVersion();
}
public static final Main instance = new Main();
public static void main(String[] args) {
{
Thread.setDefaultUncaughtExceptionHandler(new CrashReport(true));
try {
File file = new File("hmcl.log");
if (!file.exists())
file.createNewFile();
Configuration.DEFAULT.appenders.add(new ConsoleAppender("File", new DefaultLayout(), true, new FileOutputStream(file), true));
} catch (IOException ex) {
System.err.println("Failed to add log appender File because an error occurred while creating or opening hmcl.log");
ex.printStackTrace();
}
HMCLog.log("*** " + Main.makeTitle() + " ***");
LogWindow.instance.clean();
LogWindow.instance.setTerminateGame(GameLauncher.PROCESS_MANAGER::stopAllProcesses);
try {
UIManager.setLookAndFeel(new HelloMinecraftLookAndFeel());
} catch (Throwable ex) {
HMCLog.warn("Failed to set look and feel...", ex);
}
Settings.UPDATE_CHECKER.start();
MainFrame.showMainFrame(Settings.isFirstLoad());
}
}
@Override
public void onDone() {
GameLauncher.PROCESS_MANAGER.stopAllProcesses();
}
public static void update() {
if (MessageBox.Show(C.i18n("update.newest_version") + Settings.UPDATE_CHECKER.getNewVersion().firstVer + "." + Settings.UPDATE_CHECKER.getNewVersion().secondVer + "." + Settings.UPDATE_CHECKER.getNewVersion().thirdVer + "\n"
+ C.i18n("update.should_open_link"),
MessageBox.YES_NO_OPTION) == MessageBox.YES_OPTION)
try {
java.awt.Desktop.getDesktop().browse(new URI(C.URL_PUBLISH));
} catch (Throwable e) {
HMCLog.warn("Failed to browse uri: " + C.URL_PUBLISH, e);
Clipboard cb = Toolkit.getDefaultToolkit().getSystemClipboard();
cb.setContents(new StringSelection(C.URL_PUBLISH), null);
MessageBox.Show(C.i18n("update.no_browser"));
}
else
Settings.s().setCheckUpdate(false);
}
public static void invokeUpdate() {
if (Settings.s().isCheckUpdate()) update();
MainFrame.instance.invokeUpdate();
}
public static ImageIcon getIcon(String path) {
try {
return new ImageIcon(Main.class.getResource("/org/jackhuang/hellominecraft/launcher/" + path));
} catch (Exception e) {
HMCLog.err("Failed to load icon", e);
return null;
}
}
}

@ -0,0 +1,69 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.jackhuang.hellominecraft.launcher.launch;
import java.io.IOException;
import org.jackhuang.hellominecraft.C;
import org.jackhuang.hellominecraft.HMCLog;
import org.jackhuang.hellominecraft.launcher.launch.GameLauncher.DownloadLibraryJob;
import org.jackhuang.hellominecraft.launcher.utils.auth.IAuthenticator;
import org.jackhuang.hellominecraft.launcher.utils.auth.LoginInfo;
import org.jackhuang.hellominecraft.launcher.utils.download.DownloadType;
import org.jackhuang.hellominecraft.launcher.utils.settings.Profile;
import org.jackhuang.hellominecraft.tasks.ParallelTask;
import org.jackhuang.hellominecraft.tasks.TaskWindow;
import org.jackhuang.hellominecraft.tasks.download.FileDownloadTask;
import org.jackhuang.hellominecraft.utils.Compressor;
import org.jackhuang.hellominecraft.utils.MessageBox;
/**
*
* @author hyh
*/
public class DefaultGameLauncher extends GameLauncher {
public DefaultGameLauncher(Profile version, LoginInfo info, IAuthenticator lg) {
super(version, info, lg);
register();
}
public DefaultGameLauncher(Profile version, LoginInfo info, IAuthenticator lg, DownloadType downloadType) {
super(version, info, lg, downloadType);
register();
}
private void register() {
downloadLibrariesEvent.register((sender, t) -> {
final TaskWindow dw = TaskWindow.getInstance();
ParallelTask parallelTask = new ParallelTask();
for (DownloadLibraryJob o : t) {
final DownloadLibraryJob s = (DownloadLibraryJob) o;
parallelTask.addDependsTask(new FileDownloadTask(s.url, s.path).setTag(s.name));
}
dw.addTask(parallelTask);
boolean flag = true;
if (t.size() > 0) flag = dw.start();
if (!flag && MessageBox.Show(C.i18n("launch.not_finished_downloading_libraries"), MessageBox.YES_NO_OPTION) == MessageBox.YES_OPTION)
flag = true;
return flag;
});
decompressNativesEvent.register((sender, value) -> {
//boolean flag = true;
for (int i = 0; i < value.decompressFiles.length; i++)
try {
Compressor.unzip(value.decompressFiles[i], value.decompressTo, value.extractRules[i]);
} catch (IOException ex) {
HMCLog.err("Unable to decompress library file: " + value.decompressFiles[i] + " to " + value.decompressTo, ex);
//flag = false;
}
/*if(!flag)
if(MessageBox.Show(C.i18n("launch.not_finished_decompressing_natives"), MessageBox.YES_NO_OPTION) == MessageBox.YES_OPTION)
flag = true;*/
return true;
});
}
}

@ -0,0 +1,191 @@
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package org.jackhuang.hellominecraft.launcher.launch;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.UnsupportedEncodingException;
import java.util.List;
import org.jackhuang.hellominecraft.C;
import org.jackhuang.hellominecraft.HMCLog;
import org.jackhuang.hellominecraft.launcher.utils.auth.IAuthenticator;
import org.jackhuang.hellominecraft.launcher.utils.auth.LoginInfo;
import org.jackhuang.hellominecraft.launcher.utils.auth.UserProfileProvider;
import org.jackhuang.hellominecraft.launcher.utils.download.DownloadType;
import org.jackhuang.hellominecraft.launcher.utils.settings.Profile;
import org.jackhuang.hellominecraft.utils.FileUtils;
import org.jackhuang.hellominecraft.utils.IOUtils;
import org.jackhuang.hellominecraft.utils.JavaProcess;
import org.jackhuang.hellominecraft.utils.MessageBox;
import org.jackhuang.hellominecraft.utils.OS;
import org.jackhuang.hellominecraft.utils.StrUtils;
import org.jackhuang.hellominecraft.utils.EventHandler;
import org.jackhuang.hellominecraft.utils.ProcessManager;
/**
*
* @author hyh
*/
public class GameLauncher {
public static final ProcessManager PROCESS_MANAGER = new ProcessManager();
Profile get;
IMinecraftProvider provider;
LoginInfo info;
UserProfileProvider result;
IAuthenticator login;
public final EventHandler<String> failEvent = new EventHandler(this);
public final EventHandler<List<DownloadLibraryJob>> downloadLibrariesEvent = new EventHandler(this);
public final EventHandler<List<String>> successEvent = new EventHandler(this);
public final EventHandler<JavaProcess> launchEvent = new EventHandler(this);
public final EventHandler<DecompressLibraryJob> decompressNativesEvent = new EventHandler(this);
DownloadType downloadType;
public GameLauncher(Profile version, LoginInfo info, IAuthenticator lg) {
this(version, info, lg, DownloadType.Mojang);
}
public GameLauncher(Profile version, LoginInfo info, IAuthenticator lg, DownloadType downloadType) {
this.get = version;
this.provider = get.getMinecraftProvider();
this.info = info;
this.login = lg;
this.downloadType = downloadType;
}
public Profile getProfile() {
return get;
}
public IMinecraftLoader makeLaunchCommand() {
IMinecraftLoader loader;
try {
if (info != null) result = login.login(info);
else result = login.loginBySettings();
} catch (Exception e) {
HMCLog.err("An exception has thrown when logging in.", e);
result = new UserProfileProvider();
result.setSuccess(false);
result.setErrorReason(e.getLocalizedMessage());
}
if (result == null || result.isSuccessful() == false) {
String error;
if (result == null || result.getErrorReason() == null)
error = C.i18n("login.failed");
else {
error = C.i18n("login.failed") + result.getErrorReason();
HMCLog.warn("Login failed by method: " + login.getName() + ", state: " + result.isSuccessful() + ", error reason: " + result.getErrorReason());
}
failEvent.execute(error);
return null;
}
try {
loader = provider.provideMinecraftLoader(result, downloadType);
} catch (IllegalStateException e) {
HMCLog.err("Failed to get minecraft loader", e);
failEvent.execute(C.i18n("launch.circular_dependency_versions"));
return null;
}
File file = provider.getDecompressNativesToLocation();
if (file != null) FileUtils.cleanDirectoryQuietly(file);
if(!downloadLibrariesEvent.execute(provider.getDownloadLibraries(downloadType))) { failEvent.execute(C.i18n("launch.failed")); return null; }
if(!decompressNativesEvent.execute(provider.getDecompressLibraries())) { failEvent.execute(C.i18n("launch.failed")); return null; }
successEvent.execute(loader.makeLaunchingCommand());
return loader;
}
/**
* Launch the game "as soon as possible".
*
* @param str launch command
*/
public void launch(List str) {
try {
provider.onLaunch();
ProcessBuilder builder = new ProcessBuilder(str);
builder.directory(provider.getRunDirectory(get.getSelectedMinecraftVersion().id))
.environment().put("APPDATA", get.getCanonicalGameDirFile().getParent());
JavaProcess jp = new JavaProcess(str, builder.start(), PROCESS_MANAGER);
launchEvent.execute(jp);
} catch (IOException e) {
failEvent.execute(C.i18n("launch.failed_creating_process") + "\n" + e.getMessage());
HMCLog.err("Failed to launch when creating a new process.", e);
}
}
/**
* According to the name...
*
* @param launcherName the name of launch bat/sh
* @param str launch command
* @return launcher location
* @throws java.io.IOException write contents failed.
*/
public File makeLauncher(String launcherName, List str) throws IOException {
provider.onLaunch();
boolean isWin = OS.os() == OS.WINDOWS;
File f = new File(launcherName + (isWin ? ".bat" : ".sh"));
if (!f.exists()) f.createNewFile();
BufferedWriter writer;
try {
writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(f), System.getProperty("sun.jnu.encoding", "UTF-8")));
} catch (UnsupportedEncodingException ex) {
HMCLog.warn("Failed to create writer, will try again.", ex);
writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(f)));
}
if (isWin) {
writer.write("@echo off");
writer.newLine();
String appdata = IOUtils.tryGetCanonicalFilePath(get.getCanonicalGameDirFile().getParentFile());
if (appdata != null) {
writer.write("set appdata=" + appdata);
writer.newLine();
}
}
writer.write(StrUtils.makeCommand(str));
writer.close();
if (!isWin)
try {
Runtime.getRuntime().exec("chmod +x " + IOUtils.tryGetCanonicalFilePath(f));
} catch (IOException e) {
HMCLog.warn("Failed to give sh file permission.", e);
MessageBox.Show(C.i18n("launch.failed_sh_permission"));
}
HMCLog.log("Command: " + StrUtils.parseParams("", str, " "));
return f;
}
public static class DownloadLibraryJob {
String url, name;
File path;
public DownloadLibraryJob(String n, String u, File p) {
url = u;
name = n;
path = IOUtils.tryGetCanonicalFile(p);
}
}
public static class DecompressLibraryJob {
File[] decompressFiles;
String[][] extractRules;
File decompressTo;
public DecompressLibraryJob(File[] decompressFiles, String[][] extractRules, File decompressTo) {
this.decompressFiles = decompressFiles;
this.extractRules = extractRules;
this.decompressTo = decompressTo;
}
}
}

@ -0,0 +1,19 @@
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package org.jackhuang.hellominecraft.launcher.launch;
/**
*
* @author hyh
*/
public enum GameLauncherRequest {
ERROR,
DOWNLOAD_ASSETS,
DOWNLOAD_LIBRARIES,
UNZIP_LIBRARIES,
PROCESS_STARTED,
SUCCEED
}

@ -0,0 +1,179 @@
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package org.jackhuang.hellominecraft.launcher.launch;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import org.jackhuang.hellominecraft.C;
import org.jackhuang.hellominecraft.HMCLog;
import org.jackhuang.hellominecraft.launcher.Launcher;
import org.jackhuang.hellominecraft.launcher.utils.auth.UserProfileProvider;
import org.jackhuang.hellominecraft.launcher.utils.settings.Profile;
import org.jackhuang.hellominecraft.utils.FileUtils;
import org.jackhuang.hellominecraft.utils.JdkVersion;
import org.jackhuang.hellominecraft.utils.MathUtils;
import org.jackhuang.hellominecraft.utils.MessageBox;
import org.jackhuang.hellominecraft.utils.OS;
import org.jackhuang.hellominecraft.utils.StrUtils;
import org.jackhuang.hellominecraft.utils.Utils;
/**
*
* @author hyh
*/
public abstract class IMinecraftLoader {
protected File minecraftJar;
protected Profile v;
protected UserProfileProvider lr;
protected File gameDir;
protected IMinecraftProvider provider;
public IMinecraftLoader(Profile ver, IMinecraftProvider provider, UserProfileProvider lr, File minecraftJar) {
this.lr = lr;
this.minecraftJar = minecraftJar;
v = ver;
this.provider = provider;
gameDir = v.getCanonicalGameDirFile();
}
public void makeHeadCommand(List<String> res) {
HMCLog.log("On making head command.");
if (StrUtils.isNotBlank(v.getWrapperLauncher()))
res.addAll(Arrays.asList(v.getWrapperLauncher().split(" ")));
String str = v.getJavaDir();
JdkVersion jv = null;
File f = new File(str + ".hmc");
try {
String s = FileUtils.readFileToString(f);
String[] strs = s.split("\n");
if (str.length() >= 2)
jv = new JdkVersion(strs[0], MathUtils.parseInt(strs[1], -1));
else
throw new IllegalStateException("The format of file: " + f + " is wrong: " + s);
} catch (IOException | IllegalStateException e) {
try {
jv = JdkVersion.getJavaVersionFromExecutable(str);
jv.write(f);
if (!f.exists())
HMCLog.warn("Failed to load version from file " + f, e);
} catch (Exception ex) {
HMCLog.warn("Failed to read JDKVersion.", ex);
}
}
res.add(str);
if (v.hasJavaArgs())
res.addAll(Arrays.asList(StrUtils.tokenize(v.getJavaArgs())));
if (!v.isNoJVMArgs() && !(jv != null && jv.isEarlyAccess())) {
res.add("-Xincgc");
res.add("-XX:+UseConcMarkSweepGC");
res.add("-XX:+CMSIncrementalMode");
res.add("-XX:-UseAdaptiveSizePolicy");
res.add("-Xmn128m");
}
if (jv != null && jv.is64Bit == 0 && OS.is64Bit())
MessageBox.Show(C.i18n("advice.os64butjdk32"));
if (!StrUtils.isBlank(v.getMaxMemory())) {
int mem = MathUtils.parseMemory(v.getMaxMemory(), 2147483647);
if (jv != null && jv.is64Bit == 0 && mem > 1024)
MessageBox.Show(C.i18n("launch.too_big_memory_alloc_64bit"));
else {
long a = OS.getTotalPhysicalMemory() / 1024 / 1024;
HMCLog.log("System Physical Memory: " + a);
if (a > 0 && a < mem)
MessageBox.Show(C.i18n("launch.too_big_memory_alloc_free_space_too_low", a));
}
String a = "-Xmx" + v.getMaxMemory();
if (MathUtils.canParseInt(v.getMaxMemory())) a += "m";
res.add(a);
}
if (!StrUtils.isBlank(v.getPermSize()) && !v.isNoJVMArgs())
if (jv != null && jv.ver != null && (jv.ver.startsWith("1.8") || jv.ver.startsWith("1.9"))); else res.add("-XX:MaxPermSize=" + v.getPermSize() + "m");
if (!v.isNoJVMArgs())
appendJVMArgs(res);
HMCLog.log("On making java.library.path.");
res.add("-Djava.library.path=" + provider.getDecompressNativesToLocation().getPath());//v.getSelectedMinecraftVersion().getNatives(v.getCanonicalGameDirFile()));
res.add("-Dfml.ignoreInvalidMinecraftCertificates=true");
res.add("-Dfml.ignorePatchDiscrepancies=true");
if (OS.os() != OS.WINDOWS)
res.add("-Duser.home=" + gameDir.getParent());
if (!v.isCanceledWrapper()) {
res.add("-cp");
res.add(StrUtils.parseParams("", Utils.getURL(), File.pathSeparator));
res.add(Launcher.class.getCanonicalName());
}
}
public List<String> makeLaunchingCommand() {
HMCLog.log("*** Make shell command ***");
ArrayList<String> res = new ArrayList<>();
makeHeadCommand(res);
makeSelf(res);
HMCLog.log("On making launcher args.");
if (StrUtils.isNotBlank(v.getHeight()) && StrUtils.isNotBlank(v.getWidth())) {
res.add("--height");
res.add(v.getHeight());
res.add("--width");
res.add(v.getWidth());
}
if (StrUtils.isNotBlank(v.getServerIp())) {
String[] args = v.getServerIp().split(":");
res.add("--server");
res.add(args[0]);
res.add("--port");
res.add(args.length > 1 ? args[1] : "25565");
}
if (v.isFullscreen())
res.add("--fullscreen");
if (v.isDebug() && !v.isCanceledWrapper())
res.add("-debug");
if (StrUtils.isNotBlank(v.getMinecraftArgs()))
res.addAll(Arrays.asList(v.getMinecraftArgs().split(" ")));
return res;
}
/**
* 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);
protected void appendJVMArgs(List<String> list) {
}
public Profile getUserVersion() {
return v;
}
}

@ -0,0 +1,63 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.jackhuang.hellominecraft.launcher.launch;
import java.io.File;
import java.util.Collection;
import java.util.List;
import org.jackhuang.hellominecraft.launcher.utils.auth.UserProfileProvider;
import org.jackhuang.hellominecraft.launcher.utils.download.DownloadType;
import org.jackhuang.hellominecraft.launcher.utils.settings.Profile;
import org.jackhuang.hellominecraft.launcher.utils.version.MinecraftVersion;
/**
*
* @author huangyuhui
*/
public abstract class IMinecraftProvider {
Profile profile;
public IMinecraftProvider(Profile profile) {
this.profile = profile;
}
public abstract File getRunDirectory(String id);
public abstract List<GameLauncher.DownloadLibraryJob> getDownloadLibraries(DownloadType type);
public abstract void openSelf(String version);
public abstract void open(String version, String folder);
public abstract File getAssets();
public abstract File getResourcePacks();
public abstract GameLauncher.DecompressLibraryJob getDecompressLibraries();
public abstract File getDecompressNativesToLocation();
public abstract File getMinecraftJar();
public abstract File getBaseFolder();
/**
* Launch
* @param p player informations, including username & auth_token
* @param type according to the class name 233
* @return what you want
* @throws IllegalStateException circular denpendency versions
*/
public abstract IMinecraftLoader provideMinecraftLoader(UserProfileProvider p, DownloadType type) throws IllegalStateException;
// Versions
public abstract boolean renameVersion(String from, String to);
public abstract boolean removeVersionFromDisk(String a);
public abstract boolean refreshJson(String a);
public abstract boolean refreshAssetsIndex(String a);
public abstract MinecraftVersion getOneVersion();
public abstract Collection<MinecraftVersion> getVersions();
public abstract MinecraftVersion getVersionById(String id);
public abstract int getVersionCount();
public abstract void refreshVersions();
public abstract boolean install(String version, DownloadType type);
public abstract void onLaunch();
}

@ -0,0 +1,103 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.jackhuang.hellominecraft.launcher.launch;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import org.jackhuang.hellominecraft.C;
import org.jackhuang.hellominecraft.utils.functions.TrueDoneListener;
import org.jackhuang.hellominecraft.launcher.views.MainFrame;
import org.jackhuang.hellominecraft.utils.tinystream.CollectionUtils;
import org.jackhuang.hellominecraft.utils.Event;
import org.jackhuang.hellominecraft.utils.JavaProcess;
import org.jackhuang.hellominecraft.utils.MessageBox;
import org.jackhuang.hellominecraft.utils.functions.Predicate;
import org.jackhuang.hellominecraft.utils.ProcessThread;
import org.jackhuang.hellominecraft.utils.StrUtils;
import org.jackhuang.hellominecraft.views.LogWindow;
/**
*
* @author huangyuhui
*/
public class LaunchFinisher implements Event<List<String>> {
private final HashSet<Thread> al = new HashSet<Thread>();
@Override
public boolean call(Object sender, List<String> str) {
final GameLauncher obj = (GameLauncher) sender;
obj.launchEvent.register(new Event<JavaProcess>() {
@Override
public boolean call(Object sender, JavaProcess p) {
if (obj.getProfile().getLauncherVisibility() == 0 && !LogWindow.instance.isVisible())
System.exit(0);
else if (obj.getProfile().getLauncherVisibility() == 2)
MainFrame.instance.closeMessage();
else {
if (LogWindow.instance.isVisible())
LogWindow.instance.setExit(TrueDoneListener.instance);
MainFrame.instance.dispose();
}
Event<JavaProcess> event = new Event<JavaProcess>() {
@Override
public boolean call(Object sender, JavaProcess t) {
processThreadStopped((ProcessThread) sender, obj, t, false);
return true;
}
};
ProcessThread a = new ProcessThread(p, true, true);
a.stopEvent.register(new Event<JavaProcess>() {
@Override
public boolean call(Object sender, JavaProcess p) {
if (p.getExitCode() != 0 && p.getStdErrLines().size() > 0 && StrUtils.containsOne(p.getStdErrLines(),
Arrays.asList("Could not create the Java Virtual Machine.",
"Error occurred during initialization of VM",
"A fatal exception has occurred. Program will exit.")))
MessageBox.Show(C.i18n("launch.cannot_create_jvm"));
processThreadStopped((ProcessThread) sender, obj, p, false);
return true;
}
});
a.start();
al.add(a);
a = new ProcessThread(p, false, true);
a.stopEvent.register(event);
a.start();
al.add(a);
a = new ProcessThread(p, false, false);
a.stopEvent.register(event);
a.start();
al.add(a);
return true;
}
});
obj.launch(str);
return true;
}
void processThreadStopped(ProcessThread t, GameLauncher obj, JavaProcess p, boolean forceTermintate) {
al.remove(t);
al.removeAll(CollectionUtils.sortOut(al, new Predicate<Thread>() {
@Override
public boolean apply(Thread t) {
return !t.isAlive();
}
}));
if (al.isEmpty() || forceTermintate) {
for (Thread a : al) a.interrupt();
al.clear();
GameLauncher.PROCESS_MANAGER.onProcessStopped(p);
if (obj.getProfile().getLauncherVisibility() != 2 && !LogWindow.instance.isVisible())
System.exit(0);
}
}
}

@ -0,0 +1,38 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.jackhuang.hellominecraft.launcher.launch;
import java.io.IOException;
import java.util.List;
import javax.swing.JOptionPane;
import org.jackhuang.hellominecraft.C;
import org.jackhuang.hellominecraft.HMCLog;
import org.jackhuang.hellominecraft.launcher.views.MainFrame;
import org.jackhuang.hellominecraft.utils.Event;
import org.jackhuang.hellominecraft.utils.MessageBox;
/**
*
* @author huangyuhui
*/
public class LaunchScriptFinisher implements Event<List<String>> {
@Override
public boolean call(Object sender, List str) {
boolean flag = false;
try {
String s = JOptionPane.showInputDialog(C.i18n("mainwindow.enter_script_name"));
if(s != null) MessageBox.Show(C.i18n("mainwindow.make_launch_succeed") + " " + ((GameLauncher)sender).makeLauncher(s, str).getAbsolutePath());
flag = true;
} catch (IOException ex) {
MessageBox.Show(C.i18n("mainwindow.make_launch_script_failed"));
HMCLog.err("Failed to create script file.", ex);
}
MainFrame.instance.closeMessage();
return flag;
}
}

@ -0,0 +1,48 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.jackhuang.hellominecraft.launcher.launch;
import java.util.ConcurrentModificationException;
import org.jackhuang.hellominecraft.C;
/**
* Give the advice to solve the Minecraft crashing.
*
* @author hyh
*/
public final class MinecraftCrashAdvicer {
public static String getAdvice(Throwable t) {
return getAdvice(t, false);
}
public static String getAdvice(Throwable t, boolean selfCrash) {
if (t.getCause() instanceof UnsupportedClassVersionError) {
return C.i18n("crash.advice.UnsupportedClassVersionError");
} else if (t instanceof ConcurrentModificationException) {
return C.i18n("crash.advice.ConcurrentModificationException");
} else if (t instanceof SecurityException) {
return C.i18n("crash.advice.SecurityException");
} else if (t instanceof NoSuchFieldError || (t.getCause() != null && t.getCause() instanceof NoSuchFieldException)) {
return C.i18n("crash.advice.NoSuchFieldError");
} else if (t instanceof NoClassDefFoundError || (t.getCause() != null && t.getCause() instanceof ClassNotFoundException)) {
return C.i18n("crash.advice.ClassNotFondException");
}
if (t.getMessage() != null) {
if (t.getMessage().contains("OpenGL") || t.getMessage().contains("OpenAL")) {
return C.i18n("crash.advice.OpenGL");
}
}
if (t.getCause() != null && t.getCause().getMessage() != null) {
if (t.getCause().getMessage().contains("no lwjgl in java.library.path")) {
return C.i18n("crash.advice.no_lwjgl");
}
}
return selfCrash ? C.i18n("crash.advice.no") : C.i18n("crash.advice.otherwise");
}
}

@ -0,0 +1,136 @@
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package org.jackhuang.hellominecraft.launcher.launch;
import java.io.File;
import java.io.IOException;
import java.util.List;
import java.util.Map;
import org.jackhuang.hellominecraft.C;
import org.jackhuang.hellominecraft.HMCLog;
import org.jackhuang.hellominecraft.launcher.utils.auth.UserProfileProvider;
import org.jackhuang.hellominecraft.launcher.utils.settings.Profile;
import org.jackhuang.hellominecraft.utils.IOUtils;
import org.jackhuang.hellominecraft.launcher.utils.MCUtils;
import org.jackhuang.hellominecraft.launcher.utils.assets.AssetsIndex;
import org.jackhuang.hellominecraft.launcher.utils.assets.AssetsObject;
import org.jackhuang.hellominecraft.launcher.utils.download.DownloadType;
import org.jackhuang.hellominecraft.utils.OS;
import org.jackhuang.hellominecraft.launcher.utils.version.MinecraftLibrary;
import org.jackhuang.hellominecraft.launcher.utils.version.MinecraftVersion;
import org.jackhuang.hellominecraft.utils.FileUtils;
import org.jackhuang.hellominecraft.utils.MessageBox;
/**
*
* @author hyh
*/
public class MinecraftLoader extends IMinecraftLoader {
private MinecraftVersion version;
String text;
public MinecraftLoader(Profile ver, IMinecraftProvider provider, UserProfileProvider lr, File minecraftJar) throws IllegalStateException {
this(ver, provider, lr, minecraftJar, DownloadType.Mojang);
}
public MinecraftLoader(Profile ver, IMinecraftProvider provider, UserProfileProvider lr, File minecraftJar, DownloadType downloadtype) throws IllegalStateException {
super(ver, provider, lr, minecraftJar);
version = ver.getSelectedMinecraftVersion().resolve(provider, downloadtype);
}
@Override
protected void makeSelf(List<String> res) {
String library = v.isCanceledWrapper() ? "" : "-cp=";
for (MinecraftLibrary l : version.libraries) {
l.init();
if (l.allow())
library += l.getFilePath(gameDir).getAbsolutePath() + File.pathSeparator;
}
library += IOUtils.tryGetCanonicalFilePath(minecraftJar) + File.pathSeparator;
library = library.substring(0, library.length() - File.pathSeparator.length());
if (v.isCanceledWrapper()) res.add("-cp");
res.add(library);
String mainClass = version.mainClass;
res.add((v.isCanceledWrapper() ? "" : "-mainClass=") + mainClass);
String arg = v.getSelectedMinecraftVersion().minecraftArguments;
String[] splitted = org.jackhuang.hellominecraft.utils.StrUtils.tokenize(arg);
if (!new File(v.getGameDirFile(), "assets").exists())
MessageBox.Show(C.i18n("assets.no_assets"));
String game_assets = reconstructAssets().getAbsolutePath();
for (String t : splitted) {
t = t.replace("${auth_player_name}", lr.getUserName());
t = t.replace("${auth_session}", lr.getSession());
t = t.replace("${auth_uuid}", lr.getUserId());
t = t.replace("${version_name}", version.id);
t = t.replace("${profile_name}", provider.profile.getName());
t = t.replace("${game_directory}", provider.getRunDirectory(version.id).getAbsolutePath());
t = t.replace("${game_assets}", game_assets);
t = t.replace("${assets_root}", provider.getAssets().getAbsolutePath());
t = t.replace("${auth_access_token}", lr.getAccessToken());
t = t.replace("${user_type}", lr.getUserType());
t = t.replace("${assets_index_name}", version.assets == null ? "legacy" : version.assets);
t = t.replace("${user_properties}", lr.getUserProperties());
t = t.replace("${user_property_map}", lr.getUserPropertyMap());
res.add(t);
}
if (res.indexOf("--gameDir") != -1 && res.indexOf("--workDir") != -1) {
res.add("--workDir");
res.add(gameDir.getAbsolutePath());
}
}
@Override
protected void appendJVMArgs(List<String> list) {
super.appendJVMArgs(list);
try {
if (OS.os() == OS.OSX) {
list.add("-Xdock:icon=" + MCUtils.getAssetObject(C.gson, v.getCanonicalGameDir(), version.assets, "icons/minecraft.icns").getAbsolutePath());
list.add("-Xdock:name=Minecraft");
}
} catch (IOException e) {
HMCLog.err("Failed to append jvm arguments when searching for asset objects.", e);
}
}
private File reconstructAssets() {
File assetsDir = new File(provider.getBaseFolder(), "assets");
File indexDir = new File(assetsDir, "indexes");
File objectDir = new File(assetsDir, "objects");
String assetVersion = version.assets == null ? "legacy" : version.assets;
File indexFile = new File(indexDir, assetVersion + ".json");
File virtualRoot = new File(new File(assetsDir, "virtual"), assetVersion);
if (!indexFile.isFile()) {
HMCLog.warn("No assets index file " + virtualRoot + "; can't reconstruct assets");
return virtualRoot;
}
try {
AssetsIndex index = (AssetsIndex) C.gson.fromJson(FileUtils.readFileToString(indexFile, "UTF-8"), AssetsIndex.class);
if (index.isVirtual()) {
HMCLog.log("Reconstructing virtual assets folder at " + virtualRoot);
for (Map.Entry entry : index.getFileMap().entrySet()) {
File target = new File(virtualRoot, (String) entry.getKey());
File original = new File(new File(objectDir, ((AssetsObject) entry.getValue()).getHash().substring(0, 2)), ((AssetsObject) entry.getValue()).getHash());
if (!target.isFile())
FileUtils.copyFile(original, target, false);
}
}
} catch (IOException e) {
HMCLog.warn("Failed to create virutal assets.", e);
}
return virtualRoot;
}
}

@ -0,0 +1,59 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.jackhuang.hellominecraft.launcher.utils;
import java.text.DateFormat;
import java.util.Date;
import javax.swing.SwingUtilities;
import org.jackhuang.hellominecraft.HMCLog;
import org.jackhuang.hellominecraft.launcher.Main;
import org.jackhuang.hellominecraft.launcher.launch.MinecraftCrashAdvicer;
import org.jackhuang.hellominecraft.utils.UpdateChecker;
import org.jackhuang.hellominecraft.utils.MessageBox;
import org.jackhuang.hellominecraft.utils.StrUtils;
import org.jackhuang.hellominecraft.views.LogWindow;
/**
*
* @author hyh
*/
public class CrashReport implements Thread.UncaughtExceptionHandler {
boolean enableLogger = false;
public CrashReport(boolean enableLogger) {
this.enableLogger = enableLogger;
}
@Override
public void uncaughtException(Thread t, Throwable e) {
try {
String text = "\n---- Hello Minecraft! Crash Report ----\n";
text += " Version: " + Main.makeVersion() + "\n";
text += " Time: " + DateFormat.getDateInstance().format(new Date()) + "\n";
text += " Thread: " + t.toString() + "\n";
text += "\n Advice: \n ";
text += MinecraftCrashAdvicer.getAdvice(e, true);
text += "\n Content: \n ";
text += StrUtils.getStackTrace(e) + "\n\n";
text += "-- System Details --\n";
text += " Operating System: " + System.getProperty("os.name") + " (" + System.getProperty("os.arch") + ") version " + System.getProperty("os.version") + "\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);
SwingUtilities.invokeLater(() -> LogWindow.instance.showAsCrashWindow(UpdateChecker.OUT_DATED));
} catch (Throwable ex) {
try {
MessageBox.Show(e.getMessage() + "\n" + ex.getMessage(), "ERROR", MessageBox.ERROR_MESSAGE);
} catch (Throwable exx) {
System.out.println("Failed to catch exception thrown by " + t + " on " + Main.makeVersion() + ".");
exx.printStackTrace();
}
}
}
}

@ -0,0 +1,306 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.jackhuang.hellominecraft.launcher.utils;
import com.google.gson.Gson;
import com.google.gson.JsonSyntaxException;
import java.io.File;
import java.io.IOException;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import org.jackhuang.hellominecraft.HMCLog;
import org.jackhuang.hellominecraft.launcher.utils.assets.AssetsIndex;
import org.jackhuang.hellominecraft.launcher.utils.assets.AssetsObject;
import org.jackhuang.hellominecraft.launcher.utils.download.DownloadType;
import org.jackhuang.hellominecraft.launcher.utils.version.MinecraftVersion;
import org.jackhuang.hellominecraft.version.MinecraftRemoteVersions;
import org.jackhuang.hellominecraft.tasks.TaskWindow;
import org.jackhuang.hellominecraft.tasks.download.FileDownloadTask;
import org.jackhuang.hellominecraft.utils.ArrayUtils;
import org.jackhuang.hellominecraft.utils.FileUtils;
import org.jackhuang.hellominecraft.utils.IOUtils;
import org.jackhuang.hellominecraft.utils.MinecraftVersionRequest;
import org.jackhuang.hellominecraft.utils.NetUtils;
import org.jackhuang.hellominecraft.utils.OS;
/**
*
* @author huang
*/
public final class MCUtils {
public static File getAssetObject(Gson gson, String dir, String assetVersion, String name) throws IOException {
File assetsDir = new File(dir, "assets");
File indexDir = new File(assetsDir, "indexes");
File objectsDir = new File(assetsDir, "objects");
File indexFile = new File(indexDir, assetVersion + ".json");
try {
AssetsIndex index = (AssetsIndex) gson.fromJson(FileUtils.readFileToString(indexFile, "UTF-8"), AssetsIndex.class);
String hash = ((AssetsObject) index.getFileMap().get(name)).getHash();
return new File(objectsDir, hash.substring(0, 2) + "/" + hash);
} catch(JsonSyntaxException e) {
throw new IOException("Assets file format malformed.", e);
}
}
private static int lessThan32(byte[] b, int x) {
for (; x < b.length; x++) {
if (b[x] < 32) {
return x;
}
}
return -1;
}
private static MinecraftVersionRequest getVersionOfOldMinecraft(ZipFile paramZipFile, ZipEntry paramZipEntry) throws IOException {
MinecraftVersionRequest r = new MinecraftVersionRequest();
byte[] tmp = NetUtils.getBytesFromStream(paramZipFile.getInputStream(paramZipEntry));
byte[] arrayOfByte = "Minecraft Minecraft ".getBytes("ASCII");
int j;
if ((j = ArrayUtils.matchArray(tmp, arrayOfByte)) < 0) {
r.type = MinecraftVersionRequest.Unkown;
return r;
}
int i = j + arrayOfByte.length;
if ((j = lessThan32(tmp, i)) < 0) {
r.type = MinecraftVersionRequest.Unkown;
return r;
}
String ver = new String(tmp, i, j - i, "ASCII");
r.version = ver;
if (paramZipFile.getEntry("META-INF/MANIFEST.MF") == null) {
r.type = MinecraftVersionRequest.Modified;
} else {
r.type = MinecraftVersionRequest.OK;
}
return r;
}
private static MinecraftVersionRequest getVersionOfNewMinecraft(ZipFile file, ZipEntry entry) throws IOException {
MinecraftVersionRequest r = new MinecraftVersionRequest();
byte[] tmp = NetUtils.getBytesFromStream(file.getInputStream(entry));
byte[] str = "-server.txt".getBytes("ASCII");
int j = ArrayUtils.matchArray(tmp, str);
if (j < 0) {
r.type = MinecraftVersionRequest.Unkown;
return r;
}
int i = j + str.length;
i += 11;
j = lessThan32(tmp, i);
if (j < 0) {
r.type = MinecraftVersionRequest.Unkown;
return r;
}
r.version = new String(tmp, i, j - i, "ASCII");
char ch = r.version.charAt(0);
// 1.8.1+
if(ch < '0' || ch > '9') {
str = "Can't keep up! Did the system time change, or is the server overloaded?".getBytes("ASCII");
j = ArrayUtils.matchArray(tmp, str);
if (j < 0) {
r.type = MinecraftVersionRequest.Unkown;
return r;
}
i = -1;
while (j > 0) {
if(tmp[j] >= 48 && tmp[j] <= 57) {
i = j;
break;
}
j--;
}
if (i == -1) {
r.type = MinecraftVersionRequest.Unkown;
return r;
}
int k = i;
while (tmp[k] >= 48 && tmp[k] <= 57 || tmp[k] == 46) k--;
k++;
r.version = new String(tmp, k, i - k + 1);
}
if (file.getEntry("META-INF/MANIFEST.MF") == null) {
r.type = MinecraftVersionRequest.Modified;
} else {
r.type = MinecraftVersionRequest.OK;
}
return r;
}
public static MinecraftVersionRequest minecraftVersion(File file) {
MinecraftVersionRequest r = new MinecraftVersionRequest();
if (!file.exists()) {
r.type = MinecraftVersionRequest.NotFound;
return r;
}
if (!file.isFile()) {
r.type = MinecraftVersionRequest.NotAFile;
return r;
}
if (!file.canRead()) {
r.type = MinecraftVersionRequest.NotReadable;
return r;
}
ZipFile localZipFile = null;
try {
localZipFile = new ZipFile(file);
ZipEntry minecraft = localZipFile
.getEntry("net/minecraft/client/Minecraft.class");
if (minecraft != null) {
return getVersionOfOldMinecraft(localZipFile, minecraft);
}
ZipEntry main = localZipFile.getEntry("net/minecraft/client/main/Main.class");
ZipEntry minecraftserver = localZipFile.getEntry("net/minecraft/server/MinecraftServer.class");
if ((main != null) && (minecraftserver != null)) {
return getVersionOfNewMinecraft(localZipFile, minecraftserver);
}
r.type = MinecraftVersionRequest.Invaild;
return r;
} catch (IOException localException) {
HMCLog.warn("Zip file is invalid", localException);
r.type = MinecraftVersionRequest.InvaildJar;
return r;
} finally {
if (localZipFile != null) {
try {
localZipFile.close();
} catch (IOException ex) {
HMCLog.warn("Failed to close zip file", ex);
}
}
}
}
public static File getLocation() {
String localObject = "minecraft";
String str1 = System.getProperty("user.home", ".");
File file;
OS os = OS.os();
if (os == OS.LINUX) {
file = new File(str1, '.' + (String) localObject + '/');
} else if (os == OS.WINDOWS) {
String str2;
if ((str2 = System.getenv("APPDATA")) != null) {
file = new File(str2, "." + (String) localObject + '/');
} else {
file = new File(str1, '.' + (String) localObject + '/');
}
} else if (os == OS.OSX) {
file = new File(str1, "Library/Application Support/" + localObject);
} else {
file = new File(str1, localObject + '/');
}
return file;
}
public static boolean is16Folder(String path) {
path = IOUtils.addSeparator(path);
return new File(path, "versions").exists();
}
public static String minecraft() {
String os = System.getProperty("os.name").trim().toLowerCase();
if (os.contains("mac")) {
return "minecraft";
}
return ".minecraft";
}
public static File getInitGameDir() {
File gameDir = IOUtils.currentDir();
if (gameDir.exists()) {
gameDir = new File(gameDir, MCUtils.minecraft());
if (!gameDir.exists()) {
File newFile = MCUtils.getLocation();
if(newFile.exists()) gameDir = newFile;
}
}
return gameDir;
}
public static MinecraftVersion downloadMinecraft(File gameDir, String id, DownloadType sourceType) {
String vurl = sourceType.getProvider().getVersionsDownloadURL() + id + "/";
File vpath = new File(gameDir, "versions/" + id);
File mvt = new File(vpath, id + ".json");
File mvj = new File(vpath, id + ".jar");
vpath.mkdirs();
mvt.delete();
mvj.delete();
if (TaskWindow.getInstance()
.addTask(new FileDownloadTask(vurl + id + ".json", IOUtils.tryGetCanonicalFile(mvt)).setTag(id + ".json"))
.addTask(new FileDownloadTask(vurl + id + ".jar", IOUtils.tryGetCanonicalFile(mvj)).setTag(id + ".jar"))
.start()) {
MinecraftVersion mv = new Gson().fromJson(FileUtils.readFileToStringQuietly(mvt), MinecraftVersion.class);
//File apath = new File(gameDir, "assets/indexes");
//downloadMinecraftAssetsIndex(apath, mv.assets, sourceType);
return mv;
}
return null;
}
public static boolean downloadMinecraftVersionJson(File gameDir, String id, DownloadType sourceType) {
String vurl = sourceType.getProvider().getVersionsDownloadURL() + id + "/";
File vpath = new File(gameDir, "versions/" + id);
File mvv = new File(vpath, id + ".json"), moved = null;
if (mvv.exists()) {
moved = new File(vpath, id + "-renamed.json");
mvv.renameTo(moved);
}
File mvt = new File(vpath, id + ".json");
vpath.mkdirs();
if (TaskWindow.getInstance()
.addTask(new FileDownloadTask(vurl + id + ".json", IOUtils.tryGetCanonicalFile(mvt)).setTag(id + ".json"))
.start()) {
if (moved != null) {
moved.delete();
}
return true;
} else {
mvt.delete();
if (moved != null) {
moved.renameTo(mvt);
}
return false;
}
}
public static boolean downloadMinecraftAssetsIndex(File assetsLocation, String assetsId, DownloadType sourceType) {
String aurl = sourceType.getProvider().getIndexesDownloadURL();
assetsLocation.mkdirs();
File assetsIndex = new File(assetsLocation, "indexes/" + assetsId + ".json");
File renamed = null;
if (assetsIndex.exists()) {
renamed = new File(assetsLocation, "indexes/" + assetsId + "-renamed.json");
assetsIndex.renameTo(renamed);
}
if (TaskWindow.getInstance()
.addTask(new FileDownloadTask(aurl + assetsId + ".json", IOUtils.tryGetCanonicalFile(assetsIndex)).setTag(assetsId + ".json"))
.start()) {
if (renamed != null) {
renamed.delete();
}
return true;
}
if (renamed != null) {
renamed.renameTo(assetsIndex);
}
return false;
}
public static MinecraftRemoteVersions getRemoteMinecraftVersions(DownloadType sourceType) throws IOException {
String result = NetUtils.doGet(sourceType.getProvider().getVersionsListDownloadURL());
return MinecraftRemoteVersions.fromJson(result);
}
}

@ -0,0 +1,38 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.jackhuang.hellominecraft.launcher.utils.assets;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Set;
/**
*
* @author hyh
*/
public class AssetsIndex {
public static final String DEFAULT_ASSET_NAME = "legacy";
private Map<String, AssetsObject> objects;
private boolean virtual;
public AssetsIndex() {
this.objects = new LinkedHashMap();
}
public Map<String, AssetsObject> getFileMap() {
return this.objects;
}
public Set<AssetsObject> getUniqueObjects() {
return new HashSet(this.objects.values());
}
public boolean isVirtual() {
return this.virtual;
}
}

@ -0,0 +1,91 @@
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package org.jackhuang.hellominecraft.launcher.utils.assets;
import java.util.ArrayList;
import java.util.List;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import org.jackhuang.hellominecraft.HMCLog;
import org.jackhuang.hellominecraft.utils.EventHandler;
import org.jackhuang.hellominecraft.utils.MathUtils;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
/**
*
* @author hyh
*/
public class AssetsLoader extends Thread {
Document doc;
Element root;
NodeList nodes;
public String uri;
ArrayList<Contents> al;
public final EventHandler<Throwable> failedEvent = new EventHandler<Throwable>(this);
public final EventHandler<List<Contents>> successEvent = new EventHandler<List<Contents>>(this);
AssetsLoader(String uri) {
this.uri = uri;
}
private Contents modifyContents(NodeList contents) {
Contents ret = new Contents();
for (int i = 0; i < contents.getLength(); i++) {
Node result = contents.item(i);
if (result.getNodeType() == Node.ELEMENT_NODE) {
if (result.getNodeName().equalsIgnoreCase("Key")) {
ret.key = result.getTextContent();
}
if (result.getNodeName().equalsIgnoreCase("ETag")) {
ret.eTag = result.getTextContent();
}
if (result.getNodeName().equalsIgnoreCase("LastModified")) {
ret.lastModified = result.getTextContent();
}
if (result.getNodeName().equalsIgnoreCase("Size")) {
ret.size = MathUtils.parseInt(result.getTextContent(), 0);
}
if (result.getNodeName().equalsIgnoreCase("StorageClass")) {
ret.storageClass = result.getTextContent();
}
}
}
return ret;
}
@Override
public void run() {
Thread.currentThread().setName("AssetsLoader");
al = new ArrayList<Contents>();
try {
HMCLog.log("AssetsLoader - Download begin.");
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder db = factory.newDocumentBuilder();
doc = db.parse(uri);
HMCLog.log("AssetsLoader - Download end and format begin.");
root = doc.getDocumentElement();
nodes = root.getChildNodes();
for (int i = 0; i < nodes.getLength(); i++) {
Node result = nodes.item(i);
if (result.getNodeType() == Node.ELEMENT_NODE && result.getNodeName().equals("Contents")) {
Contents c = modifyContents(result.getChildNodes());
if(c.key != null)
al.add(c);
}
}
HMCLog.log("AssetsLoader - Format end.");
successEvent.execute(al);
} catch (Exception e) {
HMCLog.warn("AssetsLoader - Failed", e);
failedEvent.execute(e);
}
}
}

@ -0,0 +1,18 @@
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package org.jackhuang.hellominecraft.launcher.utils.assets;
import java.util.ArrayList;
/**
*
* @author hyh
*/
public interface AssetsLoaderListener {
void OnDone(ArrayList<Contents> loader);
void OnFailed(Exception e);
}

@ -0,0 +1,99 @@
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package org.jackhuang.hellominecraft.launcher.utils.assets;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Map;
import org.jackhuang.hellominecraft.C;
import org.jackhuang.hellominecraft.HMCLog;
import org.jackhuang.hellominecraft.launcher.utils.settings.Settings;
import org.jackhuang.hellominecraft.tasks.Task;
import org.jackhuang.hellominecraft.utils.FileUtils;
import org.jackhuang.hellominecraft.utils.IOUtils;
import org.jackhuang.hellominecraft.utils.StrUtils;
import org.jackhuang.hellominecraft.launcher.utils.MCUtils;
import org.jackhuang.hellominecraft.launcher.utils.download.IDownloadProvider;
import org.jackhuang.hellominecraft.utils.functions.Consumer;
import org.jackhuang.hellominecraft.utils.VersionNumber;
/**
*
* @author hyh
*/
public class AssetsMojangLoader extends IAssetsHandler {
public AssetsMojangLoader(String name) {
super(name);
}
@Override
public void getList(final Consumer<String[]> dl) {
if (mv == null) {
dl.accept(null);
return;
}
String assetsId = mv.assets == null ? "legacy" : mv.assets;
File assets = mp.getAssets();
HMCLog.log("Get index: " + assetsId);
File f = IOUtils.tryGetCanonicalFile(new File(assets, "indexes/" + assetsId + ".json"));
if (!f.exists() && !MCUtils.downloadMinecraftAssetsIndex(assets, assetsId, Settings.s().getDownloadSource())) {
dl.accept(null);
return;
}
String result;
try {
result = FileUtils.readFileToString(f);
} catch (IOException ex) {
HMCLog.warn("Failed to read index json: " + f, ex);
dl.accept(null);
return;
}
if (StrUtils.isBlank(result)) {
HMCLog.err("Index json is empty, please redownload it!");
dl.accept(null);
return;
}
AssetsIndex o;
try {
o = C.gson.fromJson(result, AssetsIndex.class);
} catch (Exception e) {
HMCLog.err("Failed to parse index json, please redownload it!", e);
dl.accept(null);
return;
}
assetsDownloadURLs = new ArrayList<>();
assetsLocalNames = new ArrayList<>();
ArrayList<String> al = new ArrayList<>();
contents = new ArrayList<>();
if (o != null && o.getFileMap() != null)
for (Map.Entry<String, AssetsObject> e : o.getFileMap().entrySet()) {
Contents c = new Contents();
c.key = e.getValue().getHash().substring(0, 2) + "/" + e.getValue().getHash();
c.eTag = e.getValue().getHash();
c.size = e.getValue().getSize();
contents.add(c);
assetsDownloadURLs.add(c.key);
assetsLocalNames.add(new File(assets, "objects" + File.separator + c.key.replace("/", File.separator)));
al.add(e.getKey());
}
dl.accept(al.toArray(new String[1]));
}
@Override
public Task getDownloadTask(IDownloadProvider sourceType) {
return new AssetsTask(sourceType.getAssetsDownloadURL());
}
@Override
public boolean isVersionAllowed(String formattedVersion) {
VersionNumber ur = VersionNumber.check(formattedVersion);
if (ur == null) return false;
return VersionNumber.check("1.6.0").compareTo(ur) <= 0;
}
}

@ -0,0 +1,61 @@
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package org.jackhuang.hellominecraft.launcher.utils.assets;
import java.io.File;
import java.util.ArrayList;
import org.jackhuang.hellominecraft.HMCLog;
import org.jackhuang.hellominecraft.launcher.utils.download.IDownloadProvider;
import org.jackhuang.hellominecraft.utils.VersionNumber;
import org.jackhuang.hellominecraft.tasks.Task;
import org.jackhuang.hellominecraft.utils.functions.Consumer;
/**
*
* @author hyh
*/
public class AssetsMojangOldLoader extends IAssetsHandler {
private static final String URL = "http://bmclapi.bangbang93.com/resources/";
public AssetsMojangOldLoader(String name) {
super(name);
}
@Override
public void getList(final Consumer<String[]> dl) {
AssetsLoader al = new AssetsLoader(URL);
al.failedEvent.register((sender, e) -> {
HMCLog.warn("Failed to get assets list.", e);
dl.accept(null);
return true;
});
al.successEvent.register((sender, t) -> {
assetsDownloadURLs = new ArrayList<>();
assetsLocalNames = new ArrayList<>();
contents = t;
for (Contents c : t) {
assetsDownloadURLs.add(c.key);
assetsLocalNames.add(new File(mp.getAssets(), c.key.replace("/", File.separator)));
}
dl.accept(assetsDownloadURLs.toArray(new String[1]));
return true;
});
new Thread(al).start();
}
@Override
public boolean isVersionAllowed(String formattedVersion) {
VersionNumber r = VersionNumber.check(formattedVersion);
if(r == null) return false;
return VersionNumber.check("1.7.2").compareTo(r) >= 0 &&
VersionNumber.check("1.6.0").compareTo(r) <= 0;
}
@Override
public Task getDownloadTask(IDownloadProvider sourceType) {
return new AssetsTask(URL);
}
}

@ -0,0 +1,42 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.jackhuang.hellominecraft.launcher.utils.assets;
/**
*
* @author hyh
*/
public class AssetsObject {
private String hash;
private long size;
public AssetsObject() {
}
public String getHash() {
return this.hash;
}
public long getSize() {
return this.size;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
AssetsObject that = (AssetsObject) o;
if (this.size != that.size) return false;
return this.hash.equals(that.hash);
}
@Override
public int hashCode() {
int result = this.hash.hashCode();
result = 31 * result + (int) (this.size ^ this.size >>> 32);
return result;
}
}

@ -0,0 +1,16 @@
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package org.jackhuang.hellominecraft.launcher.utils.assets;
/**
*
* @author hyh
*/
public class Contents {
public String key, eTag, lastModified, storageClass;
public long size;
}

@ -0,0 +1,152 @@
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package org.jackhuang.hellominecraft.launcher.utils.assets;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import org.jackhuang.hellominecraft.C;
import org.jackhuang.hellominecraft.HMCLog;
import org.jackhuang.hellominecraft.launcher.launch.IMinecraftProvider;
import org.jackhuang.hellominecraft.launcher.utils.download.IDownloadProvider;
import org.jackhuang.hellominecraft.launcher.utils.version.MinecraftVersion;
import org.jackhuang.hellominecraft.tasks.Task;
import org.jackhuang.hellominecraft.tasks.download.FileDownloadTask;
import org.jackhuang.hellominecraft.utils.functions.Consumer;
import org.jackhuang.hellominecraft.utils.DigestUtils;
import org.jackhuang.hellominecraft.utils.IOUtils;
import org.jackhuang.hellominecraft.utils.NetUtils;
/**
* Assets
*
* @author hyh
*/
public abstract class IAssetsHandler {
protected ArrayList<String> assetsDownloadURLs;
protected ArrayList<File> assetsLocalNames;
protected final String name;
protected List<Contents> contents;
public IAssetsHandler(String name) {
this.name = name;
}
private static final List<IAssetsHandler> assetsHandlers = new ArrayList<>();
public static IAssetsHandler getAssetsHandler(int i) {
return assetsHandlers.get(i);
}
public static List<IAssetsHandler> getAssetsHandlers() {
return assetsHandlers;
}
static {
assetsHandlers.add(new AssetsMojangLoader(C.i18n("assets.list.1_7_3_after")));
//assetsHandlers.add(new AssetsMojangOldLoader(C.i18n("assets.list.1_6")));
}
/**
* interface name
*
* @return
*/
public String getName() {
return name;
}
/**
* All the files assets needed
*
* @param x finished event
*/
public abstract void getList(Consumer<String[]> x);
/**
* Will be invoked when the user invoked "Download all assets".
*
* @param sourceType Download Source
* @return Download File Task
*/
public abstract Task getDownloadTask(IDownloadProvider sourceType);
/**
* assets path
*/
protected MinecraftVersion mv;
protected IMinecraftProvider mp;
/**
* @param mp
* @param mv
*/
public void setAssets(IMinecraftProvider mp, MinecraftVersion mv) {
this.mp = mp;
this.mv = mv;
}
public abstract boolean isVersionAllowed(String formattedVersion);
protected class AssetsTask extends Task {
ArrayList<Task> al;
String u;
int progress, max;
public AssetsTask(String url) {
this.u = url;
}
@Override
public boolean executeTask() {
if (mv == null || assetsDownloadURLs == null) {
setFailReason(new RuntimeException(C.i18n("assets.not_refreshed")));
return false;
}
progress = 0;
max = assetsDownloadURLs.size();
al = new ArrayList<>();
for (int i = 0; i < max; i++) {
String mark = assetsDownloadURLs.get(i);
String url = u + mark;
File location = assetsLocalNames.get(i);
if (!location.getParentFile().exists()) location.getParentFile().mkdirs();
if (location.isDirectory()) continue;
boolean need = true;
try {
if (location.exists()) {
FileInputStream fis = new FileInputStream(location);
String sha = DigestUtils.sha1Hex(NetUtils.getBytesFromStream(fis));
IOUtils.closeQuietly(fis);
if (contents.get(i).eTag.equals(sha)) {
HMCLog.log("File " + assetsLocalNames.get(i) + " has downloaded successfully, skipped downloading.");
continue;
}
}
} catch (IOException e) {
HMCLog.warn("Failed to get hash: " + location, e);
need = !location.exists();
}
if (need) al.add(new FileDownloadTask(url, location).setTag(mark));
}
return true;
}
@Override
public Collection<Task> getAfterTasks() {
return al;
}
@Override
public String getInfo() {
return C.i18n("assets.download");
}
}
}

@ -0,0 +1,95 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.jackhuang.hellominecraft.launcher.utils.auth;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import org.jackhuang.hellominecraft.utils.DigestUtils;
/**
*
* @author hyh
*/
public final class BestLogin extends IAuthenticator {
public BestLogin(String clientToken) {
super(clientToken);
}
@Override
public UserProfileProvider login(LoginInfo info) {
try {
String request = "bl:l:" + info.username + ":" + DigestUtils.sha1Hex(info.password);
Socket socket = new Socket("auth.zhh0000zhh.com", 8);
OutputStream os = socket.getOutputStream();
os.write(request.length());
os.write(request.getBytes());
UserProfileProvider lr = new UserProfileProvider();
lr.setSuccess(false);
InputStream is = socket.getInputStream();
int code = is.read();
switch (code) {
case -1:
lr.setErrorReason("internet error.");
break;
case 200:
lr.setErrorReason("server restarting.");
break;
case 255:
lr.setErrorReason("unknown error");
break;
case 3:
lr.setErrorReason("unregistered.");
break;
case 50:
lr.setErrorReason("please update your launcher and act your account.");
break;
case 2:
lr.setErrorReason("wrong password.");
break;
case 100:
lr.setErrorReason("server reloading.");
break;
case 0:
lr.setSuccess(true);
byte[] b = new byte[64];
is.read(b, 0, b.length);
String[] ss = new String(b).split(":");
lr.setUserName(info.username);
lr.setUserId(ss[1]);
lr.setSession(ss[0]);
lr.setAccessToken(ss[0]);
break;
}
lr.setUserType("Legacy");
return lr;
} catch (Throwable t) {
UserProfileProvider lr = new UserProfileProvider();
lr.setSuccess(false);
lr.setErrorReason(t.getMessage());
return lr;
}
}
@Override
public String getName() {
return "BestLogin";
}
@Override
public UserProfileProvider loginBySettings() {
return null;
}
@Override
public void logout() {
}
}

@ -0,0 +1,83 @@
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package org.jackhuang.hellominecraft.launcher.utils.auth;
import java.util.ArrayList;
import java.util.List;
import org.jackhuang.hellominecraft.launcher.utils.settings.Settings;
/**
* Login interface
*
* @author hyh
*/
public abstract class IAuthenticator {
public static final YggdrasilAuthenticator yggdrasilLogin;
public static final OfflineAuthenticator offlineLogin;
public static final SkinmeAuthenticator skinmeLogin;
//public static final BestLogin bestLogin;
public static final List<IAuthenticator> logins;
static {
String clientToken = Settings.s().getClientToken();
logins = new ArrayList<>();
logins.add(offlineLogin = new OfflineAuthenticator(clientToken));
logins.add(yggdrasilLogin = new YggdrasilAuthenticator(clientToken));
logins.add(skinmeLogin = new SkinmeAuthenticator(clientToken));
//logins.add(bestLogin = new BestLogin(clientToken));
yggdrasilLogin.onLoadSettings(Settings.s().getYggdrasilConfig());
Runtime.getRuntime().addShutdownHook(new Thread() {
@Override
public void run() {
Settings.s().setYggdrasilConfig(yggdrasilLogin.onSaveSettings());
}
});
}
protected String clientToken;
public IAuthenticator(String clientToken) {
this.clientToken = clientToken;
}
/**
* Login Method
*
* @param info username & password
* @return login result
*/
public abstract UserProfileProvider login(LoginInfo info);
/**
*
* @return the name of login method.
*/
public abstract String getName();
/**
* Has password?
*
* @return Will I hide password box?
*/
public boolean isHidePasswordBox() {
return false;
}
public boolean isLoggedIn() {
return false;
}
public void setRememberMe(boolean is) {
}
public abstract UserProfileProvider loginBySettings();
public abstract void logout();
}

@ -0,0 +1,18 @@
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package org.jackhuang.hellominecraft.launcher.utils.auth;
/**
*
* @author hyh
*/
public final class LoginInfo {
public String username, password;
public LoginInfo(String username, String password) {
this.username = username;
this.password = password;
}
}

@ -0,0 +1,55 @@
package org.jackhuang.hellominecraft.launcher.utils.auth;
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
import org.jackhuang.hellominecraft.C;
import org.jackhuang.hellominecraft.utils.StrUtils;
import org.jackhuang.hellominecraft.utils.DigestUtils;
/**
*
* @author hyh
*/
public final class OfflineAuthenticator extends IAuthenticator {
public OfflineAuthenticator(String clientToken) {
super(clientToken);
}
@Override
public UserProfileProvider login(LoginInfo info) {
UserProfileProvider result = new UserProfileProvider();
result.setSuccess(StrUtils.isNotBlank(info.username));
result.setUserName(info.username);
String md5 = DigestUtils.md5Hex(info.username);
String uuid = md5.substring(0, 8) + '-' + md5.substring(8, 12) + '-' + md5.substring(12, 16) + '-' + md5.substring(16, 21) + md5.substring(21);
result.setSession(uuid);
result.setUserId(uuid);
result.setAccessToken("${auth_access_token}");
result.setUserType("Legacy");
result.setErrorReason(C.i18n("login.no_Player007"));
return result;
}
@Override
public String getName() {
return C.i18n("login.methods.offline");
}
@Override
public boolean isHidePasswordBox() {
return true;
}
@Override
public UserProfileProvider loginBySettings() {
return null;
}
@Override
public void logout() {
}
}

@ -0,0 +1,125 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.jackhuang.hellominecraft.launcher.utils.auth;
import org.jackhuang.hellominecraft.C;
import org.jackhuang.hellominecraft.HMCLog;
import org.jackhuang.hellominecraft.utils.DigestUtils;
import org.jackhuang.hellominecraft.utils.NetUtils;
import org.jackhuang.hellominecraft.views.Selector;
/**
*
* @author hyh
*/
public final class SkinmeAuthenticator extends IAuthenticator {
public SkinmeAuthenticator(String clientToken) {
super(clientToken);
}
public String[] parseType1(String s) {
return s.split(",");
}
public String getCharacter(String user, String hash, String $char) throws Exception {
if ($char == null)
return NetUtils.doGet(
"http://www.skinme.cc/api/login.php?user=" + user + "&hash=" + hash);
else
return NetUtils.doGet(
"http://www.skinme.cc/api/login.php?user=" + user + "&hash=" + hash + "&char=" + $char);
}
@Override
public UserProfileProvider login(LoginInfo info) {
UserProfileProvider req = new UserProfileProvider();
if (info.username == null || !info.username.contains("@")) {
req.setSuccess(false);
req.setErrorReason(C.i18n("login.not_email"));
return req;
}
try {
String usr = info.username.toLowerCase();
String pwd = info.password;
String str = DigestUtils.sha1Hex(usr);
String hashCode = DigestUtils.sha1Hex(DigestUtils.md5Hex(DigestUtils.sha1Hex(pwd) + pwd) + str);
String data = getCharacter(usr, hashCode, null);
String[] sl = data.split(":");
if (null != sl[0]) switch (sl[0]) {
case "0":
req.setSuccess(false);
req.setErrorReason(sl[1]);
break;
case "1": {
req.setSuccess(true);
String[] s = parseType1(sl[1]);
req.setUserName(s[0]);
req.setSession(s[1]);
req.setUserId(s[1]);
req.setAccessToken(s[1]);
break;
}
case "2": {
req.setSuccess(true);
String[] charators = sl[1].split(";");
int len = charators.length;
String[] $char = new String[len];
String[] user = new String[len];
System.out.println(sl[1]);
for (int i = 0; i < len; i++) {
String[] charator = charators[i].split(",");
$char[i] = charator[0];
user[i] = charator[1];
}
Selector s = new Selector(null, user, C.i18n("login.choose_charactor"));
s.setVisible(true);
if (s.sel == Selector.failedToSel) {
req.setSuccess(false);
req.setErrorReason(C.i18n("message.cancelled"));
} else {
int index = s.sel;
String character = $char[index];
sl = getCharacter(usr, hashCode, character).split(":");
String[] s2 = parseType1(sl[1]);
req.setUserName(s2[0]);
req.setSession(s2[1]);
req.setUserId(s2[1]);
req.setAccessToken(s2[1]);
}
break;
}
}
req.setUserType("Legacy");
return req;
} catch (Exception e) {
HMCLog.warn("Failed to login skinme.", e);
req.setUserName(info.username);
req.setSuccess(false);
req.setUserType("Legacy");
req.setErrorReason(e.getMessage());
return req;
}
}
@Override
public String getName() {
return "Skinme";
}
@Override
public UserProfileProvider loginBySettings() {
return null;
}
@Override
public void logout() {
}
}

@ -0,0 +1,112 @@
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package org.jackhuang.hellominecraft.launcher.utils.auth;
/**
*
* @author hyh
*/
public final class UserProfileProvider {
public String getUserName() {
return username;
}
public void setUserName(String username) {
this.username = username;
}
public String getUserId() {
return userId;
}
public void setUserId(String userId) {
this.userId = userId;
}
public String getSession() {
return session;
}
public void setSession(String session) {
this.session = session;
}
public String getAccessToken() {
return accessToken;
}
public void setAccessToken(String accessToken) {
this.accessToken = accessToken;
}
public boolean isSuccessful() {
return success;
}
public void setSuccess(boolean success) {
this.success = success;
}
public String getErrorReason() {
return error;
}
public void setErrorReason(String error) {
this.error = error;
}
public String getUserProperties() {
return userProperties;
}
public void setUserProperties(String userProperties) {
this.userProperties = userProperties;
}
public String getUserPropertyMap() {
return userPropertyMap;
}
public void setUserPropertyMap(String userPropertyMap) {
this.userPropertyMap = userPropertyMap;
}
public String getOtherInfo() {
return otherInfo;
}
public void setOtherInfo(String otherInfo) {
this.otherInfo = otherInfo;
}
public String getClientIdentifier() {
return clientIdentifier;
}
public void setClientIdentifier(String clientIdentifier) {
this.clientIdentifier = clientIdentifier;
}
public String getUserType() {
return userType;
}
public void setUserType(String userType) {
this.userType = userType;
}
private String username = "";
private String userId = "";
private String session = "";
private String accessToken = "";
private boolean success = false;
private String error = "";
private String userProperties = "{}";
private String userPropertyMap = "{}";
private String otherInfo = "";
private String clientIdentifier = "";
private String userType = "Offline";
}

@ -0,0 +1,145 @@
package org.jackhuang.hellominecraft.launcher.utils.auth;
import com.google.gson.GsonBuilder;
import java.net.Proxy;
import java.util.Map;
import javax.swing.JOptionPane;
import org.jackhuang.hellominecraft.C;
import org.jackhuang.hellominecraft.HMCLog;
import org.jackhuang.hellominecraft.utils.ArrayUtils;
import org.jackhuang.hellominecraft.views.Selector;
import org.jackhuang.mojang.authlib.Agent;
import org.jackhuang.mojang.authlib.GameProfile;
import org.jackhuang.mojang.authlib.UserType;
import org.jackhuang.mojang.authlib.properties.PropertyMap;
import org.jackhuang.mojang.authlib.yggdrasil.YggdrasilAuthenticationService;
import org.jackhuang.mojang.authlib.yggdrasil.YggdrasilUserAuthentication;
import org.jackhuang.mojang.util.LegacyPropertyMapSerializer;
import org.jackhuang.mojang.util.UUIDTypeAdapter;
/**
*
* @author hyh
*/
public final class YggdrasilAuthenticator extends IAuthenticator {
YggdrasilAuthenticationService service;
YggdrasilUserAuthentication ua;
public YggdrasilAuthenticator(String clientToken) {
super(clientToken);
service = new YggdrasilAuthenticationService(Proxy.NO_PROXY, clientToken);
ua = (YggdrasilUserAuthentication)service.createUserAuthentication(Agent.MINECRAFT);
}
@Override
public UserProfileProvider login(LoginInfo info) {
if(ua.canPlayOnline()) {
UserProfileProvider result = new UserProfileProvider();
result.setUserName(info.username);
result.setSuccess(true);
result.setUserId(UUIDTypeAdapter.fromUUID(ua.getSelectedProfile().getId()));
result.setUserProperties(new GsonBuilder().registerTypeAdapter(PropertyMap.class, new LegacyPropertyMapSerializer()).create().toJson(ua.getUserProperties()));
result.setUserPropertyMap(new GsonBuilder().registerTypeAdapter(PropertyMap.class, new PropertyMap.Serializer()).create().toJson(ua.getUserProperties()));
result.setAccessToken(ua.getAuthenticatedToken());
result.setSession(ua.getAuthenticatedToken());
result.setUserType(ua.getUserType().getName());
return result;
}
UserProfileProvider result = new UserProfileProvider();
String usr = info.username;
if(info.username == null || !info.username.contains("@")) {
result.setSuccess(false);
result.setErrorReason(C.i18n("login.not_email"));
return result;
}
String pwd = info.password;
if(!ua.isLoggedIn())
ua.setPassword(pwd);
ua.setUsername(usr);
try {
ua.logIn();
if(!ua.isLoggedIn()) throw new Exception(C.i18n("login.wrong_password"));
GameProfile selectedProfile = ua.getSelectedProfile();
GameProfile[] profiles = ua.getAvailableProfiles();
String[] names;
String username;
if(selectedProfile == null) {
if(ArrayUtils.isNotEmpty(profiles)) {
names = new String[profiles.length];
for(int i = 0; i < profiles.length; i++) {
names[i] = profiles[i].getName();
}
Selector s = new Selector(null, names, C.i18n("login.choose_charactor"));
s.setVisible(true);
selectedProfile = profiles[s.sel];
username = names[s.sel];
} else {
username = JOptionPane.showInputDialog(C.i18n("login.no_charactor"));
}
} else {
username = selectedProfile.getName();
}
result.setUserName(username);
result.setSuccess(true);
result.setUserId(UUIDTypeAdapter.fromUUID(selectedProfile.getId()));
result.setUserProperties(new GsonBuilder().registerTypeAdapter(PropertyMap.class, new LegacyPropertyMapSerializer()).create().toJson(ua.getUserProperties()));
result.setUserPropertyMap(new GsonBuilder().registerTypeAdapter(PropertyMap.class, new PropertyMap.Serializer()).create().toJson(ua.getUserProperties()));
result.setAccessToken(ua.getAuthenticatedToken());
result.setSession(ua.getAuthenticatedToken());
result.setUserType(ua.getUserType().getName());
} catch (Exception ex) {
result.setErrorReason(ex.getMessage());
result.setSuccess(false);
result.setUserName(ua.getUserID());
result.setUserType(UserType.MOJANG.getName());
HMCLog.err("Failed to login by yggdrasil authentication.", ex);
}
return result;
}
@Override
public boolean isLoggedIn() {
return ua.isLoggedIn();
}
@Override
public String getName() {
return C.i18n("login.methods.yggdrasil");
}
public Map onSaveSettings() {
return ua.saveForStorage();
}
public void onLoadSettings(Map settings) {
if(settings == null) return;
ua.loadFromStorage(settings);
}
@Override
public UserProfileProvider loginBySettings() {
UserProfileProvider info = new UserProfileProvider();
try {
ua.logIn();
if(!ua.isLoggedIn()) throw new Exception(C.i18n("WrongPassword"));
GameProfile profile = ua.getSelectedProfile();
info.setUserName(profile.getName());
info.setSuccess(true);
info.setUserId(profile.getId().toString());
info.setAccessToken(ua.getAuthenticatedToken());
} catch (Exception ex) {
info.setErrorReason(ex.getMessage());
info.setSuccess(false);
info.setUserName(ua.getUserID());
}
return info;
}
@Override
public void logout() {
ua.logOut();
}
}

@ -0,0 +1,70 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.jackhuang.hellominecraft.launcher.utils.download;
import org.jackhuang.hellominecraft.C;
import org.jackhuang.hellominecraft.launcher.utils.installers.InstallerVersionList;
/**
*
* @author huangyuhui
*/
public class BMCLAPIDownloadProvider implements IDownloadProvider {
@Override
public InstallerVersionList getForgeInstaller() {
return org.jackhuang.hellominecraft.launcher.utils.installers.forge.bmcl.ForgeBMCLVersionList.getInstance();
}
@Override
public InstallerVersionList getLiteLoaderInstaller() {
return org.jackhuang.hellominecraft.launcher.utils.installers.liteloader.LiteLoaderVersionList.getInstance();
}
@Override
public InstallerVersionList getOptiFineInstaller() {
return org.jackhuang.hellominecraft.launcher.utils.installers.optifine.bmcl.OptiFineBMCLVersionList.getInstance();
}
@Override
public InstallerVersionList getInstallerByType(String type) {
if(type.equalsIgnoreCase("forge")) return getForgeInstaller();
if(type.equalsIgnoreCase("liteloader")) return getLiteLoaderInstaller();
if(type.equalsIgnoreCase("optifine")) return getOptiFineInstaller();
return null;
}
@Override
public String getLibraryDownloadURL() {
return "http://bmclapi2.bangbang93.com/libraries";
}
@Override
public String getVersionsDownloadURL() {
return "http://bmclapi2.bangbang93.com/versions/";
}
@Override
public String getIndexesDownloadURL() {
return "http://bmclapi2.bangbang93.com/indexes/";
}
@Override
public String getVersionsListDownloadURL() {
return "http://bmclapi2.bangbang93.com/versions/versions.json";
}
@Override
public String getAssetsDownloadURL() {
return "http://bmclapi2.bangbang93.com/assets/";
}
@Override
public boolean isAllowedToUseSelfURL() {
return false;
}
}

@ -0,0 +1,33 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.jackhuang.hellominecraft.launcher.utils.download;
import org.jackhuang.hellominecraft.C;
/**
*
* @author hyh
*/
public enum DownloadType {
Mojang(C.i18n("download.mojang"), new MojangDownloadProvider()),
BMCL(C.i18n("download.BMCL"), new BMCLAPIDownloadProvider());
private final String name;
private final IDownloadProvider provider;
DownloadType(String a, IDownloadProvider provider) {
name = a;
this.provider = provider;
}
public IDownloadProvider getProvider() {
return provider;
}
public String getName() {
return name;
}
}

@ -0,0 +1,25 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.jackhuang.hellominecraft.launcher.utils.download;
import org.jackhuang.hellominecraft.launcher.utils.installers.InstallerVersionList;
/**
*
* @author huangyuhui
*/
public interface IDownloadProvider {
InstallerVersionList getInstallerByType(String type);
InstallerVersionList getForgeInstaller();
InstallerVersionList getLiteLoaderInstaller();
InstallerVersionList getOptiFineInstaller();
String getLibraryDownloadURL();
String getVersionsDownloadURL();
String getIndexesDownloadURL();
String getVersionsListDownloadURL();
String getAssetsDownloadURL();
boolean isAllowedToUseSelfURL();
}

@ -0,0 +1,70 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.jackhuang.hellominecraft.launcher.utils.download;
import org.jackhuang.hellominecraft.C;
import org.jackhuang.hellominecraft.launcher.utils.installers.InstallerVersionList;
/**
*
* @author huangyuhui
*/
public class MojangDownloadProvider implements IDownloadProvider {
@Override
public InstallerVersionList getForgeInstaller() {
return org.jackhuang.hellominecraft.launcher.utils.installers.forge.vanilla.MinecraftForgeVersionList.getInstance();
}
@Override
public InstallerVersionList getLiteLoaderInstaller() {
return org.jackhuang.hellominecraft.launcher.utils.installers.liteloader.LiteLoaderVersionList.getInstance();
}
@Override
public InstallerVersionList getOptiFineInstaller() {
return org.jackhuang.hellominecraft.launcher.utils.installers.optifine.vanilla.OptiFineVersionList.getInstance();
}
@Override
public InstallerVersionList getInstallerByType(String type) {
if(type.equalsIgnoreCase("forge")) return getForgeInstaller();
if(type.equalsIgnoreCase("liteloader")) return getLiteLoaderInstaller();
if(type.equalsIgnoreCase("optifine")) return getOptiFineInstaller();
return null;
}
@Override
public String getLibraryDownloadURL() {
return "https://libraries.minecraft.net";
}
@Override
public String getVersionsDownloadURL() {
return "https://s3.amazonaws.com/Minecraft.Download/versions/";
}
@Override
public String getIndexesDownloadURL() {
return "https://s3.amazonaws.com/Minecraft.Download/indexes/";
}
@Override
public String getVersionsListDownloadURL() {
return "https://s3.amazonaws.com/Minecraft.Download/versions/versions.json";
}
@Override
public String getAssetsDownloadURL() {
return "http://resources.download.minecraft.net/";
}
@Override
public boolean isAllowedToUseSelfURL() {
return true;
}
}

@ -0,0 +1,22 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.jackhuang.hellominecraft.launcher.utils.installers;
import com.google.gson.annotations.SerializedName;
import org.jackhuang.hellominecraft.launcher.utils.version.MinecraftVersion;
import org.jackhuang.hellominecraft.launcher.utils.installers.forge.Install;
/**
*
* @author hyh
*/
public class InstallProfile {
@SerializedName("install")
public Install install;
@SerializedName("versionInfo")
public MinecraftVersion versionInfo;
}

@ -0,0 +1,56 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.jackhuang.hellominecraft.launcher.utils.installers;
import java.util.Comparator;
import java.util.List;
import org.jackhuang.hellominecraft.utils.functions.Consumer;
/**
*
* @author hyh
*/
public abstract class InstallerVersionList implements Consumer<String[]> {
/**
* Refresh installer versions list from the downloaded content.
*/
public abstract void refreshList(String[] versions) throws Exception;
public abstract String getName();
public abstract List<InstallerVersion> getVersions(String mcVersion);
public static class InstallerVersion implements Comparable<InstallerVersion> {
public String selfVersion, mcVersion;
public String installer, universal;
public String changelog;
public InstallerVersion(String selfVersion, String mcVersion) {
this.selfVersion = selfVersion;
this.mcVersion = mcVersion;
}
@Override
public int compareTo(InstallerVersion o) {
return selfVersion.compareTo(o.selfVersion);
}
}
public static class InstallerVersionComparator implements Comparator<InstallerVersion> {
public static final InstallerVersionComparator INSTANCE = new InstallerVersionComparator();
@Override
public int compare(InstallerVersion o1, InstallerVersion o2) {
return o2.compareTo(o1);
}
}
@Override
public void accept(String[] v) {
try {
refreshList(v);
} catch (Exception ex) {
throw new RuntimeException(ex);
}
}
}

@ -0,0 +1,21 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.jackhuang.hellominecraft.launcher.utils.installers;
import java.util.Comparator;
import org.jackhuang.hellominecraft.launcher.utils.installers.InstallerVersionList.InstallerVersion;
/**
*
* @author hyh
*/
public class InstallerVersionNewerComparator implements Comparator<InstallerVersion> {
@Override
public int compare(InstallerVersion o1, InstallerVersion o2) {
return -o1.compareTo(o2);
}
}

@ -0,0 +1,35 @@
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package org.jackhuang.hellominecraft.launcher.utils.installers;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import org.jackhuang.hellominecraft.utils.Compressor;
import org.jackhuang.hellominecraft.utils.FileUtils;
import org.jackhuang.hellominecraft.utils.IOUtils;
/**
*
* @author hyh
*/
public class PackMinecraftInstaller {
File dest;
ArrayList<String> src;
public PackMinecraftInstaller(ArrayList<String> src, File dest) {
this.dest = dest;
this.src = src;
}
public void install() throws IOException {
File file = new File(IOUtils.currentDir(), "HMCL-MERGE-TEMP");
file.mkdirs();
for (String src1 : src) Compressor.unzip(new File(src1), file);
Compressor.zip(file, dest);
FileUtils.deleteDirectory(file);
}
}

@ -0,0 +1,103 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.jackhuang.hellominecraft.launcher.utils.installers.forge;
import org.jackhuang.hellominecraft.launcher.utils.installers.InstallProfile;
import com.google.gson.Gson;
import com.google.gson.JsonSyntaxException;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import org.jackhuang.hellominecraft.C;
import org.jackhuang.hellominecraft.HMCLog;
import org.jackhuang.hellominecraft.launcher.launch.IMinecraftProvider;
import org.jackhuang.hellominecraft.launcher.utils.settings.Settings;
import org.jackhuang.hellominecraft.tasks.Task;
import org.jackhuang.hellominecraft.utils.FileUtils;
import org.jackhuang.hellominecraft.utils.NetUtils;
import org.jackhuang.hellominecraft.launcher.utils.version.MinecraftLibrary;
import org.jackhuang.hellominecraft.utils.MessageBox;
/**
*
* @author hyh
*/
public class ForgeInstaller extends Task {
private final Gson gson = new Gson();
public File gameDir;
public File forgeInstaller;
public IMinecraftProvider mp;
public ForgeInstaller(IMinecraftProvider mp, File forgeInstaller) {
this.gameDir = mp.getBaseFolder();
this.forgeInstaller = forgeInstaller;
this.mp = mp;
}
@Override
public boolean executeTask() {
try {
HMCLog.log("Extracting install profiles...");
ZipFile zipFile = new ZipFile(forgeInstaller);
ZipEntry entry = zipFile.getEntry("install_profile.json");
String content = NetUtils.getStreamContent(zipFile.getInputStream(entry));
InstallProfile profile = gson.fromJson(content, InstallProfile.class);
File from = new File(gameDir, "versions" + File.separator + profile.install.minecraft);
if(!from.exists()) {
if(MessageBox.Show(C.i18n("install.no_version_if_intall")) == MessageBox.YES_OPTION) {
if(!mp.install(profile.install.minecraft, Settings.s().getDownloadSource())) {
setFailReason(new RuntimeException(C.i18n("install.no_version")));
}
} else {
setFailReason(new RuntimeException(C.i18n("install.no_version")));
}
return false;
}
File to = new File(gameDir, "versions" + File.separator + profile.install.target);
to.mkdirs();
HMCLog.log("Copying jar..." + profile.install.minecraft + ".jar to " + profile.install.target + ".jar");
FileUtils.copyFile(new File(from, profile.install.minecraft + ".jar"),
new File(to, profile.install.target + ".jar"));
HMCLog.log("Creating new version profile..." + profile.install.target + ".json");
FileUtils.write(new File(to, profile.install.target + ".json"), gson.toJson(profile.versionInfo));
HMCLog.log("Extracting universal forge pack..." + profile.install.filePath);
entry = zipFile.getEntry(profile.install.filePath);
InputStream is = zipFile.getInputStream(entry);
MinecraftLibrary forge = new MinecraftLibrary(profile.install.path);
forge.init();
File file = new File(gameDir, "libraries/" + forge.formatted);
file.getParentFile().mkdirs();
try (FileOutputStream fos = new FileOutputStream(file)) {
BufferedOutputStream bos = new BufferedOutputStream(fos);
int c;
while ((c = is.read()) != -1) bos.write((byte) c);
bos.close();
}
return true;
} catch(IOException | JsonSyntaxException e) {
setFailReason(e);
return false;
}
}
@Override
public String getInfo() {
return C.i18n("install.forge.install");
}
}

@ -0,0 +1,25 @@
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package org.jackhuang.hellominecraft.launcher.utils.installers.forge;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import org.jackhuang.hellominecraft.launcher.utils.installers.PackMinecraftInstaller;
/**
*
* @author hyh
*/
public class ForgeOldInstaller {
public static void install(String destMinecraftJar, String srcMinecraftJar, String forgeUniversal) throws IOException {
ArrayList<String> al = new ArrayList<String>();
al.add(srcMinecraftJar);
al.add(forgeUniversal);
new PackMinecraftInstaller(al, new File(destMinecraftJar)).install();
}
}

@ -0,0 +1,23 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.jackhuang.hellominecraft.launcher.utils.installers.forge;
/**
*
* @author hyh
*/
public class Install {
public String profileName;
public String target;
public String path;
public String version;
public String filePath;
public String welcome;
public String minecraft;
public String mirrorList;
public String logo;
}

@ -0,0 +1,16 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.jackhuang.hellominecraft.launcher.utils.installers.forge.bmcl;
/**
*
* @author huangyuhui
*/
public class Downloads {
public String changelog;
public String[] universal, src, javadoc, installer;
}

@ -0,0 +1,87 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.jackhuang.hellominecraft.launcher.utils.installers.forge.bmcl;
import com.google.gson.JsonSyntaxException;
import com.google.gson.reflect.TypeToken;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.jackhuang.hellominecraft.C;
import org.jackhuang.hellominecraft.HMCLog;
import org.jackhuang.hellominecraft.utils.ArrayUtils;
import org.jackhuang.hellominecraft.utils.StrUtils;
import org.jackhuang.hellominecraft.launcher.utils.installers.InstallerVersionList;
import org.jackhuang.hellominecraft.utils.NetUtils;
/**
*
* @author hyh
*/
public class ForgeBMCLVersionList extends InstallerVersionList {
private static ForgeBMCLVersionList instance;
public static ForgeBMCLVersionList getInstance() {
if (instance == null) instance = new ForgeBMCLVersionList();
return instance;
}
public ArrayList<ForgeVersion> root;
public Map<String, List<InstallerVersion>> versionMap;
public List<InstallerVersion> versions;
@Override
public void refreshList(String[] neededVersions) throws Exception {
if(versionMap == null) {
versionMap = new HashMap<String, List<InstallerVersion>>();
versions = new ArrayList<InstallerVersion>();
}
for (String x : neededVersions) {
if(versionMap.containsKey(x)) continue;
String s = NetUtils.doGet("http://bmclapi2.bangbang93.com/forge/minecraft/" + x);
if (s == null) {
continue;
}
try {
root = C.gson.fromJson(s, new TypeToken<ArrayList<ForgeVersion>>(){}.getType());
for (ForgeVersion v : root) {
InstallerVersion iv = new InstallerVersion(v.version, StrUtils.formatVersion(v.minecraft));
List<InstallerVersion> al = ArrayUtils.tryGetMapWithList(versionMap, StrUtils.formatVersion(v.minecraft));
iv.changelog = v.downloads.changelog;
iv.installer = "http://bmclapi.bangbang93.com/forge/getforge/" + iv.mcVersion + "/" + iv.selfVersion;
iv.universal = ArrayUtils.getEnd(v.downloads.universal);
al.add(iv);
versions.add(iv);
}
} catch(JsonSyntaxException e) {
HMCLog.warn("Failed to parse BMCLAPI response.", e);
}
}
Collections.sort(versions, new InstallerVersionComparator());
}
@Override
public List<InstallerVersion> getVersions(String mcVersion) {
if (versions == null || versionMap == null) return null;
if (StrUtils.isBlank(mcVersion)) return versions;
List c = versionMap.get(mcVersion);
if (c == null) return versions;
Collections.sort(c, InstallerVersionComparator.INSTANCE);
return c;
}
@Override
public String getName() {
return "Forge - BMCLAPI (By: bangbang93)";
}
}

@ -0,0 +1,14 @@
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package org.jackhuang.hellominecraft.launcher.utils.installers.forge.bmcl;
/**
*
* @author hyh
*/
public class ForgeVersion {
public String time, minecraft, version, _id, __v;
public Downloads downloads;
}

@ -0,0 +1,17 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.jackhuang.hellominecraft.launcher.utils.installers.forge.vanilla;
/**
*
* @author huangyuhui
*/
public class MinecraftForgeVersion {
public String branch, mcversion, jobver, version;
public int build;
public double modified;
public String[][] files;
}

@ -0,0 +1,95 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.jackhuang.hellominecraft.launcher.utils.installers.forge.vanilla;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.jackhuang.hellominecraft.C;
import org.jackhuang.hellominecraft.utils.StrUtils;
import org.jackhuang.hellominecraft.launcher.utils.installers.InstallerVersionList;
import org.jackhuang.hellominecraft.launcher.utils.installers.InstallerVersionNewerComparator;
import org.jackhuang.hellominecraft.utils.NetUtils;
/**
*
* @author hyh
*/
public class MinecraftForgeVersionList extends InstallerVersionList {
private static MinecraftForgeVersionList instance;
public static MinecraftForgeVersionList getInstance() {
if(instance == null)
instance = new MinecraftForgeVersionList();
return instance;
}
public MinecraftForgeVersionRoot root;
public Map<String, List<InstallerVersion>> versionMap;
public List<InstallerVersion> versions;
@Override
public void refreshList(String[] needed) throws Exception {
String s = NetUtils.doGet(C.URL_FORGE_LIST);
if(root!=null) return;
root = C.gson.fromJson(s, MinecraftForgeVersionRoot.class);
versionMap = new HashMap<String, List<InstallerVersion>>();
versions = new ArrayList<InstallerVersion>();
for(Map.Entry<String, int[]> arr : root.mcversion.entrySet()) {
String mcver = StrUtils.formatVersion(arr.getKey());
ArrayList<InstallerVersion> al = new ArrayList<InstallerVersion>();
for(int num : arr.getValue()) {
MinecraftForgeVersion v = root.number.get(num);
InstallerVersion iv = new InstallerVersion(v.version, StrUtils.formatVersion(v.mcversion));
for(String[] f : v.files) {
String ver = v.mcversion + "-" + v.version;
if(!StrUtils.isBlank(v.branch)) {
ver = ver + "-" + v.branch;
}
String filename = root.artifact + "-" + ver + "-" + f[1] + "." + f[0];
String url = root.webpath + "/" + ver + "/" + filename;
if(f[1].equals("installer")) {
iv.installer = url;
} else if(f[1].equals("universal")) {
iv.universal = url;
} else if(f[1].equals("changelog")) {
iv.changelog = url;
}
}
if(StrUtils.isBlank(iv.installer) || StrUtils.isBlank(iv.universal)) {
continue;
}
Collections.sort(al, new InstallerVersionNewerComparator());
al.add(iv);
versions.add(iv);
}
versionMap.put(StrUtils.formatVersion(mcver), al);
}
Collections.sort(versions, new InstallerVersionComparator());
}
@Override
public List<InstallerVersion> getVersions(String mcVersion) {
if (versions == null || versionMap == null) return null;
if(StrUtils.isBlank(mcVersion)) return versions;
List c = versionMap.get(mcVersion);
if(c == null) return versions;
Collections.sort(c, InstallerVersionComparator.INSTANCE);
return c;
}
@Override
public String getName() {
return "Forge - MinecraftForge Offical Site";
}
}

@ -0,0 +1,19 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.jackhuang.hellominecraft.launcher.utils.installers.forge.vanilla;
import java.util.Map;
/**
*
* @author hyh
*/
public class MinecraftForgeVersionRoot {
public String artifact, webpath, adfly, homepage, name;
public Map<String, int[]> branches, mcversion;
public Map<String, Integer> promos;
public Map<Integer, MinecraftForgeVersion> number;
}

@ -0,0 +1,90 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.jackhuang.hellominecraft.launcher.utils.installers.liteloader;
import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import org.jackhuang.hellominecraft.C;
import org.jackhuang.hellominecraft.HMCLog;
import org.jackhuang.hellominecraft.tasks.Task;
import org.jackhuang.hellominecraft.tasks.communication.PreviousResult;
import org.jackhuang.hellominecraft.tasks.communication.PreviousResultRegistrator;
import org.jackhuang.hellominecraft.launcher.utils.settings.Profile;
import org.jackhuang.hellominecraft.utils.FileUtils;
import org.jackhuang.hellominecraft.launcher.utils.version.MinecraftLibrary;
import org.jackhuang.hellominecraft.launcher.utils.version.MinecraftVersion;
/**
*
* @author hyh
*/
public class LiteLoaderInstaller extends Task implements PreviousResultRegistrator<File> {
public LiteLoaderVersionList.LiteLoaderInstallerVersion version;
public File installer;
public Profile profile;
public LiteLoaderInstaller(Profile profile, LiteLoaderVersionList.LiteLoaderInstallerVersion v) {
this(profile, v, null);
}
public LiteLoaderInstaller(Profile profile, LiteLoaderVersionList.LiteLoaderInstallerVersion v, File installer) {
this.profile = profile;
this.version = v;
this.installer = installer;
}
@Override
public boolean executeTask() {
if(profile == null || profile.getSelectedMinecraftVersion() == null) {
setFailReason(new RuntimeException(C.i18n("install.no_version")));
return false;
}
if(pre.size() != 1 && installer == null) throw new IllegalStateException("No registered previous task.");
if(installer == null)
installer = pre.get(pre.size() - 1).getResult();
try {
MinecraftVersion mv = (MinecraftVersion) profile.getSelectedMinecraftVersion().clone();
mv.inheritsFrom = mv.id;
mv.jar = mv.jar == null ? mv.id : mv.jar;
mv.libraries = new ArrayList(Arrays.asList(version.libraries));
mv.libraries.add(0, new MinecraftLibrary("com.mumfrey:liteloader:" + version.selfVersion));
FileUtils.copyFile(installer, new File(profile.getCanonicalGameDir(), "libraries/com/mumfrey/liteloader/" + version.selfVersion + "/liteloader-" + version.selfVersion + ".jar"));
mv.id += "-LiteLoader" + version.selfVersion;
if(!mv.mainClass.startsWith("net.minecraft.launchwrapper.")) {
mv.mainClass = "net.minecraft.launchwrapper.Launch";
mv.minecraftArguments += " --tweakClass " + version.tweakClass;
}
File folder = new File(profile.getCanonicalGameDir(), "versions/" + mv.id);
folder.mkdirs();
File json = new File(folder, mv.id + ".json");
HMCLog.log("Creating new version profile..." + mv.id + ".json");
FileUtils.write(json, C.gsonPrettyPrinting.toJson(mv));
return true;
} catch (Exception e) {
setFailReason(e);
return false;
}
}
@Override
public String getInfo() {
return C.i18n("install.liteloader.install");
}
ArrayList<PreviousResult<File>> pre = new ArrayList();
@Override
public Task registerPreviousResult(PreviousResult pr) {
pre.add(pr);
return this;
}
}

@ -0,0 +1,16 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.jackhuang.hellominecraft.launcher.utils.installers.liteloader;
import java.util.Map;
/**
*
* @author huangyuhui
*/
public class LiteLoaderMCVersions {
public Map<String, Map<String, LiteLoaderVersion>> artefacts;
}

@ -0,0 +1,17 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.jackhuang.hellominecraft.launcher.utils.installers.liteloader;
import org.jackhuang.hellominecraft.launcher.utils.version.MinecraftLibrary;
/**
*
* @author huangyuhui
*/
public class LiteLoaderVersion {
public String tweakClass, file, version, md5, timestamp;
public MinecraftLibrary[] libraries;
}

@ -0,0 +1,94 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.jackhuang.hellominecraft.launcher.utils.installers.liteloader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.jackhuang.hellominecraft.C;
import org.jackhuang.hellominecraft.launcher.utils.version.MinecraftLibrary;
import org.jackhuang.hellominecraft.launcher.utils.installers.InstallerVersionList;
import org.jackhuang.hellominecraft.launcher.utils.installers.InstallerVersionList.InstallerVersion;
import org.jackhuang.hellominecraft.launcher.utils.installers.InstallerVersionNewerComparator;
import org.jackhuang.hellominecraft.utils.NetUtils;
import org.jackhuang.hellominecraft.utils.StrUtils;
/**
*
* @author hyh
*/
public class LiteLoaderVersionList extends InstallerVersionList {
private static LiteLoaderVersionList instance;
public static LiteLoaderVersionList getInstance() {
if(instance == null) {
instance = new LiteLoaderVersionList();
}
return instance;
}
public LiteLoaderVersionsRoot root;
public Map<String, List<InstallerVersion>> versionMap;
public List<InstallerVersion> versions;
@Override
public void refreshList(String[] needed) throws Exception {
String s = NetUtils.doGet(C.URL_LITELOADER_LIST);
if(root != null) return;
root = C.gson.fromJson(s, LiteLoaderVersionsRoot.class);
versionMap = new HashMap<String, List<InstallerVersion>>();
versions = new ArrayList<InstallerVersion>();
for(Map.Entry<String, LiteLoaderMCVersions> arr : root.versions.entrySet()) {
ArrayList<InstallerVersion> al = new ArrayList<InstallerVersion>();
LiteLoaderMCVersions mcv = arr.getValue();
for(Map.Entry<String, LiteLoaderVersion> entry : mcv.artefacts.get("com.mumfrey:liteloader").entrySet()) {
if("latest".equals(entry.getKey())) continue;
LiteLoaderVersion v = entry.getValue();
LiteLoaderInstallerVersion iv = new LiteLoaderInstallerVersion(v.version, StrUtils.formatVersion(arr.getKey()));
iv.universal = "http://dl.liteloader.com/versions/com/mumfrey/liteloader/" + arr.getKey() + "/" + v.file;
iv.tweakClass = v.tweakClass;
iv.libraries = Arrays.copyOf(v.libraries, v.libraries.length);
iv.installer = "http://dl.liteloader.com/redist/" + iv.mcVersion + "/liteloader-installer-" + iv.selfVersion.replace("_", "-") + ".jar";
al.add(iv);
versions.add(iv);
}
Collections.sort(al, new InstallerVersionNewerComparator());
versionMap.put(StrUtils.formatVersion(arr.getKey()), al);
}
Collections.sort(versions, InstallerVersionComparator.INSTANCE);
}
@Override
public List<InstallerVersion> getVersions(String mcVersion) {
if (versions == null || versionMap == null) return null;
if(StrUtils.isBlank(mcVersion)) return versions;
List c = versionMap.get(mcVersion);
if(c == null) return versions;
Collections.sort(c, InstallerVersionComparator.INSTANCE);
return c;
}
@Override
public String getName() {
return "LiteLoader - LiteLoader Official Site(By: Mumfrey)";
}
public static class LiteLoaderInstallerVersion extends InstallerVersion {
public MinecraftLibrary[] libraries;
public String tweakClass;
public LiteLoaderInstallerVersion(String selfVersion, String mcVersion) {
super(selfVersion, mcVersion);
}
}
}

@ -0,0 +1,14 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.jackhuang.hellominecraft.launcher.utils.installers.liteloader;
/**
*
* @author huangyuhui
*/
public class LiteLoaderVersionsMeta {
public String description, authors, url;
}

@ -0,0 +1,17 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.jackhuang.hellominecraft.launcher.utils.installers.liteloader;
import java.util.Map;
/**
*
* @author hyh
*/
public class LiteLoaderVersionsRoot {
public Map<String, LiteLoaderMCVersions> versions;
public LiteLoaderVersionsMeta meta;
}

@ -0,0 +1,87 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.jackhuang.hellominecraft.launcher.utils.installers.optifine;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.zip.ZipFile;
import org.jackhuang.hellominecraft.C;
import org.jackhuang.hellominecraft.launcher.utils.settings.Profile;
import org.jackhuang.hellominecraft.tasks.Task;
import org.jackhuang.hellominecraft.tasks.communication.PreviousResult;
import org.jackhuang.hellominecraft.tasks.communication.PreviousResultRegistrator;
import org.jackhuang.hellominecraft.utils.FileUtils;
import org.jackhuang.hellominecraft.launcher.utils.version.MinecraftLibrary;
import org.jackhuang.hellominecraft.launcher.utils.version.MinecraftVersion;
/**
*
* @author hyh
*/
public class OptiFineInstaller extends Task implements PreviousResultRegistrator<File> {
public File installer;
public Profile profile;
public String version;
public OptiFineInstaller(Profile profile, String version) {
this(profile, version, null);
}
public OptiFineInstaller(Profile profile, String version, File installer) {
this.profile = profile;
this.installer = installer;
this.version = version;
}
@Override
public boolean executeTask() {
if(profile == null || profile.getSelectedMinecraftVersion() == null) {
setFailReason(new RuntimeException(C.i18n("install.no_version")));
return false;
}
MinecraftVersion mv = (MinecraftVersion)profile.getSelectedMinecraftVersion().clone();
try {
mv.inheritsFrom = mv.id;
mv.jar = mv.jar == null ? mv.id : mv.jar;
mv.libraries.clear();
mv.libraries.add(0, new MinecraftLibrary("optifine:OptiFine:" + version));
FileUtils.copyFile(installer, new File(profile.getCanonicalGameDir(), "libraries/optifine/OptiFine/" + version + "/OptiFine-" + version + ".jar"));
mv.id += "-" + version;
if(new ZipFile(installer).getEntry("optifine/OptiFineTweaker.class") != null) {
if(!mv.mainClass.startsWith("net.minecraft.launchwrapper.")) {
mv.mainClass = "net.minecraft.launchwrapper.Launch";
mv.minecraftArguments += " --tweakClass optifine.OptiFineTweaker";
mv.libraries.add(1, new MinecraftLibrary("net.minecraft:launchwrapper:1.7"));
}
}
File loc = new File(profile.getCanonicalGameDir(), "versions/" + mv.id);
loc.mkdirs();
File json = new File(loc, mv.id + ".json");
FileUtils.writeStringToFile(json, C.gsonPrettyPrinting.toJson(mv, MinecraftVersion.class));
} catch (IOException ex) {
setFailReason(ex);
return false;
}
return true;
}
@Override
public String getInfo() {
return "Optifine Installer";
}
ArrayList<PreviousResult<File>> pre = new ArrayList();
@Override
public Task registerPreviousResult(PreviousResult pr) {
pre.add(pr);
return this;
}
}

@ -0,0 +1,13 @@
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package org.jackhuang.hellominecraft.launcher.utils.installers.optifine;
/**
*
* @author hyh
*/
public class OptiFineVersion {
public String dl, ver, date, mirror, mcver;
}

@ -0,0 +1,87 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.jackhuang.hellominecraft.launcher.utils.installers.optifine.bmcl;
import com.google.gson.reflect.TypeToken;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.jackhuang.hellominecraft.C;
import org.jackhuang.hellominecraft.utils.ArrayUtils;
import org.jackhuang.hellominecraft.launcher.utils.installers.InstallerVersionList;
import org.jackhuang.hellominecraft.launcher.utils.installers.optifine.OptiFineVersion;
import org.jackhuang.hellominecraft.utils.tinystream.CollectionUtils;
import org.jackhuang.hellominecraft.utils.NetUtils;
import org.jackhuang.hellominecraft.utils.StrUtils;
/**
*
* @author hyh
*/
public class OptiFineBMCLVersionList extends InstallerVersionList {
private static OptiFineBMCLVersionList instance;
public static OptiFineBMCLVersionList getInstance() {
if (null == instance)
instance = new OptiFineBMCLVersionList();
return instance;
}
public ArrayList<OptiFineVersion> root;
public Map<String, List<InstallerVersion>> versionMap;
public List<InstallerVersion> versions;
@Override
public void refreshList(String[] needed) throws Exception {
String s = NetUtils.doGet("http://bmclapi.bangbang93.com/optifine/versionlist");
versionMap = new HashMap<>();
versions = new ArrayList<>();
if (s == null) return;
root = C.gson.fromJson(s, new TypeToken<ArrayList<OptiFineVersion>>() {
}.getType());
for(OptiFineVersion v : root) {
v.mirror = v.mirror.replace("http://optifine.net/http://optifine.net/", "http://optifine.net/");
if (StrUtils.isBlank(v.mcver)) {
Pattern p = Pattern.compile("OptiFine (.*) HD");
Matcher m = p.matcher(v.ver);
while (m.find()) v.mcver = m.group(1);
}
InstallerVersion iv = new InstallerVersion(v.ver, StrUtils.formatVersion(v.mcver));
List<InstallerVersion> al = ArrayUtils.tryGetMapWithList(versionMap, StrUtils.formatVersion(v.mcver));
String url = "http://bmclapi.bangbang93.com/optifine/" + iv.selfVersion.replace(" ", "%20");
iv.installer = iv.universal = v.mirror;
al.add(iv);
versions.add(iv);
}
Collections.sort(versions, InstallerVersionComparator.INSTANCE);
}
@Override
public List<InstallerVersion> getVersions(String mcVersion) {
if (versions == null || versionMap == null) return null;
if (StrUtils.isBlank(mcVersion)) return versions;
List c = versionMap.get(mcVersion);
if (c == null) return versions;
Collections.sort(c, InstallerVersionComparator.INSTANCE);
return c;
}
@Override
public String getName() {
return "OptiFine - BMCLAPI(By: bangbang93)";
}
}

@ -0,0 +1,49 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.jackhuang.hellominecraft.launcher.utils.installers.optifine.vanilla;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.jackhuang.hellominecraft.tasks.Task;
import org.jackhuang.hellominecraft.tasks.communication.PreviousResult;
import org.jackhuang.hellominecraft.utils.NetUtils;
/**
*
* @author hyh
*/
public class OptiFineDownloadFormatter extends Task implements PreviousResult<String> {
String url, result;
public OptiFineDownloadFormatter(String url) {
this.url = url;
}
@Override
public boolean executeTask() {
try {
String content = NetUtils.doGet(url);
Pattern p = Pattern.compile("\"downloadx\\?f=OptiFine(.*)\"");
Matcher m = p.matcher(content);
while(m.find()) result = m.group(1);
result = "http://optifine.net/downloadx?f=OptiFine" + result;
return true;
} catch (Exception ex) {
setFailReason(ex);
return false;
}
}
@Override
public String getInfo() {
return "Get OptiFine Download Link.";
}
@Override
public String getResult() {
return result;
}
}

@ -0,0 +1,119 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.jackhuang.hellominecraft.launcher.utils.installers.optifine.vanilla;
import java.io.StringBufferInputStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import org.jackhuang.hellominecraft.launcher.utils.installers.InstallerVersionList;
import org.jackhuang.hellominecraft.launcher.utils.installers.optifine.OptiFineVersion;
import org.jackhuang.hellominecraft.utils.ArrayUtils;
import org.jackhuang.hellominecraft.utils.NetUtils;
import org.jackhuang.hellominecraft.utils.StrUtils;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
/**
*
* @author hyh
*/
public class OptiFineVersionList extends InstallerVersionList {
private static OptiFineVersionList instance;
public static OptiFineVersionList getInstance() {
if(null == instance)
instance = new OptiFineVersionList();
return instance;
}
public ArrayList<OptiFineVersion> root = new ArrayList();
public Map<String, List<InstallerVersion>> versionMap;
public List<InstallerVersion> versions;
@Override
public void refreshList(String[] sss) throws Exception {
String content = NetUtils.doGet("http://optifine.net/downloads");
if(versions != null) return;
versionMap = new HashMap<String, List<InstallerVersion>>();
versions = new ArrayList<InstallerVersion>();
content = content.replace("&nbsp;", " ").replace("&gt;", ">").replace("&lt;", "<");
try {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder db = factory.newDocumentBuilder();
Document doc = db.parse(new StringBufferInputStream(content));
Element r = doc.getDocumentElement();
NodeList tables = r.getElementsByTagName("table");
for(int i = 0; i < tables.getLength(); i++) {
Element e = (Element)tables.item(i);
if("downloadTable".equals(e.getAttribute("class"))) {
NodeList tr = e.getElementsByTagName("tr");
for(int k = 0; k < tr.getLength(); k++) {
NodeList downloadLine = ((Element)tr.item(k)).getElementsByTagName("td");
OptiFineVersion v = new OptiFineVersion();
for(int j = 0; j < downloadLine.getLength(); j++) {
Element td = (Element)downloadLine.item(j);
if(StrUtils.startsWith(td.getAttribute("class"), "downloadLineMirror")) {
v.mirror = ((Element)td.getElementsByTagName("a").item(0)).getAttribute("href");
}
if(StrUtils.startsWith(td.getAttribute("class"), "downloadLineDownload")) {
v.dl = ((Element)td.getElementsByTagName("a").item(0)).getAttribute("href");
}
if(StrUtils.startsWith(td.getAttribute("class"), "downloadLineDate")) {
v.date = td.getTextContent();
}
if(StrUtils.startsWith(td.getAttribute("class"), "downloadLineFile")) {
v.ver = td.getTextContent();
}
}
if(StrUtils.isBlank(v.mcver)) {
Pattern p = Pattern.compile("OptiFine (.*?) ");
Matcher m = p.matcher(v.ver);
while(m.find()) v.mcver = StrUtils.formatVersion(m.group(1));
}
InstallerVersion iv = new InstallerVersion(v.ver, StrUtils.formatVersion(v.mcver));
iv.installer = iv.universal = v.mirror;
root.add(v);
versions.add(iv);
List<InstallerVersion> ivl = ArrayUtils.tryGetMapWithList(versionMap, StrUtils.formatVersion(v.mcver));
ivl.add(iv);
}
}
}
} catch (Exception ex) {
throw new RuntimeException(ex);
}
Collections.sort(versions, InstallerVersionComparator.INSTANCE);
}
@Override
public String getName() {
return "OptiFine - OptiFine Official Site";
}
@Override
public List<InstallerVersion> getVersions(String mcVersion) {
if (versions == null || versionMap == null) return null;
if(StrUtils.isBlank(mcVersion)) return versions;
List c = versionMap.get(mcVersion);
if(c == null) return versions;
Collections.sort(c, InstallerVersionComparator.INSTANCE);
return c;
}
}

@ -0,0 +1,151 @@
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package org.jackhuang.hellominecraft.launcher.utils.settings;
import org.jackhuang.hellominecraft.launcher.utils.download.DownloadType;
import com.google.gson.annotations.SerializedName;
import java.util.Map;
import java.util.TreeMap;
import java.util.UUID;
import org.jackhuang.hellominecraft.utils.OS;
/**
*
* @author hyh
*/
public final class Config {
@SerializedName("last")
private String last;
@SerializedName("bgpath")
private String bgpath;
@SerializedName("username")
private String username;
@SerializedName("clientToken")
private String clientToken;
@SerializedName("enableShadow")
private boolean enableShadow;
@SerializedName("theme")
private int theme;
public int getTheme() {
return theme;
}
public void setTheme(int theme) {
this.theme = theme;
Settings.save();
}
public boolean isEnableShadow() {
return enableShadow;
}
public void setEnableShadow(boolean enableShadow) {
this.enableShadow = enableShadow;
Settings.save();
}
public String getLast() {
return last;
}
public void setLast(String last) {
this.last = last;
Settings.save();
}
public String getBgpath() {
return bgpath;
}
public void setBgpath(String bgpath) {
this.bgpath = bgpath;
Settings.save();
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
Settings.save();
}
public String getClientToken() {
return clientToken;
}
public int getLoginType() {
return logintype;
}
public void setLoginType(int logintype) {
this.logintype = logintype;
Settings.save();
}
public int getDownloadType() {
return downloadtype;
}
public void setDownloadType(int downloadtype) {
this.downloadtype = downloadtype;
Settings.save();
}
public TreeMap<String, Profile> getConfigurations() {
if(configurations == null)
configurations = new TreeMap<String, Profile>();
return configurations;
}
public boolean isCheckUpdate() {
return checkUpdate;
}
public void setCheckUpdate(boolean checkUpdate) {
this.checkUpdate = checkUpdate;
Settings.save();
}
public Map getYggdrasilConfig() {
return yggdrasil;
}
public void setYggdrasilConfig(Map yggdrasil) {
this.yggdrasil = yggdrasil;
Settings.save();
}
@SerializedName("logintype")
private int logintype;
@SerializedName("downloadtype")
private int downloadtype;
@SerializedName("configurations")
private TreeMap<String, Profile> configurations;
@SerializedName("checkUpdate")
private boolean checkUpdate;
@SerializedName("yggdrasil")
private Map yggdrasil;
public Config()
{
clientToken = UUID.randomUUID().toString();
username = "";
logintype = downloadtype = 0;
checkUpdate = true;
configurations = new TreeMap<String, Profile>();
Profile profile = new Profile();
configurations.put(profile.getName(), profile);
enableShadow = OS.os() == OS.WINDOWS;
theme = 0;
}
public DownloadType getDownloadSource() {
if(downloadtype >= DownloadType.values().length || downloadtype < 0) return null;
return DownloadType.values()[downloadtype];
}
}

@ -0,0 +1,297 @@
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package org.jackhuang.hellominecraft.launcher.utils.settings;
import java.io.File;
import org.jackhuang.hellominecraft.launcher.launch.IMinecraftProvider;
import org.jackhuang.hellominecraft.utils.IOUtils;
import org.jackhuang.hellominecraft.launcher.utils.MCUtils;
import org.jackhuang.hellominecraft.launcher.utils.version.GameDirType;
import org.jackhuang.hellominecraft.utils.StrUtils;
import org.jackhuang.hellominecraft.utils.Utils;
import org.jackhuang.hellominecraft.launcher.utils.version.MinecraftVersion;
import org.jackhuang.hellominecraft.launcher.utils.version.MinecraftVersionManager;
/**
*
* @author hyh
*/
public final class Profile {
private String name, selectedMinecraftVersion = "", javaArgs, minecraftArgs, maxMemory, permSize, width, height, userProperties;
private String gameDir, javaDir, wrapperLauncher, serverIp;
private boolean fullscreen, debug, noJVMArgs, canceledWrapper;
/**
* 0 - Close the launcher when the game starts.<br/>
* 1 - Hide the launcher when the game starts.<br/>
* 2 - Keep the launcher open.<br/>
*/
private int launcherVisibility;
/**
* 0 - .minecraft<br/>
* 1 - .minecraft/versions/&lt;version&gt;/<br/>
*/
private int gameDirType;
protected transient IMinecraftProvider minecraftProvider;
public Profile() {
this("Default");
}
public Profile(String name) {
this.name = name;
gameDir = MCUtils.getInitGameDir().getPath();
debug = fullscreen = canceledWrapper = false;
javaDir = IOUtils.getJavaDir();
launcherVisibility = gameDirType = 0;
minecraftArgs = serverIp = "";
}
public Profile(Profile v) {
this();
if (v == null) {
return;
}
name = v.name;
gameDir = v.gameDir;
maxMemory = v.maxMemory;
width = v.width;
height = v.height;
fullscreen = v.fullscreen;
javaArgs = v.javaArgs;
javaDir = v.javaDir;
debug = v.debug;
minecraftArgs = v.minecraftArgs;
permSize = v.permSize;
gameDirType = v.gameDirType;
canceledWrapper = v.canceledWrapper;
noJVMArgs = v.noJVMArgs;
launcherVisibility = v.launcherVisibility;
wrapperLauncher = v.wrapperLauncher;
serverIp = v.serverIp;
}
public IMinecraftProvider getMinecraftProvider() {
if(minecraftProvider == null) minecraftProvider = new MinecraftVersionManager(this);
return minecraftProvider;
}
public MinecraftVersion getSelectedMinecraftVersion() {
if (StrUtils.isBlank(selectedMinecraftVersion)) {
MinecraftVersion v = getMinecraftProvider().getOneVersion();
if (v == null) {
return null;
}
selectedMinecraftVersion = v.id;
return v;
}
MinecraftVersion v = getMinecraftProvider().getVersionById(selectedMinecraftVersion);
if(v == null) v = getMinecraftProvider().getOneVersion();
if(v != null) setSelectedMinecraftVersion(v.id);
return v;
}
public String getGameDir() {
if (StrUtils.isBlank(gameDir)) {
gameDir = MCUtils.getInitGameDir().getPath();
}
return IOUtils.addSeparator(gameDir);
}
public String getCanonicalGameDir() {
return IOUtils.tryGetCanonicalFolderPath(getGameDirFile());
}
public File getCanonicalGameDirFile() {
return IOUtils.tryGetCanonicalFile(getGameDirFile());
}
public File getGameDirFile() {
return new File(getGameDir());
}
public Profile setGameDir(String gameDir) {
this.gameDir = gameDir;
Settings.save();
return this;
}
public String getJavaDir() {
if (StrUtils.isBlank(javaDir)) {
javaDir = IOUtils.getJavaDir();
}
return javaDir;
}
public File getJavaDirFile() {
return new File(getJavaDir());
}
public void setJavaDir(String javaDir) {
this.javaDir = javaDir;
Settings.save();
}
public File getFolder(String folder) {
return new File(getGameDir(), folder);
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public void setSelectedMinecraftVersion(String selectedMinecraftVersion) {
this.selectedMinecraftVersion = selectedMinecraftVersion;
}
public String getJavaArgs() {
if(StrUtils.isBlank(javaArgs)) return "";
return javaArgs;
}
public void setJavaArgs(String javaArgs) {
this.javaArgs = javaArgs;
Settings.save();
}
public boolean hasJavaArgs() {
return StrUtils.isNotBlank(getJavaArgs().trim());
}
public String getMaxMemory() {
if(StrUtils.isBlank(maxMemory)) return String.valueOf(Utils.getSuggestedMemorySize());
return maxMemory;
}
public void setMaxMemory(String maxMemory) {
this.maxMemory = maxMemory;
Settings.save();
}
public String getWidth() {
if(StrUtils.isBlank(width)) return "854";
return width;
}
public void setWidth(String width) {
this.width = width;
}
public String getHeight() {
if(StrUtils.isBlank(height)) return "480";
return height;
}
public void setHeight(String height) {
this.height = height;
Settings.save();
}
public String getUserProperties() {
if(userProperties == null) return "";
return userProperties;
}
public void setUserProperties(String userProperties) {
this.userProperties = userProperties;
}
public boolean isFullscreen() {
return fullscreen;
}
public void setFullscreen(boolean fullscreen) {
this.fullscreen = fullscreen;
Settings.save();
}
public boolean isDebug() {
return debug;
}
public void setDebug(boolean debug) {
this.debug = debug;
Settings.save();
}
public int getLauncherVisibility() {
return launcherVisibility;
}
public void setLauncherVisibility(int launcherVisibility) {
this.launcherVisibility = launcherVisibility;
Settings.save();
}
public GameDirType getGameDirType() {
return GameDirType.values()[gameDirType];
}
public void setGameDirType(GameDirType gameDirType) {
this.gameDirType = gameDirType.ordinal();
Settings.save();
}
public String getPermSize() {
return permSize;
}
public void setPermSize(String permSize) {
this.permSize = permSize;
Settings.save();
}
public boolean isNoJVMArgs() {
return noJVMArgs;
}
public void setNoJVMArgs(boolean noJVMArgs) {
this.noJVMArgs = noJVMArgs;
}
public String getMinecraftArgs() {
return minecraftArgs;
}
public void setMinecraftArgs(String minecraftArgs) {
this.minecraftArgs = minecraftArgs;
Settings.save();
}
public boolean isCanceledWrapper() {
return canceledWrapper;
}
public void setCanceledWrapper(boolean canceledWrapper) {
this.canceledWrapper = canceledWrapper;
Settings.save();
}
public String getWrapperLauncher() {
return wrapperLauncher;
}
public void setWrapperLauncher(String wrapperLauncher) {
this.wrapperLauncher = wrapperLauncher;
Settings.save();
}
public String getServerIp() {
return serverIp;
}
public void setServerIp(String serverIp) {
this.serverIp = serverIp;
Settings.save();
}
}

@ -0,0 +1,148 @@
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package org.jackhuang.hellominecraft.launcher.utils.settings;
import java.io.File;
import java.io.IOException;
import java.util.Collection;
import java.util.Map;
import org.jackhuang.hellominecraft.C;
import org.jackhuang.hellominecraft.utils.functions.DoneListener0;
import org.jackhuang.hellominecraft.HMCLog;
import org.jackhuang.hellominecraft.launcher.Main;
import org.jackhuang.hellominecraft.utils.tinystream.CollectionUtils;
import org.jackhuang.hellominecraft.utils.FileUtils;
import org.jackhuang.hellominecraft.utils.IOUtils;
import org.jackhuang.hellominecraft.utils.MessageBox;
import org.jackhuang.hellominecraft.utils.StrUtils;
import org.jackhuang.hellominecraft.utils.UpdateChecker;
import org.jackhuang.hellominecraft.utils.VersionNumber;
/**
*
* @author hyh
*/
public final class Settings {
public static final File settingsFile = new File(IOUtils.currentDir(), "hmcl.json");
private static boolean isFirstLoad;
private static Config settings;
public static final UpdateChecker UPDATE_CHECKER;
public static Config s() {
return settings;
}
public static boolean isFirstLoad() {
return isFirstLoad;
}
static {
if (settingsFile.exists()) {
try {
String str = FileUtils.readFileToString(settingsFile);
if (str == null || str.trim().equals("")) {
init();
HMCLog.log("Settings file is empty, use the default settings.");
} else {
settings = C.gsonPrettyPrinting.fromJson(str, Config.class);
}
HMCLog.log("Initialized settings.");
} catch (Exception e) {
HMCLog.warn("Something happened wrongly when load settings.", e);
if (MessageBox.Show(C.i18n("settings.failed_load"), MessageBox.YES_NO_OPTION) == MessageBox.YES_OPTION) {
init();
} else {
HMCLog.err("Cancelled loading settings.");
System.exit(1);
}
}
} else {
HMCLog.log("No settings file here, may be first loading.");
isFirstLoad = true;
init();
}
if(settings == null) init();
isFirstLoad = StrUtils.isBlank(settings.getUsername());
if(!settings.getConfigurations().containsKey("Default")) {
settings.getConfigurations().put("Default", new Profile());
}
UPDATE_CHECKER = new UpdateChecker(new VersionNumber(Main.firstVer, Main.secondVer, Main.thirdVer), "hmcl", settings.isCheckUpdate(), new DoneListener0() {
@Override
public void onDone() {
Main.invokeUpdate();
}
});
}
public static void init() {
settings = new Config();
save();
}
public static void save() {
try {
FileUtils.write(settingsFile, C.gsonPrettyPrinting.toJson(settings));
} catch (IOException ex) {
HMCLog.err("Failed to save config", ex);
}
}
public static Profile getVersion(String name) {
if (settings == null) {
return null;
}
if (settings.getConfigurations() == null) {
return null;
}
return settings.getConfigurations().get(name);
}
public static Map<String, Profile> getVersions() {
return settings.getConfigurations();
}
public static void setVersion(Profile ver) {
if (ver == null) {
return;
}
settings.getConfigurations().put(ver.getName(), ver);
}
public static Collection<Profile> getProfiles() {
return CollectionUtils.sortOut(settings.getConfigurations().values(), (t) -> t != null && t.getName() != null);
}
public static Profile getOneProfile() {
if(settings.getConfigurations().size() == 0) {
settings.getConfigurations().put("Default", new Profile());
}
return settings.getConfigurations().firstEntry().getValue();
}
public static boolean trySetVersion(Profile ver) {
if (ver == null || ver.getName() == null) {
return false;
}
if (settings.getConfigurations().containsKey(ver.getName())) {
return false;
}
settings.getConfigurations().put(ver.getName(), ver);
return true;
}
public static void delVersion(Profile ver) {
delVersion(ver.getName());
}
public static void delVersion(String ver) {
if (settings == null) return;
settings.getConfigurations().remove(ver);
}
}

@ -0,0 +1,25 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.jackhuang.hellominecraft.launcher.utils.version;
import java.util.Arrays;
/**
*
* @author huangyuhui
*/
public class Extract extends Object implements Cloneable {
String[] exclude;
@Override
protected Object clone() {
Extract e = new Extract();
e.exclude = exclude == null ? null : Arrays.copyOf(exclude, exclude.length);
return e;
}
}

@ -0,0 +1,15 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.jackhuang.hellominecraft.launcher.utils.version;
/**
*
* @author huangyuhui
*/
public enum GameDirType {
ROOT_FOLDER,
VERSION_FOLDER;
}

@ -0,0 +1,46 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.jackhuang.hellominecraft.launcher.utils.version;
import java.io.File;
import org.jackhuang.hellominecraft.launcher.utils.download.DownloadType;
/**
*
* @author hyh
*/
public abstract class IMinecraftLibrary {
public String name;
public IMinecraftLibrary(String name) {
this.name = name;
}
public abstract boolean isRequiredToUnzip();
public abstract String[] getDecompressExtractRules();
public abstract void init();
public abstract boolean allow();
public abstract File getFilePath(File gameDir);
public abstract String getDownloadURL(String urlBase, DownloadType downloadType);
@Override
public boolean equals(Object obj) {
if(obj instanceof MinecraftLibrary)
return ((MinecraftLibrary) obj).name.equals(name);
return false;
}
@Override
public int hashCode() {
int hash = 3;
hash = 89 * hash + (this.name != null ? this.name.hashCode() : 0);
return hash;
}
@Override
protected abstract Object clone();
}

@ -0,0 +1,63 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.jackhuang.hellominecraft.launcher.utils.version;
import java.io.File;
import java.util.ArrayList;
import java.util.Set;
import org.jackhuang.hellominecraft.launcher.launch.IMinecraftProvider;
import org.jackhuang.hellominecraft.launcher.utils.download.DownloadType;
/**
*
* @author hyh
*/
public class MinecraftClassicVersion extends MinecraftVersion {
public MinecraftClassicVersion() {
super();
mainClass = "net.minecraft.client.Minecraft";
id = "Classic";
type = "release";
processArguments = assets = releaseTime = time = null;
minecraftArguments = "${auth_player_name} ${auth_session} --workDir ${game_directory}";
libraries = new ArrayList<>();
libraries.add(new MinecraftOldLibrary("lwjgl"));
libraries.add(new MinecraftOldLibrary("jinput"));
libraries.add(new MinecraftOldLibrary("lwjgl_util"));
}
@Override
public Object clone() {
return super.clone();
}
@Override
public MinecraftVersion resolve(IMinecraftProvider manager, Set<String> resolvedSoFar, DownloadType sourceType) {
return this;
}
@Override
public File getJar(File gameDir) {
return new File(gameDir, "bin/minecraft.jar");
}
@Override
public File getJar(File gameDir, String suffix) {
return new File(gameDir, "bin/minecraft" + suffix + ".jar");
}
@Override
public File getNatives(File gameDir) {
return new File(gameDir, "bin/natives");
}
@Override
public boolean isAllowedToUnpackNatives() {
return false;
}
}

@ -0,0 +1,137 @@
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package org.jackhuang.hellominecraft.launcher.utils.version;
import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import org.jackhuang.hellominecraft.launcher.utils.download.DownloadType;
import org.jackhuang.hellominecraft.utils.OS;
import org.jackhuang.hellominecraft.utils.StrUtils;
/**
*
* @author hyh
*/
public class MinecraftLibrary extends IMinecraftLibrary implements Cloneable {
public ArrayList<Rules> rules;
public String url, formatted=null;
//public boolean serverreq=true, clientreq=true;
public String[] checksums;
public Natives natives;
public Extract extract;
public MinecraftLibrary(String name) {
super(name);
}
public MinecraftLibrary(ArrayList<Rules> rules, String url, String[] checksums, Natives natives, String name, Extract extract) {
super(name);
this.rules = rules == null ? null : (ArrayList<Rules>) rules.clone();
this.url = url;
this.checksums = checksums == null ? null : Arrays.copyOf(checksums, checksums.length);
this.natives = natives == null ? null : (Natives)natives.clone();
this.extract = extract == null ? null :(Extract)extract.clone();
}
@Override
public Object clone() {
return new MinecraftLibrary(rules, url, checksums, natives, name, extract);
}
/**
* is the library allowed to load.
*
* @return
*/
@Override
public boolean allow() {
boolean flag = false;
if (rules == null || rules.isEmpty()) {
flag = true;
} else {
for (Rules r : rules) {
if (r.action.equals("disallow")) {
if (r.os != null && (StrUtils.isBlank(r.os.name) || r.os.name.equalsIgnoreCase(OS.os().toString()))) {
flag = false;
break;
}
} else {
if (r.os != null && (StrUtils.isBlank(r.os.name) || r.os.name.equalsIgnoreCase(OS.os().toString()))) {
flag = true;
}
if (r.os == null) {
flag = true;
}
}
}
}
return flag;
}
private String formatArch(String nati) {
String arch = System.getProperty("os.arch");
if (arch.contains("64")) {
arch = "64";
} else {
arch = "32";
}
if (nati == null) {
return "";
}
return nati.replace("${arch}", arch);
}
private String getNative() {
OS os = OS.os();
if (os == OS.WINDOWS) {
return formatArch(natives.windows);
} else if (os == OS.OSX) {
return formatArch(natives.osx);
} else {
return formatArch(natives.linux);
}
}
@Override
public boolean isRequiredToUnzip() {
return natives != null && allow();
}
@Override
public void init() {
String str = name;
String[] s = str.split(":");
str = s[0];
str = str.replace('.', File.separatorChar);
if (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 += getNative();
str += ".jar";
}
formatted = str;
}
@Override
public File getFilePath(File gameDir) {
return new File(gameDir, "libraries" + File.separatorChar + formatted);
}
@Override
public String getDownloadURL(String urlBase, DownloadType downloadType) {
if(StrUtils.isNotBlank(url)&&downloadType.getProvider().isAllowedToUseSelfURL()) urlBase = this.url;
return urlBase + formatted.replace('\\', '/');
}
@Override
public String[] getDecompressExtractRules() {
return extract == null || extract.exclude == null ? new String[0] : extract.exclude;
}
}

@ -0,0 +1,51 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.jackhuang.hellominecraft.launcher.utils.version;
import java.io.File;
import org.jackhuang.hellominecraft.launcher.utils.download.DownloadType;
/**
*
* @author hyh
*/
public class MinecraftOldLibrary extends MinecraftLibrary {
public MinecraftOldLibrary(String name) {
super(name);
}
@Override
public boolean isRequiredToUnzip() {
return false;
}
@Override
public void init() {
}
@Override
public boolean allow() {
return true;
}
@Override
public File getFilePath(File gameDir) {
return new File(gameDir, "bin/" + name + ".jar");
}
@Override
public Object clone() {
return new MinecraftOldLibrary(name);
}
@Override
public String getDownloadURL(String urlBase, DownloadType downloadType) {
return null;
}
}

@ -0,0 +1,113 @@
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package org.jackhuang.hellominecraft.launcher.utils.version;
import java.io.File;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.jackhuang.hellominecraft.launcher.launch.IMinecraftProvider;
import org.jackhuang.hellominecraft.launcher.utils.download.DownloadType;
import org.jackhuang.hellominecraft.utils.ArrayUtils;
/**
*
* @author hyh
*/
public class MinecraftVersion implements Cloneable, Comparable<MinecraftVersion> {
public String minecraftArguments, mainClass, time, id, type, processArguments,
releaseTime, assets, jar, inheritsFrom;
public int minimumLauncherVersion;
public boolean hidden;
public List<MinecraftLibrary> libraries;
public MinecraftVersion() {
}
public MinecraftVersion(String minecraftArguments, String mainClass, String time, String id, String type, String processArguments, String releaseTime, String assets, String jar, String inheritsFrom, int minimumLauncherVersion, List<MinecraftLibrary> libraries, boolean hidden) {
this();
this.minecraftArguments = minecraftArguments;
this.mainClass = mainClass;
this.time = time;
this.id = id;
this.type = type;
this.processArguments = processArguments;
this.releaseTime = releaseTime;
this.assets = assets;
this.jar = jar;
this.inheritsFrom = inheritsFrom;
this.minimumLauncherVersion = minimumLauncherVersion;
this.hidden = hidden;
if(libraries == null) this.libraries = new ArrayList<>();
else {
this.libraries = new ArrayList<>(libraries.size());
for (IMinecraftLibrary library : libraries) {
this.libraries.add((MinecraftLibrary) library.clone());
}
}
}
@Override
public Object clone() {
return new MinecraftVersion(minecraftArguments, mainClass, time, id, type, processArguments, releaseTime, assets, jar, inheritsFrom, minimumLauncherVersion, libraries, hidden);
}
public MinecraftVersion resolve(IMinecraftProvider manager, DownloadType sourceType) {
return resolve(manager, new HashSet<>(), sourceType);
}
protected MinecraftVersion resolve(IMinecraftProvider manager, Set<String> resolvedSoFar, DownloadType sourceType) {
if (inheritsFrom == null) {
return this;
}
if (!resolvedSoFar.add(id)) {
throw new IllegalStateException("Circular dependency detected.");
}
MinecraftVersion parent = manager.getVersionById(inheritsFrom);
if(parent == null) {
if(!manager.install(inheritsFrom, sourceType)) return this;
parent = manager.getVersionById(inheritsFrom);
}
parent = parent.resolve(manager, resolvedSoFar, sourceType);
MinecraftVersion result = new MinecraftVersion(
this.minecraftArguments != null ? this.minecraftArguments : parent.minecraftArguments,
this.mainClass != null ? this.mainClass : parent.mainClass,
this.time, this.id, this.type, parent.processArguments, this.releaseTime,
this.assets != null ? this.assets : parent.assets,
this.jar != null ? this.jar : parent.jar,
null, parent.minimumLauncherVersion,
this.libraries != null ? ArrayUtils.merge(this.libraries, parent.libraries) : parent.libraries, this.hidden);
return result;
}
public File getJar(File gameDir) {
String jarId = this.jar == null ? this.id : this.jar;
return new File(gameDir, "versions/" + jarId + "/" + jarId + ".jar");
}
public File getJar(File gameDir, String suffix) {
String jarId = this.jar == null ? this.id : this.jar;
return new File(gameDir, "versions/" + jarId + "/" + jarId + suffix + ".jar");
}
public File getNatives(File gameDir) {
return new File(gameDir, "versions/" + id + "/" + id
+ "-natives");
}
public boolean isAllowedToUnpackNatives() {
return true;
}
@Override
public int compareTo(MinecraftVersion o) {
return id.compareTo(((MinecraftVersion) o).id);
}
}

@ -0,0 +1,306 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.jackhuang.hellominecraft.launcher.utils.version;
import com.google.gson.Gson;
import com.google.gson.JsonSyntaxException;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import org.jackhuang.hellominecraft.C;
import org.jackhuang.hellominecraft.HMCLog;
import org.jackhuang.hellominecraft.launcher.launch.GameLauncher;
import org.jackhuang.hellominecraft.launcher.launch.GameLauncher.DownloadLibraryJob;
import org.jackhuang.hellominecraft.launcher.launch.IMinecraftLoader;
import org.jackhuang.hellominecraft.launcher.launch.IMinecraftProvider;
import org.jackhuang.hellominecraft.launcher.launch.MinecraftLoader;
import org.jackhuang.hellominecraft.utils.BaseLauncherProfile;
import org.jackhuang.hellominecraft.utils.FileUtils;
import org.jackhuang.hellominecraft.launcher.utils.MCUtils;
import org.jackhuang.hellominecraft.launcher.utils.auth.UserProfileProvider;
import org.jackhuang.hellominecraft.launcher.utils.download.DownloadType;
import org.jackhuang.hellominecraft.launcher.utils.settings.Profile;
import org.jackhuang.hellominecraft.launcher.utils.settings.Settings;
import org.jackhuang.hellominecraft.utils.IOUtils;
import org.jackhuang.hellominecraft.utils.MessageBox;
import org.jackhuang.hellominecraft.utils.StrUtils;
import org.jackhuang.hellominecraft.utils.Utils;
/**
*
* @author hyh
*/
public final class MinecraftVersionManager extends IMinecraftProvider {
private File baseFolder;
private final Profile profile;
private final Map<String, MinecraftVersion> versions = new TreeMap();
private final Gson gson = Utils.getDefaultGsonBuilder().create();
/**
*
* @param p
*/
public MinecraftVersionManager(Profile p) {
super(p);
this.profile = p;
refreshVersions();
}
public File getFolder() {
return baseFolder;
}
@Override
public Collection<MinecraftVersion> getVersions() {
return versions.values();
}
@Override
public int getVersionCount() {
return versions.size();
}
@Override
public void refreshVersions() {
baseFolder = profile.getCanonicalGameDirFile();
try {
BaseLauncherProfile.tryWriteProfile(baseFolder);
} catch (IOException ex) {
HMCLog.warn("Failed to create launcher_profiles.json, Forge/LiteLoader installer will not work.", ex);
}
versions.clear();
File oldDir = new File(baseFolder, "bin");
if (oldDir.exists()) {
MinecraftClassicVersion v = new MinecraftClassicVersion();
versions.put(v.id, v);
}
File version = new File(baseFolder, "versions");
File[] files = version.listFiles();
if (files == null || files.length == 0) return;
for (File dir : files) {
String id = dir.getName();
File jsonFile = new File(dir, id + ".json");
if (!dir.isDirectory()) continue;
boolean ask = false;
File[] jsons = null;
if (!jsonFile.exists()) {
jsons = FileUtils.searchSuffix(dir, "json");
if (jsons.length == 1) ask = true;
}
if (ask) {
HMCLog.warn("Found not matched filenames version: " + id + ", json: " + jsons[0].getName());
if (MessageBox.Show(String.format(C.i18n("launcher.versions_json_not_matched"), id, jsons[0].getName()), MessageBox.YES_NO_OPTION) == MessageBox.YES_OPTION)
jsons[0].renameTo(new File(jsons[0].getParent(), id + ".json"));
}
if (!jsonFile.exists()) {
if (StrUtils.formatVersion(id) == null) {
if (MessageBox.Show(C.i18n("launcher.versions_json_not_matched_cannot_auto_completion", id), MessageBox.YES_NO_OPTION) == MessageBox.YES_OPTION)
FileUtils.deleteDirectoryQuietly(dir);
} else if (MessageBox.Show(C.i18n("launcher.versions_json_not_matched_needs_auto_completion", id), MessageBox.YES_NO_OPTION) == MessageBox.YES_OPTION) {
if (!refreshJson(id)) {
if (MessageBox.Show(C.i18n("launcher.versions_json_not_matched_cannot_auto_completion", id), MessageBox.YES_NO_OPTION) == MessageBox.YES_OPTION)
FileUtils.deleteDirectoryQuietly(dir);
}
}
continue;
}
MinecraftVersion mcVersion = null;
try {
mcVersion = gson.fromJson(FileUtils.readFileToString(jsonFile), MinecraftVersion.class);
if (mcVersion == null) throw new RuntimeException("Wrong json format, got null.");
} catch (IOException | RuntimeException e) {
HMCLog.warn("Found wrong format json, try to fix it.", e);
if (MessageBox.Show(C.i18n("launcher.versions_json_not_formattedn", id), MessageBox.YES_NO_OPTION) == MessageBox.YES_OPTION) {
refreshJson(id);
try {
mcVersion = gson.fromJson(FileUtils.readFileToString(jsonFile), MinecraftVersion.class);
if (mcVersion == null) throw new RuntimeException("Wrong json format, got null.");
} catch (IOException | RuntimeException ex) {
HMCLog.err("Retried but still failed.");
HMCLog.warn("Ignoring: " + dir + ", the json of this Minecraft is malformed.", ex);
continue;
}
}
}
try {
if (!id.equals(mcVersion.id)) {
HMCLog.warn("Found: " + dir + ", it contains id: " + mcVersion.id + ", expected: " + id + ", the launcher will fix this problem.");
mcVersion.id = id;
FileUtils.writeQuietly(jsonFile, gson.toJson(mcVersion));
}
if (mcVersion.libraries != null)
for (MinecraftLibrary ml : mcVersion.libraries)
ml.init();
versions.put(id, mcVersion);
} catch (Exception e) {
HMCLog.warn("Ignoring: " + dir + ", the json of this Minecraft is malformed.");
}
}
}
@Override
public boolean removeVersionFromDisk(String name) {
File version = new File(baseFolder, "versions/" + name);
if (!version.exists()) return true;
versions.remove(name);
return FileUtils.deleteDirectoryQuietly(version);
}
@Override
public boolean renameVersion(String from, String to) {
try {
File fromJson = new File(baseFolder, "versions/" + from + "/" + from + ".json");
MinecraftVersion mcVersion = gson.fromJson(FileUtils.readFileToString(fromJson), MinecraftVersion.class);
mcVersion.id = to;
FileUtils.writeQuietly(fromJson, gson.toJson(mcVersion));
File toDir = new File(baseFolder, "versions/" + to);
new File(baseFolder, "versions/" + from).renameTo(toDir);
File toJson = new File(toDir, to + ".json");
File toJar = new File(toDir, to + ".jar");
new File(toDir, from + ".json").renameTo(toJson);
new File(toDir, from + ".jar").renameTo(toJar);
return true;
} catch (IOException | JsonSyntaxException e) {
HMCLog.warn("Failed to rename " + from + " to " + to + ", the json of this Minecraft is malformed.", e);
return false;
}
}
@Override
public boolean refreshJson(String id) {
return MCUtils.downloadMinecraftVersionJson(baseFolder, id, Settings.s().getDownloadSource());
}
@Override
public boolean refreshAssetsIndex(String id) {
MinecraftVersion mv = getVersionById(id);
if (mv == null) return false;
return MCUtils.downloadMinecraftAssetsIndex(new File(baseFolder, "assets"), mv.assets, Settings.s().getDownloadSource());
}
@Override
public boolean install(String id, DownloadType sourceType) {
MinecraftVersion v = MCUtils.downloadMinecraft(baseFolder, id, sourceType);
if (v != null) {
versions.put(v.id, v);
return true;
}
return false;
}
@Override
public File getRunDirectory(String id) {
switch (profile.getGameDirType()) {
case VERSION_FOLDER:
return new File(baseFolder, "versions/" + id + "/");
default:
return baseFolder;
}
}
@Override
public List<GameLauncher.DownloadLibraryJob> getDownloadLibraries(DownloadType downloadType) {
ArrayList<DownloadLibraryJob> downloadLibraries = new ArrayList<>();
MinecraftVersion v = profile.getSelectedMinecraftVersion().resolve(this, Settings.s().getDownloadSource());
for (IMinecraftLibrary l : v.libraries) {
l.init();
if (l.allow()) {
File ff = l.getFilePath(baseFolder);
if (!ff.exists()) {
String libURL = downloadType.getProvider().getLibraryDownloadURL() + "/";
libURL = l.getDownloadURL(libURL, downloadType);
if (libURL != null)
downloadLibraries.add(new DownloadLibraryJob(l.name, libURL, ff));
}
}
}
return downloadLibraries;
}
@Override
public void openSelf(String mv) {
Utils.openFolder(getRunDirectory(mv));
}
@Override
public void open(String mv, String name) {
Utils.openFolder(new File(getRunDirectory(mv), name));
}
@Override
public File getAssets() {
return new File(profile.getCanonicalGameDirFile(), "assets");
}
@Override
public GameLauncher.DecompressLibraryJob getDecompressLibraries() {
MinecraftVersion v = profile.getSelectedMinecraftVersion().resolve(this, Settings.s().getDownloadSource());
ArrayList<File> unzippings = new ArrayList<>();
ArrayList<String[]> extractRules = new ArrayList<>();
for (IMinecraftLibrary l : v.libraries) {
l.init();
if (l.isRequiredToUnzip() && v.isAllowedToUnpackNatives()) {
unzippings.add(IOUtils.tryGetCanonicalFile(l.getFilePath(baseFolder)));
extractRules.add(l.getDecompressExtractRules());
}
}
return new GameLauncher.DecompressLibraryJob(unzippings.toArray(new File[0]), extractRules.toArray(new String[0][]), getDecompressNativesToLocation());
}
@Override
public File getDecompressNativesToLocation() {
MinecraftVersion v = profile.getSelectedMinecraftVersion();
return v.getNatives(profile.getCanonicalGameDirFile());
}
@Override
public File getMinecraftJar() {
return profile.getSelectedMinecraftVersion().getJar(baseFolder);
}
@Override
public IMinecraftLoader provideMinecraftLoader(UserProfileProvider p, DownloadType type)
throws IllegalStateException {
return new MinecraftLoader(profile, this, p, getMinecraftJar(), type);
}
@Override
public MinecraftVersion getOneVersion() {
return versions.isEmpty() ? null : versions.values().iterator().next();
}
@Override
public MinecraftVersion getVersionById(String id) {
return id == null ? null : versions.get(id);
}
@Override
public File getResourcePacks() {
return new File(profile.getCanonicalGameDirFile(), "resourcepacks");
}
@Override
public File getBaseFolder() {
return baseFolder;
}
@Override
public void onLaunch() {
File resourcePacks = getResourcePacks();
if (!resourcePacks.exists()) resourcePacks.mkdirs();
}
}

@ -0,0 +1,22 @@
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package org.jackhuang.hellominecraft.launcher.utils.version;
/**
*
* @author hyh
*/
public class Natives implements Cloneable {
public String windows, osx, linux;
@Override
protected Object clone() {
Natives n = new Natives();
n.windows = windows;
n.osx = osx;
n.linux = linux;
return n;
}
}

@ -0,0 +1,13 @@
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package org.jackhuang.hellominecraft.launcher.utils.version;
/**
*
* @author hyh
*/
public class OS {
public String version, name;
}

@ -0,0 +1,14 @@
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package org.jackhuang.hellominecraft.launcher.utils.version;
/**
*
* @author hyh
*/
public class Rules {
public String action;
public OS os;
}

@ -0,0 +1,63 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.jackhuang.hellominecraft.launcher.views;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import javax.swing.JFrame;
/**
*
* @author hyh
*/
public class DraggableFrame extends JFrame
implements MouseListener, MouseMotionListener {
private int dragGripX;
private int dragGripY;
public DraggableFrame() {
setUndecorated(true);
addMouseListener(this);
addMouseMotionListener(this);
}
@Override
public void mouseClicked(MouseEvent e) {
}
@Override
public void mousePressed(MouseEvent e) {
if (e.getButton() == 1) {
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) {
setLocation(e.getXOnScreen() - this.dragGripX, e.getYOnScreen() - this.dragGripY);
}
}
@Override
public void mouseMoved(MouseEvent e) {
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

@ -0,0 +1,92 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.jackhuang.hellominecraft.launcher.views;
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 hyh
*/
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 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 removeActionListener(ActionListener listener) {
this.model.removeActionListener(listener);
}
public void setActionCommand(String command) {
this.model.setActionCommand(command);
}
@Override
public void mouseClicked(MouseEvent e) {
}
@Override
public void mousePressed(MouseEvent e) {
this.model.setPressed(true);
this.model.setArmed(true);
}
@Override
public void mouseReleased(MouseEvent e) {
this.model.setPressed(false);
this.model.setArmed(false);
}
@Override
public void mouseEntered(MouseEvent e) {
this.model.setRollover(true);
}
@Override
public void mouseExited(MouseEvent e) {
this.model.setRollover(false);
}
}

@ -0,0 +1,178 @@
<?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">
<Group type="102" attributes="0">
<Component id="jLabel4" min="-2" max="-2" attributes="0"/>
<EmptySpace min="0" pref="0" max="32767" attributes="0"/>
</Group>
<Group type="102" alignment="0" attributes="0">
<Component id="chkEnableShadow" min="-2" max="-2" attributes="0"/>
<EmptySpace max="32767" attributes="0"/>
<Component id="btnCheckUpdate" min="-2" max="-2" attributes="0"/>
</Group>
<Group type="102" alignment="1" attributes="0">
<Group type="103" groupAlignment="0" attributes="0">
<Component id="jLabel7" alignment="0" min="-2" max="-2" attributes="0"/>
<Component id="jLabel1" alignment="0" min="-2" max="-2" attributes="0"/>
<Component id="jLabel14" alignment="0" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace min="-2" max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="1" attributes="0">
<Component id="txtBackgroundPath" max="32767" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="btnSelBackgroundPath" min="-2" max="-2" attributes="0"/>
</Group>
<Component id="cboDownloadSource" alignment="1" max="32767" attributes="0"/>
<Component id="cboTheme" 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="jLabel14" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="btnSelBackgroundPath" alignment="3" min="-2" pref="26" max="-2" attributes="0"/>
<Component id="txtBackgroundPath" 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="jLabel7" 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="jLabel1" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="cboTheme" alignment="3" min="-2" pref="26" max="-2" attributes="0"/>
</Group>
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Component id="chkEnableShadow" min="-2" max="-2" attributes="0"/>
<Component id="btnCheckUpdate" alignment="0" min="-2" pref="26" max="-2" attributes="0"/>
</Group>
<EmptySpace pref="119" max="32767" attributes="0"/>
<Component id="jLabel4" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
</Layout>
<SubComponents>
<Component class="javax.swing.JComboBox" name="cboDownloadSource">
<Properties>
<Property name="model" type="javax.swing.ComboBoxModel" editor="org.netbeans.modules.form.editors2.ComboBoxModelEditor">
<StringArray count="2">
<StringItem index="0" value="Mojang"/>
<StringItem index="1" value="BMCLAPI(By bangbang93)"/>
</StringArray>
</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="jLabel4">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/jackhuang/hellominecraft/launcher/I18N.properties" key="launcher.about" replaceFormat="java.util.ResourceBundle.getBundle(&quot;{bundleNameSlashes}&quot;).getString(&quot;{key}&quot;)"/>
</Property>
</Properties>
</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/hellominecraft/launcher/I18N.properties" key="ui.button.explore" replaceFormat="java.util.ResourceBundle.getBundle(&quot;{bundleNameSlashes}&quot;).getString(&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.JLabel" name="jLabel14">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/jackhuang/hellominecraft/launcher/I18N.properties" key="launcher.background_location" replaceFormat="java.util.ResourceBundle.getBundle(&quot;{bundleNameSlashes}&quot;).getString(&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/hellominecraft/launcher/I18N.properties" key="launcher.background_tooltip" replaceFormat="java.util.ResourceBundle.getBundle(&quot;{bundleNameSlashes}&quot;).getString(&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.JLabel" name="jLabel7">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/jackhuang/hellominecraft/launcher/I18N.properties" key="launcher.download_source" replaceFormat="java.util.ResourceBundle.getBundle(&quot;{bundleNameSlashes}&quot;).getString(&quot;{key}&quot;)"/>
</Property>
</Properties>
</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/hellominecraft/launcher/I18N.properties" key="launcher.update_launcher" replaceFormat="java.util.ResourceBundle.getBundle(&quot;{bundleNameSlashes}&quot;).getString(&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.JCheckBox" name="chkEnableShadow">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/jackhuang/hellominecraft/launcher/I18N.properties" key="launcher.enable_shadow" replaceFormat="java.util.ResourceBundle.getBundle(&quot;{bundleNameSlashes}&quot;).getString(&quot;{key}&quot;)"/>
</Property>
</Properties>
<Events>
<EventHandler event="focusLost" listener="java.awt.event.FocusListener" parameters="java.awt.event.FocusEvent" handler="chkEnableShadowFocusLost"/>
</Events>
</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/launcher/I18N.properties" key="launcher.theme" replaceFormat="java.util.ResourceBundle.getBundle(&quot;{bundleNameSlashes}&quot;).getString(&quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JComboBox" name="cboTheme">
<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="cboThemeItemStateChanged"/>
</Events>
</Component>
</SubComponents>
</Form>

@ -0,0 +1,223 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.jackhuang.hellominecraft.launcher.views;
import java.awt.Color;
import java.io.IOException;
import javax.swing.DefaultComboBoxModel;
import javax.swing.JFileChooser;
import org.jackhuang.hellominecraft.C;
import org.jackhuang.hellominecraft.HMCLog;
import org.jackhuang.hellominecraft.launcher.utils.settings.Settings;
import org.jackhuang.hellominecraft.utils.IOUtils;
import org.jackhuang.hellominecraft.utils.MessageBox;
/**
*
* @author hyh
*/
public class LauncherSettingsPanel extends javax.swing.JPanel {
/**
* Creates new form LancherSettingsPanel
*/
public LauncherSettingsPanel() {
initComponents();
txtBackgroundPath.setText(Settings.s().getBgpath());
cboDownloadSource.setSelectedIndex(Settings.s().getDownloadType());
cboTheme.setSelectedIndex(Settings.s().getTheme());
chkEnableShadow.setSelected(Settings.s().isEnableShadow());
setBackground(Color.white);
setOpaque(true);
}
/**
* 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() {
cboDownloadSource = new javax.swing.JComboBox();
jLabel4 = new javax.swing.JLabel();
btnSelBackgroundPath = new javax.swing.JButton();
jLabel14 = new javax.swing.JLabel();
txtBackgroundPath = new javax.swing.JTextField();
jLabel7 = new javax.swing.JLabel();
btnCheckUpdate = new javax.swing.JButton();
chkEnableShadow = new javax.swing.JCheckBox();
jLabel1 = new javax.swing.JLabel();
cboTheme = new javax.swing.JComboBox();
cboDownloadSource.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "Mojang", "BMCLAPI(By bangbang93)" }));
cboDownloadSource.addItemListener(new java.awt.event.ItemListener() {
public void itemStateChanged(java.awt.event.ItemEvent evt) {
cboDownloadSourceItemStateChanged(evt);
}
});
java.util.ResourceBundle bundle = java.util.ResourceBundle.getBundle("org/jackhuang/hellominecraft/launcher/I18N"); // NOI18N
jLabel4.setText(bundle.getString("launcher.about")); // NOI18N
btnSelBackgroundPath.setText(bundle.getString("ui.button.explore")); // NOI18N
btnSelBackgroundPath.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
btnSelBackgroundPathActionPerformed(evt);
}
});
jLabel14.setText(bundle.getString("launcher.background_location")); // NOI18N
jLabel14.setToolTipText("");
txtBackgroundPath.setToolTipText(bundle.getString("launcher.background_tooltip")); // NOI18N
txtBackgroundPath.addFocusListener(new java.awt.event.FocusAdapter() {
public void focusLost(java.awt.event.FocusEvent evt) {
txtBackgroundPathFocusLost(evt);
}
});
jLabel7.setText(bundle.getString("launcher.download_source")); // NOI18N
btnCheckUpdate.setText(bundle.getString("launcher.update_launcher")); // NOI18N
btnCheckUpdate.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
btnCheckUpdateActionPerformed(evt);
}
});
chkEnableShadow.setText(bundle.getString("launcher.enable_shadow")); // NOI18N
chkEnableShadow.addFocusListener(new java.awt.event.FocusAdapter() {
public void focusLost(java.awt.event.FocusEvent evt) {
chkEnableShadowFocusLost(evt);
}
});
jLabel1.setText(bundle.getString("launcher.theme")); // NOI18N
cboTheme.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")}));
cboTheme.addItemListener(new java.awt.event.ItemListener() {
public void itemStateChanged(java.awt.event.ItemEvent evt) {
cboThemeItemStateChanged(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)
.addGroup(layout.createSequentialGroup()
.addComponent(jLabel4, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGap(0, 0, Short.MAX_VALUE))
.addGroup(layout.createSequentialGroup()
.addComponent(chkEnableShadow)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(btnCheckUpdate))
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(jLabel7)
.addComponent(jLabel1)
.addComponent(jLabel14))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
.addComponent(txtBackgroundPath)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(btnSelBackgroundPath))
.addComponent(cboDownloadSource, javax.swing.GroupLayout.Alignment.TRAILING, 0, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(cboTheme, javax.swing.GroupLayout.Alignment.TRAILING, 0, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))))
.addContainerGap())
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addContainerGap()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(jLabel14)
.addComponent(btnSelBackgroundPath, javax.swing.GroupLayout.PREFERRED_SIZE, 26, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(txtBackgroundPath, javax.swing.GroupLayout.PREFERRED_SIZE, 26, javax.swing.GroupLayout.PREFERRED_SIZE))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(jLabel7)
.addComponent(cboDownloadSource, javax.swing.GroupLayout.PREFERRED_SIZE, 26, javax.swing.GroupLayout.PREFERRED_SIZE))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(jLabel1)
.addComponent(cboTheme, javax.swing.GroupLayout.PREFERRED_SIZE, 26, javax.swing.GroupLayout.PREFERRED_SIZE))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(chkEnableShadow)
.addComponent(btnCheckUpdate, javax.swing.GroupLayout.PREFERRED_SIZE, 26, javax.swing.GroupLayout.PREFERRED_SIZE))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 119, Short.MAX_VALUE)
.addComponent(jLabel4, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addContainerGap())
);
}// </editor-fold>//GEN-END:initComponents
private void cboDownloadSourceItemStateChanged(java.awt.event.ItemEvent evt) {//GEN-FIRST:event_cboDownloadSourceItemStateChanged
Settings.s().setDownloadType(cboDownloadSource.getSelectedIndex());
}//GEN-LAST:event_cboDownloadSourceItemStateChanged
private void btnSelBackgroundPathActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnSelBackgroundPathActionPerformed
JFileChooser fc = new JFileChooser();
fc.setFileSelectionMode(JFileChooser.FILES_ONLY);
fc.setDialogTitle(C.i18n("launcher.choose_bgpath"));
fc.setMultiSelectionEnabled(false);
fc.showOpenDialog(this);
if (fc.getSelectedFile() == null) {
return;
}
try {
String path = fc.getSelectedFile().getCanonicalPath();
path = IOUtils.removeLastSeparator(path);
txtBackgroundPath.setText(path);
Settings.s().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
String path = txtBackgroundPath.getText();
Settings.s().setBgpath(path);
MainFrame.instance.loadBackground();
}//GEN-LAST:event_txtBackgroundPathFocusLost
private void btnCheckUpdateActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnCheckUpdateActionPerformed
Settings.UPDATE_CHECKER.process(true);
}//GEN-LAST:event_btnCheckUpdateActionPerformed
private void chkEnableShadowFocusLost(java.awt.event.FocusEvent evt) {//GEN-FIRST:event_chkEnableShadowFocusLost
Settings.s().setEnableShadow(chkEnableShadow.isSelected());
}//GEN-LAST:event_chkEnableShadowFocusLost
private void cboThemeItemStateChanged(java.awt.event.ItemEvent evt) {//GEN-FIRST:event_cboThemeItemStateChanged
Settings.s().setTheme(cboTheme.getSelectedIndex());
if(MainFrame.instance != null)
MainFrame.instance.reloadColor();
}//GEN-LAST:event_cboThemeItemStateChanged
// Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.JButton btnCheckUpdate;
private javax.swing.JButton btnSelBackgroundPath;
private javax.swing.JComboBox cboDownloadSource;
private javax.swing.JComboBox cboTheme;
private javax.swing.JCheckBox chkEnableShadow;
private javax.swing.JLabel jLabel1;
private javax.swing.JLabel jLabel14;
private javax.swing.JLabel jLabel4;
private javax.swing.JLabel jLabel7;
private javax.swing.JTextField txtBackgroundPath;
// End of variables declaration//GEN-END:variables
}

@ -0,0 +1,360 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.jackhuang.hellominecraft.launcher.views;
import com.sun.awt.AWTUtilities;
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.Transparency;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.image.BufferedImage;
import javax.swing.BorderFactory;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JPanel;
import org.jackhuang.hellominecraft.C;
import org.jackhuang.hellominecraft.HMCLog;
import org.jackhuang.hellominecraft.launcher.Main;
import org.jackhuang.hellominecraft.launcher.utils.settings.Settings;
import org.jackhuang.hellominecraft.utils.UpdateChecker;
import org.jackhuang.hellominecraft.utils.Utils;
import org.jackhuang.hellominecraft.views.DropShadowBorder;
import org.jackhuang.hellominecraft.views.TintablePanel;
import org.jackhuang.hellominecraft.views.BasicColors;
/**
*
* @author hyh
*/
public final class MainFrame extends DraggableFrame {
public static final MainFrame instance = new MainFrame();
HeaderTab mainTab, gameTab, launcherTab;
TintablePanel centralPanel;
JPanel header;
MainPagePanel mainPanel;
GameSettingsPanel gamePanel;
LauncherSettingsPanel launcherPanel;
CardLayout infoLayout;
JPanel infoSwap;
JLabel backgroundLabel, windowTitle;
JPanel realPanel;
DropShadowBorder border;
boolean enableShadow;
String defaultTitle;
MainFrame() {
defaultTitle = Main.makeTitle();
enableShadow = Settings.s().isEnableShadow();
if (enableShadow)
setSize(834, 542);
else
setSize(802, 511);
setDefaultCloseOperation(3);
setTitle(Main.makeTitle());
initComponents();
selectTab("main");
loadBackground();
setLocationRelativeTo(null);
if (enableShadow)
try {
AWTUtilities.setWindowOpaque(this, false);
getRootPane().setBorder(border = new DropShadowBorder(borderColor, 4));
} catch (Throwable ex) {
HMCLog.err("Failed to set window transparent.", ex);
Settings.s().setEnableShadow(false);
setSize(802, 511);
}
((JPanel) getContentPane()).setOpaque(true);
}
private void initComponents() {
borderColor = BasicColors.bgcolors[Settings.s().getTheme()];
borderColorDarker = BasicColors.bgcolors_darker[Settings.s().getTheme()];
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 = Utils.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)));
ActionListener tabListener = (e) -> MainFrame.this.selectTab(e.getActionCommand());
this.mainTab = new HeaderTab(C.i18n("launcher.title.main"));
this.mainTab.setForeground(BasicColors.COLOR_WHITE_TEXT);
this.mainTab.setBackground(borderColorDarker);
this.mainTab.setActionCommand("main");
this.mainTab.addActionListener(tabListener);
header.add(this.mainTab);
this.gameTab = new HeaderTab(C.i18n("launcher.title.game"));
this.gameTab.setForeground(BasicColors.COLOR_WHITE_TEXT);
this.gameTab.setBackground(borderColorDarker);
this.gameTab.setIsActive(true);
this.gameTab.setHorizontalTextPosition(10);
this.gameTab.addActionListener(tabListener);
this.gameTab.setActionCommand("game");
header.add(this.gameTab);
this.launcherTab = new HeaderTab(C.i18n("launcher.title.launcher"));
this.launcherTab.setForeground(BasicColors.COLOR_WHITE_TEXT);
this.launcherTab.setBackground(borderColorDarker);
this.launcherTab.setLayout(null);
this.launcherTab.addActionListener(tabListener);
this.launcherTab.setActionCommand("launcher");
header.add(this.launcherTab);
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);
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);
windowTitle.addMouseListener(new MouseListener() {
@Override
public void mouseClicked(MouseEvent e) {
if (UpdateChecker.OUT_DATED) Main.update();
}
@Override
public void mousePressed(MouseEvent e) {
}
@Override
public void mouseReleased(MouseEvent e) {
}
@Override
public void mouseEntered(MouseEvent e) {
}
@Override
public void mouseExited(MouseEvent e) {
}
});
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);
this.mainPanel = new MainPagePanel();
this.infoSwap.add(mainPanel, "main");
this.gamePanel = new GameSettingsPanel();
this.infoSwap.add(gamePanel, "game");
this.launcherPanel = new LauncherSettingsPanel();
this.infoSwap.add(launcherPanel, "launcher");
truePanel.add(this.infoSwap, "Center");
centralPanel.setLayout(null);
centralPanel.add(truePanel);
truePanel.setBounds(0, 0, 800, 480);
centralPanel.setBounds(0, 30, 800, 480);
setLayout(null);
realPanel.setBounds(1, 0, 800, 511);
add(realPanel);
}
public void selectTab(String tabName) {
this.mainTab.setIsActive(false);
this.gameTab.setIsActive(false);
this.launcherTab.setIsActive(false);
if (tabName.equalsIgnoreCase("main")) {
this.mainTab.setIsActive(true);
this.mainPanel.onSelected();
} else if (tabName.equalsIgnoreCase("game")) {
this.gameTab.setIsActive(true);
this.gamePanel.onSelected();
} else if (tabName.equalsIgnoreCase("launcher"))
this.launcherTab.setIsActive(true);
this.infoLayout.show(this.infoSwap, tabName);
}
protected void closeWindow() {
System.exit(0);
}
protected void minimizeWindow() {
setState(1);
}
ImageIcon background;
public void loadBackground() {
background = Utils.searchBackgroundImage(Main.getIcon("background.jpg"), Settings.s().getBgpath(), 800, 480);
if (background != null) {
if (backgroundLabel == null) {
backgroundLabel = new JLabel(background);
backgroundLabel.setBounds(0, 0, 800, 480);
} else
backgroundLabel.setIcon(background);
centralPanel.add(backgroundLabel, -1);
} else
HMCLog.warn("No Background Image, the background will be white!");
}
public JPanel getTitleBar() {
return header;
}
boolean isShowedMessage = false;
public void closeMessage() {
if (isShowedMessage) {
isShowedMessage = false;
reloadColor();
windowTitle.setText(defaultTitle);
windowTitle.setForeground(UpdateChecker.OUT_DATED ? Color.red : Color.white);
}
}
public void showMessage(String message) {
isShowedMessage = true;
borderColor = BasicColors.COLOR_RED;
borderColorDarker = BasicColors.COLOR_RED_DARKER;
header.setBackground(borderColor);
mainTab.setBackground(borderColorDarker);
gameTab.setBackground(borderColorDarker);
launcherTab.setBackground(borderColorDarker);
if (border != null)
border.setColor(borderColor);
repaint();
windowTitle.setText(message);
windowTitle.setForeground(Color.white);
}
public static void showMainFrame(boolean firstLoad) {
instance.mainPanel.onShow(firstLoad);
instance.show();
}
Color borderColor = BasicColors.COLOR_BLUE;
Color borderColorDarker = BasicColors.COLOR_BLUE_DARKER;
public void reloadColor() {
borderColor = BasicColors.bgcolors[Settings.s().getTheme()];
borderColorDarker = BasicColors.bgcolors_darker[Settings.s().getTheme()];
if (border != null)
border.setColor(borderColor);
header.setBackground(borderColor);
mainTab.setBackground(borderColorDarker);
gameTab.setBackground(borderColorDarker);
launcherTab.setBackground(borderColorDarker);
repaint();
}
private void paintImpl(Graphics g) {
super.paint(g);
g.setColor(borderColor);
int off = enableShadow ? 16 : 0;
int width = 800;
int height = header.getHeight() + 480 - 1;
g.drawLine(off, off, off, height + off + 1);
g.drawLine(off + width + 1, off, off + width + 1, height + off + 1);
g.drawLine(off, height + off + 1, off + width + 1, height + off + 1);
}
@Override
public void paint(Graphics g) {
if (!enableShadow)
paintImpl(g);
else {
int off = enableShadow ? 16 : 0;
int width = this.getWidth();
int height = this.getHeight();
int contentWidth = width - off - off;
int contentHeight = height - off - off;
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() {
if (!isVisible()) return;
defaultTitle = defaultTitle + C.i18n("update.found");
if (!isShowedMessage) {
windowTitle.setText(defaultTitle);
windowTitle.setForeground(Color.red);
}
}
}

@ -0,0 +1,280 @@
<?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="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>
<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" alignment="0" 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="1" attributes="0">
<Component id="jLabel10" alignment="1" min="-2" max="-2" attributes="0"/>
<Component id="jLabel1" 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>
<Component id="btnMakeLaunchScript" alignment="0" max="32767" attributes="0"/>
<Component id="btnShowLog" alignment="0" max="32767" attributes="0"/>
<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="jLabel7" 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>
</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="jLabel10" 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="jLabel1" alignment="3" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="3" attributes="0">
<Component id="jLabel7" 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="btnShowLog" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="btnMakeLaunchScript" 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="jLabel7">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/jackhuang/hellominecraft/launcher/I18N.properties" key="login.type" replaceFormat="java.util.ResourceBundle.getBundle(&quot;{bundleNameSlashes}&quot;).getString(&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/hellominecraft/launcher/I18N.properties" key="login.username" replaceFormat="java.util.ResourceBundle.getBundle(&quot;{bundleNameSlashes}&quot;).getString(&quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JLabel" name="jLabel10">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/jackhuang/hellominecraft/launcher/I18N.properties" key="ui.label.profile" replaceFormat="java.util.ResourceBundle.getBundle(&quot;{bundleNameSlashes}&quot;).getString(&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="jLabel1">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/jackhuang/hellominecraft/launcher/I18N.properties" key="ui.label.version" replaceFormat="C.I18N.getString(&quot;{key}&quot;)"/>
</Property>
<Property name="toolTipText" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/jackhuang/hellominecraft/launcher/I18N.properties" key="ui.label.version" replaceFormat="java.util.ResourceBundle.getBundle(&quot;{bundleNameSlashes}&quot;).getString(&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>
</Component>
<Container class="javax.swing.JPanel" name="pnlPassword">
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignCardLayout"/>
<SubComponents>
<Container class="javax.swing.JPanel" name="jPanel1">
<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="jLabel9" 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="jLabel9" 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="jLabel9">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/jackhuang/hellominecraft/launcher/I18N.properties" key="ui.label.password" replaceFormat="java.util.ResourceBundle.getBundle(&quot;{bundleNameSlashes}&quot;).getString(&quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JPasswordField" name="txtPassword">
<Events>
<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="jPanel3">
<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" pref="26" 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/hellominecraft/launcher/I18N.properties" key="ui.button.logout" replaceFormat="C.I18N.getString(&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="btnShowLog">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/jackhuang/hellominecraft/launcher/I18N.properties" key="mainwindow.show_log" replaceFormat="java.util.ResourceBundle.getBundle(&quot;{bundleNameSlashes}&quot;).getString(&quot;{key}&quot;)"/>
</Property>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="btnShowLogActionPerformed"/>
</Events>
</Component>
<Component class="javax.swing.JButton" name="btnMakeLaunchScript">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/jackhuang/hellominecraft/launcher/I18N.properties" key="mainwindow.make_launch_script" replaceFormat="java.util.ResourceBundle.getBundle(&quot;{bundleNameSlashes}&quot;).getString(&quot;{key}&quot;)"/>
</Property>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="btnMakeLaunchScriptActionPerformed"/>
</Events>
</Component>
</SubComponents>
</Container>
</SubComponents>
</Form>

@ -0,0 +1,540 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.jackhuang.hellominecraft.launcher.views;
import java.awt.CardLayout;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.event.ItemEvent;
import java.awt.event.KeyEvent;
import java.io.File;
import java.util.List;
import javax.swing.SwingUtilities;
import org.jackhuang.hellominecraft.C;
import org.jackhuang.hellominecraft.HMCLog;
import org.jackhuang.hellominecraft.launcher.launch.DefaultGameLauncher;
import org.jackhuang.hellominecraft.launcher.utils.auth.IAuthenticator;
import org.jackhuang.hellominecraft.launcher.utils.auth.LoginInfo;
import org.jackhuang.hellominecraft.launcher.utils.settings.Profile;
import org.jackhuang.hellominecraft.utils.MessageBox;
import org.jackhuang.hellominecraft.utils.StrUtils;
import org.jackhuang.hellominecraft.launcher.utils.version.MinecraftVersion;
import org.jackhuang.hellominecraft.launcher.launch.GameLauncher;
import org.jackhuang.hellominecraft.launcher.launch.LaunchFinisher;
import org.jackhuang.hellominecraft.launcher.launch.LaunchScriptFinisher;
import org.jackhuang.hellominecraft.launcher.utils.settings.Settings;
import org.jackhuang.hellominecraft.lookandfeel.GraphicsUtils;
import org.jackhuang.hellominecraft.utils.Event;
import org.jackhuang.hellominecraft.views.LogWindow;
import org.jackhuang.hellominecraft.lookandfeel.components.ConstomButton;
import org.jackhuang.hellominecraft.utils.functions.Consumer;
/**
*
* @author hyh
*/
public class MainPagePanel extends javax.swing.JPanel {
/**
* Creates new form MainPagePanel
*/
public MainPagePanel() {
initComponents();
pnlButtons = new javax.swing.JPanel();
pnlButtons.setLayout(null);
btnRun = new ConstomButton();
btnRun.setBounds(0, 0, 150, 50);
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 -> btnRunActionPerformed());
this.add(pnlButtons);
pnlButtons.setBounds(0, 0, 150, 50);
this.setSize(new Dimension(deWidth, deHeight));
this.pnlButtons.setLocation(deWidth - pnlButtons.getWidth() - 25, deHeight - pnlButtons.getHeight() - 25);
pnlMore.setBounds(0, 0, pnlMore.getWidth(), deHeight);
pnlMore.setBackground(GraphicsUtils.getWebColorWithAlpha("FFFFFF7F"));
pnlMore.setOpaque(true);
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() {
pnlMore = new javax.swing.JPanel();
txtPlayerName = new javax.swing.JTextField();
jLabel7 = new javax.swing.JLabel();
cboLoginMode = new javax.swing.JComboBox();
lblUserName = new javax.swing.JLabel();
jLabel10 = new javax.swing.JLabel();
cboProfiles = new javax.swing.JComboBox();
jLabel1 = new javax.swing.JLabel();
cboVersions = new javax.swing.JComboBox();
pnlPassword = new javax.swing.JPanel();
jPanel1 = new javax.swing.JPanel();
jLabel9 = new javax.swing.JLabel();
txtPassword = new javax.swing.JPasswordField();
jPanel3 = new javax.swing.JPanel();
btnLogout = new javax.swing.JButton();
btnShowLog = new javax.swing.JButton();
btnMakeLaunchScript = new javax.swing.JButton();
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);
}
});
java.util.ResourceBundle bundle = java.util.ResourceBundle.getBundle("org/jackhuang/hellominecraft/launcher/I18N"); // NOI18N
jLabel7.setText(bundle.getString("login.type")); // NOI18N
cboLoginMode.addItemListener(new java.awt.event.ItemListener() {
public void itemStateChanged(java.awt.event.ItemEvent evt) {
cboLoginModeItemStateChanged(evt);
}
});
lblUserName.setText(bundle.getString("login.username")); // NOI18N
jLabel10.setText(bundle.getString("ui.label.profile")); // NOI18N
cboProfiles.addItemListener(new java.awt.event.ItemListener() {
public void itemStateChanged(java.awt.event.ItemEvent evt) {
cboProfilesItemStateChanged(evt);
}
});
jLabel1.setText(C.I18N.getString("ui.label.version")); // NOI18N
jLabel1.setToolTipText(bundle.getString("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());
jLabel9.setText(bundle.getString("ui.label.password")); // NOI18N
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 jPanel1Layout = new javax.swing.GroupLayout(jPanel1);
jPanel1.setLayout(jPanel1Layout);
jPanel1Layout.setHorizontalGroup(
jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(jPanel1Layout.createSequentialGroup()
.addComponent(jLabel9)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(txtPassword))
);
jPanel1Layout.setVerticalGroup(
jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel1Layout.createSequentialGroup()
.addGap(0, 0, Short.MAX_VALUE)
.addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(jLabel9, 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(jPanel1, "card2");
btnLogout.setText(C.I18N.getString("ui.button.logout")); // NOI18N
btnLogout.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
btnLogoutActionPerformed(evt);
}
});
javax.swing.GroupLayout jPanel3Layout = new javax.swing.GroupLayout(jPanel3);
jPanel3.setLayout(jPanel3Layout);
jPanel3Layout.setHorizontalGroup(
jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(btnLogout, javax.swing.GroupLayout.DEFAULT_SIZE, 170, Short.MAX_VALUE)
);
jPanel3Layout.setVerticalGroup(
jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(btnLogout, javax.swing.GroupLayout.DEFAULT_SIZE, 26, Short.MAX_VALUE)
);
pnlPassword.add(jPanel3, "card3");
btnShowLog.setText(bundle.getString("mainwindow.show_log")); // NOI18N
btnShowLog.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
btnShowLogActionPerformed(evt);
}
});
btnMakeLaunchScript.setText(bundle.getString("mainwindow.make_launch_script")); // NOI18N
btnMakeLaunchScript.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
btnMakeLaunchScriptActionPerformed(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.TRAILING)
.addComponent(jLabel10)
.addComponent(jLabel1))
.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)))
.addComponent(btnMakeLaunchScript, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(btnShowLog, 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(lblUserName)
.addComponent(jLabel7))
.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))))
.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(jLabel10)
.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(jLabel1))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(pnlMoreLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(jLabel7)
.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(btnShowLog)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(btnMakeLaunchScript)
.addContainerGap())
);
add(pnlMore);
pnlMore.setBounds(0, 0, 190, 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
Settings.s().setUsername(txtPlayerName.getText());
}//GEN-LAST:event_txtPlayerNameFocusLost
private void cboLoginModeItemStateChanged(java.awt.event.ItemEvent evt) {//GEN-FIRST:event_cboLoginModeItemStateChanged
if (preaparingAuth) return;
int index = cboLoginMode.getSelectedIndex();
if (index < 0) return;
IAuthenticator l = IAuthenticator.logins.get(index);
if (l.isHidePasswordBox()) {
pnlPassword.setVisible(false);
lblUserName.setText(C.i18n("login.username"));
} else {
pnlPassword.setVisible(true);
lblUserName.setText(C.i18n("login.account"));
}
CardLayout cl = (CardLayout) pnlPassword.getLayout();
if (l.isLoggedIn()) cl.last(pnlPassword);
else cl.first(pnlPassword);
String username = Settings.s().getUsername();
if (StrUtils.isNotBlank(username)) txtPlayerName.setText(username);
Settings.s().setLoginType(index);
}//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.s().setLast((String) cboProfiles.getSelectedItem());
loadMinecraftVersions();
}
}//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()) || getCurrentProfile() == null)
return;
getCurrentProfile().setSelectedMinecraftVersion(cboVersions.getSelectedItem().toString());
cboVersions.setToolTipText(cboVersions.getSelectedItem().toString());
Settings.save();
}//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
btnRunActionPerformed();
}//GEN-LAST:event_txtPasswordActionPerformed
private void btnLogoutActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnLogoutActionPerformed
if (preaparingAuth) return;
int index = cboLoginMode.getSelectedIndex();
IAuthenticator l = IAuthenticator.logins.get(index);
CardLayout cl = (CardLayout) pnlPassword.getLayout();
if (l.isLoggedIn()) l.logout();
cl.first(pnlPassword);
}//GEN-LAST:event_btnLogoutActionPerformed
private void btnShowLogActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnShowLogActionPerformed
LogWindow.instance.setVisible(true);
}//GEN-LAST:event_btnShowLogActionPerformed
private void btnMakeLaunchScriptActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnMakeLaunchScriptActionPerformed
MainFrame.instance.showMessage(C.i18n("ui.message.launching"));
genLaunchCode(value -> {
value.successEvent.register(new LaunchScriptFinisher());
value.successEvent.register(new PrepareAuthDoneListener());
});
}//GEN-LAST:event_btnMakeLaunchScriptActionPerformed
private void txtPlayerNameKeyPressed(java.awt.event.KeyEvent evt) {//GEN-FIRST:event_txtPlayerNameKeyPressed
if (evt.getKeyCode() == KeyEvent.VK_ENTER) {
int index = cboLoginMode.getSelectedIndex();
if (index < 0) return;
IAuthenticator l = IAuthenticator.logins.get(index);
if (l.isHidePasswordBox()) btnRunActionPerformed();
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) btnRunActionPerformed();
}//GEN-LAST:event_txtPasswordKeyPressed
// <editor-fold defaultstate="collapsed" desc="Game Launch">
void genLaunchCode(final Consumer<GameLauncher> listener) {
HMCLog.log("Start generating launching command...");
File file = getCurrentProfile().getCanonicalGameDirFile();
if (!file.exists()) {
HMCLog.warn("The minecraft path is wrong, please check it yourself.");
MessageBox.Show(C.i18n("minecraft.wrong_path"));
return;
}
final String name = (String) cboProfiles.getSelectedItem();
if (StrUtils.isBlank(name) || getCurrentProfile().getSelectedMinecraftVersion() == null) {
HMCLog.warn("There's no selected version, rechoose a version.");
MessageBox.Show(C.i18n("minecraft.no_selected_version"));
return;
}
if (cboLoginMode.getItemCount() == 0) {
HMCLog.warn("There's no login method.");
MessageBox.Show(C.i18n("login.methods.no_method"));
return;
}
final int index = cboLoginMode.getSelectedIndex();
final IAuthenticator l = IAuthenticator.logins.get(index);
final LoginInfo li = new LoginInfo(Settings.s().getUsername(), l.isLoggedIn() || l.isHidePasswordBox() ? null : new String(txtPassword.getPassword()));
Thread t = new Thread() {
@Override
public void run() {
Thread.currentThread().setName("Game Launcher");
DefaultGameLauncher gl = new DefaultGameLauncher(getCurrentProfile(), li, l, Settings.s().getDownloadSource());
gl.failEvent.register((sender, s) -> {
if (s != null) MessageBox.Show(s);
MainFrame.instance.closeMessage();
return true;
});
listener.accept(gl);
gl.makeLaunchCommand();
}
};
t.start();
}
//</editor-fold>
// <editor-fold defaultstate="collapsed" desc="Loads">
private void prepareAuths() {
preaparingAuth = true;
List<IAuthenticator> list = IAuthenticator.logins;
cboLoginMode.removeAllItems();
for (IAuthenticator str : list)
try {
cboLoginMode.addItem(str.getName());
} catch (Exception ex) {
HMCLog.warn("Failed to get login name", ex);
}
if (Settings.s().getLoginType() < list.size()) {
preaparingAuth = false;
cboLoginMode.setSelectedIndex(Settings.s().getLoginType());
cboLoginModeItemStateChanged(null);
}
}
void loadFromSettings() {
for (Profile s : Settings.getProfiles()) cboProfiles.addItem(s.getName());
}
boolean showedNoVersion = false;
void loadMinecraftVersions() {
isLoading = true;
cboVersions.removeAllItems();
int index = 0, i = 0;
getCurrentProfile().getMinecraftProvider().refreshVersions();
MinecraftVersion selVersion = getCurrentProfile().getSelectedMinecraftVersion();
String selectedMC = selVersion == null ? null : selVersion.id;
if (getCurrentProfile().getMinecraftProvider().getVersions().isEmpty()) {
if (!showedNoVersion)
SwingUtilities.invokeLater(() -> {
MessageBox.Show(C.i18n("mainwindow.no_version"));
showedNoVersion = true;
});
} else {
for (MinecraftVersion mcVersion : getCurrentProfile().getMinecraftProvider().getVersions()) {
if (mcVersion.hidden) continue;
cboVersions.addItem(mcVersion.id);
if (mcVersion.id.equals(selectedMC)) index = i;
i++;
}
if (index < cboVersions.getItemCount()) cboVersions.setSelectedIndex(index);
}
isLoading = false;
}
private void refreshMinecrafts(String last) {
isLoading = true;
cboProfiles.removeAllItems();
loadFromSettings();
for (int i = 0; i < cboProfiles.getItemCount(); i++) {
String s = (String) cboProfiles.getItemAt(i);
if (s != null && s.equals(last)) {
cboProfiles.setSelectedIndex(i);
break;
}
}
isLoading = false;
loadMinecraftVersions();
}
//</editor-fold>
// <editor-fold defaultstate="collapsed" desc="Private Variables">
boolean preaparingAuth = true;
private boolean isLoading = false;
private final javax.swing.JPanel pnlButtons;
private final ConstomButton btnRun;
private static final int deWidth = 800, deHeight = 480;
//</editor-fold>
class PrepareAuthDoneListener implements Event<List<String>> {
@Override
public boolean call(Object sender, List<String> value) {
prepareAuths();
return true;
}
}
private void btnRunActionPerformed() {
MainFrame.instance.showMessage(C.i18n("ui.message.launching"));
genLaunchCode(value -> {
value.successEvent.register(new LaunchFinisher());
value.successEvent.register(new PrepareAuthDoneListener());
});
}
public void onShow(boolean showLeft) {
if (showLeft)
SwingUtilities.invokeLater(() -> MainFrame.instance.showMessage(C.i18n("ui.message.first_load")));
if (cboLoginMode.getSelectedIndex() >= 0 && cboLoginMode.getSelectedIndex() < cboLoginMode.getItemCount()) {
IAuthenticator l = IAuthenticator.logins.get(cboLoginMode.getSelectedIndex());
if (!l.isHidePasswordBox() && !l.isLoggedIn())
SwingUtilities.invokeLater(() -> MainFrame.instance.showMessage(C.i18n("ui.message.enter_password")));
}
}
public Profile getCurrentProfile() {
return Settings.getVersion((String) cboProfiles.getSelectedItem());
}
public void onSelected() {
refreshMinecrafts(Settings.s().getLast());
}
// Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.JButton btnLogout;
private javax.swing.JButton btnMakeLaunchScript;
private javax.swing.JButton btnShowLog;
private javax.swing.JComboBox cboLoginMode;
private javax.swing.JComboBox cboProfiles;
private javax.swing.JComboBox cboVersions;
private javax.swing.JLabel jLabel1;
private javax.swing.JLabel jLabel10;
private javax.swing.JLabel jLabel7;
private javax.swing.JLabel jLabel9;
private javax.swing.JPanel jPanel1;
private javax.swing.JPanel jPanel3;
private javax.swing.JLabel lblUserName;
private javax.swing.JPanel pnlMore;
private javax.swing.JPanel pnlPassword;
private javax.swing.JPasswordField txtPassword;
private javax.swing.JTextField txtPlayerName;
// End of variables declaration//GEN-END:variables
}

@ -0,0 +1,124 @@
<?xml version="1.0" encoding="UTF-8" ?>
<Form version="1.3" maxVersion="1.9" type="org.netbeans.modules.form.forminfo.JDialogFormInfo">
<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/hellominecraft/launcher/I18N.properties" key="ui.newProfileWindow.title" replaceFormat="java.util.ResourceBundle.getBundle(&quot;{bundleNameSlashes}&quot;).getString(&quot;{key}&quot;)"/>
</Property>
</Properties>
<SyntheticProperties>
<SyntheticProperty name="formSizePolicy" type="int" value="1"/>
<SyntheticProperty name="generateCenter" type="boolean" value="false"/>
</SyntheticProperties>
<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="0" attributes="0">
<Component id="jLabel1" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="txtNewProfileName" max="32767" attributes="0"/>
</Group>
<Group type="102" alignment="0" attributes="0">
<Component id="jLabel2" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="cboProfiles" max="32767" attributes="0"/>
</Group>
<Group type="102" alignment="1" attributes="0">
<EmptySpace min="0" pref="262" max="32767" attributes="0"/>
<Component id="btnOK" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="btnCancel" min="-2" max="-2" 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"/>
<Group type="103" groupAlignment="3" attributes="0">
<Component id="jLabel1" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="txtNewProfileName" alignment="3" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="3" attributes="0">
<Component id="jLabel2" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="cboProfiles" alignment="3" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace max="32767" attributes="0"/>
<Group type="103" groupAlignment="3" attributes="0">
<Component id="btnCancel" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="btnOK" alignment="3" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace max="-2" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
</Layout>
<SubComponents>
<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/launcher/I18N.properties" key="ui.label.newProfileWindow.new_profile_name" replaceFormat="java.util.ResourceBundle.getBundle(&quot;{bundleNameSlashes}&quot;).getString(&quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JTextField" name="txtNewProfileName">
<Events>
<EventHandler event="keyTyped" listener="java.awt.event.KeyListener" parameters="java.awt.event.KeyEvent" handler="txtNewProfileNameKeyTyped"/>
</Events>
</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/launcher/I18N.properties" key="ui.label.newProfileWindow.copy_from" replaceFormat="java.util.ResourceBundle.getBundle(&quot;{bundleNameSlashes}&quot;).getString(&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>
</Component>
<Component class="javax.swing.JButton" name="btnCancel">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/jackhuang/hellominecraft/launcher/I18N.properties" key="button.cancel" replaceFormat="java.util.ResourceBundle.getBundle(&quot;{bundleNameSlashes}&quot;).getString(&quot;{key}&quot;)"/>
</Property>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="btnCancelActionPerformed"/>
</Events>
</Component>
<Component class="javax.swing.JButton" name="btnOK">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/jackhuang/hellominecraft/launcher/I18N.properties" key="ui.button.ok" replaceFormat="java.util.ResourceBundle.getBundle(&quot;{bundleNameSlashes}&quot;).getString(&quot;{key}&quot;)"/>
</Property>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="btnOKActionPerformed"/>
</Events>
</Component>
</SubComponents>
</Form>

@ -0,0 +1,150 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.jackhuang.hellominecraft.launcher.views;
import org.jackhuang.hellominecraft.launcher.utils.settings.Profile;
import org.jackhuang.hellominecraft.launcher.utils.settings.Settings;
/**
*
* @author hyh
*/
public final class NewProfileWindow extends javax.swing.JDialog {
/**
* Creates new form NewProfileWindow
*/
public NewProfileWindow(java.awt.Frame parent) {
super(parent, true);
initComponents();
setLocationRelativeTo(null);
for (Profile s : Settings.getProfiles()) {
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);
java.util.ResourceBundle bundle = java.util.ResourceBundle.getBundle("org/jackhuang/hellominecraft/launcher/I18N"); // NOI18N
setTitle(bundle.getString("ui.newProfileWindow.title")); // NOI18N
jLabel1.setText(bundle.getString("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(bundle.getString("ui.label.newProfileWindow.copy_from")); // NOI18N
btnCancel.setText(bundle.getString("button.cancel")); // NOI18N
btnCancel.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
btnCancelActionPerformed(evt);
}
});
btnOK.setText(bundle.getString("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:
Profile newProfile = new Profile(Settings.getVersion(cboProfiles.getSelectedItem().toString()));
newProfile.setName(txtNewProfileName.getText());
Settings.trySetVersion(newProfile);
case 27:
this.dispose();
}
}//GEN-LAST:event_txtNewProfileNameKeyTyped
private void btnOKActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnOKActionPerformed
Profile newProfile = new Profile(Settings.getVersion(cboProfiles.getSelectedItem().toString()));
newProfile.setName(txtNewProfileName.getText());
Settings.trySetVersion(newProfile);
this.dispose();
}//GEN-LAST:event_btnOKActionPerformed
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
}

@ -0,0 +1,28 @@
package org.jackhuang.mojang.authlib;
public class Agent {
public static final Agent MINECRAFT = new Agent("Minecraft", 1);
public static final Agent SCROLLS = new Agent("Scrolls", 1);
private final String name;
private final int version;
public Agent(String name, int version) {
this.name = name;
this.version = version;
}
public String getName() {
return this.name;
}
public int getVersion() {
return this.version;
}
@Override
public String toString() {
return "Agent{name='" + this.name + '\'' + ", version=" + this.version + '}';
}
}

@ -0,0 +1,12 @@
package org.jackhuang.mojang.authlib;
import org.jackhuang.mojang.authlib.minecraft.MinecraftSessionService;
public abstract interface AuthenticationService {
public abstract UserAuthentication createUserAuthentication(Agent paramAgent);
public abstract MinecraftSessionService createMinecraftSessionService();
public abstract GameProfileRepository createProfileRepository();
}

@ -0,0 +1,5 @@
package org.jackhuang.mojang.authlib;
public abstract class BaseAuthenticationService
implements AuthenticationService {
}

@ -0,0 +1,263 @@
package org.jackhuang.mojang.authlib;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.jackhuang.hellominecraft.logging.logger.Logger;
import org.jackhuang.hellominecraft.utils.StrUtils;
import org.jackhuang.hellominecraft.utils.Validate;
import org.jackhuang.mojang.authlib.properties.Property;
import org.jackhuang.mojang.authlib.properties.PropertyMap;
import org.jackhuang.mojang.util.UUIDTypeAdapter;
public abstract class BaseUserAuthentication
implements UserAuthentication {
private static final Logger LOGGER = new Logger("BaseUserAuthentication");
protected static final String STORAGE_KEY_PROFILE_NAME = "displayName";
protected static final String STORAGE_KEY_PROFILE_ID = "uuid";
protected static final String STORAGE_KEY_PROFILE_PROPERTIES = "profileProperties";
protected static final String STORAGE_KEY_USER_NAME = "username";
protected static final String STORAGE_KEY_USER_ID = "userid";
protected static final String STORAGE_KEY_USER_PROPERTIES = "userProperties";
private final AuthenticationService authenticationService;
private final PropertyMap userProperties = new PropertyMap();
private String userid;
private String username;
private String password;
private GameProfile selectedProfile;
private UserType userType;
protected BaseUserAuthentication(AuthenticationService authenticationService) {
Validate.notNull(authenticationService);
this.authenticationService = authenticationService;
}
@Override
public boolean canLogIn() {
return (!canPlayOnline()) && (StrUtils.isNotBlank(getUsername())) && (StrUtils.isNotBlank(getPassword()));
}
@Override
public void logOut() {
this.password = null;
this.userid = null;
setSelectedProfile(null);
getModifiableUserProperties().clear();
setUserType(null);
}
@Override
public boolean isLoggedIn() {
return getSelectedProfile() != null;
}
@Override
public void setUsername(String username) {
if ((isLoggedIn()) && (canPlayOnline())) {
throw new IllegalStateException("Cannot change username whilst logged in & online");
}
this.username = username;
}
@Override
public void setPassword(String password) {
if ((isLoggedIn()) && (canPlayOnline()) && (StrUtils.isNotBlank(password))) {
throw new IllegalStateException("Cannot set password whilst logged in & online");
}
this.password = password;
}
protected String getUsername() {
return this.username;
}
protected String getPassword() {
return this.password;
}
@Override
public void loadFromStorage(Map<String, Object> credentials) {
logOut();
setUsername((String)credentials.get("username"));
if (credentials.containsKey("userid")) {
this.userid = (String)credentials.get("userid");
} else {
this.userid = this.username;
}
if (credentials.containsKey("userProperties")) {
try {
List<Map> list = (List<Map>) credentials.get("userProperties");
for (Map propertyMap : list) {
String name = (String) propertyMap.get("name");
String value = (String) propertyMap.get("value");
String signature = (String) propertyMap.get("signature");
if (signature == null) {
getModifiableUserProperties().put(name, new Property(name, value));
} else {
getModifiableUserProperties().put(name, new Property(name, value, signature));
}
}
} catch (Throwable t) {
LOGGER.warn("Couldn't deserialize user properties", t);
}
}
if ((credentials.containsKey("displayName")) && (credentials.containsKey("uuid"))) {
GameProfile profile = new GameProfile(UUIDTypeAdapter.fromString((String)credentials.get("uuid")), (String)credentials.get("displayName"));
if (credentials.containsKey("profileProperties")) {
try {
List<Map> list = (List<Map>) credentials.get("profileProperties");
for (Map propertyMap : list) {
String name = (String) propertyMap.get("name");
String value = (String) propertyMap.get("value");
String signature = (String) propertyMap.get("signature");
if (signature == null) {
profile.getProperties().put(name, new Property(name, value));
} else {
profile.getProperties().put(name, new Property(name, value, signature));
}
}
} catch (Throwable t) {
LOGGER.warn("Couldn't deserialize profile properties", t);
}
}
setSelectedProfile(profile);
}
}
@Override
public Map<String, Object> saveForStorage() {
Map result = new HashMap();
if (getUsername() != null) {
result.put("username", getUsername());
}
if (getUserID() != null) {
result.put("userid", getUserID());
} else if (getUsername() != null) {
result.put("username", getUsername());
}
if (!getUserProperties().isEmpty()) {
List properties = new ArrayList();
for (Property userProperty : getUserProperties().values()) {
Map property = new HashMap();
property.put("name", userProperty.getName());
property.put("value", userProperty.getValue());
property.put("signature", userProperty.getSignature());
properties.add(property);
}
result.put("userProperties", properties);
}
GameProfile sel = getSelectedProfile();
if (sel != null) {
result.put("displayName", sel.getName());
result.put("uuid", sel.getId());
List properties = new ArrayList();
for (Property profileProperty : sel.getProperties().values()) {
Map property = new HashMap();
property.put("name", profileProperty.getName());
property.put("value", profileProperty.getValue());
property.put("signature", profileProperty.getSignature());
properties.add(property);
}
if (!properties.isEmpty()) {
result.put("profileProperties", properties);
}
}
return result;
}
protected void setSelectedProfile(GameProfile selectedProfile) {
this.selectedProfile = selectedProfile;
}
@Override
public GameProfile getSelectedProfile() {
return this.selectedProfile;
}
@Override
public String toString() {
StringBuilder result = new StringBuilder();
result.append(getClass().getSimpleName());
result.append("{");
if (isLoggedIn()) {
result.append("Logged in as ");
result.append(getUsername());
if (getSelectedProfile() != null) {
result.append(" / ");
result.append(getSelectedProfile());
result.append(" - ");
if (canPlayOnline()) {
result.append("Online");
} else {
result.append("Offline");
}
}
} else {
result.append("Not logged in");
}
result.append("}");
return result.toString();
}
public AuthenticationService getAuthenticationService() {
return this.authenticationService;
}
@Override
public String getUserID() {
return this.userid;
}
@Override
public PropertyMap getUserProperties() {
if (isLoggedIn()) {
PropertyMap result = new PropertyMap();
result.putAll(getModifiableUserProperties());
return result;
}
return new PropertyMap();
}
protected PropertyMap getModifiableUserProperties() {
return this.userProperties;
}
@Override
public UserType getUserType() {
if (isLoggedIn()) {
return this.userType == null ? UserType.LEGACY : this.userType;
}
return null;
}
protected void setUserType(UserType userType) {
this.userType = userType;
}
protected void setUserid(String userid) {
this.userid = userid;
}
}

@ -0,0 +1,72 @@
package org.jackhuang.mojang.authlib;
import org.jackhuang.mojang.authlib.properties.PropertyMap;
import java.util.UUID;
import org.jackhuang.hellominecraft.utils.StrUtils;
public class GameProfile {
private final UUID id;
private final String name;
private final PropertyMap properties = new PropertyMap();
private boolean legacy;
public GameProfile(UUID id, String name) {
if ((id == null) && (StrUtils.isBlank(name))) {
throw new IllegalArgumentException("Name and ID cannot both be blank");
}
this.id = id;
this.name = name;
}
public UUID getId() {
return this.id;
}
public String getName() {
return this.name;
}
public PropertyMap getProperties() {
return this.properties;
}
public boolean isComplete() {
return (this.id != null) && (StrUtils.isNotBlank(getName()));
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if ((o == null) || (getClass() != o.getClass())) {
return false;
}
GameProfile that = (GameProfile) o;
if (this.id != null ? !this.id.equals(that.id) : that.id != null) {
return false;
}
return this.name != null ? this.name.equals(that.name) : that.name == null;
}
@Override
public int hashCode() {
int result = this.id != null ? this.id.hashCode() : 0;
result = 31 * result + (this.name != null ? this.name.hashCode() : 0);
return result;
}
@Override
public String toString() {
return "GameProfile{" + "id=" + id + ", name=" + name + ", properties=" + properties + ", legacy=" + legacy + '}';
}
public boolean isLegacy() {
return this.legacy;
}
}

@ -0,0 +1,6 @@
package org.jackhuang.mojang.authlib;
public abstract interface GameProfileRepository {
public abstract void findProfilesByNames(String[] paramArrayOfString, Agent paramAgent, ProfileLookupCallback paramProfileLookupCallback);
}

Some files were not shown because too many files have changed in this diff Show More