diff --git a/.gitignore b/.gitignore index 32858aad3..00eaba66d 100644 --- a/.gitignore +++ b/.gitignore @@ -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/ \ No newline at end of file diff --git a/.nb-gradle-properties b/.nb-gradle-properties new file mode 100644 index 000000000..f6410c777 --- /dev/null +++ b/.nb-gradle-properties @@ -0,0 +1,46 @@ + + + + j2se + 1.8 + 1.8 + + + launch4j + no + + launch4j + + + + + + launch4jpack + no + + launch4jpack + + + + + + publish + no + + clean + build + launch4j + + + + + + + j2se + 1.8 + + + GNU General Public License + huangyuhui + + diff --git a/HMCL/build.gradle b/HMCL/build.gradle new file mode 100644 index 000000000..31c8bcb19 --- /dev/null +++ b/HMCL/build.gradle @@ -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 \ No newline at end of file diff --git a/HMCL/icon.ico b/HMCL/icon.ico new file mode 100644 index 000000000..fe7ac703b Binary files /dev/null and b/HMCL/icon.ico differ diff --git a/HMCL/image/3J33V83MSXJ6FSO4%WBZR7A.png b/HMCL/image/3J33V83MSXJ6FSO4%WBZR7A.png new file mode 100644 index 000000000..091fcdf14 Binary files /dev/null and b/HMCL/image/3J33V83MSXJ6FSO4%WBZR7A.png differ diff --git a/HMCL/image/A.jpg b/HMCL/image/A.jpg new file mode 100644 index 000000000..b20c78c8d Binary files /dev/null and b/HMCL/image/A.jpg differ diff --git a/HMCL/image/K0B_H3C~2_PSK_[SB)([))E.png b/HMCL/image/K0B_H3C~2_PSK_[SB)([))E.png new file mode 100644 index 000000000..83b1e57f1 Binary files /dev/null and b/HMCL/image/K0B_H3C~2_PSK_[SB)([))E.png differ diff --git a/HMCL/image/N9_Q[X2BQ{9$@S14RX%3}0M.png b/HMCL/image/N9_Q[X2BQ{9$@S14RX%3}0M.png new file mode 100644 index 000000000..8c55c559c Binary files /dev/null and b/HMCL/image/N9_Q[X2BQ{9$@S14RX%3}0M.png differ diff --git a/HMCL/image/WO(NA%0}M$9BCRR62ZN{%87.png b/HMCL/image/WO(NA%0}M$9BCRR62ZN{%87.png new file mode 100644 index 000000000..dae14da11 Binary files /dev/null and b/HMCL/image/WO(NA%0}M$9BCRR62ZN{%87.png differ diff --git a/HMCL/image/background.jpg b/HMCL/image/background.jpg new file mode 100644 index 000000000..972dc4e6e Binary files /dev/null and b/HMCL/image/background.jpg differ diff --git a/HMCL/launch4j.xml b/HMCL/launch4j.xml new file mode 100644 index 000000000..b78c4bf25 --- /dev/null +++ b/HMCL/launch4j.xml @@ -0,0 +1,41 @@ + + false + gui + F:\Documents\NetBeansProjects\HMCL\HMCL\build\libs\HMCL-2.1.3.jar + F:\Documents\NetBeansProjects\HMCL\HMCL\build\libs\HMCL-2.1.3-Launch4j.exe + + + + normal + http://java.com/download + + false + + F:\Documents\NetBeansProjects\HMCL\HMCL\icon.ico + + + false + 1.6.0 + + preferJre + + + 2.1.3.0 + 2.1.3.0 + Hello Minecraft! Launcher + Copyright(c) 2013~2014 huangyuhui + 2.1.3.0 + 2.1.3.0 + Hello Minecraft! Launcher + + Hello Minecraft! Launcher + HMCL-2.1.3.exe + + + 启动程序时出现错误 + 未找到内置Java + 此程序需要Java + 未找到Java + 已存在一个程序实例 + + \ No newline at end of file diff --git a/HMCL/proguard.pro b/HMCL/proguard.pro new file mode 100644 index 000000000..cda8d2319 --- /dev/null +++ b/HMCL/proguard.pro @@ -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 ; public ; } +-keepclassmembers class org.jackhuang.hellominecraft.launcher.utils.settings.Config { public ; } + +-keepclassmembers class org.jackhuang.hellominecraft.launcher.utils.assets.AssetsObject { ; } +-keepclassmembers class org.jackhuang.hellominecraft.launcher.utils.assets.AssetsIndex { ; } + +-keepclassmembers class org.jackhuang.hellominecraft.launcher.utils.version.MinecraftLibrary { public ; } +-keepclassmembers class org.jackhuang.hellominecraft.launcher.utils.version.IMinecraftLibrary { public ; } +-keepclassmembers class org.jackhuang.hellominecraft.launcher.utils.version.Natives { public ; } +-keepclassmembers class org.jackhuang.hellominecraft.launcher.utils.version.OS { public ; } +-keepclassmembers class org.jackhuang.hellominecraft.launcher.utils.version.Rules { public ; } +-keepclassmembers class org.jackhuang.hellominecraft.launcher.utils.version.MinecraftVersion { public ; } + +-keepclassmembers class org.jackhuang.hellominecraft.launcher.utils.installers.forge.InstallProfile { public ; } +-keepclassmembers class org.jackhuang.hellominecraft.launcher.utils.installers.forge.Install { public ; } + +-keepclassmembers class org.jackhuang.hellominecraft.launcher.utils.installers.forge.vanilla.MinecraftForgeVersionRoot { public ; } +-keepclassmembers class org.jackhuang.hellominecraft.launcher.utils.installers.forge.vanilla.MinecraftForgeVersion { public ; } +-keepclassmembers class org.jackhuang.hellominecraft.launcher.utils.installers.forge.bmcl.ForgeVersion { public ; } +-keepclassmembers class org.jackhuang.hellominecraft.launcher.utils.installers.forge.bmcl.Downloads { public ; } + +-keepclassmembers class org.jackhuang.hellominecraft.launcher.utils.installers.optifine.OptiFineVersion { public ; } + +-keepclassmembers class org.jackhuang.hellominecraft.launcher.utils.installers.liteloader.LiteLoaderVersionsRoot { public ; } +-keepclassmembers class org.jackhuang.hellominecraft.launcher.utils.installers.liteloader.LiteLoaderMCVersions { public ; } +-keepclassmembers class org.jackhuang.hellominecraft.launcher.utils.installers.liteloader.LiteLoaderVersion { public ; } +-keepclassmembers class org.jackhuang.hellominecraft.launcher.utils.installers.liteloader.LiteLoaderVersionsMeta { public ; } + +-keepclassmembers class org.jackhuang.hellominecraft.version.MinecraftRemoteLatestVersion { public ; } +-keepclassmembers class org.jackhuang.hellominecraft.version.MinecraftRemoteVersion { public ; } +-keepclassmembers class org.jackhuang.hellominecraft.version.MinecraftRemoteVersions { public ; } diff --git a/HMCL/src/main/icon.icns b/HMCL/src/main/icon.icns new file mode 100644 index 000000000..dc329d24b Binary files /dev/null and b/HMCL/src/main/icon.icns differ diff --git a/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/Launcher.java b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/Launcher.java new file mode 100644 index 000000000..4cb62e5e3 --- /dev/null +++ b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/Launcher.java @@ -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 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 ***"); + } +} diff --git a/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/Main.java b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/Main.java new file mode 100644 index 000000000..8e64bde4a --- /dev/null +++ b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/Main.java @@ -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; + } + } +} diff --git a/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/launch/DefaultGameLauncher.java b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/launch/DefaultGameLauncher.java new file mode 100644 index 000000000..1b3f7ca5f --- /dev/null +++ b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/launch/DefaultGameLauncher.java @@ -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; + }); + } + +} diff --git a/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/launch/GameLauncher.java b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/launch/GameLauncher.java new file mode 100644 index 000000000..ee5f61140 --- /dev/null +++ b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/launch/GameLauncher.java @@ -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 failEvent = new EventHandler(this); + public final EventHandler> downloadLibrariesEvent = new EventHandler(this); + public final EventHandler> successEvent = new EventHandler(this); + public final EventHandler launchEvent = new EventHandler(this); + public final EventHandler 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; + } + + } +} diff --git a/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/launch/GameLauncherRequest.java b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/launch/GameLauncherRequest.java new file mode 100644 index 000000000..8be1580b2 --- /dev/null +++ b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/launch/GameLauncherRequest.java @@ -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 +} diff --git a/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/launch/IMinecraftLoader.java b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/launch/IMinecraftLoader.java new file mode 100644 index 000000000..301f574f2 --- /dev/null +++ b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/launch/IMinecraftLoader.java @@ -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 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 makeLaunchingCommand() { + HMCLog.log("*** Make shell command ***"); + + ArrayList 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:
+ * 1 minecraft class path
+ * 2 main class
+ * 3 minecraft arguments
+ * + * @param list the command list you shoud edit. + */ + protected abstract void makeSelf(List list); + + protected void appendJVMArgs(List list) { + } + + public Profile getUserVersion() { + return v; + } +} diff --git a/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/launch/IMinecraftProvider.java b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/launch/IMinecraftProvider.java new file mode 100644 index 000000000..e4f52a374 --- /dev/null +++ b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/launch/IMinecraftProvider.java @@ -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 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 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(); + +} diff --git a/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/launch/LaunchFinisher.java b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/launch/LaunchFinisher.java new file mode 100644 index 000000000..2daa0fad2 --- /dev/null +++ b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/launch/LaunchFinisher.java @@ -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> { + + private final HashSet al = new HashSet(); + + @Override + public boolean call(Object sender, List str) { + final GameLauncher obj = (GameLauncher) sender; + obj.launchEvent.register(new Event() { + @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 event = new Event() { + @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() { + @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() { + + @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); + } + } +} diff --git a/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/launch/LaunchScriptFinisher.java b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/launch/LaunchScriptFinisher.java new file mode 100644 index 000000000..3b47a2b86 --- /dev/null +++ b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/launch/LaunchScriptFinisher.java @@ -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> { + + @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; + } + +} diff --git a/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/launch/MinecraftCrashAdvicer.java b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/launch/MinecraftCrashAdvicer.java new file mode 100644 index 000000000..9d7973821 --- /dev/null +++ b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/launch/MinecraftCrashAdvicer.java @@ -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"); + } + +} diff --git a/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/launch/MinecraftLoader.java b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/launch/MinecraftLoader.java new file mode 100644 index 000000000..8904379c8 --- /dev/null +++ b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/launch/MinecraftLoader.java @@ -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 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 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; + } +} diff --git a/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/utils/CrashReport.java b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/utils/CrashReport.java new file mode 100644 index 000000000..52c5c4b90 --- /dev/null +++ b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/utils/CrashReport.java @@ -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(); + } + } + } + +} diff --git a/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/utils/MCUtils.java b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/utils/MCUtils.java new file mode 100644 index 000000000..5a7c0dcf6 --- /dev/null +++ b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/utils/MCUtils.java @@ -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); + } +} diff --git a/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/utils/assets/AssetsIndex.java b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/utils/assets/AssetsIndex.java new file mode 100644 index 000000000..249981e60 --- /dev/null +++ b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/utils/assets/AssetsIndex.java @@ -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 objects; + private boolean virtual; + + public AssetsIndex() { + this.objects = new LinkedHashMap(); + } + + public Map getFileMap() { + return this.objects; + } + + public Set getUniqueObjects() { + return new HashSet(this.objects.values()); + } + + public boolean isVirtual() { + return this.virtual; + } +} diff --git a/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/utils/assets/AssetsLoader.java b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/utils/assets/AssetsLoader.java new file mode 100644 index 000000000..67d0ae0ee --- /dev/null +++ b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/utils/assets/AssetsLoader.java @@ -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 al; + public final EventHandler failedEvent = new EventHandler(this); + public final EventHandler> successEvent = new EventHandler>(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(); + 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); + } + } + +} diff --git a/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/utils/assets/AssetsLoaderListener.java b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/utils/assets/AssetsLoaderListener.java new file mode 100644 index 000000000..7f3877382 --- /dev/null +++ b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/utils/assets/AssetsLoaderListener.java @@ -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 loader); + + void OnFailed(Exception e); +} \ No newline at end of file diff --git a/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/utils/assets/AssetsMojangLoader.java b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/utils/assets/AssetsMojangLoader.java new file mode 100644 index 000000000..f2279826f --- /dev/null +++ b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/utils/assets/AssetsMojangLoader.java @@ -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 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 al = new ArrayList<>(); + contents = new ArrayList<>(); + if (o != null && o.getFileMap() != null) + for (Map.Entry 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; + } +} diff --git a/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/utils/assets/AssetsMojangOldLoader.java b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/utils/assets/AssetsMojangOldLoader.java new file mode 100644 index 000000000..a14651c3e --- /dev/null +++ b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/utils/assets/AssetsMojangOldLoader.java @@ -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 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); + } +} diff --git a/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/utils/assets/AssetsObject.java b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/utils/assets/AssetsObject.java new file mode 100644 index 000000000..421e4d1ab --- /dev/null +++ b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/utils/assets/AssetsObject.java @@ -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; + } +} diff --git a/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/utils/assets/Contents.java b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/utils/assets/Contents.java new file mode 100644 index 000000000..51384eebc --- /dev/null +++ b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/utils/assets/Contents.java @@ -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; + +} diff --git a/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/utils/assets/IAssetsHandler.java b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/utils/assets/IAssetsHandler.java new file mode 100644 index 000000000..64e95dff3 --- /dev/null +++ b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/utils/assets/IAssetsHandler.java @@ -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 assetsDownloadURLs; + protected ArrayList assetsLocalNames; + protected final String name; + protected List contents; + + public IAssetsHandler(String name) { + this.name = name; + } + + private static final List assetsHandlers = new ArrayList<>(); + + public static IAssetsHandler getAssetsHandler(int i) { + return assetsHandlers.get(i); + } + + public static List 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 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 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 getAfterTasks() { + return al; + } + + @Override + public String getInfo() { + return C.i18n("assets.download"); + } + } +} diff --git a/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/utils/auth/BestLogin.java b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/utils/auth/BestLogin.java new file mode 100644 index 000000000..1a0bed932 --- /dev/null +++ b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/utils/auth/BestLogin.java @@ -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() { + } + +} diff --git a/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/utils/auth/IAuthenticator.java b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/utils/auth/IAuthenticator.java new file mode 100644 index 000000000..852005385 --- /dev/null +++ b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/utils/auth/IAuthenticator.java @@ -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 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(); +} diff --git a/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/utils/auth/LoginInfo.java b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/utils/auth/LoginInfo.java new file mode 100644 index 000000000..ff1537882 --- /dev/null +++ b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/utils/auth/LoginInfo.java @@ -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; + } +} diff --git a/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/utils/auth/OfflineAuthenticator.java b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/utils/auth/OfflineAuthenticator.java new file mode 100644 index 000000000..15b025651 --- /dev/null +++ b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/utils/auth/OfflineAuthenticator.java @@ -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() { + } + +} diff --git a/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/utils/auth/SkinmeAuthenticator.java b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/utils/auth/SkinmeAuthenticator.java new file mode 100644 index 000000000..e8e9443de --- /dev/null +++ b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/utils/auth/SkinmeAuthenticator.java @@ -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() { + + } +} diff --git a/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/utils/auth/UserProfileProvider.java b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/utils/auth/UserProfileProvider.java new file mode 100644 index 000000000..9e91b2ea0 --- /dev/null +++ b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/utils/auth/UserProfileProvider.java @@ -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"; +} diff --git a/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/utils/auth/YggdrasilAuthenticator.java b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/utils/auth/YggdrasilAuthenticator.java new file mode 100644 index 000000000..7057caae4 --- /dev/null +++ b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/utils/auth/YggdrasilAuthenticator.java @@ -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(); + } +} diff --git a/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/utils/download/BMCLAPIDownloadProvider.java b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/utils/download/BMCLAPIDownloadProvider.java new file mode 100644 index 000000000..be7fafdc8 --- /dev/null +++ b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/utils/download/BMCLAPIDownloadProvider.java @@ -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; + } + +} diff --git a/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/utils/download/DownloadType.java b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/utils/download/DownloadType.java new file mode 100644 index 000000000..81a0a529a --- /dev/null +++ b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/utils/download/DownloadType.java @@ -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; + } +} diff --git a/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/utils/download/IDownloadProvider.java b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/utils/download/IDownloadProvider.java new file mode 100644 index 000000000..9f5015ccc --- /dev/null +++ b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/utils/download/IDownloadProvider.java @@ -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(); +} diff --git a/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/utils/download/MojangDownloadProvider.java b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/utils/download/MojangDownloadProvider.java new file mode 100644 index 000000000..4c0c4b72f --- /dev/null +++ b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/utils/download/MojangDownloadProvider.java @@ -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; + } + +} diff --git a/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/utils/installers/InstallProfile.java b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/utils/installers/InstallProfile.java new file mode 100644 index 000000000..125c118ba --- /dev/null +++ b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/utils/installers/InstallProfile.java @@ -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; +} diff --git a/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/utils/installers/InstallerVersionList.java b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/utils/installers/InstallerVersionList.java new file mode 100644 index 000000000..0ecb7ac20 --- /dev/null +++ b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/utils/installers/InstallerVersionList.java @@ -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 { + /** + * Refresh installer versions list from the downloaded content. + */ + public abstract void refreshList(String[] versions) throws Exception; + public abstract String getName(); + public abstract List getVersions(String mcVersion); + + public static class InstallerVersion implements Comparable { + 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 { + 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); + } + } +} diff --git a/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/utils/installers/InstallerVersionNewerComparator.java b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/utils/installers/InstallerVersionNewerComparator.java new file mode 100644 index 000000000..45e5ba6f8 --- /dev/null +++ b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/utils/installers/InstallerVersionNewerComparator.java @@ -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 { + + @Override + public int compare(InstallerVersion o1, InstallerVersion o2) { + return -o1.compareTo(o2); + } +} diff --git a/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/utils/installers/PackMinecraftInstaller.java b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/utils/installers/PackMinecraftInstaller.java new file mode 100644 index 000000000..31c33d684 --- /dev/null +++ b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/utils/installers/PackMinecraftInstaller.java @@ -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 src; + + public PackMinecraftInstaller(ArrayList 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); + } +} diff --git a/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/utils/installers/forge/ForgeInstaller.java b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/utils/installers/forge/ForgeInstaller.java new file mode 100644 index 000000000..35d587a21 --- /dev/null +++ b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/utils/installers/forge/ForgeInstaller.java @@ -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"); + } + +} diff --git a/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/utils/installers/forge/ForgeOldInstaller.java b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/utils/installers/forge/ForgeOldInstaller.java new file mode 100644 index 000000000..a0017f1fc --- /dev/null +++ b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/utils/installers/forge/ForgeOldInstaller.java @@ -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 al = new ArrayList(); + al.add(srcMinecraftJar); + al.add(forgeUniversal); + new PackMinecraftInstaller(al, new File(destMinecraftJar)).install(); + } + +} diff --git a/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/utils/installers/forge/Install.java b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/utils/installers/forge/Install.java new file mode 100644 index 000000000..82598700b --- /dev/null +++ b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/utils/installers/forge/Install.java @@ -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; +} diff --git a/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/utils/installers/forge/bmcl/Downloads.java b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/utils/installers/forge/bmcl/Downloads.java new file mode 100644 index 000000000..ce6e91d9c --- /dev/null +++ b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/utils/installers/forge/bmcl/Downloads.java @@ -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; +} diff --git a/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/utils/installers/forge/bmcl/ForgeBMCLVersionList.java b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/utils/installers/forge/bmcl/ForgeBMCLVersionList.java new file mode 100644 index 000000000..72b5f7450 --- /dev/null +++ b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/utils/installers/forge/bmcl/ForgeBMCLVersionList.java @@ -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 root; + public Map> versionMap; + public List versions; + + @Override + public void refreshList(String[] neededVersions) throws Exception { + if(versionMap == null) { + versionMap = new HashMap>(); + versions = new ArrayList(); + } + + 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>(){}.getType()); + for (ForgeVersion v : root) { + InstallerVersion iv = new InstallerVersion(v.version, StrUtils.formatVersion(v.minecraft)); + + List 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 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)"; + } +} diff --git a/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/utils/installers/forge/bmcl/ForgeVersion.java b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/utils/installers/forge/bmcl/ForgeVersion.java new file mode 100644 index 000000000..a8d7a45d9 --- /dev/null +++ b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/utils/installers/forge/bmcl/ForgeVersion.java @@ -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; +} diff --git a/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/utils/installers/forge/vanilla/MinecraftForgeVersion.java b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/utils/installers/forge/vanilla/MinecraftForgeVersion.java new file mode 100644 index 000000000..9ad018d19 --- /dev/null +++ b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/utils/installers/forge/vanilla/MinecraftForgeVersion.java @@ -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; +} diff --git a/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/utils/installers/forge/vanilla/MinecraftForgeVersionList.java b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/utils/installers/forge/vanilla/MinecraftForgeVersionList.java new file mode 100644 index 000000000..b86212373 --- /dev/null +++ b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/utils/installers/forge/vanilla/MinecraftForgeVersionList.java @@ -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> versionMap; + public List 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>(); + versions = new ArrayList(); + + for(Map.Entry arr : root.mcversion.entrySet()) { + String mcver = StrUtils.formatVersion(arr.getKey()); + ArrayList al = new ArrayList(); + 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 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"; + } +} diff --git a/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/utils/installers/forge/vanilla/MinecraftForgeVersionRoot.java b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/utils/installers/forge/vanilla/MinecraftForgeVersionRoot.java new file mode 100644 index 000000000..db55d564e --- /dev/null +++ b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/utils/installers/forge/vanilla/MinecraftForgeVersionRoot.java @@ -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 branches, mcversion; + public Map promos; + public Map number; +} diff --git a/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/utils/installers/liteloader/LiteLoaderInstaller.java b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/utils/installers/liteloader/LiteLoaderInstaller.java new file mode 100644 index 000000000..03a7122cc --- /dev/null +++ b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/utils/installers/liteloader/LiteLoaderInstaller.java @@ -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 { + + 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> pre = new ArrayList(); + @Override + public Task registerPreviousResult(PreviousResult pr) { + pre.add(pr); + return this; + } + +} diff --git a/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/utils/installers/liteloader/LiteLoaderMCVersions.java b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/utils/installers/liteloader/LiteLoaderMCVersions.java new file mode 100644 index 000000000..d1b9e9bfa --- /dev/null +++ b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/utils/installers/liteloader/LiteLoaderMCVersions.java @@ -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> artefacts; +} diff --git a/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/utils/installers/liteloader/LiteLoaderVersion.java b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/utils/installers/liteloader/LiteLoaderVersion.java new file mode 100644 index 000000000..9b18bc18d --- /dev/null +++ b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/utils/installers/liteloader/LiteLoaderVersion.java @@ -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; +} diff --git a/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/utils/installers/liteloader/LiteLoaderVersionList.java b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/utils/installers/liteloader/LiteLoaderVersionList.java new file mode 100644 index 000000000..a8b2f6c87 --- /dev/null +++ b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/utils/installers/liteloader/LiteLoaderVersionList.java @@ -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> versionMap; + public List 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>(); + versions = new ArrayList(); + + for(Map.Entry arr : root.versions.entrySet()) { + ArrayList al = new ArrayList(); + LiteLoaderMCVersions mcv = arr.getValue(); + for(Map.Entry 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 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); + } + } + +} diff --git a/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/utils/installers/liteloader/LiteLoaderVersionsMeta.java b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/utils/installers/liteloader/LiteLoaderVersionsMeta.java new file mode 100644 index 000000000..1da5f165e --- /dev/null +++ b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/utils/installers/liteloader/LiteLoaderVersionsMeta.java @@ -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; +} diff --git a/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/utils/installers/liteloader/LiteLoaderVersionsRoot.java b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/utils/installers/liteloader/LiteLoaderVersionsRoot.java new file mode 100644 index 000000000..17dc78118 --- /dev/null +++ b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/utils/installers/liteloader/LiteLoaderVersionsRoot.java @@ -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 versions; + public LiteLoaderVersionsMeta meta; +} diff --git a/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/utils/installers/optifine/OptiFineInstaller.java b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/utils/installers/optifine/OptiFineInstaller.java new file mode 100644 index 000000000..d71d43765 --- /dev/null +++ b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/utils/installers/optifine/OptiFineInstaller.java @@ -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 { + + 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> pre = new ArrayList(); + @Override + public Task registerPreviousResult(PreviousResult pr) { + pre.add(pr); + return this; + } + +} diff --git a/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/utils/installers/optifine/OptiFineVersion.java b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/utils/installers/optifine/OptiFineVersion.java new file mode 100644 index 000000000..d72e02e2f --- /dev/null +++ b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/utils/installers/optifine/OptiFineVersion.java @@ -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; +} diff --git a/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/utils/installers/optifine/bmcl/OptiFineBMCLVersionList.java b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/utils/installers/optifine/bmcl/OptiFineBMCLVersionList.java new file mode 100644 index 000000000..226551497 --- /dev/null +++ b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/utils/installers/optifine/bmcl/OptiFineBMCLVersionList.java @@ -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 root; + public Map> versionMap; + public List 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>() { + }.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 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 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)"; + } + +} diff --git a/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/utils/installers/optifine/vanilla/OptiFineDownloadFormatter.java b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/utils/installers/optifine/vanilla/OptiFineDownloadFormatter.java new file mode 100644 index 000000000..09833cac0 --- /dev/null +++ b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/utils/installers/optifine/vanilla/OptiFineDownloadFormatter.java @@ -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 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; + } +} diff --git a/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/utils/installers/optifine/vanilla/OptiFineVersionList.java b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/utils/installers/optifine/vanilla/OptiFineVersionList.java new file mode 100644 index 000000000..5bd3f8295 --- /dev/null +++ b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/utils/installers/optifine/vanilla/OptiFineVersionList.java @@ -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 root = new ArrayList(); + public Map> versionMap; + public List versions; + + @Override + public void refreshList(String[] sss) throws Exception { + String content = NetUtils.doGet("http://optifine.net/downloads"); + if(versions != null) return; + versionMap = new HashMap>(); + versions = new ArrayList(); + + content = content.replace(" ", " ").replace(">", ">").replace("<", "<"); + + 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 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 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; + } + +} diff --git a/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/utils/settings/Config.java b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/utils/settings/Config.java new file mode 100644 index 000000000..5fee69978 --- /dev/null +++ b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/utils/settings/Config.java @@ -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 getConfigurations() { + if(configurations == null) + configurations = new TreeMap(); + 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 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(); + 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]; + } +} diff --git a/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/utils/settings/Profile.java b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/utils/settings/Profile.java new file mode 100644 index 000000000..9ad0470ff --- /dev/null +++ b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/utils/settings/Profile.java @@ -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.
+ * 1 - Hide the launcher when the game starts.
+ * 2 - Keep the launcher open.
+ */ + private int launcherVisibility; + + /** + * 0 - .minecraft
+ * 1 - .minecraft/versions/<version>/
+ */ + 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(); + } + +} diff --git a/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/utils/settings/Settings.java b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/utils/settings/Settings.java new file mode 100644 index 000000000..be5b40f56 --- /dev/null +++ b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/utils/settings/Settings.java @@ -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 getVersions() { + return settings.getConfigurations(); + } + + public static void setVersion(Profile ver) { + if (ver == null) { + return; + } + settings.getConfigurations().put(ver.getName(), ver); + } + + public static Collection 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); + } +} diff --git a/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/utils/version/Extract.java b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/utils/version/Extract.java new file mode 100644 index 000000000..af987a497 --- /dev/null +++ b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/utils/version/Extract.java @@ -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; + } + + +} diff --git a/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/utils/version/GameDirType.java b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/utils/version/GameDirType.java new file mode 100644 index 000000000..511021f52 --- /dev/null +++ b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/utils/version/GameDirType.java @@ -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; +} diff --git a/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/utils/version/IMinecraftLibrary.java b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/utils/version/IMinecraftLibrary.java new file mode 100644 index 000000000..f6a86e7a4 --- /dev/null +++ b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/utils/version/IMinecraftLibrary.java @@ -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(); +} diff --git a/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/utils/version/MinecraftClassicVersion.java b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/utils/version/MinecraftClassicVersion.java new file mode 100644 index 000000000..8b99dd27f --- /dev/null +++ b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/utils/version/MinecraftClassicVersion.java @@ -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 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; + } +} diff --git a/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/utils/version/MinecraftLibrary.java b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/utils/version/MinecraftLibrary.java new file mode 100644 index 000000000..ff3961fff --- /dev/null +++ b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/utils/version/MinecraftLibrary.java @@ -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; + 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, String url, String[] checksums, Natives natives, String name, Extract extract) { + super(name); + this.rules = rules == null ? null : (ArrayList) 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; + } +} diff --git a/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/utils/version/MinecraftOldLibrary.java b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/utils/version/MinecraftOldLibrary.java new file mode 100644 index 000000000..011095699 --- /dev/null +++ b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/utils/version/MinecraftOldLibrary.java @@ -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; + } + +} diff --git a/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/utils/version/MinecraftVersion.java b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/utils/version/MinecraftVersion.java new file mode 100644 index 000000000..e90e50c8a --- /dev/null +++ b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/utils/version/MinecraftVersion.java @@ -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 { + + public String minecraftArguments, mainClass, time, id, type, processArguments, + releaseTime, assets, jar, inheritsFrom; + public int minimumLauncherVersion; + public boolean hidden; + + public List 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 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 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); + } +} diff --git a/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/utils/version/MinecraftVersionManager.java b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/utils/version/MinecraftVersionManager.java new file mode 100644 index 000000000..f8aacc522 --- /dev/null +++ b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/utils/version/MinecraftVersionManager.java @@ -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 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 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 getDownloadLibraries(DownloadType downloadType) { + ArrayList 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 unzippings = new ArrayList<>(); + ArrayList 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(); + } +} diff --git a/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/utils/version/Natives.java b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/utils/version/Natives.java new file mode 100644 index 000000000..c2a2bf353 --- /dev/null +++ b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/utils/version/Natives.java @@ -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; + } +} diff --git a/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/utils/version/OS.java b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/utils/version/OS.java new file mode 100644 index 000000000..0bc04d8fd --- /dev/null +++ b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/utils/version/OS.java @@ -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; +} diff --git a/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/utils/version/Rules.java b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/utils/version/Rules.java new file mode 100644 index 000000000..4d346f317 --- /dev/null +++ b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/utils/version/Rules.java @@ -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; +} diff --git a/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/views/DraggableFrame.java b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/views/DraggableFrame.java new file mode 100644 index 000000000..8b09d92b4 --- /dev/null +++ b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/views/DraggableFrame.java @@ -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) { + } +} diff --git a/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/views/GameSettingsPanel.form b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/views/GameSettingsPanel.form new file mode 100644 index 000000000..89290ee9e --- /dev/null +++ b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/views/GameSettingsPanel.form @@ -0,0 +1,1073 @@ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/views/GameSettingsPanel.java b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/views/GameSettingsPanel.java new file mode 100644 index 000000000..8c8de5d27 --- /dev/null +++ b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/views/GameSettingsPanel.java @@ -0,0 +1,1468 @@ +/* + * 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.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.io.File; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.List; +import javax.swing.JFileChooser; +import javax.swing.JMenuItem; +import javax.swing.JOptionPane; +import javax.swing.JPopupMenu; +import javax.swing.JTable; +import javax.swing.SwingUtilities; +import javax.swing.table.DefaultTableModel; +import org.jackhuang.hellominecraft.C; +import org.jackhuang.hellominecraft.HMCLog; +import org.jackhuang.hellominecraft.launcher.utils.MCUtils; +import org.jackhuang.hellominecraft.launcher.utils.assets.IAssetsHandler; +import org.jackhuang.hellominecraft.launcher.utils.installers.InstallerVersionList; +import org.jackhuang.hellominecraft.launcher.utils.installers.InstallerVersionList.InstallerVersion; +import org.jackhuang.hellominecraft.launcher.utils.installers.forge.ForgeInstaller; +import org.jackhuang.hellominecraft.launcher.utils.installers.liteloader.LiteLoaderInstaller; +import org.jackhuang.hellominecraft.launcher.utils.installers.liteloader.LiteLoaderVersionList.LiteLoaderInstallerVersion; +import org.jackhuang.hellominecraft.launcher.utils.installers.optifine.OptiFineInstaller; +import org.jackhuang.hellominecraft.launcher.utils.installers.optifine.vanilla.OptiFineDownloadFormatter; +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.launcher.utils.version.GameDirType; +import org.jackhuang.hellominecraft.launcher.utils.version.MinecraftVersion; +import org.jackhuang.hellominecraft.tasks.Task; +import org.jackhuang.hellominecraft.tasks.TaskRunnableArg1; +import org.jackhuang.hellominecraft.tasks.TaskWindow; +import org.jackhuang.hellominecraft.tasks.communication.DefaultPreviousResult; +import org.jackhuang.hellominecraft.tasks.download.FileDownloadTask; +import org.jackhuang.hellominecraft.tasks.download.HTTPGetTask; +import org.jackhuang.hellominecraft.utils.IOUtils; +import org.jackhuang.hellominecraft.utils.MessageBox; +import org.jackhuang.hellominecraft.utils.MinecraftVersionRequest; +import org.jackhuang.hellominecraft.utils.OS; +import org.jackhuang.hellominecraft.utils.StrUtils; +import org.jackhuang.hellominecraft.utils.SwingUtils; +import org.jackhuang.hellominecraft.version.MinecraftRemoteVersion; +import org.jackhuang.hellominecraft.version.MinecraftRemoteVersions; +import org.jackhuang.hellominecraft.views.Selector; + +/** + * + * @author hyh + */ +public class GameSettingsPanel extends javax.swing.JPanel { + + /** + * Creates new form GameSettingsPanel + */ + public GameSettingsPanel() { + initComponents(); + setBackground(Color.white); + setOpaque(true); + + forge = new InstallerHelper(lstForge, "forge"); + liteloader = new InstallerHelper(lstLiteLoader, "liteloader"); + optifine = new InstallerHelper(lstOptifine, "optifine"); + // + ppmExplore = new JPopupMenu(); + class ImplementedActionListener implements ActionListener { + + ImplementedActionListener(String s) { + a = s; + } + String a; + + @Override + public void actionPerformed(ActionEvent e) { + Profile v = getProfile(); + if (v != null) + v.getMinecraftProvider().open(mcVersion, a); + } + } + JMenuItem itm; + itm = new JMenuItem(C.i18n("folder.game")); + itm.addActionListener((e) -> { + Profile v = getProfile(); + if (v != null) v.getMinecraftProvider().openSelf(mcVersion); + }); + ppmExplore.add(itm); + itm = new JMenuItem(C.i18n("folder.mod")); + itm.addActionListener(new ImplementedActionListener("mods")); + ppmExplore.add(itm); + itm = new JMenuItem(C.i18n("folder.coremod")); + itm.addActionListener(new ImplementedActionListener("coremods")); + ppmExplore.add(itm); + itm = new JMenuItem(C.i18n("folder.config")); + itm.addActionListener(new ImplementedActionListener("config")); + ppmExplore.add(itm); + itm = new JMenuItem(C.i18n("folder.resourcepacks")); + itm.addActionListener(new ImplementedActionListener("resourcepacks")); + ppmExplore.add(itm); + itm = new JMenuItem(C.i18n("folder.screenshots")); + itm.addActionListener(new ImplementedActionListener("screenshots")); + ppmExplore.add(itm); + // + // + ppmManage = new JPopupMenu(); + itm = new JMenuItem(C.i18n("versions.manage.rename")); + itm.addActionListener((e) -> { + Profile v = getProfile(); + if (v != null && mcVersion != null) { + String newName = JOptionPane.showInputDialog(C.i18n("versions.manage.rename.message"), mcVersion); + if (newName != null) + if (v.getMinecraftProvider().renameVersion(mcVersion, newName)) + refreshVersions(); + } + }); + ppmManage.add(itm); + itm = new JMenuItem(C.i18n("versions.manage.remove")); + itm.addActionListener((e) -> { + Profile v = getProfile(); + if (v != null && mcVersion != null && MessageBox.Show(C.i18n("versions.manage.remove.confirm") + mcVersion, MessageBox.YES_NO_OPTION) == MessageBox.YES_OPTION) + if (v.getMinecraftProvider().removeVersionFromDisk(mcVersion)) + refreshVersions(); + }); + ppmManage.add(itm); + itm = new JMenuItem(C.i18n("versions.manage.redownload_json")); + itm.addActionListener((e) -> { + Profile v = getProfile(); + if (v != null && mcVersion != null) + v.getMinecraftProvider().refreshJson(mcVersion); + }); + ppmManage.add(itm); + itm = new JMenuItem(C.i18n("versions.manage.redownload_assets_index")); + itm.addActionListener((e) -> { + Profile v = getProfile(); + if (v != null && mcVersion != null) + v.getMinecraftProvider().refreshAssetsIndex(mcVersion); + }); + ppmManage.add(itm); + // + } + + /** + * 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") + // //GEN-BEGIN:initComponents + private void initComponents() { + + jPanel1 = new javax.swing.JPanel(); + jPanel4 = new javax.swing.JPanel(); + jLabel1 = new javax.swing.JLabel(); + cboProfiles = new javax.swing.JComboBox(); + cboVersions = new javax.swing.JComboBox(); + jLabel2 = new javax.swing.JLabel(); + jPanel5 = new javax.swing.JPanel(); + btnModify = new javax.swing.JButton(); + btnRefreshVersions = new javax.swing.JButton(); + txtMinecraftVersion = new javax.swing.JTextField(); + btnNewProfile = new javax.swing.JButton(); + btnRemoveProfile = new javax.swing.JButton(); + btnExplore = new javax.swing.JButton(); + tabVersionEdit = new javax.swing.JTabbedPane(); + jPanel22 = new javax.swing.JPanel(); + jLabel24 = new javax.swing.JLabel(); + txtGameDir = new javax.swing.JTextField(); + jLabel25 = new javax.swing.JLabel(); + txtWidth = new javax.swing.JTextField(); + txtHeight = new javax.swing.JTextField(); + jLabel9 = new javax.swing.JLabel(); + chkFullscreen = new javax.swing.JCheckBox(); + txtJavaDir = new javax.swing.JTextField(); + jLabel11 = new javax.swing.JLabel(); + jLabel27 = new javax.swing.JLabel(); + txtMaxMemory = new javax.swing.JTextField(); + lblMaxMemory = new javax.swing.JLabel(); + btnDownloadAllAssets = new javax.swing.JButton(); + cboLauncherVisibility = new javax.swing.JComboBox(); + jLabel10 = new javax.swing.JLabel(); + jLabel12 = new javax.swing.JLabel(); + cboGameDirType = new javax.swing.JComboBox(); + jPanel2 = new javax.swing.JPanel(); + chkDebug = new javax.swing.JCheckBox(); + jLabel26 = new javax.swing.JLabel(); + txtJavaArgs = new javax.swing.JTextField(); + txtMinecraftArgs = new javax.swing.JTextField(); + jLabel28 = new javax.swing.JLabel(); + jLabel29 = new javax.swing.JLabel(); + txtPermSize = new javax.swing.JTextField(); + chkNoJVMArgs = new javax.swing.JCheckBox(); + chkCancelWrapper = new javax.swing.JCheckBox(); + jLabel30 = new javax.swing.JLabel(); + txtWrapperLauncher = new javax.swing.JTextField(); + jLabel31 = new javax.swing.JLabel(); + txtServerIP = new javax.swing.JTextField(); + pnlAutoInstall = new javax.swing.JPanel(); + tabInstallers = new javax.swing.JTabbedPane(); + jPanel16 = new javax.swing.JPanel(); + jScrollPane11 = new javax.swing.JScrollPane(); + lstForge = new javax.swing.JTable(); + btnRefreshForge = new javax.swing.JButton(); + btnDownloadForge = new javax.swing.JButton(); + btnRetryForge = new javax.swing.JButton(); + pnlOptifine = new javax.swing.JPanel(); + jScrollPane13 = new javax.swing.JScrollPane(); + lstOptifine = new javax.swing.JTable(); + btnRefreshOptifine = new javax.swing.JButton(); + btnDownloadOptifine = new javax.swing.JButton(); + jPanel3 = new javax.swing.JPanel(); + btnInstallLiteLoader = new javax.swing.JButton(); + jScrollPane12 = new javax.swing.JScrollPane(); + lstLiteLoader = new javax.swing.JTable(); + btnRefreshLiteLoader = new javax.swing.JButton(); + btnRetryLiteLoader = new javax.swing.JButton(); + pnlGameDownloads = new javax.swing.JPanel(); + btnDownload = new javax.swing.JButton(); + jScrollPane2 = new javax.swing.JScrollPane(); + lstDownloads = new javax.swing.JTable(); + btnRefreshGameDownloads = new javax.swing.JButton(); + btnIncludeMinecraft = new javax.swing.JButton(); + + setBackground(new java.awt.Color(255, 255, 255)); + + java.util.ResourceBundle bundle = java.util.ResourceBundle.getBundle("org/jackhuang/hellominecraft/launcher/I18N"); // NOI18N + jLabel1.setText(bundle.getString("ui.label.profile")); // NOI18N + + cboProfiles.setMinimumSize(new java.awt.Dimension(32, 23)); + cboProfiles.setPreferredSize(new java.awt.Dimension(32, 23)); + cboProfiles.addItemListener(new java.awt.event.ItemListener() { + public void itemStateChanged(java.awt.event.ItemEvent evt) { + cboProfilesItemStateChanged(evt); + } + }); + + cboVersions.addItemListener(new java.awt.event.ItemListener() { + public void itemStateChanged(java.awt.event.ItemEvent evt) { + cboVersionsItemStateChanged(evt); + } + }); + + jLabel2.setText(bundle.getString("ui.label.version")); // NOI18N + + javax.swing.GroupLayout jPanel4Layout = new javax.swing.GroupLayout(jPanel4); + jPanel4.setLayout(jPanel4Layout); + jPanel4Layout.setHorizontalGroup( + jPanel4Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jPanel4Layout.createSequentialGroup() + .addContainerGap() + .addGroup(jPanel4Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jPanel4Layout.createSequentialGroup() + .addComponent(jLabel1) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(cboProfiles, 0, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) + .addGroup(jPanel4Layout.createSequentialGroup() + .addComponent(jLabel2) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(cboVersions, 0, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)))) + ); + jPanel4Layout.setVerticalGroup( + jPanel4Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jPanel4Layout.createSequentialGroup() + .addContainerGap() + .addGroup(jPanel4Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(cboProfiles, javax.swing.GroupLayout.PREFERRED_SIZE, 26, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(jLabel1)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(jPanel4Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(cboVersions, javax.swing.GroupLayout.PREFERRED_SIZE, 26, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(jLabel2)) + .addContainerGap(11, Short.MAX_VALUE)) + ); + + btnModify.setText(bundle.getString("settings.manage")); // NOI18N + btnModify.addMouseListener(new java.awt.event.MouseAdapter() { + public void mouseClicked(java.awt.event.MouseEvent evt) { + btnModifyMouseClicked(evt); + } + }); + + btnRefreshVersions.setText(bundle.getString("ui.button.refresh")); // NOI18N + btnRefreshVersions.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + btnRefreshVersionsActionPerformed(evt); + } + }); + + txtMinecraftVersion.setEditable(false); + + btnNewProfile.setText(bundle.getString("setupwindow.new")); // NOI18N + btnNewProfile.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + btnNewProfileActionPerformed(evt); + } + }); + + btnRemoveProfile.setText(bundle.getString("ui.button.delete")); // NOI18N + btnRemoveProfile.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + btnRemoveProfileActionPerformed(evt); + } + }); + + btnExplore.setText(bundle.getString("settings.explore")); // NOI18N + btnExplore.setToolTipText(""); + btnExplore.addMouseListener(new java.awt.event.MouseAdapter() { + public void mouseClicked(java.awt.event.MouseEvent evt) { + btnExploreMouseClicked(evt); + } + }); + + javax.swing.GroupLayout jPanel5Layout = new javax.swing.GroupLayout(jPanel5); + jPanel5.setLayout(jPanel5Layout); + jPanel5Layout.setHorizontalGroup( + jPanel5Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jPanel5Layout.createSequentialGroup() + .addGap(0, 0, 0) + .addGroup(jPanel5Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false) + .addComponent(btnNewProfile, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(txtMinecraftVersion)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(jPanel5Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false) + .addComponent(btnRemoveProfile, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(btnRefreshVersions, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(jPanel5Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false) + .addComponent(btnModify, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(btnExplore, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) + .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) + ); + jPanel5Layout.setVerticalGroup( + jPanel5Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jPanel5Layout.createSequentialGroup() + .addContainerGap() + .addGroup(jPanel5Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(btnNewProfile, javax.swing.GroupLayout.PREFERRED_SIZE, 26, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(btnRemoveProfile, javax.swing.GroupLayout.PREFERRED_SIZE, 26, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(btnExplore, javax.swing.GroupLayout.PREFERRED_SIZE, 26, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(jPanel5Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(txtMinecraftVersion, javax.swing.GroupLayout.PREFERRED_SIZE, 26, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(btnRefreshVersions, javax.swing.GroupLayout.PREFERRED_SIZE, 26, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(btnModify, javax.swing.GroupLayout.PREFERRED_SIZE, 26, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) + ); + + javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1); + jPanel1.setLayout(jPanel1Layout); + jPanel1Layout.setHorizontalGroup( + jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jPanel1Layout.createSequentialGroup() + .addComponent(jPanel4, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(jPanel5, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) + ); + jPanel1Layout.setVerticalGroup( + jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jPanel1Layout.createSequentialGroup() + .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false) + .addComponent(jPanel4, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(jPanel5, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) + .addGap(0, 0, Short.MAX_VALUE)) + ); + + tabVersionEdit.setName("tabVersionEdit"); // NOI18N + + jLabel24.setText(bundle.getString("settings.game_directory")); // NOI18N + + txtGameDir.addFocusListener(new java.awt.event.FocusAdapter() { + public void focusLost(java.awt.event.FocusEvent evt) { + txtGameDirFocusLost(evt); + } + }); + + jLabel25.setText(bundle.getString("settings.dimension")); // NOI18N + + txtWidth.setToolTipText(""); + txtWidth.addFocusListener(new java.awt.event.FocusAdapter() { + public void focusLost(java.awt.event.FocusEvent evt) { + txtWidthFocusLost(evt); + } + }); + + txtHeight.addFocusListener(new java.awt.event.FocusAdapter() { + public void focusLost(java.awt.event.FocusEvent evt) { + txtHeightFocusLost(evt); + } + }); + + jLabel9.setText("x"); + + chkFullscreen.setText(bundle.getString("settings.fullscreen")); // NOI18N + chkFullscreen.addFocusListener(new java.awt.event.FocusAdapter() { + public void focusLost(java.awt.event.FocusEvent evt) { + chkFullscreenFocusLost(evt); + } + }); + + txtJavaDir.addFocusListener(new java.awt.event.FocusAdapter() { + public void focusLost(java.awt.event.FocusEvent evt) { + txtJavaDirFocusLost(evt); + } + }); + txtJavaDir.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + txtJavaDirActionPerformed(evt); + } + }); + + jLabel11.setText(bundle.getString("settings.java_dir")); // NOI18N + + jLabel27.setText(bundle.getString("settings.max_memory")); // NOI18N + + txtMaxMemory.addFocusListener(new java.awt.event.FocusAdapter() { + public void focusLost(java.awt.event.FocusEvent evt) { + txtMaxMemoryFocusLost(evt); + } + }); + + lblMaxMemory.setText(C.i18n("settings.physical_memory") + ": " + OS.getTotalPhysicalMemory() / 1024 / 1024 + "MB"); + + btnDownloadAllAssets.setText(bundle.getString("assets.download_all")); // NOI18N + btnDownloadAllAssets.setToolTipText(""); + btnDownloadAllAssets.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + btnDownloadAllAssetsActionPerformed(evt); + } + }); + + cboLauncherVisibility.setModel(new javax.swing.DefaultComboBoxModel(new String[] { C.I18N.getString("advancedsettings.launcher_visibility.close"), C.I18N.getString("advancedsettings.launcher_visibility.hide"), C.I18N.getString("advancedsettings.launcher_visibility.keep") })); + cboLauncherVisibility.addFocusListener(new java.awt.event.FocusAdapter() { + public void focusLost(java.awt.event.FocusEvent evt) { + cboLauncherVisibilityFocusLost(evt); + } + }); + + jLabel10.setText(bundle.getString("advancedsettings.launcher_visible")); // NOI18N + + jLabel12.setText(bundle.getString("advancedsettings.run_directory")); // NOI18N + + cboGameDirType.setModel(new javax.swing.DefaultComboBoxModel(new String[] { C.I18N.getString("advancedsettings.game_dir.default"), C.I18N.getString("advancedsettings.game_dir.independent") })); + cboGameDirType.addFocusListener(new java.awt.event.FocusAdapter() { + public void focusLost(java.awt.event.FocusEvent evt) { + cboGameDirTypeFocusLost(evt); + } + }); + + javax.swing.GroupLayout jPanel22Layout = new javax.swing.GroupLayout(jPanel22); + jPanel22.setLayout(jPanel22Layout); + jPanel22Layout.setHorizontalGroup( + jPanel22Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jPanel22Layout.createSequentialGroup() + .addContainerGap() + .addGroup(jPanel22Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jPanel22Layout.createSequentialGroup() + .addComponent(btnDownloadAllAssets) + .addGap(0, 0, Short.MAX_VALUE)) + .addGroup(jPanel22Layout.createSequentialGroup() + .addGroup(jPanel22Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(jLabel11) + .addComponent(jLabel27) + .addComponent(jLabel24) + .addComponent(jLabel12) + .addComponent(jLabel10) + .addComponent(jLabel25)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(jPanel22Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(cboGameDirType, javax.swing.GroupLayout.Alignment.TRAILING, 0, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(cboLauncherVisibility, javax.swing.GroupLayout.Alignment.TRAILING, 0, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(txtJavaDir, javax.swing.GroupLayout.Alignment.TRAILING) + .addGroup(jPanel22Layout.createSequentialGroup() + .addComponent(txtMaxMemory) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) + .addComponent(lblMaxMemory)) + .addComponent(txtGameDir) + .addGroup(jPanel22Layout.createSequentialGroup() + .addComponent(txtWidth, javax.swing.GroupLayout.PREFERRED_SIZE, 100, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(jLabel9) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(txtHeight, javax.swing.GroupLayout.PREFERRED_SIZE, 100, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 306, Short.MAX_VALUE) + .addComponent(chkFullscreen))))) + .addContainerGap()) + ); + jPanel22Layout.setVerticalGroup( + jPanel22Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jPanel22Layout.createSequentialGroup() + .addContainerGap() + .addGroup(jPanel22Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(txtGameDir, javax.swing.GroupLayout.PREFERRED_SIZE, 26, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(jLabel24)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(jPanel22Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(txtJavaDir, javax.swing.GroupLayout.PREFERRED_SIZE, 26, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(jLabel11)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(jPanel22Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(lblMaxMemory) + .addComponent(txtMaxMemory, javax.swing.GroupLayout.PREFERRED_SIZE, 26, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(jLabel27)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(jPanel22Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(cboLauncherVisibility, javax.swing.GroupLayout.PREFERRED_SIZE, 26, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(jLabel10)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(jPanel22Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(cboGameDirType, javax.swing.GroupLayout.PREFERRED_SIZE, 26, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(jLabel12)) + .addGap(4, 4, 4) + .addGroup(jPanel22Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(txtHeight, javax.swing.GroupLayout.PREFERRED_SIZE, 26, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(chkFullscreen, javax.swing.GroupLayout.PREFERRED_SIZE, 26, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(jLabel9, javax.swing.GroupLayout.PREFERRED_SIZE, 26, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(jLabel25) + .addComponent(txtWidth, javax.swing.GroupLayout.PREFERRED_SIZE, 26, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 92, Short.MAX_VALUE) + .addComponent(btnDownloadAllAssets) + .addContainerGap()) + ); + + tabVersionEdit.addTab(bundle.getString("settings"), jPanel22); // NOI18N + + chkDebug.setText(bundle.getString("advencedsettings.debug_mode")); // NOI18N + chkDebug.addFocusListener(new java.awt.event.FocusAdapter() { + public void focusLost(java.awt.event.FocusEvent evt) { + chkDebugFocusLost(evt); + } + }); + + jLabel26.setText(bundle.getString("advancedsettings.jvm_args")); // NOI18N + + txtJavaArgs.setToolTipText(bundle.getString("advancedsettings.java_args_default")); // NOI18N + txtJavaArgs.addFocusListener(new java.awt.event.FocusAdapter() { + public void focusLost(java.awt.event.FocusEvent evt) { + txtJavaArgsFocusLost(evt); + } + }); + + txtMinecraftArgs.addFocusListener(new java.awt.event.FocusAdapter() { + public void focusLost(java.awt.event.FocusEvent evt) { + txtMinecraftArgsFocusLost(evt); + } + }); + + jLabel28.setText(bundle.getString("advancedsettings.Minecraft_arguments")); // NOI18N + + jLabel29.setText(bundle.getString("advancedsettings.java_permanent_generation_space")); // NOI18N + + txtPermSize.addFocusListener(new java.awt.event.FocusAdapter() { + public void focusLost(java.awt.event.FocusEvent evt) { + txtPermSizeFocusLost(evt); + } + }); + + chkNoJVMArgs.setText(bundle.getString("advancedsettings.no_jvm_args")); // NOI18N + chkNoJVMArgs.addFocusListener(new java.awt.event.FocusAdapter() { + public void focusLost(java.awt.event.FocusEvent evt) { + chkNoJVMArgsFocusLost(evt); + } + }); + + chkCancelWrapper.setText("鍙栨秷鍖呰9鍚姩鍣紙鍑虹幇濂囨棶棰樻椂鍙皾璇曚娇鐢,涓庤皟璇曟ā寮忓啿绐侊級"); + chkCancelWrapper.addFocusListener(new java.awt.event.FocusAdapter() { + public void focusLost(java.awt.event.FocusEvent evt) { + chkCancelWrapperFocusLost(evt); + } + }); + + jLabel30.setText(bundle.getString("advancedsettings.wrapper_launcher")); // NOI18N + + txtWrapperLauncher.addFocusListener(new java.awt.event.FocusAdapter() { + public void focusLost(java.awt.event.FocusEvent evt) { + txtWrapperLauncherFocusLost(evt); + } + }); + + jLabel31.setText(bundle.getString("advancedsettings.server_ip")); // NOI18N + + txtServerIP.addFocusListener(new java.awt.event.FocusAdapter() { + public void focusLost(java.awt.event.FocusEvent evt) { + txtServerIPFocusLost(evt); + } + }); + + javax.swing.GroupLayout jPanel2Layout = new javax.swing.GroupLayout(jPanel2); + jPanel2.setLayout(jPanel2Layout); + jPanel2Layout.setHorizontalGroup( + jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jPanel2Layout.createSequentialGroup() + .addContainerGap() + .addGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(txtWrapperLauncher) + .addComponent(txtServerIP) + .addGroup(jPanel2Layout.createSequentialGroup() + .addGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(jLabel30) + .addGroup(jPanel2Layout.createSequentialGroup() + .addComponent(chkDebug) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(chkCancelWrapper) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(chkNoJVMArgs)) + .addComponent(jLabel31)) + .addGap(0, 0, Short.MAX_VALUE)) + .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel2Layout.createSequentialGroup() + .addGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(jLabel28) + .addComponent(jLabel29) + .addComponent(jLabel26)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(txtJavaArgs) + .addComponent(txtMinecraftArgs) + .addComponent(txtPermSize, javax.swing.GroupLayout.Alignment.TRAILING)))) + .addContainerGap()) + ); + jPanel2Layout.setVerticalGroup( + jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jPanel2Layout.createSequentialGroup() + .addContainerGap() + .addGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(txtJavaArgs, javax.swing.GroupLayout.PREFERRED_SIZE, 26, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(jLabel26)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(txtMinecraftArgs, javax.swing.GroupLayout.PREFERRED_SIZE, 26, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(jLabel28)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(txtPermSize, javax.swing.GroupLayout.PREFERRED_SIZE, 26, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(jLabel29)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(jLabel30) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(txtWrapperLauncher, javax.swing.GroupLayout.PREFERRED_SIZE, 26, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(jLabel31) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(txtServerIP, javax.swing.GroupLayout.PREFERRED_SIZE, 26, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 85, Short.MAX_VALUE) + .addGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(chkDebug) + .addComponent(chkNoJVMArgs) + .addComponent(chkCancelWrapper)) + .addContainerGap()) + ); + + tabVersionEdit.addTab(bundle.getString("advancedsettings"), jPanel2); // NOI18N + + lstForge.setModel(SwingUtils.makeDefaultTableModel(new String[]{C.I18N.getString("install.version"), C.I18N.getString("install.mcversion")}, + new Class[]{String.class, String.class}, new boolean[]{false, false})); + lstForge.setSelectionMode(javax.swing.ListSelectionModel.SINGLE_SELECTION); + jScrollPane11.setViewportView(lstForge); + + btnRefreshForge.setText(bundle.getString("ui.button.refresh")); // NOI18N + btnRefreshForge.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + btnRefreshForgeActionPerformed(evt); + } + }); + + btnDownloadForge.setText(bundle.getString("ui.button.install")); // NOI18N + btnDownloadForge.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + btnDownloadForgeActionPerformed(evt); + } + }); + + btnRetryForge.setText(bundle.getString("ui.button.retry")); // NOI18N + btnRetryForge.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + btnRetryForgeActionPerformed(evt); + } + }); + + javax.swing.GroupLayout jPanel16Layout = new javax.swing.GroupLayout(jPanel16); + jPanel16.setLayout(jPanel16Layout); + jPanel16Layout.setHorizontalGroup( + jPanel16Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel16Layout.createSequentialGroup() + .addComponent(jScrollPane11, javax.swing.GroupLayout.DEFAULT_SIZE, 587, Short.MAX_VALUE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(jPanel16Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false) + .addComponent(btnRetryForge, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(btnDownloadForge, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(btnRefreshForge, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) + .addContainerGap()) + ); + jPanel16Layout.setVerticalGroup( + jPanel16Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(jScrollPane11, javax.swing.GroupLayout.PREFERRED_SIZE, 0, Short.MAX_VALUE) + .addGroup(jPanel16Layout.createSequentialGroup() + .addComponent(btnDownloadForge) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(btnRetryForge) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(btnRefreshForge) + .addGap(0, 210, Short.MAX_VALUE)) + ); + + tabInstallers.addTab("Forge", jPanel16); + + lstOptifine.setModel(SwingUtils.makeDefaultTableModel(new String[]{C.I18N.getString("install.version"), C.I18N.getString("install.mcversion")}, + new Class[]{String.class, String.class}, new boolean[]{false, false})); +lstOptifine.setSelectionMode(javax.swing.ListSelectionModel.SINGLE_SELECTION); +jScrollPane13.setViewportView(lstOptifine); + +btnRefreshOptifine.setText(bundle.getString("ui.button.refresh")); // NOI18N +btnRefreshOptifine.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + btnRefreshOptifineActionPerformed(evt); + } + }); + + btnDownloadOptifine.setText(bundle.getString("ui.button.install")); // NOI18N + btnDownloadOptifine.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + btnDownloadOptifineActionPerformed(evt); + } + }); + + javax.swing.GroupLayout pnlOptifineLayout = new javax.swing.GroupLayout(pnlOptifine); + pnlOptifine.setLayout(pnlOptifineLayout); + pnlOptifineLayout.setHorizontalGroup( + pnlOptifineLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(pnlOptifineLayout.createSequentialGroup() + .addComponent(jScrollPane13, javax.swing.GroupLayout.DEFAULT_SIZE, 587, Short.MAX_VALUE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(pnlOptifineLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false) + .addComponent(btnDownloadOptifine, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(btnRefreshOptifine)) + .addContainerGap()) + ); + pnlOptifineLayout.setVerticalGroup( + pnlOptifineLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(jScrollPane13, javax.swing.GroupLayout.PREFERRED_SIZE, 0, Short.MAX_VALUE) + .addGroup(pnlOptifineLayout.createSequentialGroup() + .addComponent(btnDownloadOptifine) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(btnRefreshOptifine) + .addGap(0, 239, Short.MAX_VALUE)) + ); + + tabInstallers.addTab("OptiFine", pnlOptifine); + + btnInstallLiteLoader.setText(bundle.getString("ui.button.install")); // NOI18N + btnInstallLiteLoader.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + btnInstallLiteLoaderActionPerformed(evt); + } + }); + + lstLiteLoader.setModel(SwingUtils.makeDefaultTableModel(new String[]{C.I18N.getString("install.version"), C.I18N.getString("install.mcversion")}, + new Class[]{String.class, String.class}, new boolean[]{false, false})); +lstLiteLoader.setSelectionMode(javax.swing.ListSelectionModel.SINGLE_SELECTION); +jScrollPane12.setViewportView(lstLiteLoader); + +btnRefreshLiteLoader.setText(bundle.getString("ui.button.refresh")); // NOI18N +btnRefreshLiteLoader.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + btnRefreshLiteLoaderActionPerformed(evt); + } + }); + + btnRetryLiteLoader.setText(bundle.getString("ui.button.retry")); // NOI18N + btnRetryLiteLoader.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + btnRetryLiteLoaderActionPerformed(evt); + } + }); + + javax.swing.GroupLayout jPanel3Layout = new javax.swing.GroupLayout(jPanel3); + jPanel3.setLayout(jPanel3Layout); + jPanel3Layout.setHorizontalGroup( + jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jPanel3Layout.createSequentialGroup() + .addComponent(jScrollPane12, javax.swing.GroupLayout.DEFAULT_SIZE, 587, Short.MAX_VALUE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false) + .addComponent(btnInstallLiteLoader, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(btnRetryLiteLoader, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(btnRefreshLiteLoader)) + .addContainerGap()) + ); + jPanel3Layout.setVerticalGroup( + jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(jScrollPane12, javax.swing.GroupLayout.PREFERRED_SIZE, 0, Short.MAX_VALUE) + .addGroup(jPanel3Layout.createSequentialGroup() + .addComponent(btnInstallLiteLoader) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(btnRetryLiteLoader) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(btnRefreshLiteLoader) + .addGap(0, 210, Short.MAX_VALUE)) + ); + + tabInstallers.addTab("LiteLoader", jPanel3); + + javax.swing.GroupLayout pnlAutoInstallLayout = new javax.swing.GroupLayout(pnlAutoInstall); + pnlAutoInstall.setLayout(pnlAutoInstallLayout); + pnlAutoInstallLayout.setHorizontalGroup( + pnlAutoInstallLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(tabInstallers) + ); + pnlAutoInstallLayout.setVerticalGroup( + pnlAutoInstallLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(tabInstallers) + ); + + tabVersionEdit.addTab(bundle.getString("settings.tabs.installers"), pnlAutoInstall); // NOI18N + + btnDownload.setText(bundle.getString("ui.button.download")); // NOI18N + btnDownload.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + btnDownloadActionPerformed(evt); + } + }); + + lstDownloads.setModel(SwingUtils.makeDefaultTableModel(new String[]{C.I18N.getString("install.version"), C.I18N.getString("install.time"), C.I18N.getString("install.type")},new Class[]{String.class, String.class, String.class}, new boolean[]{false, false, false})); + lstDownloads.setToolTipText(""); + lstDownloads.setSelectionMode(javax.swing.ListSelectionModel.SINGLE_SELECTION); + jScrollPane2.setViewportView(lstDownloads); + + btnRefreshGameDownloads.setText(bundle.getString("ui.button.refresh")); // NOI18N + btnRefreshGameDownloads.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + btnRefreshGameDownloadsActionPerformed(evt); + } + }); + + javax.swing.GroupLayout pnlGameDownloadsLayout = new javax.swing.GroupLayout(pnlGameDownloads); + pnlGameDownloads.setLayout(pnlGameDownloadsLayout); + pnlGameDownloadsLayout.setHorizontalGroup( + pnlGameDownloadsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(pnlGameDownloadsLayout.createSequentialGroup() + .addComponent(jScrollPane2, javax.swing.GroupLayout.DEFAULT_SIZE, 592, Short.MAX_VALUE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(pnlGameDownloadsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false) + .addComponent(btnRefreshGameDownloads, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(btnDownload)) + .addContainerGap()) + ); + pnlGameDownloadsLayout.setVerticalGroup( + pnlGameDownloadsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(pnlGameDownloadsLayout.createSequentialGroup() + .addComponent(btnRefreshGameDownloads) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(btnDownload)) + .addComponent(jScrollPane2, javax.swing.GroupLayout.DEFAULT_SIZE, 320, Short.MAX_VALUE) + ); + + tabVersionEdit.addTab(bundle.getString("settings.tabs.game_download"), pnlGameDownloads); // NOI18N + + btnIncludeMinecraft.setText(bundle.getString("setupwindow.include_minecraft")); // NOI18N + btnIncludeMinecraft.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + btnIncludeMinecraftActionPerformed(evt); + } + }); + + javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); + this.setLayout(layout); + layout.setHorizontalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(jPanel1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup() + .addContainerGap() + .addComponent(btnIncludeMinecraft) + .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) + .addComponent(tabVersionEdit) + ); + layout.setVerticalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(layout.createSequentialGroup() + .addComponent(jPanel1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(tabVersionEdit) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(btnIncludeMinecraft) + .addContainerGap()) + ); + }// //GEN-END:initComponents + // + private void cboProfilesItemStateChanged(java.awt.event.ItemEvent evt) {//GEN-FIRST:event_cboProfilesItemStateChanged + if (isLoading) return; + profile = getProfile(); + if (profile.getMinecraftProvider().getVersionCount() <= 0) + versionChanged(profile, null); + prepare(profile); + }//GEN-LAST:event_cboProfilesItemStateChanged + + private void btnNewProfileActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnNewProfileActionPerformed + NewProfileWindow window = new NewProfileWindow(null); + window.setVisible(true); + loadProfiles(); + }//GEN-LAST:event_btnNewProfileActionPerformed + + private void btnRemoveProfileActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnRemoveProfileActionPerformed + if (profile == null) return; + if ("Default".equals(profile.getName())) { + MessageBox.Show(C.i18n("settings.cannot_remove_default_config")); + return; + } + if (MessageBox.Show(C.i18n("ui.message.sure_remove", profile.getName()), MessageBox.YES_NO_OPTION) == MessageBox.NO_OPTION) return; + cboProfiles.removeItem(profile.getName()); + Settings.delVersion(profile); + profile = Settings.getOneProfile(); + if (profile != null) { + prepare(profile); + loadVersions(); + } + }//GEN-LAST:event_btnRemoveProfileActionPerformed + + private void cboVersionsItemStateChanged(java.awt.event.ItemEvent evt) {//GEN-FIRST:event_cboVersionsItemStateChanged + if (isLoading || cboVersions.getSelectedIndex() < 0 || StrUtils.isBlank((String) cboVersions.getSelectedItem()) || getProfile() == null) return; + loadMinecraftVersion((String) cboVersions.getSelectedItem()); + versionChanged(getProfile(), (String) cboVersions.getSelectedItem()); + }//GEN-LAST:event_cboVersionsItemStateChanged + + private void btnRefreshVersionsActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnRefreshVersionsActionPerformed + refreshVersions(); + }//GEN-LAST:event_btnRefreshVersionsActionPerformed + + private void btnRefreshForgeActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnRefreshForgeActionPerformed + forge.refreshVersions();//refreshForgeVersions(); + }//GEN-LAST:event_btnRefreshForgeActionPerformed + + private void btnDownloadForgeActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnDownloadForgeActionPerformed + int idx = lstForge.getSelectedRow(); + if (idx == -1) { + MessageBox.Show(C.i18n("install.not_refreshed")); + return; + } + InstallerVersion v = forge.getVersion(idx);//forgeVersions.get(idx); + String url; + File filepath = IOUtils.tryGetCanonicalFile(IOUtils.currentDirWithSeparator() + "forge-installer.jar"); + if (v.installer != null) { + url = v.installer; + TaskWindow.getInstance() + .addTask(new FileDownloadTask(url, filepath).setTag("forge")) + .addTask(new ForgeInstaller(profile.getMinecraftProvider(), filepath)) + .start(); + } + }//GEN-LAST:event_btnDownloadForgeActionPerformed + + private void btnRetryForgeActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnRetryForgeActionPerformed + if (profile == null) return; + MinecraftVersion v = profile.getMinecraftProvider().getVersionById(mcVersion); + if (v == null) return; + TaskWindow.getInstance().addTask(new ForgeInstaller(profile.getMinecraftProvider(), IOUtils.tryGetCanonicalFile(IOUtils.currentDirWithSeparator() + "forge-installer.jar"))).start(); + }//GEN-LAST:event_btnRetryForgeActionPerformed + + private void btnRefreshOptifineActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnRefreshOptifineActionPerformed + optifine.refreshVersions(); + }//GEN-LAST:event_btnRefreshOptifineActionPerformed + + private void btnDownloadOptifineActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnDownloadOptifineActionPerformed + int idx = lstOptifine.getSelectedRow(); + if (idx == -1) { + MessageBox.Show(C.i18n("install.not_refreshed")); + return; + } + InstallerVersion v = optifine.getVersion(idx); + File filepath = IOUtils.tryGetCanonicalFile(IOUtils.currentDirWithSeparator() + "optifine-installer.jar"); + if (v.installer != null) { + OptiFineDownloadFormatter task = new OptiFineDownloadFormatter(v.installer); + TaskWindow.getInstance().addTask(task) + .addTask(new FileDownloadTask(filepath).registerPreviousResult(task).setTag("optifine")) + .addTask(new OptiFineInstaller(profile, v.selfVersion, filepath)) + .start(); + } + }//GEN-LAST:event_btnDownloadOptifineActionPerformed + + private void btnInstallLiteLoaderActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnInstallLiteLoaderActionPerformed + int idx = lstLiteLoader.getSelectedRow(); + if (idx == -1) { + MessageBox.Show(C.i18n("install.not_refreshed")); + return; + } + InstallerVersion v = liteloader.getVersion(idx); + String url; + File filepath = IOUtils.tryGetCanonicalFile(IOUtils.currentDirWithSeparator() + "liteloader-universal.jar"); + url = v.universal; + FileDownloadTask task = (FileDownloadTask) new FileDownloadTask(url, filepath).setTag("LiteLoader"); + TaskWindow.getInstance() + .addTask(task).addTask(new LiteLoaderInstaller(profile, (LiteLoaderInstallerVersion) v).registerPreviousResult(task)) + .start(); + }//GEN-LAST:event_btnInstallLiteLoaderActionPerformed + + private void btnRefreshLiteLoaderActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnRefreshLiteLoaderActionPerformed + liteloader.refreshVersions(); + }//GEN-LAST:event_btnRefreshLiteLoaderActionPerformed + + private void btnRetryLiteLoaderActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnRetryLiteLoaderActionPerformed + if (profile == null) return; + int idx = lstLiteLoader.getSelectedRow(); + if (idx == -1) return; + InstallerVersion v = liteloader.getVersion(idx); + File filepath = new File(IOUtils.currentDir(), "liteloader-universal.jar"); + TaskWindow.getInstance().addTask(new LiteLoaderInstaller(profile, (LiteLoaderInstallerVersion) v, filepath)).start(); + }//GEN-LAST:event_btnRetryLiteLoaderActionPerformed + + private void btnDownloadActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnDownloadActionPerformed + downloadMinecraft(Settings.s().getDownloadSource()); + refreshVersions(); + }//GEN-LAST:event_btnDownloadActionPerformed + + private void btnRefreshGameDownloadsActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnRefreshGameDownloadsActionPerformed + refreshDownloads(Settings.s().getDownloadSource()); + }//GEN-LAST:event_btnRefreshGameDownloadsActionPerformed + + private void btnExploreMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_btnExploreMouseClicked + ppmExplore.show(evt.getComponent(), evt.getPoint().x, evt.getPoint().y); + }//GEN-LAST:event_btnExploreMouseClicked + + private void btnIncludeMinecraftActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnIncludeMinecraftActionPerformed + JFileChooser fc = new JFileChooser(IOUtils.currentDir()); + fc.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY); + int ret = fc.showOpenDialog(this); + if (ret == JFileChooser.APPROVE_OPTION) { + File newGameDir = fc.getSelectedFile(); + String name = JOptionPane.showInputDialog(C.i18n("setupwindow.give_a_name")); + if (StrUtils.isBlank(name)) { + MessageBox.Show(C.i18n("setupwindow.no_empty_name")); + return; + } + Settings.trySetVersion(new Profile(name).setGameDir(newGameDir.getAbsolutePath())); + MessageBox.Show(C.i18n("setupwindow.find_in_configurations")); + loadProfiles(); + } + }//GEN-LAST:event_btnIncludeMinecraftActionPerformed + + private void btnModifyMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_btnModifyMouseClicked + ppmManage.show(evt.getComponent(), evt.getPoint().x, evt.getPoint().y); + }//GEN-LAST:event_btnModifyMouseClicked + + private void txtJavaArgsFocusLost(java.awt.event.FocusEvent evt) {//GEN-FIRST:event_txtJavaArgsFocusLost + profile.setJavaArgs(txtJavaArgs.getText()); + }//GEN-LAST:event_txtJavaArgsFocusLost + + private void txtMinecraftArgsFocusLost(java.awt.event.FocusEvent evt) {//GEN-FIRST:event_txtMinecraftArgsFocusLost + profile.setMinecraftArgs(txtMinecraftArgs.getText()); + }//GEN-LAST:event_txtMinecraftArgsFocusLost + + private void txtPermSizeFocusLost(java.awt.event.FocusEvent evt) {//GEN-FIRST:event_txtPermSizeFocusLost + profile.setPermSize(txtPermSize.getText()); + }//GEN-LAST:event_txtPermSizeFocusLost + + private void chkDebugFocusLost(java.awt.event.FocusEvent evt) {//GEN-FIRST:event_chkDebugFocusLost + profile.setDebug(chkDebug.isSelected()); + }//GEN-LAST:event_chkDebugFocusLost + + private void chkNoJVMArgsFocusLost(java.awt.event.FocusEvent evt) {//GEN-FIRST:event_chkNoJVMArgsFocusLost + profile.setNoJVMArgs(chkNoJVMArgs.isSelected()); + }//GEN-LAST:event_chkNoJVMArgsFocusLost + + private void chkCancelWrapperFocusLost(java.awt.event.FocusEvent evt) {//GEN-FIRST:event_chkCancelWrapperFocusLost + profile.setCanceledWrapper(chkCancelWrapper.isSelected()); + }//GEN-LAST:event_chkCancelWrapperFocusLost + + private void txtWrapperLauncherFocusLost(java.awt.event.FocusEvent evt) {//GEN-FIRST:event_txtWrapperLauncherFocusLost + profile.setWrapperLauncher(txtWrapperLauncher.getText()); + }//GEN-LAST:event_txtWrapperLauncherFocusLost + + private void txtServerIPFocusLost(java.awt.event.FocusEvent evt) {//GEN-FIRST:event_txtServerIPFocusLost + profile.setServerIp(txtServerIP.getText()); + }//GEN-LAST:event_txtServerIPFocusLost + + private void cboGameDirTypeFocusLost(java.awt.event.FocusEvent evt) {//GEN-FIRST:event_cboGameDirTypeFocusLost + if (cboGameDirType.getSelectedIndex() >= 0) + profile.setGameDirType(GameDirType.values()[cboGameDirType.getSelectedIndex()]); + }//GEN-LAST:event_cboGameDirTypeFocusLost + + private void cboLauncherVisibilityFocusLost(java.awt.event.FocusEvent evt) {//GEN-FIRST:event_cboLauncherVisibilityFocusLost + if (cboLauncherVisibility.getSelectedIndex() >= 0) + profile.setLauncherVisibility(cboLauncherVisibility.getSelectedIndex()); + }//GEN-LAST:event_cboLauncherVisibilityFocusLost + + private void btnDownloadAllAssetsActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnDownloadAllAssetsActionPerformed + boolean flag = false; + ArrayList al = new ArrayList<>(); + if (minecraftVersion == null) { + MessageBox.Show(C.i18n("mainwindow.no_version")); + return; + } + String s = StrUtils.formatVersion(minecraftVersion.version); + for (IAssetsHandler a : IAssetsHandler.getAssetsHandlers()) { + if (a.isVersionAllowed(s)) { + downloadAssets(a); + return; + } + al.add(a.getName()); + } + if (!flag) { + Selector selector = new Selector(MainFrame.instance, al.toArray(new String[0]), C.i18n("assets.unkown_type_select_one", mcVersion)); + selector.setVisible(true); + if (selector.sel != -1) + downloadAssets(IAssetsHandler.getAssetsHandler(selector.sel)); + } + }//GEN-LAST:event_btnDownloadAllAssetsActionPerformed + + private void txtMaxMemoryFocusLost(java.awt.event.FocusEvent evt) {//GEN-FIRST:event_txtMaxMemoryFocusLost + profile.setMaxMemory(txtMaxMemory.getText()); + }//GEN-LAST:event_txtMaxMemoryFocusLost + + private void txtJavaDirActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_txtJavaDirActionPerformed + // TODO add your handling code here: + }//GEN-LAST:event_txtJavaDirActionPerformed + + private void txtJavaDirFocusLost(java.awt.event.FocusEvent evt) {//GEN-FIRST:event_txtJavaDirFocusLost + profile.setJavaDir(txtJavaDir.getText()); + }//GEN-LAST:event_txtJavaDirFocusLost + + private void chkFullscreenFocusLost(java.awt.event.FocusEvent evt) {//GEN-FIRST:event_chkFullscreenFocusLost + profile.setFullscreen(chkFullscreen.isSelected()); + }//GEN-LAST:event_chkFullscreenFocusLost + + private void txtHeightFocusLost(java.awt.event.FocusEvent evt) {//GEN-FIRST:event_txtHeightFocusLost + profile.setHeight(txtHeight.getText()); + }//GEN-LAST:event_txtHeightFocusLost + + private void txtWidthFocusLost(java.awt.event.FocusEvent evt) {//GEN-FIRST:event_txtWidthFocusLost + profile.setWidth(txtWidth.getText()); + }//GEN-LAST:event_txtWidthFocusLost + + private void txtGameDirFocusLost(java.awt.event.FocusEvent evt) {//GEN-FIRST:event_txtGameDirFocusLost + if (profile == null) return; + profile.setGameDir(txtGameDir.getText()); + loadVersions(); + }//GEN-LAST:event_txtGameDirFocusLost + + // + // + private void loadProfiles() { + isLoading = true; + cboProfiles.removeAllItems(); + Profile firstProfile = null, selectedProfile = null; + int index = 0, i = 0; + for (Profile s : Settings.getProfiles()) { + if (firstProfile == null) firstProfile = s; + cboProfiles.addItem(s.getName()); + if (Settings.s().getLast() != null && Settings.s().getLast().equals(s.getName())) { + index = i; + selectedProfile = s; + } + i++; + } + if (selectedProfile == null) selectedProfile = Settings.getOneProfile(); + + isLoading = false; + if (index < cboProfiles.getItemCount()) { + cboProfiles.setSelectedIndex(index); + profile = selectedProfile; + if (profile == null) profile = firstProfile; + prepare(profile); + loadVersions(); + } + } + + Profile getProfile() { + if (cboProfiles.getSelectedIndex() >= 0) + return Settings.getVersion(cboProfiles.getSelectedItem().toString()); + else return null; + } + + void prepare(Profile profile) { + if (profile == null) return; + txtWidth.setText(profile.getWidth()); + txtHeight.setText(profile.getHeight()); + txtMaxMemory.setText(profile.getMaxMemory()); + txtPermSize.setText(profile.getPermSize()); + txtGameDir.setText(profile.getGameDir()); + txtJavaArgs.setText(profile.getJavaArgs()); + txtMinecraftArgs.setText(profile.getMinecraftArgs()); + txtJavaDir.setText(profile.getJavaDir()); + txtWrapperLauncher.setText(profile.getWrapperLauncher()); + txtServerIP.setText(profile.getServerIp()); + chkDebug.setSelected(profile.isDebug()); + chkNoJVMArgs.setSelected(profile.isNoJVMArgs()); + chkFullscreen.setSelected(profile.isFullscreen()); + chkCancelWrapper.setSelected(profile.isCanceledWrapper()); + cboLauncherVisibility.setSelectedIndex(profile.getLauncherVisibility()); + cboGameDirType.setSelectedIndex(profile.getGameDirType().ordinal()); + + loadVersions(); + loadMinecraftVersion(); + } + + void loadVersions() { + if (profile == null) return; + isLoading = true; + cboVersions.removeAllItems(); + int index = 0, i = 0; + MinecraftVersion selVersion = profile.getSelectedMinecraftVersion(); + String selectedMC = selVersion == null ? null : selVersion.id; + for (MinecraftVersion each : profile.getMinecraftProvider().getVersions()) { + cboVersions.addItem(each.id); + if (each.id.equals(selectedMC)) index = i; + i++; + } + isLoading = false; + if (index < cboVersions.getItemCount()) cboVersions.setSelectedIndex(index); + } + + void loadMinecraftVersion() { + loadMinecraftVersion(profile.getSelectedMinecraftVersion()); + } + + void loadMinecraftVersion(String v) { + loadMinecraftVersion(profile.getMinecraftProvider().getVersionById(v)); + } + + /** + * Anaylze the jar of selected minecraft version of current profile to get + * the version. + * + * @param v + */ + void loadMinecraftVersion(MinecraftVersion v) { + txtMinecraftVersion.setText(""); + if (v == null) return; + File minecraftJar = v.getJar(profile.getGameDirFile()); + minecraftVersion = MCUtils.minecraftVersion(minecraftJar); + txtMinecraftVersion.setText(MinecraftVersionRequest.getResponse(minecraftVersion)); + } + // + // + public int assetsType; + + private void downloadAssets(final IAssetsHandler type) { + if (mcVersion == null || profile == null) return; + type.getList((value) -> { + if (value != null) + TaskWindow.getInstance().addTask(type.getDownloadTask(Settings.s().getDownloadSource().getProvider())).start(); + }); + } + + // + // + public void refreshDownloads(final DownloadType provider) { + TaskWindow.getInstance().addTask(new Task() { + HTTPGetTask tsk = new HTTPGetTask(provider.getProvider().getVersionsListDownloadURL()); + + @Override + public boolean executeTask() { + final MinecraftRemoteVersions v = MinecraftRemoteVersions.fromJson(tsk.getResult()); + if (v == null || v.versions == null) + return true; + SwingUtilities.invokeLater(() -> { + DefaultTableModel model = (DefaultTableModel) lstDownloads.getModel(); + while (model.getRowCount() > 0) model.removeRow(0); + for (MinecraftRemoteVersion ver : v.versions) { + Object[] line = new Object[3]; + line[0] = ver.id; + line[1] = ver.time; + if (StrUtils.equalsOne(ver.type, "old_beta", "old_alpha", "release", "snapshot")) + line[2] = C.i18n("versions." + ver.type); + else line[2] = ver.type; + model.addRow(line); + } + lstDownloads.updateUI(); + }); + return true; + } + + @Override + public String getInfo() { + return "Format list."; + } + + @Override + public Collection getDependTasks() { + return Arrays.asList((Task) tsk); + } + }).start(); + } + + void downloadMinecraft(DownloadType index) { + if (profile == null) return; + if (lstDownloads.getSelectedRow() < 0) + refreshDownloads(Settings.s().getDownloadSource()); + if (lstDownloads.getSelectedRow() < 0) { + MessageBox.Show(C.i18n("gamedownload.not_refreshed")); + return; + } + String id = (String) lstDownloads.getModel().getValueAt(lstDownloads.getSelectedRow(), 0); + MCUtils.downloadMinecraft(profile.getGameDirFile(), id, index); + } + + // + // + private String getMinecraftVersionFormatted() { + return minecraftVersion == null ? "" : (StrUtils.formatVersion(minecraftVersion.version) == null) ? mcVersion : minecraftVersion.version; + } + + class InstallerHelper { + List versions; + InstallerVersionList list; + JTable jt; + String id; + + public InstallerHelper(JTable jt, String id) { + this.jt = jt; + this.id = id; + } + + public void loadVersions() { + versions = loadVersions(list, jt); + } + + void refreshVersions() { + list = Settings.s().getDownloadSource().getProvider().getInstallerByType(id); + if (TaskWindow.getInstance().addTask(new TaskRunnableArg1<>(C.i18n("install." + id + ".get_list"), list) + .registerPreviousResult(new DefaultPreviousResult<>(new String[]{getMinecraftVersionFormatted()}))) + .start()) + loadVersions(); + } + + public InstallerVersion getVersion(int idx) { + return versions.get(idx); + } + + private List loadVersions(InstallerVersionList list, JTable table) { + if (list == null) + return null; + DefaultTableModel model = (DefaultTableModel) table.getModel(); + while (model.getRowCount() > 0) + model.removeRow(0); + String mcver = StrUtils.formatVersion(getMinecraftVersionFormatted()); + List versions = list.getVersions(mcver); + if (versions != null) { + for (InstallerVersionList.InstallerVersion v : versions) { + Object a = v.selfVersion == null ? "null" : v.selfVersion; + Object b = v.mcVersion == null ? "null" : v.mcVersion; + Object[] row = new Object[]{a, b}; + model.addRow(row); + } + table.updateUI(); + } + return versions; + } + } + + private void refreshVersions() { + getProfile().getMinecraftProvider().refreshVersions(); + loadVersions(); + } + + // + // + boolean isLoading = false; + Profile profile; + public MinecraftVersionRequest minecraftVersion; + InstallerHelper forge, optifine, liteloader; + String mcVersion; + + // + + // + public void versionChanged(Profile profile, String version) { + this.mcVersion = version; + forge.loadVersions(); + optifine.loadVersions(); + liteloader.loadVersions(); + + MinecraftVersion v = profile.getMinecraftProvider().getVersionById(version); + if (v != null) + for (IAssetsHandler ph : IAssetsHandler.getAssetsHandlers()) + try { + ph.setAssets(profile.getMinecraftProvider(), v); + } catch (Exception e) { + HMCLog.warn("Failed to load assets", e); + } + } + + public void onSelected() { + loadProfiles(); + if (profile == null) return; + if (profile.getMinecraftProvider().getVersionCount() <= 0) + versionChanged(profile, null); + else versionChanged(getProfile(), (String) cboVersions.getSelectedItem()); + } + + // + JPopupMenu ppmManage, ppmExplore; + // Variables declaration - do not modify//GEN-BEGIN:variables + private javax.swing.JButton btnDownload; + private javax.swing.JButton btnDownloadAllAssets; + private javax.swing.JButton btnDownloadForge; + private javax.swing.JButton btnDownloadOptifine; + private javax.swing.JButton btnExplore; + private javax.swing.JButton btnIncludeMinecraft; + private javax.swing.JButton btnInstallLiteLoader; + private javax.swing.JButton btnModify; + private javax.swing.JButton btnNewProfile; + private javax.swing.JButton btnRefreshForge; + private javax.swing.JButton btnRefreshGameDownloads; + private javax.swing.JButton btnRefreshLiteLoader; + private javax.swing.JButton btnRefreshOptifine; + private javax.swing.JButton btnRefreshVersions; + private javax.swing.JButton btnRemoveProfile; + private javax.swing.JButton btnRetryForge; + private javax.swing.JButton btnRetryLiteLoader; + private javax.swing.JComboBox cboGameDirType; + private javax.swing.JComboBox cboLauncherVisibility; + private javax.swing.JComboBox cboProfiles; + private javax.swing.JComboBox cboVersions; + private javax.swing.JCheckBox chkCancelWrapper; + private javax.swing.JCheckBox chkDebug; + private javax.swing.JCheckBox chkFullscreen; + private javax.swing.JCheckBox chkNoJVMArgs; + private javax.swing.JLabel jLabel1; + private javax.swing.JLabel jLabel10; + private javax.swing.JLabel jLabel11; + private javax.swing.JLabel jLabel12; + private javax.swing.JLabel jLabel2; + private javax.swing.JLabel jLabel24; + private javax.swing.JLabel jLabel25; + private javax.swing.JLabel jLabel26; + private javax.swing.JLabel jLabel27; + private javax.swing.JLabel jLabel28; + private javax.swing.JLabel jLabel29; + private javax.swing.JLabel jLabel30; + private javax.swing.JLabel jLabel31; + private javax.swing.JLabel jLabel9; + private javax.swing.JPanel jPanel1; + private javax.swing.JPanel jPanel16; + private javax.swing.JPanel jPanel2; + private javax.swing.JPanel jPanel22; + private javax.swing.JPanel jPanel3; + private javax.swing.JPanel jPanel4; + private javax.swing.JPanel jPanel5; + private javax.swing.JScrollPane jScrollPane11; + private javax.swing.JScrollPane jScrollPane12; + private javax.swing.JScrollPane jScrollPane13; + private javax.swing.JScrollPane jScrollPane2; + private javax.swing.JLabel lblMaxMemory; + private javax.swing.JTable lstDownloads; + private javax.swing.JTable lstForge; + private javax.swing.JTable lstLiteLoader; + private javax.swing.JTable lstOptifine; + private javax.swing.JPanel pnlAutoInstall; + private javax.swing.JPanel pnlGameDownloads; + private javax.swing.JPanel pnlOptifine; + private javax.swing.JTabbedPane tabInstallers; + private javax.swing.JTabbedPane tabVersionEdit; + private javax.swing.JTextField txtGameDir; + private javax.swing.JTextField txtHeight; + private javax.swing.JTextField txtJavaArgs; + private javax.swing.JTextField txtJavaDir; + private javax.swing.JTextField txtMaxMemory; + private javax.swing.JTextField txtMinecraftArgs; + private javax.swing.JTextField txtMinecraftVersion; + private javax.swing.JTextField txtPermSize; + private javax.swing.JTextField txtServerIP; + private javax.swing.JTextField txtWidth; + private javax.swing.JTextField txtWrapperLauncher; + // End of variables declaration//GEN-END:variables + // +} diff --git a/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/views/HeaderTab.java b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/views/HeaderTab.java new file mode 100644 index 000000000..1e4f2171a --- /dev/null +++ b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/views/HeaderTab.java @@ -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); + } +} diff --git a/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/views/LauncherSettingsPanel.form b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/views/LauncherSettingsPanel.form new file mode 100644 index 000000000..8f5af0159 --- /dev/null +++ b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/views/LauncherSettingsPanel.form @@ -0,0 +1,178 @@ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/views/LauncherSettingsPanel.java b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/views/LauncherSettingsPanel.java new file mode 100644 index 000000000..4cc8fd676 --- /dev/null +++ b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/views/LauncherSettingsPanel.java @@ -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") + // //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()) + ); + }// //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 +} diff --git a/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/views/MainFrame.java b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/views/MainFrame.java new file mode 100644 index 000000000..b0a3fc8ba --- /dev/null +++ b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/views/MainFrame.java @@ -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); + } + } + +} diff --git a/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/views/MainPagePanel.form b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/views/MainPagePanel.form new file mode 100644 index 000000000..dbf9f9ed4 --- /dev/null +++ b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/views/MainPagePanel.form @@ -0,0 +1,280 @@ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/views/MainPagePanel.java b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/views/MainPagePanel.java new file mode 100644 index 000000000..98a1fea68 --- /dev/null +++ b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/views/MainPagePanel.java @@ -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") + // //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); + }// //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 + + // + void genLaunchCode(final Consumer 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(); + } + // + + // + private void prepareAuths() { + preaparingAuth = true; + List 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(); + } + // + + // + 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; + // + + class PrepareAuthDoneListener implements Event> { + + @Override + public boolean call(Object sender, List 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 +} diff --git a/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/views/NewProfileWindow.form b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/views/NewProfileWindow.form new file mode 100644 index 000000000..65e0f21bf --- /dev/null +++ b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/views/NewProfileWindow.form @@ -0,0 +1,124 @@ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/views/NewProfileWindow.java b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/views/NewProfileWindow.java new file mode 100644 index 000000000..69f2839ff --- /dev/null +++ b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/views/NewProfileWindow.java @@ -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") + // //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(); + }// //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 +} diff --git a/HMCL/src/main/java/org/jackhuang/mojang/authlib/Agent.java b/HMCL/src/main/java/org/jackhuang/mojang/authlib/Agent.java new file mode 100644 index 000000000..a83b0f678 --- /dev/null +++ b/HMCL/src/main/java/org/jackhuang/mojang/authlib/Agent.java @@ -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 + '}'; + } + +} \ No newline at end of file diff --git a/HMCL/src/main/java/org/jackhuang/mojang/authlib/AuthenticationService.java b/HMCL/src/main/java/org/jackhuang/mojang/authlib/AuthenticationService.java new file mode 100644 index 000000000..8776477a9 --- /dev/null +++ b/HMCL/src/main/java/org/jackhuang/mojang/authlib/AuthenticationService.java @@ -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(); +} diff --git a/HMCL/src/main/java/org/jackhuang/mojang/authlib/BaseAuthenticationService.java b/HMCL/src/main/java/org/jackhuang/mojang/authlib/BaseAuthenticationService.java new file mode 100644 index 000000000..3b484d3c4 --- /dev/null +++ b/HMCL/src/main/java/org/jackhuang/mojang/authlib/BaseAuthenticationService.java @@ -0,0 +1,5 @@ +package org.jackhuang.mojang.authlib; + +public abstract class BaseAuthenticationService + implements AuthenticationService { +} diff --git a/HMCL/src/main/java/org/jackhuang/mojang/authlib/BaseUserAuthentication.java b/HMCL/src/main/java/org/jackhuang/mojang/authlib/BaseUserAuthentication.java new file mode 100644 index 000000000..19fbe0a1e --- /dev/null +++ b/HMCL/src/main/java/org/jackhuang/mojang/authlib/BaseUserAuthentication.java @@ -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 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 list = (List) 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 list = (List) 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 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; + } +} \ No newline at end of file diff --git a/HMCL/src/main/java/org/jackhuang/mojang/authlib/GameProfile.java b/HMCL/src/main/java/org/jackhuang/mojang/authlib/GameProfile.java new file mode 100644 index 000000000..5475f5f3a --- /dev/null +++ b/HMCL/src/main/java/org/jackhuang/mojang/authlib/GameProfile.java @@ -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; + } +} \ No newline at end of file diff --git a/HMCL/src/main/java/org/jackhuang/mojang/authlib/GameProfileRepository.java b/HMCL/src/main/java/org/jackhuang/mojang/authlib/GameProfileRepository.java new file mode 100644 index 000000000..7b7eccfe3 --- /dev/null +++ b/HMCL/src/main/java/org/jackhuang/mojang/authlib/GameProfileRepository.java @@ -0,0 +1,6 @@ +package org.jackhuang.mojang.authlib; + +public abstract interface GameProfileRepository { + + public abstract void findProfilesByNames(String[] paramArrayOfString, Agent paramAgent, ProfileLookupCallback paramProfileLookupCallback); +} diff --git a/HMCL/src/main/java/org/jackhuang/mojang/authlib/HttpAuthenticationService.java b/HMCL/src/main/java/org/jackhuang/mojang/authlib/HttpAuthenticationService.java new file mode 100644 index 000000000..754b1917a --- /dev/null +++ b/HMCL/src/main/java/org/jackhuang/mojang/authlib/HttpAuthenticationService.java @@ -0,0 +1,153 @@ +package org.jackhuang.mojang.authlib; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.UnsupportedEncodingException; +import java.net.HttpURLConnection; +import java.net.Proxy; +import java.net.URL; +import java.net.URLEncoder; +import java.util.Map; +import org.jackhuang.hellominecraft.logging.logger.Logger; +import org.jackhuang.hellominecraft.utils.IOUtils; +import org.jackhuang.hellominecraft.utils.NetUtils; +import org.jackhuang.hellominecraft.utils.Validate; + +public abstract class HttpAuthenticationService extends BaseAuthenticationService { + + private static final Logger LOGGER = new Logger("HttpAuthenticationService"); + private final Proxy proxy; + + protected HttpAuthenticationService(Proxy proxy) { + Validate.notNull(proxy); + this.proxy = proxy; + } + + public Proxy getProxy() { + return this.proxy; + } + + protected HttpURLConnection createUrlConnection(URL url) throws IOException { + Validate.notNull(url); + LOGGER.debug(new StringBuilder().append("Opening connection to ").append(url).toString()); + HttpURLConnection connection = (HttpURLConnection) url.openConnection(this.proxy); + connection.setConnectTimeout(15000); + connection.setReadTimeout(15000); + connection.setUseCaches(false); + return connection; + } + + public String performPostRequest(URL url, String post, String contentType) throws IOException { + Validate.notNull(url); + Validate.notNull(post); + Validate.notNull(contentType); + HttpURLConnection connection = createUrlConnection(url); + byte[] postAsBytes = post.getBytes("UTF-8"); + + connection.setRequestProperty("Content-Type", new StringBuilder().append(contentType).append("; charset=utf-8").toString()); + connection.setRequestProperty("Content-Length", new StringBuilder().append("").append(postAsBytes.length).toString()); + connection.setDoOutput(true); + + LOGGER.debug(new StringBuilder().append("Writing POST data to ").append(url).append(": ").append(post).toString()); + + OutputStream outputStream = null; + try { + outputStream = connection.getOutputStream(); + IOUtils.write(postAsBytes, outputStream); + } finally { + IOUtils.closeQuietly(outputStream); + } + + LOGGER.debug(new StringBuilder().append("Reading data from ").append(url).toString()); + + InputStream inputStream = null; + try { + inputStream = connection.getInputStream(); + String result = NetUtils.getStreamContent(inputStream, "UTF-8"); + LOGGER.debug(new StringBuilder().append("Successful read, server response was ").append(connection.getResponseCode()).toString()); + LOGGER.debug(new StringBuilder().append("Response: ").append(result).toString()); + String str1 = result; + return str1; + } catch (IOException e) { + IOUtils.closeQuietly(inputStream); + inputStream = connection.getErrorStream(); + + if (inputStream != null) { + LOGGER.debug(new StringBuilder().append("Reading error page from ").append(url).toString()); + String result = NetUtils.getStreamContent(inputStream, "UTF-8"); + LOGGER.debug(new StringBuilder().append("Successful read, server response was ").append(connection.getResponseCode()).toString()); + LOGGER.debug(new StringBuilder().append("Response: ").append(result).toString()); + String str2 = result; + return str2; + } + LOGGER.debug("Request failed", e); + throw e; + } finally { + IOUtils.closeQuietly(inputStream); + } + } + + public String performGetRequest(URL url) + throws IOException { + Validate.notNull(url); + HttpURLConnection connection = createUrlConnection(url); + + LOGGER.debug(new StringBuilder().append("Reading data from ").append(url).toString()); + + InputStream inputStream = null; + try { + inputStream = connection.getInputStream(); + String result = NetUtils.getStreamContent(inputStream, "UTF-8"); + LOGGER.debug(new StringBuilder().append("Successful read, server response was ").append(connection.getResponseCode()).toString()); + LOGGER.debug(new StringBuilder().append("Response: ").append(result).toString()); + String str1 = result; + return str1; + } catch (IOException e) { + IOUtils.closeQuietly(inputStream); + inputStream = connection.getErrorStream(); + + if (inputStream != null) { + LOGGER.debug(new StringBuilder().append("Reading error page from ").append(url).toString()); + String result = NetUtils.getStreamContent(inputStream, "UTF-8"); + LOGGER.debug(new StringBuilder().append("Successful read, server response was ").append(connection.getResponseCode()).toString()); + LOGGER.debug(new StringBuilder().append("Response: ").append(result).toString()); + String str2 = result; + return str2; + } + LOGGER.debug("Request failed", e); + throw e; + } finally { + IOUtils.closeQuietly(inputStream); + } + } + + public static String buildQuery(Map query) { + if (query == null) { + return ""; + } + StringBuilder builder = new StringBuilder(); + + for (Map.Entry entry : query.entrySet()) { + if (builder.length() > 0) { + builder.append('&'); + } + try { + builder.append(URLEncoder.encode((String) entry.getKey(), "UTF-8")); + } catch (UnsupportedEncodingException e) { + LOGGER.error("Unexpected exception building query", e); + } + + if (entry.getValue() != null) { + builder.append('='); + try { + builder.append(URLEncoder.encode(entry.getValue().toString(), "UTF-8")); + } catch (UnsupportedEncodingException e) { + LOGGER.error("Unexpected exception building query", e); + } + } + } + + return builder.toString(); + } +} \ No newline at end of file diff --git a/HMCL/src/main/java/org/jackhuang/mojang/authlib/HttpUserAuthentication.java b/HMCL/src/main/java/org/jackhuang/mojang/authlib/HttpUserAuthentication.java new file mode 100644 index 000000000..27b7027f9 --- /dev/null +++ b/HMCL/src/main/java/org/jackhuang/mojang/authlib/HttpUserAuthentication.java @@ -0,0 +1,13 @@ +package org.jackhuang.mojang.authlib; + +public abstract class HttpUserAuthentication extends BaseUserAuthentication { + + protected HttpUserAuthentication(HttpAuthenticationService authenticationService) { + super(authenticationService); + } + + @Override + public HttpAuthenticationService getAuthenticationService() { + return (HttpAuthenticationService) super.getAuthenticationService(); + } +} diff --git a/HMCL/src/main/java/org/jackhuang/mojang/authlib/ProfileLookupCallback.java b/HMCL/src/main/java/org/jackhuang/mojang/authlib/ProfileLookupCallback.java new file mode 100644 index 000000000..335a118f2 --- /dev/null +++ b/HMCL/src/main/java/org/jackhuang/mojang/authlib/ProfileLookupCallback.java @@ -0,0 +1,8 @@ +package org.jackhuang.mojang.authlib; + +public abstract interface ProfileLookupCallback { + + public abstract void onProfileLookupSucceeded(GameProfile paramGameProfile); + + public abstract void onProfileLookupFailed(GameProfile paramGameProfile, Exception paramException); +} diff --git a/HMCL/src/main/java/org/jackhuang/mojang/authlib/UserAuthentication.java b/HMCL/src/main/java/org/jackhuang/mojang/authlib/UserAuthentication.java new file mode 100644 index 000000000..1069ff8f1 --- /dev/null +++ b/HMCL/src/main/java/org/jackhuang/mojang/authlib/UserAuthentication.java @@ -0,0 +1,42 @@ +package org.jackhuang.mojang.authlib; + +import org.jackhuang.mojang.authlib.exceptions.AuthenticationException; +import org.jackhuang.mojang.authlib.properties.PropertyMap; +import java.util.Map; + +public abstract interface UserAuthentication { + + public abstract boolean canLogIn(); + + public abstract void logIn() + throws AuthenticationException; + + public abstract void logOut(); + + public abstract boolean isLoggedIn(); + + public abstract boolean canPlayOnline(); + + public abstract GameProfile[] getAvailableProfiles(); + + public abstract GameProfile getSelectedProfile(); + + public abstract void selectGameProfile(GameProfile paramGameProfile) + throws AuthenticationException; + + public abstract void loadFromStorage(Map paramMap); + + public abstract Map saveForStorage(); + + public abstract void setUsername(String paramString); + + public abstract void setPassword(String paramString); + + public abstract String getAuthenticatedToken(); + + public abstract String getUserID(); + + public abstract PropertyMap getUserProperties(); + + public abstract UserType getUserType(); +} diff --git a/HMCL/src/main/java/org/jackhuang/mojang/authlib/UserType.java b/HMCL/src/main/java/org/jackhuang/mojang/authlib/UserType.java new file mode 100644 index 000000000..7896022bb --- /dev/null +++ b/HMCL/src/main/java/org/jackhuang/mojang/authlib/UserType.java @@ -0,0 +1,33 @@ +package org.jackhuang.mojang.authlib; + +import java.util.HashMap; +import java.util.Map; + +public enum UserType { + + LEGACY("legacy"), + MOJANG("mojang"); + + private static final Map BY_NAME; + private final String name; + + private UserType(String name) { + this.name = name; + } + + public static UserType byName(String name) { + return (UserType) BY_NAME.get(name.toLowerCase()); + } + + public String getName() { + return this.name; + } + + static { + BY_NAME = new HashMap(); + + for (UserType type : values()) { + BY_NAME.put(type.name, type); + } + } +} \ No newline at end of file diff --git a/HMCL/src/main/java/org/jackhuang/mojang/authlib/exceptions/AuthenticationException.java b/HMCL/src/main/java/org/jackhuang/mojang/authlib/exceptions/AuthenticationException.java new file mode 100644 index 000000000..e76598982 --- /dev/null +++ b/HMCL/src/main/java/org/jackhuang/mojang/authlib/exceptions/AuthenticationException.java @@ -0,0 +1,19 @@ +package org.jackhuang.mojang.authlib.exceptions; + +public class AuthenticationException extends Exception { + + public AuthenticationException() { + } + + public AuthenticationException(String message) { + super(message); + } + + public AuthenticationException(String message, Throwable cause) { + super(message, cause); + } + + public AuthenticationException(Throwable cause) { + super(cause); + } +} diff --git a/HMCL/src/main/java/org/jackhuang/mojang/authlib/exceptions/AuthenticationUnavailableException.java b/HMCL/src/main/java/org/jackhuang/mojang/authlib/exceptions/AuthenticationUnavailableException.java new file mode 100644 index 000000000..f26dcda70 --- /dev/null +++ b/HMCL/src/main/java/org/jackhuang/mojang/authlib/exceptions/AuthenticationUnavailableException.java @@ -0,0 +1,19 @@ +package org.jackhuang.mojang.authlib.exceptions; + +public class AuthenticationUnavailableException extends AuthenticationException { + + public AuthenticationUnavailableException() { + } + + public AuthenticationUnavailableException(String message) { + super(message); + } + + public AuthenticationUnavailableException(String message, Throwable cause) { + super(message, cause); + } + + public AuthenticationUnavailableException(Throwable cause) { + super(cause); + } +} diff --git a/HMCL/src/main/java/org/jackhuang/mojang/authlib/exceptions/InvalidCredentialsException.java b/HMCL/src/main/java/org/jackhuang/mojang/authlib/exceptions/InvalidCredentialsException.java new file mode 100644 index 000000000..5b37162b1 --- /dev/null +++ b/HMCL/src/main/java/org/jackhuang/mojang/authlib/exceptions/InvalidCredentialsException.java @@ -0,0 +1,19 @@ +package org.jackhuang.mojang.authlib.exceptions; + +public class InvalidCredentialsException extends AuthenticationException { + + public InvalidCredentialsException() { + } + + public InvalidCredentialsException(String message) { + super(message); + } + + public InvalidCredentialsException(String message, Throwable cause) { + super(message, cause); + } + + public InvalidCredentialsException(Throwable cause) { + super(cause); + } +} diff --git a/HMCL/src/main/java/org/jackhuang/mojang/authlib/exceptions/UserMigratedException.java b/HMCL/src/main/java/org/jackhuang/mojang/authlib/exceptions/UserMigratedException.java new file mode 100644 index 000000000..0093630d2 --- /dev/null +++ b/HMCL/src/main/java/org/jackhuang/mojang/authlib/exceptions/UserMigratedException.java @@ -0,0 +1,19 @@ +package org.jackhuang.mojang.authlib.exceptions; + +public class UserMigratedException extends InvalidCredentialsException { + + public UserMigratedException() { + } + + public UserMigratedException(String message) { + super(message); + } + + public UserMigratedException(String message, Throwable cause) { + super(message, cause); + } + + public UserMigratedException(Throwable cause) { + super(cause); + } +} diff --git a/HMCL/src/main/java/org/jackhuang/mojang/authlib/minecraft/BaseMinecraftSessionService.java b/HMCL/src/main/java/org/jackhuang/mojang/authlib/minecraft/BaseMinecraftSessionService.java new file mode 100644 index 000000000..b4ed7691d --- /dev/null +++ b/HMCL/src/main/java/org/jackhuang/mojang/authlib/minecraft/BaseMinecraftSessionService.java @@ -0,0 +1,17 @@ +package org.jackhuang.mojang.authlib.minecraft; + +import org.jackhuang.mojang.authlib.AuthenticationService; + +public abstract class BaseMinecraftSessionService + implements MinecraftSessionService { + + private final AuthenticationService authenticationService; + + protected BaseMinecraftSessionService(AuthenticationService authenticationService) { + this.authenticationService = authenticationService; + } + + public AuthenticationService getAuthenticationService() { + return this.authenticationService; + } +} diff --git a/HMCL/src/main/java/org/jackhuang/mojang/authlib/minecraft/HttpMinecraftSessionService.java b/HMCL/src/main/java/org/jackhuang/mojang/authlib/minecraft/HttpMinecraftSessionService.java new file mode 100644 index 000000000..1f367b20b --- /dev/null +++ b/HMCL/src/main/java/org/jackhuang/mojang/authlib/minecraft/HttpMinecraftSessionService.java @@ -0,0 +1,15 @@ +package org.jackhuang.mojang.authlib.minecraft; + +import org.jackhuang.mojang.authlib.HttpAuthenticationService; + +public abstract class HttpMinecraftSessionService extends BaseMinecraftSessionService { + + protected HttpMinecraftSessionService(HttpAuthenticationService authenticationService) { + super(authenticationService); + } + + @Override + public HttpAuthenticationService getAuthenticationService() { + return (HttpAuthenticationService) super.getAuthenticationService(); + } +} diff --git a/HMCL/src/main/java/org/jackhuang/mojang/authlib/minecraft/MinecraftSessionService.java b/HMCL/src/main/java/org/jackhuang/mojang/authlib/minecraft/MinecraftSessionService.java new file mode 100644 index 000000000..5041967be --- /dev/null +++ b/HMCL/src/main/java/org/jackhuang/mojang/authlib/minecraft/MinecraftSessionService.java @@ -0,0 +1,16 @@ +package org.jackhuang.mojang.authlib.minecraft; + +import org.jackhuang.mojang.authlib.GameProfile; +import org.jackhuang.mojang.authlib.exceptions.AuthenticationException; +import org.jackhuang.mojang.authlib.exceptions.AuthenticationUnavailableException; + +public abstract interface MinecraftSessionService { + + public abstract void joinServer(GameProfile paramGameProfile, String paramString1, String paramString2) + throws AuthenticationException; + + public abstract GameProfile hasJoinedServer(GameProfile paramGameProfile, String paramString) + throws AuthenticationUnavailableException; + + public abstract GameProfile fillProfileProperties(GameProfile paramGameProfile, boolean paramBoolean); +} diff --git a/HMCL/src/main/java/org/jackhuang/mojang/authlib/properties/Property.java b/HMCL/src/main/java/org/jackhuang/mojang/authlib/properties/Property.java new file mode 100644 index 000000000..1d5266969 --- /dev/null +++ b/HMCL/src/main/java/org/jackhuang/mojang/authlib/properties/Property.java @@ -0,0 +1,57 @@ +package org.jackhuang.mojang.authlib.properties; + +import java.security.InvalidKeyException; +import java.security.NoSuchAlgorithmException; +import java.security.PublicKey; +import java.security.Signature; +import java.security.SignatureException; +import org.jackhuang.hellominecraft.utils.Base64; + +public class Property { + + private final String name; + private final String value; + private final String signature; + + public Property(String value, String name) { + this(value, name, null); + } + + public Property(String name, String value, String signature) { + this.name = name; + this.value = value; + this.signature = signature; + } + + public String getName() { + return this.name; + } + + public String getValue() { + return this.value; + } + + public String getSignature() { + return this.signature; + } + + public boolean hasSignature() { + return this.signature != null; + } + + public boolean isSignatureValid(PublicKey publicKey) { + try { + Signature signature = Signature.getInstance("SHA1withRSA"); + signature.initVerify(publicKey); + signature.update(this.value.getBytes()); + return signature.verify(Base64.decode(this.signature.toCharArray())); + } catch (NoSuchAlgorithmException e) { + e.printStackTrace(); + } catch (InvalidKeyException e) { + e.printStackTrace(); + } catch (SignatureException e) { + e.printStackTrace(); + } + return false; + } +} diff --git a/HMCL/src/main/java/org/jackhuang/mojang/authlib/properties/PropertyMap.java b/HMCL/src/main/java/org/jackhuang/mojang/authlib/properties/PropertyMap.java new file mode 100644 index 000000000..c5bd1868b --- /dev/null +++ b/HMCL/src/main/java/org/jackhuang/mojang/authlib/properties/PropertyMap.java @@ -0,0 +1,79 @@ +package org.jackhuang.mojang.authlib.properties; + +import com.google.gson.JsonArray; +import com.google.gson.JsonDeserializationContext; +import com.google.gson.JsonDeserializer; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonParseException; +import com.google.gson.JsonSerializationContext; +import com.google.gson.JsonSerializer; +import java.lang.reflect.Type; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; + +public class PropertyMap extends HashMap { + + public PropertyMap() { + } + + public static class Serializer implements JsonSerializer, JsonDeserializer { + + @Override + public PropertyMap deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { + PropertyMap result = new PropertyMap(); + Iterator i$; + Map.Entry entry; + if ((json instanceof JsonObject)) { + JsonObject object = (JsonObject) json; + + for (i$ = object.entrySet().iterator(); i$.hasNext();) { + entry = (Map.Entry) i$.next(); + if ((entry.getValue() instanceof JsonArray)) { + for (JsonElement element : (JsonArray) entry.getValue()) { + result.put(entry.getKey(), + new Property((String) entry.getKey(), element.getAsString())); + } + } + } + } else if ((json instanceof JsonArray)) { + for (JsonElement element : (JsonArray) json) { + if ((element instanceof JsonObject)) { + JsonObject object = (JsonObject) element; + String name = object.getAsJsonPrimitive("name").getAsString(); + String value = object.getAsJsonPrimitive("value").getAsString(); + + if (object.has("signature")) { + result.put(name, new Property(name, value, object.getAsJsonPrimitive("signature").getAsString())); + } else { + result.put(name, new Property(name, value)); + } + } + } + } + + return result; + } + + @Override + public JsonElement serialize(PropertyMap src, Type typeOfSrc, JsonSerializationContext context) { + JsonArray result = new JsonArray(); + + for (Property property : src.values()) { + JsonObject object = new JsonObject(); + + object.addProperty("name", property.getName()); + object.addProperty("value", property.getValue()); + + if (property.hasSignature()) { + object.addProperty("signature", property.getSignature()); + } + + result.add(object); + } + + return result; + } + } +} \ No newline at end of file diff --git a/HMCL/src/main/java/org/jackhuang/mojang/authlib/yggdrasil/ProfileIncompleteException.java b/HMCL/src/main/java/org/jackhuang/mojang/authlib/yggdrasil/ProfileIncompleteException.java new file mode 100644 index 000000000..499092168 --- /dev/null +++ b/HMCL/src/main/java/org/jackhuang/mojang/authlib/yggdrasil/ProfileIncompleteException.java @@ -0,0 +1,19 @@ +package org.jackhuang.mojang.authlib.yggdrasil; + +public class ProfileIncompleteException extends RuntimeException { + + public ProfileIncompleteException() { + } + + public ProfileIncompleteException(String message) { + super(message); + } + + public ProfileIncompleteException(String message, Throwable cause) { + super(message, cause); + } + + public ProfileIncompleteException(Throwable cause) { + super(cause); + } +} diff --git a/HMCL/src/main/java/org/jackhuang/mojang/authlib/yggdrasil/ProfileNotFoundException.java b/HMCL/src/main/java/org/jackhuang/mojang/authlib/yggdrasil/ProfileNotFoundException.java new file mode 100644 index 000000000..07a12a3e5 --- /dev/null +++ b/HMCL/src/main/java/org/jackhuang/mojang/authlib/yggdrasil/ProfileNotFoundException.java @@ -0,0 +1,19 @@ +package org.jackhuang.mojang.authlib.yggdrasil; + +public class ProfileNotFoundException extends RuntimeException { + + public ProfileNotFoundException() { + } + + public ProfileNotFoundException(String message) { + super(message); + } + + public ProfileNotFoundException(String message, Throwable cause) { + super(message, cause); + } + + public ProfileNotFoundException(Throwable cause) { + super(cause); + } +} diff --git a/HMCL/src/main/java/org/jackhuang/mojang/authlib/yggdrasil/YggdrasilAuthenticationService.java b/HMCL/src/main/java/org/jackhuang/mojang/authlib/yggdrasil/YggdrasilAuthenticationService.java new file mode 100644 index 000000000..83d6214b2 --- /dev/null +++ b/HMCL/src/main/java/org/jackhuang/mojang/authlib/yggdrasil/YggdrasilAuthenticationService.java @@ -0,0 +1,118 @@ +package org.jackhuang.mojang.authlib.yggdrasil; + +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import com.google.gson.JsonDeserializationContext; +import com.google.gson.JsonDeserializer; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonParseException; +import com.google.gson.JsonSerializationContext; +import com.google.gson.JsonSerializer; +import org.jackhuang.mojang.authlib.Agent; +import org.jackhuang.mojang.authlib.GameProfile; +import org.jackhuang.mojang.authlib.GameProfileRepository; +import org.jackhuang.mojang.authlib.HttpAuthenticationService; +import org.jackhuang.mojang.authlib.UserAuthentication; +import org.jackhuang.mojang.authlib.exceptions.AuthenticationException; +import org.jackhuang.mojang.authlib.exceptions.AuthenticationUnavailableException; +import org.jackhuang.mojang.authlib.exceptions.InvalidCredentialsException; +import org.jackhuang.mojang.authlib.exceptions.UserMigratedException; +import org.jackhuang.mojang.authlib.minecraft.MinecraftSessionService; +import org.jackhuang.mojang.authlib.properties.PropertyMap; +import org.jackhuang.mojang.authlib.yggdrasil.response.Response; +import org.jackhuang.mojang.util.UUIDTypeAdapter; +import java.io.IOException; +import java.lang.reflect.Type; +import java.net.Proxy; +import java.net.URL; +import java.util.UUID; +import org.jackhuang.hellominecraft.C; +import org.jackhuang.hellominecraft.utils.StrUtils; + +public class YggdrasilAuthenticationService extends HttpAuthenticationService { + + private final String clientToken; + private final Gson gson; + + public YggdrasilAuthenticationService(Proxy proxy, String clientToken) { + super(proxy); + this.clientToken = clientToken; + GsonBuilder builder = new GsonBuilder(); + builder.registerTypeAdapter(GameProfile.class, new GameProfileSerializer()); + builder.registerTypeAdapter(PropertyMap.class, new PropertyMap.Serializer()); + builder.registerTypeAdapter(UUID.class, new UUIDTypeAdapter()); + this.gson = builder.create(); + } + + @Override + public UserAuthentication createUserAuthentication(Agent agent) { + return new YggdrasilUserAuthentication(this, agent); + } + + @Override + public MinecraftSessionService createMinecraftSessionService() { + return new YggdrasilMinecraftSessionService(this); + } + + @Override + public GameProfileRepository createProfileRepository() { + return new YggdrasilGameProfileRepository(this); + } + + protected T makeRequest(URL url, Object input, Class classOfT) throws AuthenticationException { + try { + String jsonResult = input == null ? performGetRequest(url) : performPostRequest(url, this.gson.toJson(input), "application/json"); + Response result = (Response) this.gson.fromJson(jsonResult, classOfT); + + if (result == null) { + return null; + } + + if (StrUtils.isNotBlank(result.getError())) { + if ("UserMigratedException".equals(result.getCause())) { + throw new UserMigratedException(result.getErrorMessage()); + } + if (result.getError().equals("ForbiddenOperationException")) { + throw new InvalidCredentialsException(result.getErrorMessage()); + } + throw new AuthenticationException(result.getErrorMessage()); + } + + return (T) result; + } catch (IOException e) { + throw new AuthenticationUnavailableException(C.i18n("login.failed.connect_authentication_server"), e); + } catch (IllegalStateException e) { + throw new AuthenticationUnavailableException(C.i18n("login.failed.connect_authentication_server"), e); + } catch (JsonParseException e) { + throw new AuthenticationUnavailableException(C.i18n("login.failed.connect_authentication_server"), e); + } + } + + public String getClientToken() { + return this.clientToken; + } + + private static class GameProfileSerializer implements JsonSerializer, JsonDeserializer { + + @Override + public GameProfile deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { + JsonObject object = (JsonObject) json; + UUID id = object.has("id") ? (UUID) context.deserialize(object.get("id"), UUID.class) : null; + String name = object.has("name") ? object.getAsJsonPrimitive("name").getAsString() : null; + return new GameProfile(id, name); + } + + @Override + public JsonElement serialize(GameProfile src, Type typeOfSrc, JsonSerializationContext context) { + JsonObject result = new JsonObject(); + if (src.getId() != null) { + result.add("id", context.serialize(src.getId())); + } + if (src.getName() != null) { + result.addProperty("name", src.getName()); + } + return result; + } + } +} \ No newline at end of file diff --git a/HMCL/src/main/java/org/jackhuang/mojang/authlib/yggdrasil/YggdrasilGameProfileRepository.java b/HMCL/src/main/java/org/jackhuang/mojang/authlib/yggdrasil/YggdrasilGameProfileRepository.java new file mode 100644 index 000000000..7a7d0df91 --- /dev/null +++ b/HMCL/src/main/java/org/jackhuang/mojang/authlib/yggdrasil/YggdrasilGameProfileRepository.java @@ -0,0 +1,134 @@ +package org.jackhuang.mojang.authlib.yggdrasil; + +import java.util.HashSet; +import java.util.Set; +import org.jackhuang.hellominecraft.logging.logger.Logger; +import org.jackhuang.hellominecraft.utils.NetUtils; +import org.jackhuang.hellominecraft.utils.StrUtils; +import org.jackhuang.mojang.authlib.Agent; +import org.jackhuang.mojang.authlib.GameProfile; +import org.jackhuang.mojang.authlib.GameProfileRepository; +import org.jackhuang.mojang.authlib.ProfileLookupCallback; +import org.jackhuang.mojang.authlib.exceptions.AuthenticationException; +import org.jackhuang.mojang.authlib.yggdrasil.response.ProfileSearchResultsResponse; + +public class YggdrasilGameProfileRepository + implements GameProfileRepository { + + private static final Logger LOGGER = new Logger("YggdrasilGameProfileRepository"); + private static final String BASE_URL = "https://api.mojang.com/"; + private static final String SEARCH_PAGE_URL = BASE_URL + "profiles/page/"; + private static final int MAX_FAIL_COUNT = 3; + private static final int DELAY_BETWEEN_PAGES = 100; + private static final int DELAY_BETWEEN_FAILURES = 750; + private final YggdrasilAuthenticationService authenticationService; + + public YggdrasilGameProfileRepository(YggdrasilAuthenticationService authenticationService) { + this.authenticationService = authenticationService; + } + + @Override + public void findProfilesByNames(String[] names, Agent agent, ProfileLookupCallback callback) { + Set criteria = new HashSet(); + + for (String name : names) { + if (StrUtils.isNotBlank(name)) { + criteria.add(new ProfileCriteria(name, agent)); + } + } + + Exception exception = null; + Set request = new HashSet(criteria); + int page = 1; + int failCount = 0; + while (!criteria.isEmpty()) { + try { + ProfileSearchResultsResponse response = (ProfileSearchResultsResponse) this.authenticationService.makeRequest(NetUtils.constantURL("https://api.mojang.com/profiles/page/" + page), request, ProfileSearchResultsResponse.class); + failCount = 0; + exception = null; + + if ((response.getSize() == 0) || (response.getProfiles().length == 0)) { + LOGGER.debug("Page {} returned empty, aborting search", new Object[]{page}); + } else { + LOGGER.debug("Page {} returned {} results of {}, parsing", new Object[]{page, response.getProfiles().length, response.getSize()}); + + for (GameProfile profile : response.getProfiles()) { + LOGGER.debug("Successfully looked up profile {}", new Object[]{profile}); + criteria.remove(new ProfileCriteria(profile.getName(), agent)); + callback.onProfileLookupSucceeded(profile); + } + + LOGGER.debug("Page {} successfully parsed", new Object[]{page}); + page++; + try { + Thread.sleep(DELAY_BETWEEN_PAGES); + } catch (InterruptedException ignored) { + } + } + } catch (AuthenticationException e) { + exception = e; + failCount++; + + if (failCount != 3) { + try { + Thread.sleep(DELAY_BETWEEN_FAILURES); + } catch (InterruptedException ignored) { + } + } + } + } + if (criteria.isEmpty()) { + LOGGER.debug("Successfully found every profile requested"); + } else { + LOGGER.debug("{} profiles were missing from search results", new Object[]{criteria.size()}); + if (exception == null) { + exception = new ProfileNotFoundException("Server did not find the requested profile"); + } + for (ProfileCriteria profileCriteria : criteria) { + callback.onProfileLookupFailed(new GameProfile(null, profileCriteria.getName()), exception); + } + } + } + + private class ProfileCriteria { + + private final String name; + private final String agent; + + private ProfileCriteria(String name, Agent agent) { + this.name = name; + this.agent = agent.getName(); + } + + public String getName() { + return this.name; + } + + public String getAgent() { + return this.agent; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if ((o == null) || (getClass() != o.getClass())) { + return false; + } + ProfileCriteria that = (ProfileCriteria) o; + return (this.agent.equals(that.agent)) && (this.name.toLowerCase().equals(that.name.toLowerCase())); + } + + @Override + public int hashCode() { + return 31 * this.name.toLowerCase().hashCode() + this.agent.hashCode(); + } + + @Override + public String toString() { + return "ProfileCriteria{" + "name=" + name + ", agent=" + agent + '}'; + } + + } +} diff --git a/HMCL/src/main/java/org/jackhuang/mojang/authlib/yggdrasil/YggdrasilMinecraftSessionService.java b/HMCL/src/main/java/org/jackhuang/mojang/authlib/yggdrasil/YggdrasilMinecraftSessionService.java new file mode 100644 index 000000000..7834fa761 --- /dev/null +++ b/HMCL/src/main/java/org/jackhuang/mojang/authlib/yggdrasil/YggdrasilMinecraftSessionService.java @@ -0,0 +1,97 @@ +package org.jackhuang.mojang.authlib.yggdrasil; + +import java.net.URL; +import java.util.HashMap; +import java.util.Map; +import org.jackhuang.hellominecraft.logging.logger.Logger; +import org.jackhuang.hellominecraft.utils.NetUtils; +import org.jackhuang.mojang.authlib.GameProfile; +import org.jackhuang.mojang.authlib.HttpAuthenticationService; +import org.jackhuang.mojang.authlib.exceptions.AuthenticationException; +import org.jackhuang.mojang.authlib.exceptions.AuthenticationUnavailableException; +import org.jackhuang.mojang.authlib.minecraft.HttpMinecraftSessionService; +import org.jackhuang.mojang.authlib.yggdrasil.request.JoinMinecraftServerRequest; +import org.jackhuang.mojang.authlib.yggdrasil.response.HasJoinedMinecraftServerResponse; +import org.jackhuang.mojang.authlib.yggdrasil.response.MinecraftProfilePropertiesResponse; +import org.jackhuang.mojang.authlib.yggdrasil.response.Response; +import org.jackhuang.mojang.util.UUIDTypeAdapter; + +public class YggdrasilMinecraftSessionService extends HttpMinecraftSessionService { + + private static final Logger LOGGER = new Logger("YggdrasilMinecraftSessionService"); + private static final String BASE_URL = "https://sessionserver.mojang.com/session/minecraft/"; + private static final URL JOIN_URL = NetUtils.constantURL(BASE_URL + "join"); + private static final URL CHECK_URL = NetUtils.constantURL(BASE_URL + "hasJoined"); + + protected YggdrasilMinecraftSessionService(YggdrasilAuthenticationService authenticationService) { + super(authenticationService); + } + + @Override + public void joinServer(GameProfile profile, String authenticationToken, String serverId) throws AuthenticationException { + JoinMinecraftServerRequest request = new JoinMinecraftServerRequest(); + request.accessToken = authenticationToken; + request.selectedProfile = profile.getId(); + request.serverId = serverId; + + getAuthenticationService().makeRequest(JOIN_URL, request, Response.class); + } + + @Override + public GameProfile hasJoinedServer(GameProfile user, String serverId) throws AuthenticationUnavailableException { + Map arguments = new HashMap(); + + arguments.put("username", user.getName()); + arguments.put("serverId", serverId); + + URL url = NetUtils.concatenateURL(CHECK_URL, HttpAuthenticationService.buildQuery(arguments)); + try { + HasJoinedMinecraftServerResponse response = (HasJoinedMinecraftServerResponse) getAuthenticationService().makeRequest(url, null, HasJoinedMinecraftServerResponse.class); + + if ((response != null) && (response.getId() != null)) { + GameProfile result = new GameProfile(response.getId(), user.getName()); + + if (response.getProperties() != null) { + result.getProperties().putAll(response.getProperties()); + } + + return result; + } + return null; + } catch (AuthenticationUnavailableException e) { + throw e; + } catch (AuthenticationException e) { + } + return null; + } + + @Override + public GameProfile fillProfileProperties(GameProfile profile, boolean requireSecure) { + if (profile.getId() == null) { + return profile; + } + try { + URL url = NetUtils.constantURL(new StringBuilder().append("https://sessionserver.mojang.com/session/minecraft/profile/").append(UUIDTypeAdapter.fromUUID(profile.getId())).toString()); + url = NetUtils.concatenateURL(url, new StringBuilder().append("unsigned=").append(!requireSecure).toString()); + MinecraftProfilePropertiesResponse response = (MinecraftProfilePropertiesResponse) getAuthenticationService().makeRequest(url, null, MinecraftProfilePropertiesResponse.class); + + if (response == null) { + LOGGER.debug(new StringBuilder().append("Couldn't fetch profile properties for ").append(profile).append(" as the profile does not exist").toString()); + return profile; + } + GameProfile result = new GameProfile(response.getId(), response.getName()); + result.getProperties().putAll(response.getProperties()); + profile.getProperties().putAll(response.getProperties()); + LOGGER.debug(new StringBuilder().append("Successfully fetched profile properties for ").append(profile).toString()); + return result; + } catch (Exception e) { + LOGGER.warn(new StringBuilder().append("Couldn't look up profile properties for ").append(profile).toString(), e); + } + return profile; + } + + @Override + public YggdrasilAuthenticationService getAuthenticationService() { + return (YggdrasilAuthenticationService) super.getAuthenticationService(); + } +} \ No newline at end of file diff --git a/HMCL/src/main/java/org/jackhuang/mojang/authlib/yggdrasil/YggdrasilUserAuthentication.java b/HMCL/src/main/java/org/jackhuang/mojang/authlib/yggdrasil/YggdrasilUserAuthentication.java new file mode 100644 index 000000000..278895f92 --- /dev/null +++ b/HMCL/src/main/java/org/jackhuang/mojang/authlib/yggdrasil/YggdrasilUserAuthentication.java @@ -0,0 +1,248 @@ +package org.jackhuang.mojang.authlib.yggdrasil; + +import java.net.URL; +import java.util.Arrays; +import java.util.Map; +import org.jackhuang.hellominecraft.C; +import org.jackhuang.hellominecraft.logging.logger.Logger; +import org.jackhuang.hellominecraft.utils.ArrayUtils; +import org.jackhuang.hellominecraft.utils.NetUtils; +import org.jackhuang.hellominecraft.utils.StrUtils; +import org.jackhuang.mojang.authlib.Agent; +import org.jackhuang.mojang.authlib.GameProfile; +import org.jackhuang.mojang.authlib.HttpUserAuthentication; +import org.jackhuang.mojang.authlib.UserType; +import org.jackhuang.mojang.authlib.exceptions.AuthenticationException; +import org.jackhuang.mojang.authlib.exceptions.InvalidCredentialsException; +import org.jackhuang.mojang.authlib.yggdrasil.request.AuthenticationRequest; +import org.jackhuang.mojang.authlib.yggdrasil.request.RefreshRequest; +import org.jackhuang.mojang.authlib.yggdrasil.response.AuthenticationResponse; +import org.jackhuang.mojang.authlib.yggdrasil.response.RefreshResponse; +import org.jackhuang.mojang.authlib.yggdrasil.response.User; + +public class YggdrasilUserAuthentication extends HttpUserAuthentication { + + private static final Logger LOGGER = new Logger("YggdrasilUserAuthentication"); + private static final String BASE_URL = "https://authserver.mojang.com/"; + private static final URL ROUTE_AUTHENTICATE = NetUtils.constantURL(BASE_URL + "authenticate"); + private static final URL ROUTE_REFRESH = NetUtils.constantURL(BASE_URL + "refresh"); + private static final URL ROUTE_VALIDATE = NetUtils.constantURL(BASE_URL + "validate"); + private static final URL ROUTE_INVALIDATE = NetUtils.constantURL(BASE_URL + "invalidate"); + private static final URL ROUTE_SIGNOUT = NetUtils.constantURL(BASE_URL + "signout"); + private static final String STORAGE_KEY_ACCESS_TOKEN = "accessToken"; + private final Agent agent; + private GameProfile[] profiles; + private String accessToken; + private boolean isOnline; + + public YggdrasilUserAuthentication(YggdrasilAuthenticationService authenticationService, Agent agent) { + super(authenticationService); + this.agent = agent; + } + + @Override + public boolean canLogIn() { + return (!canPlayOnline()) && (StrUtils.isNotBlank(getUsername())) && ((StrUtils.isNotBlank(getPassword())) || (StrUtils.isNotBlank(getAuthenticatedToken()))); + } + + @Override + public void logIn() throws AuthenticationException { + if (StrUtils.isBlank(getUsername())) { + throw new InvalidCredentialsException(C.i18n("login.invalid_username")); + } + + if (StrUtils.isNotBlank(getAuthenticatedToken())) { + logInWithToken(); + } else if (StrUtils.isNotBlank(getPassword())) { + logInWithPassword(); + } else { + throw new InvalidCredentialsException(C.i18n("login.invalid_password")); + } + } + + protected void logInWithPassword() throws AuthenticationException { + if (StrUtils.isBlank(getUsername())) { + throw new InvalidCredentialsException(C.i18n("login.invalid_username")); + } + if (StrUtils.isBlank(getPassword())) { + throw new InvalidCredentialsException(C.i18n("login.invalid_password")); + } + + LOGGER.info("Logging in with username & password"); + + AuthenticationRequest request = new AuthenticationRequest(this, getUsername(), getPassword()); + AuthenticationResponse response = (AuthenticationResponse) getAuthenticationService().makeRequest(ROUTE_AUTHENTICATE, request, AuthenticationResponse.class); + + if (!response.getClientToken().equals(getAuthenticationService().getClientToken())) { + throw new AuthenticationException(C.i18n("login.changed_client_token")); + } + + if (response.getSelectedProfile() != null) { + setUserType(response.getSelectedProfile().isLegacy() ? UserType.LEGACY : UserType.MOJANG); + } else if (ArrayUtils.isNotEmpty(response.getAvailableProfiles())) { + setUserType(response.getAvailableProfiles()[0].isLegacy() ? UserType.LEGACY : UserType.MOJANG); + } + + User user = response.getUser(); + + if ((user != null) && (user.getId() != null)) { + setUserid(user.getId()); + } else { + setUserid(getUsername()); + } + + this.isOnline = true; + this.accessToken = response.getAccessToken(); + + this.profiles = response.getAvailableProfiles(); + setSelectedProfile(response.getSelectedProfile()); + getModifiableUserProperties().clear(); + + updateUserProperties(user); + } + + protected void updateUserProperties(User user) { + if (user == null) { + return; + } + + if (user.getProperties() != null) { + getModifiableUserProperties().putAll(user.getProperties()); + } + } + + protected void logInWithToken() throws AuthenticationException { + if (StrUtils.isBlank(getUserID())) { + if (StrUtils.isBlank(getUsername())) { + setUserid(getUsername()); + } else { + throw new InvalidCredentialsException(C.i18n("login.invalid_uuid_and_username")); + } + } + if (StrUtils.isBlank(getAuthenticatedToken())) { + throw new InvalidCredentialsException(C.i18n("login.invalid_access_token")); + } + + LOGGER.info("Logging in with access token"); + + RefreshRequest request = new RefreshRequest(this); + RefreshResponse response = (RefreshResponse) getAuthenticationService().makeRequest(ROUTE_REFRESH, request, RefreshResponse.class); + + if (!response.getClientToken().equals(getAuthenticationService().getClientToken())) { + throw new AuthenticationException(C.i18n("login.changed_client_token")); + } + + if (response.getSelectedProfile() != null) { + setUserType(response.getSelectedProfile().isLegacy() ? UserType.LEGACY : UserType.MOJANG); + } else if (ArrayUtils.isNotEmpty(response.getAvailableProfiles())) { + setUserType(response.getAvailableProfiles()[0].isLegacy() ? UserType.LEGACY : UserType.MOJANG); + } + + if ((response.getUser() != null) && (response.getUser().getId() != null)) { + setUserid(response.getUser().getId()); + } else { + setUserid(getUsername()); + } + + this.isOnline = true; + this.accessToken = response.getAccessToken(); + this.profiles = response.getAvailableProfiles(); + setSelectedProfile(response.getSelectedProfile()); + getModifiableUserProperties().clear(); + + updateUserProperties(response.getUser()); + } + + @Override + public void logOut() { + super.logOut(); + + this.accessToken = null; + this.profiles = null; + this.isOnline = false; + } + + @Override + public GameProfile[] getAvailableProfiles() { + return this.profiles; + } + + @Override + public boolean isLoggedIn() { + return StrUtils.isNotBlank(this.accessToken); + } + + @Override + public boolean canPlayOnline() { + return (isLoggedIn()) && (getSelectedProfile() != null) && (this.isOnline); + } + + @Override + public void selectGameProfile(GameProfile profile) throws AuthenticationException { + if (!isLoggedIn()) { + throw new AuthenticationException(C.i18n("login.profile.not_logged_in")); + } + if (getSelectedProfile() != null) { + throw new AuthenticationException(C.i18n("login.profile.selected")); + } + if ((profile == null) || (!ArrayUtils.contains(this.profiles, profile))) { + throw new IllegalArgumentException("Invalid profile '" + profile + "'"); + } + + RefreshRequest request = new RefreshRequest(this, profile); + RefreshResponse response = (RefreshResponse) getAuthenticationService().makeRequest(ROUTE_REFRESH, request, RefreshResponse.class); + + if (!response.getClientToken().equals(getAuthenticationService().getClientToken())) { + throw new AuthenticationException(C.i18n("login.changed_client_token")); + } + + this.isOnline = true; + this.accessToken = response.getAccessToken(); + setSelectedProfile(response.getSelectedProfile()); + } + + @Override + public void loadFromStorage(Map credentials) { + super.loadFromStorage(credentials); + + this.accessToken = (String)credentials.get(STORAGE_KEY_ACCESS_TOKEN); + } + + @Override + public Map saveForStorage() { + Map result = super.saveForStorage(); + + if (StrUtils.isNotBlank(getAuthenticatedToken())) { + result.put("accessToken", getAuthenticatedToken()); + } + + return result; + } + + @Deprecated + public String getSessionToken() { + if ((isLoggedIn()) && (getSelectedProfile() != null) && (canPlayOnline())) { + return String.format("token:%s:%s", new Object[]{getAuthenticatedToken(), getSelectedProfile().getId()}); + } + return null; + } + + @Override + public String getAuthenticatedToken() { + return this.accessToken; + } + + public Agent getAgent() { + return this.agent; + } + + @Override + public String toString() { + return "YggdrasilAuthenticationService{agent=" + this.agent + ", profiles=" + Arrays.toString(this.profiles) + ", selectedProfile=" + getSelectedProfile() + ", username='" + getUsername() + '\'' + ", isLoggedIn=" + isLoggedIn() + ", userType=" + getUserType() + ", canPlayOnline=" + canPlayOnline() + ", accessToken='" + this.accessToken + '\'' + ", clientToken='" + getAuthenticationService().getClientToken() + '\'' + '}'; + } + + @Override + public YggdrasilAuthenticationService getAuthenticationService() { + return (YggdrasilAuthenticationService) super.getAuthenticationService(); + } +} \ No newline at end of file diff --git a/HMCL/src/main/java/org/jackhuang/mojang/authlib/yggdrasil/request/AuthenticationRequest.java b/HMCL/src/main/java/org/jackhuang/mojang/authlib/yggdrasil/request/AuthenticationRequest.java new file mode 100644 index 000000000..23adee90d --- /dev/null +++ b/HMCL/src/main/java/org/jackhuang/mojang/authlib/yggdrasil/request/AuthenticationRequest.java @@ -0,0 +1,20 @@ +package org.jackhuang.mojang.authlib.yggdrasil.request; + +import org.jackhuang.mojang.authlib.Agent; +import org.jackhuang.mojang.authlib.yggdrasil.YggdrasilUserAuthentication; + +public class AuthenticationRequest { + + public Agent agent; + public String username; + public String password; + public String clientToken; + public boolean requestUser = true; + + public AuthenticationRequest(YggdrasilUserAuthentication authenticationService, String username, String password) { + this.agent = authenticationService.getAgent(); + this.username = username; + this.clientToken = authenticationService.getAuthenticationService().getClientToken(); + this.password = password; + } +} diff --git a/HMCL/src/main/java/org/jackhuang/mojang/authlib/yggdrasil/request/JoinMinecraftServerRequest.java b/HMCL/src/main/java/org/jackhuang/mojang/authlib/yggdrasil/request/JoinMinecraftServerRequest.java new file mode 100644 index 000000000..261946670 --- /dev/null +++ b/HMCL/src/main/java/org/jackhuang/mojang/authlib/yggdrasil/request/JoinMinecraftServerRequest.java @@ -0,0 +1,10 @@ +package org.jackhuang.mojang.authlib.yggdrasil.request; + +import java.util.UUID; + +public class JoinMinecraftServerRequest { + + public String accessToken; + public UUID selectedProfile; + public String serverId; +} diff --git a/HMCL/src/main/java/org/jackhuang/mojang/authlib/yggdrasil/request/RefreshRequest.java b/HMCL/src/main/java/org/jackhuang/mojang/authlib/yggdrasil/request/RefreshRequest.java new file mode 100644 index 000000000..7c3dab1a7 --- /dev/null +++ b/HMCL/src/main/java/org/jackhuang/mojang/authlib/yggdrasil/request/RefreshRequest.java @@ -0,0 +1,22 @@ +package org.jackhuang.mojang.authlib.yggdrasil.request; + +import org.jackhuang.mojang.authlib.GameProfile; +import org.jackhuang.mojang.authlib.yggdrasil.YggdrasilUserAuthentication; + +public class RefreshRequest { + + public String clientToken; + public String accessToken; + public GameProfile selectedProfile; + public boolean requestUser = true; + + public RefreshRequest(YggdrasilUserAuthentication authenticationService) { + this(authenticationService, null); + } + + public RefreshRequest(YggdrasilUserAuthentication authenticationService, GameProfile profile) { + this.clientToken = authenticationService.getAuthenticationService().getClientToken(); + this.accessToken = authenticationService.getAuthenticatedToken(); + this.selectedProfile = profile; + } +} diff --git a/HMCL/src/main/java/org/jackhuang/mojang/authlib/yggdrasil/response/AuthenticationResponse.java b/HMCL/src/main/java/org/jackhuang/mojang/authlib/yggdrasil/response/AuthenticationResponse.java new file mode 100644 index 000000000..7e4383243 --- /dev/null +++ b/HMCL/src/main/java/org/jackhuang/mojang/authlib/yggdrasil/response/AuthenticationResponse.java @@ -0,0 +1,32 @@ +package org.jackhuang.mojang.authlib.yggdrasil.response; + +import org.jackhuang.mojang.authlib.GameProfile; + +public class AuthenticationResponse extends Response { + + private String accessToken; + private String clientToken; + private GameProfile selectedProfile; + private GameProfile[] availableProfiles; + private User user; + + public String getAccessToken() { + return this.accessToken; + } + + public String getClientToken() { + return this.clientToken; + } + + public GameProfile[] getAvailableProfiles() { + return this.availableProfiles; + } + + public GameProfile getSelectedProfile() { + return this.selectedProfile; + } + + public User getUser() { + return this.user; + } +} diff --git a/HMCL/src/main/java/org/jackhuang/mojang/authlib/yggdrasil/response/HasJoinedMinecraftServerResponse.java b/HMCL/src/main/java/org/jackhuang/mojang/authlib/yggdrasil/response/HasJoinedMinecraftServerResponse.java new file mode 100644 index 000000000..d2564080f --- /dev/null +++ b/HMCL/src/main/java/org/jackhuang/mojang/authlib/yggdrasil/response/HasJoinedMinecraftServerResponse.java @@ -0,0 +1,18 @@ +package org.jackhuang.mojang.authlib.yggdrasil.response; + +import org.jackhuang.mojang.authlib.properties.PropertyMap; +import java.util.UUID; + +public class HasJoinedMinecraftServerResponse extends Response { + + private UUID id; + private PropertyMap properties; + + public UUID getId() { + return this.id; + } + + public PropertyMap getProperties() { + return this.properties; + } +} diff --git a/HMCL/src/main/java/org/jackhuang/mojang/authlib/yggdrasil/response/MinecraftProfilePropertiesResponse.java b/HMCL/src/main/java/org/jackhuang/mojang/authlib/yggdrasil/response/MinecraftProfilePropertiesResponse.java new file mode 100644 index 000000000..23e91296b --- /dev/null +++ b/HMCL/src/main/java/org/jackhuang/mojang/authlib/yggdrasil/response/MinecraftProfilePropertiesResponse.java @@ -0,0 +1,23 @@ +package org.jackhuang.mojang.authlib.yggdrasil.response; + +import org.jackhuang.mojang.authlib.properties.PropertyMap; +import java.util.UUID; + +public class MinecraftProfilePropertiesResponse extends Response { + + private UUID id; + private String name; + private PropertyMap properties; + + public UUID getId() { + return this.id; + } + + public String getName() { + return this.name; + } + + public PropertyMap getProperties() { + return this.properties; + } +} diff --git a/HMCL/src/main/java/org/jackhuang/mojang/authlib/yggdrasil/response/ProfileSearchResultsResponse.java b/HMCL/src/main/java/org/jackhuang/mojang/authlib/yggdrasil/response/ProfileSearchResultsResponse.java new file mode 100644 index 000000000..2aeafc88f --- /dev/null +++ b/HMCL/src/main/java/org/jackhuang/mojang/authlib/yggdrasil/response/ProfileSearchResultsResponse.java @@ -0,0 +1,17 @@ +package org.jackhuang.mojang.authlib.yggdrasil.response; + +import org.jackhuang.mojang.authlib.GameProfile; + +public class ProfileSearchResultsResponse extends Response { + + private GameProfile[] profiles; + private int size; + + public GameProfile[] getProfiles() { + return this.profiles; + } + + public int getSize() { + return this.size; + } +} diff --git a/HMCL/src/main/java/org/jackhuang/mojang/authlib/yggdrasil/response/RefreshResponse.java b/HMCL/src/main/java/org/jackhuang/mojang/authlib/yggdrasil/response/RefreshResponse.java new file mode 100644 index 000000000..fa1260277 --- /dev/null +++ b/HMCL/src/main/java/org/jackhuang/mojang/authlib/yggdrasil/response/RefreshResponse.java @@ -0,0 +1,32 @@ +package org.jackhuang.mojang.authlib.yggdrasil.response; + +import org.jackhuang.mojang.authlib.GameProfile; + +public class RefreshResponse extends Response { + + private String accessToken; + private String clientToken; + private GameProfile selectedProfile; + private GameProfile[] availableProfiles; + private User user; + + public String getAccessToken() { + return this.accessToken; + } + + public String getClientToken() { + return this.clientToken; + } + + public GameProfile[] getAvailableProfiles() { + return this.availableProfiles; + } + + public GameProfile getSelectedProfile() { + return this.selectedProfile; + } + + public User getUser() { + return this.user; + } +} diff --git a/HMCL/src/main/java/org/jackhuang/mojang/authlib/yggdrasil/response/Response.java b/HMCL/src/main/java/org/jackhuang/mojang/authlib/yggdrasil/response/Response.java new file mode 100644 index 000000000..f4c3063d3 --- /dev/null +++ b/HMCL/src/main/java/org/jackhuang/mojang/authlib/yggdrasil/response/Response.java @@ -0,0 +1,20 @@ +package org.jackhuang.mojang.authlib.yggdrasil.response; + +public class Response { + + private String error; + private String errorMessage; + private String cause; + + public String getError() { + return this.error; + } + + public String getCause() { + return this.cause; + } + + public String getErrorMessage() { + return this.errorMessage; + } +} diff --git a/HMCL/src/main/java/org/jackhuang/mojang/authlib/yggdrasil/response/User.java b/HMCL/src/main/java/org/jackhuang/mojang/authlib/yggdrasil/response/User.java new file mode 100644 index 000000000..f74207e16 --- /dev/null +++ b/HMCL/src/main/java/org/jackhuang/mojang/authlib/yggdrasil/response/User.java @@ -0,0 +1,17 @@ +package org.jackhuang.mojang.authlib.yggdrasil.response; + +import org.jackhuang.mojang.authlib.properties.PropertyMap; + +public class User { + + private String id; + private PropertyMap properties; + + public String getId() { + return this.id; + } + + public PropertyMap getProperties() { + return this.properties; + } +} diff --git a/HMCL/src/main/java/org/jackhuang/mojang/util/LegacyPropertyMapSerializer.java b/HMCL/src/main/java/org/jackhuang/mojang/util/LegacyPropertyMapSerializer.java new file mode 100644 index 000000000..ae92e7f19 --- /dev/null +++ b/HMCL/src/main/java/org/jackhuang/mojang/util/LegacyPropertyMapSerializer.java @@ -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.mojang.util; + +import com.google.gson.JsonArray; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonPrimitive; +import com.google.gson.JsonSerializationContext; +import com.google.gson.JsonSerializer; +import java.lang.reflect.Type; +import org.jackhuang.mojang.authlib.properties.PropertyMap; + +/** + * + * @author hyh + */ +public class LegacyPropertyMapSerializer + implements JsonSerializer { + + @Override + public JsonElement serialize(PropertyMap src, Type typeOfSrc, JsonSerializationContext context) { + JsonObject result = new JsonObject(); + + for (String key : src.keySet()) { + JsonArray values = new JsonArray(); + + values.add(new JsonPrimitive(src.get(key).getValue())); + + result.add(key, values); + } + + return result; + } +} diff --git a/HMCL/src/main/java/org/jackhuang/mojang/util/UUIDTypeAdapter.java b/HMCL/src/main/java/org/jackhuang/mojang/util/UUIDTypeAdapter.java new file mode 100644 index 000000000..8dc012c73 --- /dev/null +++ b/HMCL/src/main/java/org/jackhuang/mojang/util/UUIDTypeAdapter.java @@ -0,0 +1,27 @@ +package org.jackhuang.mojang.util; + +import com.google.gson.TypeAdapter; +import com.google.gson.stream.JsonReader; +import com.google.gson.stream.JsonWriter; +import java.io.IOException; +import java.util.UUID; + +public class UUIDTypeAdapter extends TypeAdapter { + + public void write(JsonWriter out, UUID value) + throws IOException { + out.value(fromUUID(value)); + } + + public UUID read(JsonReader in) throws IOException { + return fromString(in.nextString()); + } + + public static String fromUUID(UUID value) { + return value.toString().replace("-", ""); + } + + public static UUID fromString(String input) { + return UUID.fromString(input.replaceFirst("(\\w{8})(\\w{4})(\\w{4})(\\w{4})(\\w{12})", "$1-$2-$3-$4-$5")); + } +} diff --git a/HMCL/src/main/resources/org/jackhuang/hellominecraft/launcher/background.jpg b/HMCL/src/main/resources/org/jackhuang/hellominecraft/launcher/background.jpg new file mode 100644 index 000000000..b47d3ae74 Binary files /dev/null and b/HMCL/src/main/resources/org/jackhuang/hellominecraft/launcher/background.jpg differ diff --git a/HMCL/src/main/resources/org/jackhuang/hellominecraft/launcher/close.png b/HMCL/src/main/resources/org/jackhuang/hellominecraft/launcher/close.png new file mode 100644 index 000000000..ae2cb0a6f Binary files /dev/null and b/HMCL/src/main/resources/org/jackhuang/hellominecraft/launcher/close.png differ diff --git a/HMCL/src/main/resources/org/jackhuang/hellominecraft/launcher/icon.png b/HMCL/src/main/resources/org/jackhuang/hellominecraft/launcher/icon.png new file mode 100644 index 000000000..25f3cf6c8 Binary files /dev/null and b/HMCL/src/main/resources/org/jackhuang/hellominecraft/launcher/icon.png differ diff --git a/HMCL/src/main/resources/org/jackhuang/hellominecraft/launcher/minimize.png b/HMCL/src/main/resources/org/jackhuang/hellominecraft/launcher/minimize.png new file mode 100644 index 000000000..25de72edb Binary files /dev/null and b/HMCL/src/main/resources/org/jackhuang/hellominecraft/launcher/minimize.png differ diff --git a/HMCLAPI/build.gradle b/HMCLAPI/build.gradle new file mode 100644 index 000000000..2ff7ecd79 --- /dev/null +++ b/HMCLAPI/build.gradle @@ -0,0 +1,19 @@ +apply plugin: 'me.tatarka.retrolambda' + +if (!hasProperty('mainClass')) { + ext.mainClass = '' +} + +buildscript { + repositories { + mavenCentral(); + + dependencies { + classpath 'me.tatarka:gradle-retrolambda:3.1.0' + } + } +} + +retrolambda { + javaVersion = JavaVersion.VERSION_1_7 +} \ No newline at end of file diff --git a/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/C.java b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/C.java new file mode 100644 index 000000000..908786bea --- /dev/null +++ b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/C.java @@ -0,0 +1,45 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package org.jackhuang.hellominecraft; + +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import java.util.ResourceBundle; + +/** + * + * @author hyh + */ +public final class C { + public static final Gson gsonPrettyPrinting = new GsonBuilder().setPrettyPrinting().create(); + public static final Gson gson = new Gson(); + + public static final ResourceBundle I18N = ResourceBundle.getBundle("org/jackhuang/hellominecraft/launcher/I18N"); + + //http://repo1.maven.org/maven2 + + public static final String URL_PUBLISH = "http://www.mcbbs.net/thread-142335-1-1.html"; + public static final String URL_TIEBA = "http://tieba.baidu.com/f?kw=hellominecraftlauncher"; + public static final String URL_MINECRAFTFORUM = "http://www.minecraftforum.net/forums/mapping-and-modding/minecraft-tools/1265720-hello-minecraft-launcher-1-9-3-mc-1-7-4-auto"; + + public static final String FILE_MINECRAFT_VERSIONS = "versions"; + + public static final String LINE_SEPARATOR = System.getProperty("line.separator"); + + public static final String URL_FORGE_LIST = "http://files.minecraftforge.net/maven/net/minecraftforge/forge/json"; + public static final String URL_LITELOADER_LIST = "http://dl.liteloader.com/versions/versions.json"; + + private C(){} + + public static String i18n(String a, Object... format) { + try { + return String.format(C.I18N.getString(a), format); + } catch(Exception e) { + HMCLog.warn("Failed to read localization lang: " + a, e); + return a; + } + } + +} diff --git a/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/HMCLog.java b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/HMCLog.java new file mode 100644 index 000000000..2fc8381ce --- /dev/null +++ b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/HMCLog.java @@ -0,0 +1,40 @@ +/* + * 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; + +import org.jackhuang.hellominecraft.logging.logger.Logger; + + +/** + * + * @author hyh + */ +public class HMCLog { + + public static Logger logger = new Logger("HMC"); + + public static void log(String message) { + logger.info(message); + } + + public static void warn(String message) { + logger.warn(message); + } + + public static void warn(String msg, Throwable t) { + logger.warn(msg, t); + } + + public static void err(String msg) { + logger.error(msg); + } + + public static void err(String msg, Throwable t) { + logger.error(msg, t); + } + +} diff --git a/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/logging/AppenderControl.java b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/logging/AppenderControl.java new file mode 100644 index 000000000..3586825fe --- /dev/null +++ b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/logging/AppenderControl.java @@ -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.logging; + +import org.jackhuang.hellominecraft.logging.appender.IAppender; + +public class AppenderControl { + + private final ThreadLocal recursive = new ThreadLocal(); + private final IAppender appender; + private final Level level; + private final int intLevel; + + public AppenderControl(IAppender appender, Level level) { + this.appender = appender; + this.level = level; + this.intLevel = (level == null ? Level.ALL.level : level.level); + } + + public IAppender getAppender() { + return this.appender; + } + + public void callAppender(LogEvent event) { + if ((this.level != null) + && (this.intLevel < event.level.level)) { + return; + } + + if (this.recursive.get() != null) { + System.err.println("Recursive call to appender " + this.appender.getName()); + return; + } + try { + this.recursive.set(this); + + try { + this.appender.append(event); + } catch (RuntimeException ex) { + System.err.println("An exception occurred processing Appender " + this.appender.getName()); + ex.printStackTrace(); + if (!this.appender.ignoreExceptions()) { + throw ex; + } + } catch (Exception ex) { + System.err.println("An exception occurred processing Appender " + this.appender.getName()); + ex.printStackTrace(); + if (!this.appender.ignoreExceptions()) { + throw new LoggingException(ex); + } + } + } finally { + this.recursive.set(null); + } + } +} diff --git a/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/logging/Configuration.java b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/logging/Configuration.java new file mode 100644 index 000000000..8086114b9 --- /dev/null +++ b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/logging/Configuration.java @@ -0,0 +1,30 @@ +/* + * 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.logging; + +import java.util.ArrayList; +import org.jackhuang.hellominecraft.logging.appender.ConsoleAppender; +import org.jackhuang.hellominecraft.logging.appender.IAppender; +import org.jackhuang.hellominecraft.logging.layout.DefaultLayout; + +/** + * + * @author hyh + */ + +public class Configuration { + + public ArrayList appenders = new ArrayList(); + + public static Configuration DEFAULT; + + static { + DEFAULT = new Configuration(); + DEFAULT.appenders.add(new ConsoleAppender("Console", new DefaultLayout(), true, new ConsoleAppender.SystemOutStream(), true)); + } + +} diff --git a/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/logging/Level.java b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/logging/Level.java new file mode 100644 index 000000000..ae39860b5 --- /dev/null +++ b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/logging/Level.java @@ -0,0 +1,37 @@ +/* + * 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.logging; + +/** + * + * @author hyh + */ +public enum Level { + + OFF(0), + FATAL(1), + ERROR(2), + WARN(3), + INFO(4), + DEBUG(5), + TRACE(6), + ALL(2147483647); + + public final int level; + + private Level(int i) { + level = i; + } + + public boolean lessOrEqual(Level level) { + return this.level <= level.level; + } + + public boolean lessOrEqual(int level) { + return this.level <= level; + } + +} diff --git a/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/logging/LogEvent.java b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/logging/LogEvent.java new file mode 100644 index 000000000..30903da6e --- /dev/null +++ b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/logging/LogEvent.java @@ -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.logging; + +import org.jackhuang.hellominecraft.logging.message.IMessage; + +/** + * + * @author hyh + */ +public class LogEvent { + + public Level level; + public String threadName; + public Throwable thrown; + public IMessage message; + +} diff --git a/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/logging/LoggingException.java b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/logging/LoggingException.java new file mode 100644 index 000000000..e20357f5e --- /dev/null +++ b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/logging/LoggingException.java @@ -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.logging; + +/** + * + * @author hyh + */ +public class LoggingException extends RuntimeException { + + public LoggingException(Exception e) { + super(e); + } + +} diff --git a/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/logging/appender/AbstractAppender.java b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/logging/appender/AbstractAppender.java new file mode 100644 index 000000000..0eb847ef8 --- /dev/null +++ b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/logging/appender/AbstractAppender.java @@ -0,0 +1,45 @@ +/* + * 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.logging.appender; + +import java.io.Serializable; +import org.jackhuang.hellominecraft.logging.layout.ILayout; + +/** + * + * @author hyh + */ +public abstract class AbstractAppender implements IAppender { + + String name; + private final ILayout layout; + private final boolean ignoreExceptions; + + public AbstractAppender(String name, ILayout layout) { + this(name, layout, true); + } + + public AbstractAppender(String name, ILayout layout, boolean ignoreExceptions) { + this.name = name; + this.layout = layout; + this.ignoreExceptions = ignoreExceptions; + } + + @Override + public String getName() { + return name; + } + + @Override + public boolean ignoreExceptions() { + return ignoreExceptions; + } + + @Override + public ILayout getLayout() { + return this.layout; + } +} diff --git a/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/logging/appender/ConsoleAppender.java b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/logging/appender/ConsoleAppender.java new file mode 100644 index 000000000..17591b9aa --- /dev/null +++ b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/logging/appender/ConsoleAppender.java @@ -0,0 +1,78 @@ +/* + * 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.logging.appender; + +import java.io.IOException; +import java.io.OutputStream; +import java.io.Serializable; +import org.jackhuang.hellominecraft.logging.layout.ILayout; + +/** + * + * @author hyh + */ +public class ConsoleAppender extends OutputStreamAppender { + + public ConsoleAppender(String name, ILayout layout, boolean ignoreExceptions, OutputStream stream, boolean immediateFlush) { + super(name, layout, ignoreExceptions, stream, true); + } + + public static class SystemOutStream extends OutputStream { + + @Override + public void close() { + } + + @Override + public void flush() { + System.out.flush(); + } + + @Override + public void write(byte[] b) throws IOException { + System.out.write(b); + } + + @Override + public void write(byte[] b, int off, int len) + throws IOException { + System.out.write(b, off, len); + } + + @Override + public void write(int b) throws IOException { + System.out.write(b); + } + } + + public static class SystemErrStream extends OutputStream { + + @Override + public void close() { + } + + @Override + public void flush() { + System.err.flush(); + } + + @Override + public void write(byte[] b) throws IOException { + System.err.write(b); + } + + @Override + public void write(byte[] b, int off, int len) + throws IOException { + System.err.write(b, off, len); + } + + @Override + public void write(int b) { + System.err.write(b); + } + } +} diff --git a/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/logging/appender/IAppender.java b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/logging/appender/IAppender.java new file mode 100644 index 000000000..1be2e4c45 --- /dev/null +++ b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/logging/appender/IAppender.java @@ -0,0 +1,24 @@ +/* + * 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.logging.appender; + +import java.io.Serializable; +import org.jackhuang.hellominecraft.logging.LogEvent; +import org.jackhuang.hellominecraft.logging.layout.ILayout; + +/** + * + * @author hyh + */ +public interface IAppender { + + void append(LogEvent event); + String getName(); + boolean ignoreExceptions(); + ILayout getLayout(); + +} diff --git a/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/logging/appender/OutputStreamAppender.java b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/logging/appender/OutputStreamAppender.java new file mode 100644 index 000000000..1faa934c5 --- /dev/null +++ b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/logging/appender/OutputStreamAppender.java @@ -0,0 +1,52 @@ +/* + * 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.logging.appender; + +import java.io.IOException; +import java.io.OutputStream; +import java.io.PrintStream; +import java.io.Serializable; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReentrantReadWriteLock; +import org.jackhuang.hellominecraft.logging.LogEvent; +import org.jackhuang.hellominecraft.logging.LoggingException; +import org.jackhuang.hellominecraft.logging.layout.ILayout; + +/** + * + * @author hyh + */ +public abstract class OutputStreamAppender extends AbstractAppender { + + protected final OutputStream stream; + protected final boolean immediateFlush; + private final Lock readLock = new ReentrantReadWriteLock().readLock(); + + public OutputStreamAppender(String name, ILayout layout, boolean ignoreExceptions, OutputStream stream, boolean immediateFlush) { + super(name, layout, ignoreExceptions); + + this.immediateFlush = immediateFlush; + this.stream = stream; + } + + @Override + public void append(LogEvent event) { + this.readLock.lock(); + try { + byte[] bytes = getLayout().toByteArray(event); + if (bytes.length > 0) { + stream.write(bytes); + } + if(event.thrown != null) + event.thrown.printStackTrace(new PrintStream(stream)); + } catch (IOException ex) { + System.err.println("Unable to write to stream for appender: " + getName()); + throw new LoggingException(ex); + } finally { + this.readLock.unlock(); + } + } +} diff --git a/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/logging/layout/AbstractStringLayout.java b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/logging/layout/AbstractStringLayout.java new file mode 100644 index 000000000..33b757ebb --- /dev/null +++ b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/logging/layout/AbstractStringLayout.java @@ -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.logging.layout; + +import org.jackhuang.hellominecraft.logging.LogEvent; + +/** + * + * @author hyh + */ +public abstract class AbstractStringLayout implements ILayout { + + @Override + public byte[] toByteArray(LogEvent event) { + return toSerializable(event).getBytes(); + } + +} diff --git a/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/logging/layout/DefaultLayout.java b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/logging/layout/DefaultLayout.java new file mode 100644 index 000000000..13603fab9 --- /dev/null +++ b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/logging/layout/DefaultLayout.java @@ -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.logging.layout; + +import java.text.SimpleDateFormat; +import java.util.Date; +import org.jackhuang.hellominecraft.logging.LogEvent; + +/** + * + * @author hyh + */ +public class DefaultLayout extends AbstractStringLayout { + private static final SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss"); + + @Override + public String toSerializable(LogEvent event) { + return "[" + sdf.format(new Date()) + "][" + event.threadName + "/" + event.level.name() + "] " + event.message.getFormattedMessage() + "\n"; + } + +} diff --git a/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/logging/layout/ILayout.java b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/logging/layout/ILayout.java new file mode 100644 index 000000000..7326ea536 --- /dev/null +++ b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/logging/layout/ILayout.java @@ -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.logging.layout; + +import java.io.Serializable; +import org.jackhuang.hellominecraft.logging.LogEvent; + +/** + * + * @author hyh + * @param + */ +public interface ILayout { + + byte[] toByteArray(LogEvent event); + T toSerializable(LogEvent event); + +} diff --git a/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/logging/logger/AbstractLogger.java b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/logging/logger/AbstractLogger.java new file mode 100644 index 000000000..cae4f1458 --- /dev/null +++ b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/logging/logger/AbstractLogger.java @@ -0,0 +1,523 @@ +/* + * 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.logging.logger; + +import org.jackhuang.hellominecraft.logging.Level; +import org.jackhuang.hellominecraft.logging.message.IMessage; +import org.jackhuang.hellominecraft.logging.message.IMessageFactory; +import org.jackhuang.hellominecraft.logging.message.ParameterizedMessageFactory; +import org.jackhuang.hellominecraft.logging.message.StringFormattedMessage; + +public abstract class AbstractLogger + implements ILogger { + + public static final Class DEFAULT_MESSAGE_FACTORY_CLASS = ParameterizedMessageFactory.class; + + private static final String FQCN = AbstractLogger.class.getName(); + private static final String THROWING = "throwing"; + private static final String CATCHING = "catching"; + private final String name; + private final IMessageFactory messageFactory; + + public AbstractLogger() { + this.name = getClass().getName(); + this.messageFactory = createDefaultMessageFactory(); + } + + public AbstractLogger(String name) { + this.name = name; + this.messageFactory = createDefaultMessageFactory(); + } + + public AbstractLogger(String name, IMessageFactory messageFactory) { + this.name = name; + this.messageFactory = (messageFactory == null ? createDefaultMessageFactory() : messageFactory); + } + + private IMessageFactory createDefaultMessageFactory() { + try { + return (IMessageFactory) DEFAULT_MESSAGE_FACTORY_CLASS.newInstance(); + } catch (InstantiationException e) { + throw new IllegalStateException(e); + } catch (IllegalAccessException e) { + throw new IllegalStateException(e); + } + } + + @Override + public void catching(Level level, Throwable t) { + if (isEnabled(level, (Object) null, null)) { + log(level, this.messageFactory.newMessage(CATCHING), t); + } + } + + @Override + public void catching(Throwable t) { + catching(Level.ERROR, t); + } + + @Override + public void debug(IMessage msg) { + if (isEnabled(Level.DEBUG, msg, null)) { + log(Level.DEBUG, msg, null); + } + } + + @Override + public void debug(IMessage msg, Throwable t) { + if (isEnabled(Level.DEBUG, msg, t)) { + log(Level.DEBUG, msg, t); + } + } + + @Override + public void debug(Object message) { + if (isEnabled(Level.DEBUG, message, null)) { + log(Level.DEBUG, this.messageFactory.newMessage(message), null); + } + } + + @Override + public void debug(Object message, Throwable t) { + if (isEnabled(Level.DEBUG, message, t)) { + log(Level.DEBUG, this.messageFactory.newMessage(message), t); + } + } + + @Override + public void debug(String message) { + if (isEnabled(Level.DEBUG, message)) { + log(Level.DEBUG, this.messageFactory.newMessage(message), null); + } + } + + @Override + public void debug(String message, Object[] params) { + if (isEnabled(Level.DEBUG, message, params)) { + IMessage msg = this.messageFactory.newMessage(message, params); + log(Level.DEBUG, msg, msg.getThrowable()); + } + } + + @Override + public void debug(String message, Throwable t) { + if (isEnabled(Level.DEBUG, message, t)) { + log(Level.DEBUG, this.messageFactory.newMessage(message), t); + } + } + + @Override + public void entry() { + entry(new Object[0]); + } + + @Override + public void entry(Object[] params) { + if (isEnabled(Level.TRACE, (Object) null, null)) { + log(Level.TRACE, entryMsg(params.length, params), null); + } + } + + private IMessage entryMsg(int count, Object[] params) { + if (count == 0) { + return this.messageFactory.newMessage("entry"); + } + StringBuilder sb = new StringBuilder("entry params("); + int i = 0; + for (Object parm : params) { + if (parm != null) { + sb.append(parm.toString()); + } else { + sb.append("null"); + } + i++; + if (i < params.length) { + sb.append(", "); + } + } + sb.append(")"); + return this.messageFactory.newMessage(sb.toString()); + } + + @Override + public void error(IMessage msg) { + if (isEnabled(Level.ERROR, msg, null)) { + log(Level.ERROR, msg, null); + } + } + + @Override + public void error(IMessage msg, Throwable t) { + if (isEnabled(Level.ERROR, msg, t)) { + log(Level.ERROR, msg, t); + } + } + + @Override + public void error(Object message) { + if (isEnabled(Level.ERROR, message, null)) { + log(Level.ERROR, this.messageFactory.newMessage(message), null); + } + } + + @Override + public void error(Object message, Throwable t) { + if (isEnabled(Level.ERROR, message, t)) { + log(Level.ERROR, this.messageFactory.newMessage(message), t); + } + } + + @Override + public void error(String message) { + if (isEnabled(Level.ERROR, message)) { + log(Level.ERROR, this.messageFactory.newMessage(message), null); + } + } + + @Override + public void error(String message, Object[] params) { + if (isEnabled(Level.ERROR, message, params)) { + IMessage msg = this.messageFactory.newMessage(message, params); + log(Level.ERROR, msg, msg.getThrowable()); + } + } + + @Override + public void error(String message, Throwable t) { + if (isEnabled(Level.ERROR, message, t)) { + log(Level.ERROR, this.messageFactory.newMessage(message), t); + } + } + + @Override + public void fatal(IMessage msg) { + if (isEnabled(Level.FATAL, msg, null)) { + log(Level.FATAL, msg, null); + } + } + + @Override + public void fatal(IMessage msg, Throwable t) { + if (isEnabled(Level.FATAL, msg, t)) { + log(Level.FATAL, msg, t); + } + } + + @Override + public void fatal(Object message) { + if (isEnabled(Level.FATAL, message, null)) { + log(Level.FATAL, this.messageFactory.newMessage(message), null); + } + } + + @Override + public void fatal(Object message, Throwable t) { + if (isEnabled(Level.FATAL, message, t)) { + log(Level.FATAL, this.messageFactory.newMessage(message), t); + } + } + + @Override + public void fatal(String message) { + if (isEnabled(Level.FATAL, message)) { + log(Level.FATAL, this.messageFactory.newMessage(message), null); + } + } + + @Override + public void fatal(String message, Object[] params) { + if (isEnabled(Level.FATAL, message, params)) { + IMessage msg = this.messageFactory.newMessage(message, params); + log(Level.FATAL, msg, msg.getThrowable()); + } + } + + @Override + public void fatal(String message, Throwable t) { + if (isEnabled(Level.FATAL, message, t)) { + log(Level.FATAL, this.messageFactory.newMessage(message), t); + } + } + + @Override + public String getName() { + return this.name; + } + + @Override + public void info(IMessage msg) { + if (isEnabled(Level.INFO, msg, null)) { + log(Level.INFO, msg, null); + } + } + + @Override + public void info(IMessage msg, Throwable t) { + if (isEnabled(Level.INFO, msg, t)) { + log(Level.INFO, msg, t); + } + } + + @Override + public void info(Object message) { + if (isEnabled(Level.INFO, message, null)) { + log(Level.INFO, this.messageFactory.newMessage(message), null); + } + } + + @Override + public void info(Object message, Throwable t) { + if (isEnabled(Level.INFO, message, t)) { + log(Level.INFO, this.messageFactory.newMessage(message), t); + } + } + + @Override + public void info(String message) { + if (isEnabled(Level.INFO, message)) { + log(Level.INFO, this.messageFactory.newMessage(message), null); + } + } + + @Override + public void info(String message, Object[] params) { + if (isEnabled(Level.INFO, message, params)) { + IMessage msg = this.messageFactory.newMessage(message, params); + log(Level.INFO, msg, msg.getThrowable()); + } + } + + @Override + public void info(String message, Throwable t) { + if (isEnabled(Level.INFO, message, t)) { + log(Level.INFO, this.messageFactory.newMessage(message), t); + } + } + + protected abstract boolean isEnabled(Level paramLevel, IMessage paramIMessage, Throwable paramThrowable); + + protected abstract boolean isEnabled(Level paramLevel, Object paramObject, Throwable paramThrowable); + + protected abstract boolean isEnabled(Level paramLevel, String paramString); + + protected abstract boolean isEnabled(Level paramLevel, String paramString, Object[] paramArrayOfObject); + + protected abstract boolean isEnabled(Level paramLevel, String paramString, Throwable paramThrowable); + + protected abstract void abstractLog(Level level, IMessage msg, Throwable t); + + @Override + public boolean isErrorEnabled() { + return isEnabled(Level.ERROR); + } + + @Override + + public boolean isFatalEnabled() { + return isEnabled(Level.FATAL); + } + + @Override + public boolean isInfoEnabled() { + return isEnabled(Level.INFO); + } + + @Override + public boolean isTraceEnabled() { + return isEnabled(Level.TRACE); + } + + @Override + public boolean isWarnEnabled() { + return isEnabled(Level.WARN); + } + + @Override + public boolean isDebugEnabled() { + return isEnabled(Level.DEBUG); + } + + @Override + public boolean isEnabled(Level level) { + return isEnabled(level, (Object) null, null); + } + + @Override + public void log(Level level, IMessage msg) { + if (isEnabled(level, msg, null)) { + log(level, msg, null); + } + } + + @Override + public void log(Level level, IMessage msg, Throwable t) { + if (isEnabled(level, msg, t)) { + abstractLog(level, msg, t); + } + } + + @Override + public void log(Level level, Object message) { + if (isEnabled(level, message, null)) { + log(level, this.messageFactory.newMessage(message), null); + } + } + + @Override + public void log(Level level, Object message, Throwable t) { + if (isEnabled(level, message, t)) { + log(level, this.messageFactory.newMessage(message), t); + } + } + + @Override + public void log(Level level, String message) { + if (isEnabled(level, message)) { + log(level, this.messageFactory.newMessage(message), null); + } + } + + @Override + public void log(Level level, String message, Object[] params) { + if (isEnabled(level, message, params)) { + IMessage msg = this.messageFactory.newMessage(message, params); + log(level, msg, msg.getThrowable()); + } + } + + @Override + public void log(Level level, String message, Throwable t) { + if (isEnabled(level, message, t)) { + log(level, this.messageFactory.newMessage(message), t); + } + } + + @Override + public void printf(Level level, String format, Object[] params) { + if (isEnabled(level, format, params)) { + IMessage msg = new StringFormattedMessage(format, params); + log(level, msg, msg.getThrowable()); + } + } + + @Override + public T throwing(T t) { + return throwing(Level.ERROR, t); + } + + @Override + public T throwing(Level level, T t) { + if (isEnabled(level, (Object) null, null)) { + log(level, this.messageFactory.newMessage(THROWING), t); + } + return t; + } + + @Override + public String toString() { + return this.name; + } + + @Override + public void trace(IMessage msg) { + if (isEnabled(Level.TRACE, msg, null)) { + log(Level.TRACE, msg, null); + } + } + + @Override + public void trace(IMessage msg, Throwable t) { + if (isEnabled(Level.TRACE, msg, t)) { + log(Level.TRACE, msg, t); + } + } + + @Override + public void trace(Object message) { + if (isEnabled(Level.TRACE, message, null)) { + log(Level.TRACE, this.messageFactory.newMessage(message), null); + } + } + + @Override + public void trace(Object message, Throwable t) { + if (isEnabled(Level.TRACE, message, t)) { + log(Level.TRACE, this.messageFactory.newMessage(message), t); + } + } + + @Override + public void trace(String message) { + if (isEnabled(Level.TRACE, message)) { + log(Level.TRACE, this.messageFactory.newMessage(message), null); + } + } + + @Override + public void trace(String message, Object[] params) { + if (isEnabled(Level.TRACE, message, params)) { + IMessage msg = this.messageFactory.newMessage(message, params); + log(Level.TRACE, msg, msg.getThrowable()); + } + } + + @Override + public void trace(String message, Throwable t) { + if (isEnabled(Level.TRACE, message, t)) { + log(Level.TRACE, this.messageFactory.newMessage(message), t); + } + } + + @Override + public void warn(IMessage msg) { + if (isEnabled(Level.WARN, msg, null)) { + log(Level.WARN, msg, null); + } + } + + @Override + public void warn(IMessage msg, Throwable t) { + if (isEnabled(Level.WARN, msg, t)) { + log(Level.WARN, msg, t); + } + } + + @Override + public void warn(Object message) { + if (isEnabled(Level.WARN, message, null)) { + log(Level.WARN, this.messageFactory.newMessage(message), null); + } + } + + @Override + public void warn(Object message, Throwable t) { + if (isEnabled(Level.WARN, message, t)) { + log(Level.WARN, this.messageFactory.newMessage(message), t); + } + } + + @Override + public void warn(String message) { + if (isEnabled(Level.WARN, message)) { + log(Level.WARN, this.messageFactory.newMessage(message), null); + } + } + + @Override + public void warn(String message, Object[] params) { + if (isEnabled(Level.WARN, message, params)) { + IMessage msg = this.messageFactory.newMessage(message, params); + log(Level.WARN, msg, msg.getThrowable()); + } + } + + @Override + public void warn(String message, Throwable t) { + if (isEnabled(Level.WARN, message, t)) { + log(Level.WARN, this.messageFactory.newMessage(message), t); + } + } +} diff --git a/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/logging/logger/ILogger.java b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/logging/logger/ILogger.java new file mode 100644 index 000000000..307c670e5 --- /dev/null +++ b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/logging/logger/ILogger.java @@ -0,0 +1,146 @@ +/* + * 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.logging.logger; + +import org.jackhuang.hellominecraft.logging.Level; +import org.jackhuang.hellominecraft.logging.message.IMessage; + +/** + * + * @author hyh + */ +public interface ILogger { + + void catching(Level paramLevel, Throwable paramThrowable); + + void catching(Throwable paramThrowable); + + void debug(IMessage paramIMessage); + + void debug(IMessage paramIMessage, Throwable paramThrowable); + + void debug(Object paramObject); + + void debug(Object paramObject, Throwable paramThrowable); + + void debug(String paramString); + + void debug(String paramString, Object[] paramArrayOfObject); + + void debug(String paramString, Throwable paramThrowable); + + void entry(); + + void entry(Object[] paramArrayOfObject); + + void error(IMessage paramIMessage); + + void error(IMessage paramIMessage, Throwable paramThrowable); + + void error(Object paramObject); + + void error(Object paramObject, Throwable paramThrowable); + + void error(String paramString); + + void error(String paramString, Object[] paramArrayOfObject); + + void error(String paramString, Throwable paramThrowable); + + void fatal(IMessage paramIMessage); + + void fatal(IMessage paramIMessage, Throwable paramThrowable); + + void fatal(Object paramObject); + + void fatal(Object paramObject, Throwable paramThrowable); + + void fatal(String paramString); + + void fatal(String paramString, Object[] paramArrayOfObject); + + void fatal(String paramString, Throwable paramThrowable); + + String getName(); + + void info(IMessage paramIMessage); + + void info(IMessage paramIMessage, Throwable paramThrowable); + + void info(Object paramObject); + + void info(Object paramObject, Throwable paramThrowable); + + void info(String paramString); + + void info(String paramString, Object[] paramArrayOfObject); + + void info(String paramString, Throwable paramThrowable); + + boolean isDebugEnabled(); + + boolean isEnabled(Level paramLevel); + + boolean isErrorEnabled(); + + boolean isFatalEnabled(); + + boolean isInfoEnabled(); + + boolean isTraceEnabled(); + + boolean isWarnEnabled(); + + void log(Level paramLevel, IMessage paramIMessage); + + void log(Level paramLevel, IMessage paramIMessage, Throwable paramThrowable); + + void log(Level paramLevel, Object paramObject); + + void log(Level paramLevel, Object paramObject, Throwable paramThrowable); + + void log(Level paramLevel, String paramString); + + void log(Level paramLevel, String paramString, Object[] paramArrayOfObject); + + void log(Level paramLevel, String paramString, Throwable paramThrowable); + + void printf(Level paramLevel, String paramString, Object[] paramArrayOfObject); + + T throwing(Level paramLevel, T paramT); + + T throwing(T paramT); + + void trace(IMessage paramIMessage); + + void trace(IMessage paramIMessage, Throwable paramThrowable); + + void trace(Object paramObject); + + void trace(Object paramObject, Throwable paramThrowable); + + void trace(String paramString); + + void trace(String paramString, Object[] paramArrayOfObject); + + void trace(String paramString, Throwable paramThrowable); + + void warn(IMessage paramIMessage); + + void warn(IMessage paramIMessage, Throwable paramThrowable); + + void warn(Object paramObject); + + void warn(Object paramObject, Throwable paramThrowable); + + void warn(String paramString); + + void warn(String paramString, Object[] paramArrayOfObject); + + void warn(String paramString, Throwable paramThrowable); + +} diff --git a/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/logging/logger/Logger.java b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/logging/logger/Logger.java new file mode 100644 index 000000000..d9d34a2b9 --- /dev/null +++ b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/logging/logger/Logger.java @@ -0,0 +1,156 @@ +/* + * 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.logging.logger; + +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import org.jackhuang.hellominecraft.logging.AppenderControl; +import org.jackhuang.hellominecraft.logging.Configuration; +import org.jackhuang.hellominecraft.logging.Level; +import org.jackhuang.hellominecraft.logging.LogEvent; +import org.jackhuang.hellominecraft.logging.appender.IAppender; +import org.jackhuang.hellominecraft.logging.message.IMessage; +import org.jackhuang.hellominecraft.logging.message.IMessageFactory; + +public class Logger extends AbstractLogger { + + protected volatile PrivateConfig config; + private final Map appenders = new ConcurrentHashMap(); + + public Logger(String name) { + this(name, null, Level.INFO); + } + + public Logger(String name, IMessageFactory messageFactory, Level defaultLevel) { + super(name, messageFactory); + this.config = new PrivateConfig(Configuration.DEFAULT, this, defaultLevel); + } + + public synchronized void setLevel(Level level) { + if (level != null) { + this.config = new PrivateConfig(this.config, level); + } + } + + public Level getLevel() { + return this.config.level; + } + + @Override + public void abstractLog(Level level, IMessage data, Throwable t) { + LogEvent event = new LogEvent(); + event.level = level; + event.message = data; + event.thrown = t; + event.threadName = Thread.currentThread().getName(); + + log(event); + } + + public void log(LogEvent event) { + callAppenders(event); + } + + protected void callAppenders(LogEvent event) { + for (AppenderControl control : this.appenders.values()) { + control.callAppender(event); + } + } + + @Override + public boolean isEnabled(Level level, String msg) { + return this.config.filter(level, msg); + } + + @Override + public boolean isEnabled(Level level, String msg, Throwable t) { + return this.config.filter(level, msg, t); + } + + @Override + public boolean isEnabled(Level level, String msg, Object[] p1) { + return this.config.filter(level, msg, p1); + } + + @Override + public boolean isEnabled(Level level, Object msg, Throwable t) { + return this.config.filter(level, msg, t); + } + + @Override + public boolean isEnabled(Level level, IMessage msg, Throwable t) { + return this.config.filter(level, msg, t); + } + + public void addAppender(IAppender appender) { + this.appenders.put(appender.getName(), new AppenderControl(appender, null)); + } + + public void removeAppender(IAppender appender) { + this.appenders.remove(appender.getName()); + } + + public Map getAppenders() { + Map map = new HashMap(); + for (Map.Entry entry : this.appenders.entrySet()) { + map.put(entry.getKey(), ((AppenderControl) entry.getValue()).getAppender()); + } + return map; + } + + public String toString() { + String nameLevel = "" + getName() + ":" + getLevel(); + return nameLevel; + } + + protected class PrivateConfig { + + public final Configuration config; + private final Level level; + private final int intLevel; + private final Logger logger; + + public PrivateConfig(Configuration c, Logger logger, Level level) { + this.level = level; + this.intLevel = this.level.level; + this.logger = logger; + + this.config = c; + for(IAppender appender : config.appenders) + addAppender(appender); + } + + public PrivateConfig(PrivateConfig pc, Level level) { + this(pc.config, pc.logger, level); + } + + boolean filter(Level level, String msg) { + + return this.intLevel >= level.level; + } + + boolean filter(Level level, String msg, Throwable t) { + + return this.intLevel >= level.level; + } + + boolean filter(Level level, String msg, Object[] p1) { + + return this.intLevel >= level.level; + } + + boolean filter(Level level, Object msg, Throwable t) { + + return this.intLevel >= level.level; + } + + boolean filter(Level level, IMessage msg, Throwable t) { + + return this.intLevel >= level.level; + } + } +} diff --git a/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/logging/logger/SimpleLogger.java b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/logging/logger/SimpleLogger.java new file mode 100644 index 000000000..7b144b6df --- /dev/null +++ b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/logging/logger/SimpleLogger.java @@ -0,0 +1,130 @@ +/* + * 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.logging.logger; + +import java.io.ByteArrayOutputStream; +import java.io.PrintStream; +import java.text.DateFormat; +import java.text.SimpleDateFormat; +import java.util.Date; +import org.jackhuang.hellominecraft.logging.Level; +import org.jackhuang.hellominecraft.logging.message.IMessage; +import org.jackhuang.hellominecraft.logging.message.IMessageFactory; + +public class SimpleLogger extends AbstractLogger { + + private static final char SPACE = ' '; + private DateFormat dateFormatter; + private Level level; + private final boolean showDateTime; + private final boolean showContextMap; + private PrintStream stream; + private final String logName; + + public SimpleLogger(String name, Level defaultLevel, boolean showLogName, boolean showShortLogName, boolean showDateTime, boolean showContextMap, String dateTimeFormat, IMessageFactory messageFactory, PrintStream stream) { + super(name, messageFactory); + this.level = defaultLevel; + if (showShortLogName) { + int index = name.lastIndexOf("."); + if ((index > 0) && (index < name.length())) { + this.logName = name.substring(index + 1); + } else { + this.logName = name; + } + } else if (showLogName) { + this.logName = name; + } else { + this.logName = null; + } + this.showDateTime = showDateTime; + this.showContextMap = showContextMap; + this.stream = stream; + + if (showDateTime) { + try { + this.dateFormatter = new SimpleDateFormat(dateTimeFormat); + } catch (IllegalArgumentException e) { + this.dateFormatter = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss:SSS zzz"); + } + } + } + + public void setStream(PrintStream stream) { + this.stream = stream; + } + + public Level getLevel() { + return this.level; + } + + public void setLevel(Level level) { + if (level != null) { + this.level = level; + } + } + + @Override + public void abstractLog(Level level, IMessage msg, Throwable throwable) { + StringBuilder sb = new StringBuilder(); + + if (this.showDateTime) { + Date now = new Date(); + String dateText; + synchronized (this.dateFormatter) { + dateText = this.dateFormatter.format(now); + } + sb.append(dateText); + sb.append(' '); + } + + sb.append(level.toString()); + sb.append(' '); + if ((this.logName != null) && (this.logName.length() > 0)) { + sb.append(this.logName); + sb.append(' '); + } + sb.append(msg.getFormattedMessage()); + Object[] params = msg.getParameters(); + Throwable t; + if ((throwable == null) && (params != null) && ((params[(params.length - 1)] instanceof Throwable))) { + t = (Throwable) params[(params.length - 1)]; + } else { + t = throwable; + } + if (t != null) { + sb.append(' '); + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + t.printStackTrace(new PrintStream(baos)); + sb.append(baos.toString()); + } + this.stream.println(sb.toString()); + } + + @Override + protected boolean isEnabled(Level level, String msg) { + return this.level.level >= level.level; + } + + @Override + protected boolean isEnabled(Level level, String msg, Throwable t) { + return this.level.level >= level.level; + } + + @Override + protected boolean isEnabled(Level level, String msg, Object[] p1) { + return this.level.level >= level.level; + } + + @Override + protected boolean isEnabled(Level level, Object msg, Throwable t) { + return this.level.level >= level.level; + } + + @Override + protected boolean isEnabled(Level level, IMessage msg, Throwable t) { + return this.level.level >= level.level; + } +} diff --git a/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/logging/message/AbstractMessageFactory.java b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/logging/message/AbstractMessageFactory.java new file mode 100644 index 000000000..3fb16a6c2 --- /dev/null +++ b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/logging/message/AbstractMessageFactory.java @@ -0,0 +1,24 @@ +/* + * 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.logging.message; + +/** + * + * @author hyh + */ +public abstract class AbstractMessageFactory + implements IMessageFactory { + + @Override + public IMessage newMessage(Object message) { + return new ObjectMessage(message); + } + + @Override + public IMessage newMessage(String message) { + return new SimpleMessage(message); + } +} diff --git a/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/logging/message/IMessage.java b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/logging/message/IMessage.java new file mode 100644 index 000000000..062c05de8 --- /dev/null +++ b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/logging/message/IMessage.java @@ -0,0 +1,20 @@ +/* + * 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.logging.message; + +import java.io.Serializable; + +/** + * + * @author hyh + */ +public interface IMessage extends Serializable { + String getFormattedMessage(); + String getFormat(); + Object[] getParameters(); + Throwable getThrowable(); +} diff --git a/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/logging/message/IMessageFactory.java b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/logging/message/IMessageFactory.java new file mode 100644 index 000000000..0845c4309 --- /dev/null +++ b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/logging/message/IMessageFactory.java @@ -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.logging.message; + +/** + * + * @author hyh + */ +public abstract interface IMessageFactory { + + public abstract IMessage newMessage(Object paramObject); + + public abstract IMessage newMessage(String paramString); + + public abstract IMessage newMessage(String paramString, Object[] paramArrayOfObject); +} diff --git a/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/logging/message/ObjectMessage.java b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/logging/message/ObjectMessage.java new file mode 100644 index 000000000..69bf97665 --- /dev/null +++ b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/logging/message/ObjectMessage.java @@ -0,0 +1,64 @@ +/* + * 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.logging.message; + +public class ObjectMessage + implements IMessage { + + private static final long serialVersionUID = -5903272448334166185L; + private transient Object obj; + + public ObjectMessage(Object obj) { + if (obj == null) { + obj = "null"; + } + this.obj = obj; + } + + @Override + public String getFormattedMessage() { + return this.obj.toString(); + } + + @Override + public String getFormat() { + return this.obj.toString(); + } + + @Override + public Object[] getParameters() { + return new Object[]{this.obj}; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if ((o == null) || (getClass() != o.getClass())) { + return false; + } + + ObjectMessage that = (ObjectMessage) o; + + return this.obj != null ? this.obj.equals(that.obj) : that.obj == null; + } + + @Override + public int hashCode() { + return this.obj != null ? this.obj.hashCode() : 0; + } + + @Override + public String toString() { + return "ObjectMessage[obj=" + this.obj.toString() + "]"; + } + + @Override + public Throwable getThrowable() { + return (this.obj instanceof Throwable) ? (Throwable) this.obj : null; + } +} diff --git a/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/logging/message/ParameterizedMessage.java b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/logging/message/ParameterizedMessage.java new file mode 100644 index 000000000..e40b49f4c --- /dev/null +++ b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/logging/message/ParameterizedMessage.java @@ -0,0 +1,336 @@ +/* + * 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.logging.message; + +import java.text.SimpleDateFormat; +import java.util.Arrays; +import java.util.Collection; +import java.util.Date; +import java.util.HashSet; +import java.util.Iterator; +import java.util.Map; +import java.util.Set; + +/** + * + * @author hyh + */ +public class ParameterizedMessage + implements IMessage { + + public static final String RECURSION_PREFIX = "[..."; + public static final String RECURSION_SUFFIX = "...]"; + public static final String ERROR_PREFIX = "[!!!"; + public static final String ERROR_SEPARATOR = "=>"; + public static final String ERROR_MSG_SEPARATOR = ":"; + public static final String ERROR_SUFFIX = "!!!]"; + private static final long serialVersionUID = -665975803997290697L; + private static final int HASHVAL = 31; + private static final char DELIM_START = '{'; + private static final char DELIM_STOP = '}'; + private static final char ESCAPE_CHAR = '\\'; + private final String messagePattern; + private final String[] stringArgs; + private transient Object[] argArray; + private transient String formattedMessage; + private transient Throwable throwable; + + public ParameterizedMessage(String messagePattern, String[] stringArgs, Throwable throwable) { + this.messagePattern = messagePattern; + this.stringArgs = stringArgs; + this.throwable = throwable; + } + + public ParameterizedMessage(String messagePattern, Object[] objectArgs, Throwable throwable) { + this.messagePattern = messagePattern; + this.throwable = throwable; + this.stringArgs = parseArguments(objectArgs); + } + + public ParameterizedMessage(String messagePattern, Object[] arguments) { + this.messagePattern = messagePattern; + this.stringArgs = parseArguments(arguments); + } + + public ParameterizedMessage(String messagePattern, Object arg) { + this(messagePattern, new Object[]{arg}); + } + + public ParameterizedMessage(String messagePattern, Object arg1, Object arg2) { + this(messagePattern, new Object[]{arg1, arg2}); + } + + private String[] parseArguments(Object[] arguments) { + if (arguments == null) { + return null; + } + int argsCount = countArgumentPlaceholders(this.messagePattern); + int resultArgCount = arguments.length; + if ((argsCount < arguments.length) + && (this.throwable == null) && ((arguments[(arguments.length - 1)] instanceof Throwable))) { + this.throwable = ((Throwable) arguments[(arguments.length - 1)]); + resultArgCount--; + } + + this.argArray = new Object[resultArgCount]; + System.arraycopy(arguments, 0, this.argArray, 0, resultArgCount); + String[] strArgs; + if ((argsCount == 1) && (this.throwable == null) && (arguments.length > 1)) { + strArgs = new String[1]; + strArgs[0] = deepToString(arguments); + } else { + strArgs = new String[resultArgCount]; + for (int i = 0; i < strArgs.length; i++) { + strArgs[i] = deepToString(arguments[i]); + } + } + return strArgs; + } + + @Override + public String getFormattedMessage() { + if (this.formattedMessage == null) { + this.formattedMessage = formatMessage(this.messagePattern, this.stringArgs); + } + return this.formattedMessage; + } + + @Override + public String getFormat() { + return this.messagePattern; + } + + @Override + public Object[] getParameters() { + if (this.argArray != null) { + return this.argArray; + } + return this.stringArgs; + } + + @Override + public Throwable getThrowable() { + return this.throwable; + } + + protected String formatMessage(String msgPattern, String[] sArgs) { + return format(msgPattern, sArgs); + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + ParameterizedMessage that = (ParameterizedMessage) o; + if (this.messagePattern != null ? !this.messagePattern.equals(that.messagePattern) : that.messagePattern != null) + return false; + + return Arrays.equals(this.stringArgs, that.stringArgs); + } + + @Override + public int hashCode() { + int result = this.messagePattern != null ? this.messagePattern.hashCode() : 0; + result = HASHVAL * result + (this.stringArgs != null ? Arrays.hashCode(this.stringArgs) : 0); + return result; + } + + public static String format(String messagePattern, Object[] arguments) { + if ((messagePattern == null) || (arguments == null) || (arguments.length == 0)) + return messagePattern; + + StringBuilder result = new StringBuilder(); + int escapeCounter = 0; + int currentArgument = 0; + for (int i = 0; i < messagePattern.length(); i++) { + char curChar = messagePattern.charAt(i); + if (curChar == ESCAPE_CHAR) { + escapeCounter++; + } else if ((curChar == DELIM_START) + && (i < messagePattern.length() - 1) + && (messagePattern.charAt(i + 1) == DELIM_STOP)) { + int escapedEscapes = escapeCounter / 2; + for (int j = 0; j < escapedEscapes; j++) + result.append(ESCAPE_CHAR); + + if (escapeCounter % 2 == 1) { + result.append(DELIM_START); + result.append(DELIM_STOP); + } else { + if (currentArgument < arguments.length) + result.append(arguments[currentArgument]); + else + result.append(DELIM_START).append(DELIM_STOP); + currentArgument++; + } + i++; + escapeCounter = 0; + } else { + if (escapeCounter > 0) { + for (int j = 0; j < escapeCounter; j++) + result.append(ESCAPE_CHAR); + escapeCounter = 0; + } + result.append(curChar); + } + } + return result.toString(); + } + + public static int countArgumentPlaceholders(String messagePattern) { + if (messagePattern == null) return 0; + + int delim = messagePattern.indexOf(123); + + if (delim == -1) return 0; + int result = 0; + boolean isEscaped = false; + for (int i = 0; i < messagePattern.length(); i++) { + char curChar = messagePattern.charAt(i); + if (curChar == ESCAPE_CHAR) { + isEscaped = !isEscaped; + } else if (curChar == DELIM_START) { + if ((!isEscaped) + && (i < messagePattern.length() - 1) + && (messagePattern.charAt(i + 1) == DELIM_STOP)) { + result++; + i++; + } + + isEscaped = false; + } else { + isEscaped = false; + } + } + return result; + } + + public static String deepToString(Object o) { + if (o == null) return null; + if (o instanceof String) return (String) o; + StringBuilder str = new StringBuilder(); + Set dejaVu = new HashSet(); + recursiveDeepToString(o, str, dejaVu); + return str.toString(); + } + + private static void recursiveDeepToString(Object o, StringBuilder str, Set dejaVu) { + if (o == null) { + str.append("null"); + return; + } + if ((o instanceof String)) { + str.append(o); + return; + } + Class oClass = o.getClass(); + if (oClass.isArray()) { + if (oClass == byte[].class) { + str.append(Arrays.toString((byte[]) (byte[]) o)); + } else if (oClass == short[].class) { + str.append(Arrays.toString((short[]) (short[]) o)); + } else if (oClass == int[].class) { + str.append(Arrays.toString((int[]) (int[]) o)); + } else if (oClass == long[].class) { + str.append(Arrays.toString((long[]) (long[]) o)); + } else if (oClass == float[].class) { + str.append(Arrays.toString((float[]) (float[]) o)); + } else if (oClass == double[].class) { + str.append(Arrays.toString((double[]) (double[]) o)); + } else if (oClass == boolean[].class) { + str.append(Arrays.toString((boolean[]) (boolean[]) o)); + } else if (oClass == char[].class) { + str.append(Arrays.toString((char[]) (char[]) o)); + } else { + String id = identityToString(o); + if (dejaVu.contains(id)) { + str.append("[...").append(id).append("...]"); + } else { + dejaVu.add(id); + Object[] oArray = (Object[]) (Object[]) o; + str.append("["); + boolean first = true; + for (Object current : oArray) { + if (first) first = false; + else str.append(", "); + recursiveDeepToString(current, str, new HashSet(dejaVu)); + } + str.append("]"); + } + } + } else if ((o instanceof Map)) { + String id = identityToString(o); + if (dejaVu.contains(id)) { + str.append("[...").append(id).append("...]"); + } else { + dejaVu.add(id); + Map oMap = (Map) o; + str.append("{"); + boolean isFirst = true; + for (Object o1 : oMap.entrySet()) { + Map.Entry current = (Map.Entry) o1; + if (isFirst) isFirst = false; + else str.append(", "); + Object key = current.getKey(); + Object value = current.getValue(); + recursiveDeepToString(key, str, new HashSet(dejaVu)); + str.append("="); + recursiveDeepToString(value, str, new HashSet(dejaVu)); + } + str.append("}"); + } + } else if ((o instanceof Collection)) { + String id = identityToString(o); + if (dejaVu.contains(id)) { + str.append("[...").append(id).append("...]"); + } else { + dejaVu.add(id); + Collection oCol = (Collection) o; + str.append("["); + boolean isFirst = true; + for (Iterator i$ = oCol.iterator(); i$.hasNext();) { + Object anOCol = i$.next(); + if (isFirst) isFirst = false; + else str.append(", "); + recursiveDeepToString(anOCol, str, new HashSet(dejaVu)); + } + str.append("]"); + } + } else if ((o instanceof Date)) { + Date date = (Date) o; + SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ"); + + str.append(format.format(date)); + } else { + try { + str.append(o.toString()); + } catch (Throwable t) { + str.append("[!!!"); + str.append(identityToString(o)); + str.append("=>"); + String msg = t.getMessage(); + String className = t.getClass().getName(); + str.append(className); + if (!className.equals(msg)) { + str.append(":"); + str.append(msg); + } + str.append("!!!]"); + } + } + } + + public static String identityToString(Object obj) { + if (obj == null) return null; + return obj.getClass().getName()+"@"+Integer.toHexString(System.identityHashCode(obj)); + } + + @Override + public String toString() { + return "ParameterizedMessage[messagePattern="+this.messagePattern+", stringArgs="+Arrays.toString(this.stringArgs)+", throwable="+this.throwable+"]"; + } +} diff --git a/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/logging/message/ParameterizedMessageFactory.java b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/logging/message/ParameterizedMessageFactory.java new file mode 100644 index 000000000..78fec7ce6 --- /dev/null +++ b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/logging/message/ParameterizedMessageFactory.java @@ -0,0 +1,20 @@ +/* + * 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.logging.message; + +/** + * + * @author hyh + */ +public final class ParameterizedMessageFactory extends AbstractMessageFactory { + + public static final ParameterizedMessageFactory INSTANCE = new ParameterizedMessageFactory(); + + @Override + public IMessage newMessage(String message, Object[] params) { + return new ParameterizedMessage(message, params); + } +} diff --git a/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/logging/message/SimpleMessage.java b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/logging/message/SimpleMessage.java new file mode 100644 index 000000000..a665dd965 --- /dev/null +++ b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/logging/message/SimpleMessage.java @@ -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.logging.message; + +/** + * + * @author hyh + */ +public class SimpleMessage + implements IMessage { + + private static final long serialVersionUID = -8398002534962715992L; + private final String message; + + public SimpleMessage() { + this(null); + } + + public SimpleMessage(String message) { + this.message = message; + } + + @Override + public String getFormattedMessage() { + return this.message; + } + + @Override + public String getFormat() { + return this.message; + } + + @Override + public Object[] getParameters() { + return null; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if ((o == null) || (getClass() != o.getClass())) { + return false; + } + + SimpleMessage that = (SimpleMessage) o; + + return this.message != null ? this.message.equals(that.message) : that.message == null; + } + + @Override + public int hashCode() { + return this.message != null ? this.message.hashCode() : 0; + } + + @Override + public String toString() { + return "SimpleMessage[message=" + this.message + "]"; + } + + @Override + public Throwable getThrowable() { + return null; + } +} diff --git a/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/logging/message/StringFormattedMessage.java b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/logging/message/StringFormattedMessage.java new file mode 100644 index 000000000..5d39ebc08 --- /dev/null +++ b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/logging/message/StringFormattedMessage.java @@ -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.logging.message; + +import java.util.Arrays; +import java.util.IllegalFormatException; + +public class StringFormattedMessage + implements IMessage { + + private static final long serialVersionUID = -665975803997290697L; + private final String messagePattern; + private final transient Object[] argArray; + private String[] stringArgs; + private transient String formattedMessage; + private transient Throwable throwable; + + public StringFormattedMessage(String messagePattern, Object[] arguments) { + this.messagePattern = messagePattern; + this.argArray = arguments; + if ((arguments != null) && (arguments.length > 0) && ((arguments[(arguments.length - 1)] instanceof Throwable))) { + this.throwable = ((Throwable) arguments[(arguments.length - 1)]); + } + } + + @Override + public String getFormattedMessage() { + if (this.formattedMessage == null) { + this.formattedMessage = formatMessage(this.messagePattern, this.argArray); + } + return this.formattedMessage; + } + + @Override + public String getFormat() { + return this.messagePattern; + } + + @Override + public Object[] getParameters() { + if (this.argArray != null) { + return this.argArray; + } + return this.stringArgs; + } + + protected String formatMessage(String msgPattern, Object[] args) { + try { + return String.format(msgPattern, args); + } catch (IllegalFormatException ife) { + System.err.println("Unable to format msg: " + msgPattern); + ife.printStackTrace(); + } + return msgPattern; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if ((o == null) || (getClass() != o.getClass())) { + return false; + } + + StringFormattedMessage that = (StringFormattedMessage) o; + + if (this.messagePattern != null ? !this.messagePattern.equals(that.messagePattern) : that.messagePattern != null) { + return false; + } + + return Arrays.equals(this.stringArgs, that.stringArgs); + } + + @Override + public int hashCode() { + int result = this.messagePattern != null ? this.messagePattern.hashCode() : 0; + result = 31 * result + (this.stringArgs != null ? Arrays.hashCode(this.stringArgs) : 0); + return result; + } + + @Override + public String toString() { + return "StringFormatMessage[messagePattern=" + this.messagePattern + ", args=" + Arrays.toString(this.argArray) + "]"; + } + + @Override + public Throwable getThrowable() { + return this.throwable; + } +} diff --git a/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/tasks/DoingDoneListener.java b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/tasks/DoingDoneListener.java new file mode 100644 index 000000000..074ab47a2 --- /dev/null +++ b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/tasks/DoingDoneListener.java @@ -0,0 +1,28 @@ +/* + * 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.tasks; + +/** + * + * @author hyh + */ +public interface DoingDoneListener { + /** + * Task done. + * @param k + */ + void onDone(K k); + /** + * Before task executing. + * @param k + */ + void onDoing(K k); + /** + * Task failed. + * @param k + */ + void onFailed(K k); +} diff --git a/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/tasks/ParallelTask.java b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/tasks/ParallelTask.java new file mode 100644 index 000000000..754536a90 --- /dev/null +++ b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/tasks/ParallelTask.java @@ -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.tasks; + +import java.util.Collection; +import java.util.HashSet; +import org.jackhuang.hellominecraft.tasks.Task; + +/** + * + * @author huangyuhui + */ +public class ParallelTask extends Task { + Collection dependsTask = new HashSet(); + + @Override + public boolean executeTask() { + return true; + } + + @Override + public String getInfo() { + return "PARALLEL"; + } + + @Override + public Collection getDependTasks() { + return dependsTask; + } + + public void addDependsTask(Task t) { + dependsTask.add(t); + } + +} diff --git a/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/tasks/ProgressProvider.java b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/tasks/ProgressProvider.java new file mode 100644 index 000000000..0e2f95ddc --- /dev/null +++ b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/tasks/ProgressProvider.java @@ -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.tasks; + +/** + * + * @author hyh + */ +public abstract class ProgressProvider { + protected ProgressProviderListener ppl; + + public ProgressProvider setProgressProviderListener(ProgressProviderListener p) { + ppl = p; + return this; + } +} diff --git a/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/tasks/ProgressProviderListener.java b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/tasks/ProgressProviderListener.java new file mode 100644 index 000000000..d31d55c8e --- /dev/null +++ b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/tasks/ProgressProviderListener.java @@ -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.tasks; + +/** + * + * @author hyh + */ +public interface ProgressProviderListener { + void setProgress(int prog, int max); + void setStatus(String sta); + void onProgressProviderDone(); +} diff --git a/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/tasks/Task.java b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/tasks/Task.java new file mode 100644 index 000000000..f32f3b72d --- /dev/null +++ b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/tasks/Task.java @@ -0,0 +1,54 @@ +/* + * 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.tasks; + +import java.util.Collection; + +/** + * + * @author hyh + */ +public abstract class Task extends ProgressProvider { + + /** + * Run in a new thread(packed in TaskList). + * @return is task finished sucessfully. + */ + public abstract boolean executeTask(); + + /** + * if this func returns false, TaskList will force abort the thread. + * run in main thread. + * @return is aborted. + */ + public boolean abort() { return false; } + + public Throwable getFailReason() { return failReason; } + protected Throwable failReason = null; + protected void setFailReason(Throwable s) { + failReason = s; + } + + protected String tag; + protected boolean parallelExecuting; + public Task setTag(String tag) { + this.tag = tag; + return this; + } + + public boolean isParallelExecuting() { + return parallelExecuting; + } + + public void setParallelExecuting(boolean parallelExecuting) { + this.parallelExecuting = parallelExecuting; + } + + public abstract String getInfo(); + + public Collection getDependTasks() { return null; } + public Collection getAfterTasks() { return null; } +} diff --git a/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/tasks/TaskInfo.java b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/tasks/TaskInfo.java new file mode 100644 index 000000000..b06b98501 --- /dev/null +++ b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/tasks/TaskInfo.java @@ -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.tasks; + +/** + * + * @author hyh + */ +public abstract class TaskInfo extends Task { + + String info; + + public TaskInfo(String info) { + this.info = info; + } + + @Override + public String getInfo() { + return info; + } + +} diff --git a/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/tasks/TaskList.java b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/tasks/TaskList.java new file mode 100644 index 000000000..003f3f376 --- /dev/null +++ b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/tasks/TaskList.java @@ -0,0 +1,154 @@ +/* + * 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.tasks; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import org.jackhuang.hellominecraft.utils.functions.DoneListener0; +import org.jackhuang.hellominecraft.HMCLog; + +/** + * + * @author hyh + */ +public class TaskList extends Thread { + + List taskQueue = Collections.synchronizedList(new ArrayList()); + ArrayList allDone = new ArrayList(); + ArrayList> taskListener = new ArrayList(); + + int totTask = 0; + boolean shouldContinue = true; + + public TaskList() { + } + + public void clean() { + shouldContinue = true; + totTask = 0; + taskQueue.clear(); + } + + public void addAllDoneListener(DoneListener0 l) { + allDone.add(l); + } + + public void addTaskListener(DoingDoneListener l) { + taskListener.add(l); + } + + public void addTask(Task task) { + taskQueue.add(task); + totTask++; + } + + public int taskCount() { + return totTask; + } + + private class InvokeThread extends Thread { + + Task task; + Set s; + + public InvokeThread(Task task, Set ss) { + this.task = task; + s = ss; + } + + @Override + public void run() { + executeTask(task); + s.remove(this); + threadPool.remove(this); + } + + } + + static final Set threadPool = Collections.synchronizedSet(new HashSet()); + static final Set taskPool = Collections.synchronizedSet(new HashSet()); + + private void processTasks(Collection c) { + if (c == null) { + return; + } + this.totTask += c.size(); + Set runningThread = Collections.synchronizedSet(new HashSet()); + for (Task t2 : c) { + t2.setParallelExecuting(true); + InvokeThread thread = new InvokeThread(t2, runningThread); + threadPool.add(thread); + runningThread.add(thread); + thread.start(); + } + while (!runningThread.isEmpty()) { + try { + if(this.isInterrupted()) return; + Thread.sleep(1); + } catch (InterruptedException ex) { + HMCLog.warn("Failed to sleep task thread", ex); + } + } + + } + + private void executeTask(Task t) { + if (!shouldContinue || t == null) { + return; + } + processTasks(t.getDependTasks()); + + HMCLog.log("Executing task: " + t.getInfo()); + for (DoingDoneListener d : taskListener) { + d.onDoing(t); + } + + if (t.executeTask()) { + HMCLog.log("Task finished: " + t.getInfo()); + for (DoingDoneListener d : taskListener) { + d.onDone(t); + } + processTasks(t.getAfterTasks()); + } else { + HMCLog.err("Task failed: " + t.getInfo(), t.getFailReason()); + for (DoingDoneListener d : taskListener) { + d.onFailed(t); + } + } + } + + @Override + public void run() { + Thread.currentThread().setName("TaskList"); + + threadPool.clear(); + for (Task taskQueue1 : taskQueue) + executeTask(taskQueue1); + if (shouldContinue) + for (DoneListener0 d : allDone) + d.onDone(); + } + + public boolean isEmpty() { + return taskQueue.isEmpty(); + } + + public void abort() { + shouldContinue = false; + while(!threadPool.isEmpty()) + synchronized(threadPool) { + InvokeThread it = threadPool.iterator().next(); + if(!it.task.abort()) it.interrupt(); + threadPool.remove(it); + } + this.interrupt(); + } + +} diff --git a/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/tasks/TaskRunnable.java b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/tasks/TaskRunnable.java new file mode 100644 index 000000000..66b3673cb --- /dev/null +++ b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/tasks/TaskRunnable.java @@ -0,0 +1,30 @@ +/* + * 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.tasks; + +/** + * + * @author hyh + */ +public class TaskRunnable extends TaskInfo { + private final Runnable r; + public TaskRunnable(String info, Runnable r) { + super(info); + this.r = r; + } + + @Override + public boolean executeTask() { + try { + r.run(); + return true; + } catch(Throwable t) { + setFailReason(t); + return false; + } + } + +} diff --git a/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/tasks/TaskRunnableArg1.java b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/tasks/TaskRunnableArg1.java new file mode 100644 index 000000000..730ffec44 --- /dev/null +++ b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/tasks/TaskRunnableArg1.java @@ -0,0 +1,47 @@ +/* + * 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.tasks; + +import java.util.ArrayList; +import org.jackhuang.hellominecraft.tasks.communication.PreviousResult; +import org.jackhuang.hellominecraft.tasks.communication.PreviousResultRegistrator; +import org.jackhuang.hellominecraft.utils.functions.Consumer; + +/** + * + * @author hyh + * @param Runnable<T> + */ +public class TaskRunnableArg1 extends TaskInfo implements PreviousResultRegistrator { + private final Consumer r; + public TaskRunnableArg1(String info, Consumer r) { + super(info); + this.r = r; + } + + @Override + public boolean executeTask() { + if(al.size() != 1) throw new IllegalStateException("the count of args is not one."); + try { + r.accept(al.get(0).getResult()); + return true; + } catch(Throwable t) { + setFailReason(t); + return false; + } + } + + ArrayList> al = new ArrayList(); + + @Override + public Task registerPreviousResult(PreviousResult pr) { + al.add(pr); + return this; + } + + + +} \ No newline at end of file diff --git a/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/tasks/TaskWindow.form b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/tasks/TaskWindow.form new file mode 100644 index 000000000..b24570722 --- /dev/null +++ b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/tasks/TaskWindow.form @@ -0,0 +1,127 @@ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/tasks/TaskWindow.java b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/tasks/TaskWindow.java new file mode 100644 index 000000000..29f6c9144 --- /dev/null +++ b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/tasks/TaskWindow.java @@ -0,0 +1,242 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package org.jackhuang.hellominecraft.tasks; + +import java.awt.EventQueue; +import java.util.ArrayList; +import org.jackhuang.hellominecraft.C; +import org.jackhuang.hellominecraft.utils.functions.DoneListener0; +import org.jackhuang.hellominecraft.HMCLog; +import org.jackhuang.hellominecraft.utils.MessageBox; +import org.jackhuang.hellominecraft.utils.StrUtils; +import org.jackhuang.hellominecraft.utils.SwingUtils; + +/** + * + * @author hyh + */ +public class TaskWindow extends javax.swing.JDialog + implements ProgressProviderListener, DoneListener0, DoingDoneListener { + + private static final TaskWindow instance = new TaskWindow(); + + public static TaskWindow getInstance() { + instance.clean(); + return instance; + } + + boolean suc = false; + + private TaskList taskList; + private final ArrayList failReasons = new ArrayList(); + + /** + * Creates new form DownloadWindow + */ + private TaskWindow() { + initComponents(); + + setLocationRelativeTo(null); + + setModal(true); + } + + public TaskWindow addTask(Task task) { + taskList.addTask(task); + return this; + } + + public void clean() { + taskList = null; + taskList = new TaskList(); + taskList.addTaskListener(this); + taskList.addAllDoneListener(this); + } + + public boolean start() { + if (taskList.isAlive()) return false; + pgsSingle.setValue(0); + pgsTotal.setValue(0); + suc = false; + SwingUtils.clear(lstDownload); + failReasons.clear(); + try { + taskList.start(); + } catch (Exception e) { + HMCLog.warn("Failed to start thread, maybe there're already a taskwindow here.", e); + MessageBox.Show(C.i18n("taskwindow.no_more_instance")); + return false; + } + this.setVisible(true); + return this.areTasksFinished(); + } + + /** + * 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") + // //GEN-BEGIN:initComponents + private void initComponents() { + + btnCancel = new javax.swing.JButton(); + pgsSingle = new javax.swing.JProgressBar(); + lblSingleProgress = new javax.swing.JLabel(); + lblTotalProgress = new javax.swing.JLabel(); + pgsTotal = new javax.swing.JProgressBar(); + srlDownload = new javax.swing.JScrollPane(); + lstDownload = new javax.swing.JList(); + + setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE); + java.util.ResourceBundle bundle = java.util.ResourceBundle.getBundle("org/jackhuang/hellominecraft/launcher/I18N"); // NOI18N + setTitle(bundle.getString("taskwindow.title")); // NOI18N + addWindowListener(new java.awt.event.WindowAdapter() { + public void windowClosed(java.awt.event.WindowEvent evt) { + formWindowClosed(evt); + } + }); + + btnCancel.setText(bundle.getString("taskwindow.cancel")); // NOI18N + btnCancel.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + btnCancelActionPerformed(evt); + } + }); + + pgsSingle.setStringPainted(true); + + lblSingleProgress.setText(bundle.getString("taskwindow.single_progress")); // NOI18N + + lblTotalProgress.setText(bundle.getString("taskwindow.total_progress")); // NOI18N + + pgsTotal.setStringPainted(true); + + srlDownload.setViewportView(lstDownload); + + 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(lblSingleProgress) + .addGap(349, 349, 349)) + .addComponent(pgsSingle, javax.swing.GroupLayout.DEFAULT_SIZE, 434, Short.MAX_VALUE) + .addGroup(layout.createSequentialGroup() + .addComponent(lblTotalProgress) + .addGap(0, 0, Short.MAX_VALUE)) + .addComponent(pgsTotal, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(btnCancel) + .addContainerGap()) + .addComponent(srlDownload) + ); + layout.setVerticalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(layout.createSequentialGroup() + .addComponent(srlDownload, javax.swing.GroupLayout.DEFAULT_SIZE, 241, Short.MAX_VALUE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(btnCancel, javax.swing.GroupLayout.Alignment.TRAILING) + .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup() + .addComponent(lblSingleProgress) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(pgsSingle, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(lblTotalProgress) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(pgsTotal, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))) + .addContainerGap()) + ); + + pack(); + }// //GEN-END:initComponents + + private void btnCancelActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnCancelActionPerformed + if(MessageBox.Show(C.i18n("operation.confirm_stop"), MessageBox.YES_OPTION) == MessageBox.YES_OPTION) + this.dispose(); + }//GEN-LAST:event_btnCancelActionPerformed + + private void formWindowClosed(java.awt.event.WindowEvent evt) {//GEN-FIRST:event_formWindowClosed + if (!this.failReasons.isEmpty()) { + MessageBox.Show(StrUtils.parseParams("", failReasons.toArray(), "\n"), C.i18n("message.error"), MessageBox.ERROR_MESSAGE); + failReasons.clear(); + } + + if (!suc) { + EventQueue.invokeLater(new Runnable() { + @Override + public void run() { + taskList.abort(); + } + }); + HMCLog.log("Tasks have been canceled by user."); + } + }//GEN-LAST:event_formWindowClosed + + // Variables declaration - do not modify//GEN-BEGIN:variables + private javax.swing.JButton btnCancel; + private javax.swing.JLabel lblSingleProgress; + private javax.swing.JLabel lblTotalProgress; + private javax.swing.JList lstDownload; + private javax.swing.JProgressBar pgsSingle; + private javax.swing.JProgressBar pgsTotal; + private javax.swing.JScrollPane srlDownload; + // End of variables declaration//GEN-END:variables + + @Override + public void setProgress(int progress, int max) { + pgsSingle.setMaximum(max); + pgsSingle.setValue(progress); + } + + @Override + public void onDone() { + suc = true; + this.dispose(); + HMCLog.log("Tasks are finished."); + } + + @Override + public void onDoing(Task task) { + if (!task.isParallelExecuting()) + task.setProgressProviderListener(this); + + SwingUtils.appendLast(lstDownload, task.getInfo()); + SwingUtils.moveEnd(srlDownload); + } + + public boolean areTasksFinished() { + return suc; + } + + @Override + public void onDone(Task task) { + pgsTotal.setMaximum(taskList.taskCount()); + pgsTotal.setValue(pgsTotal.getValue() + 1); + } + + @Override + public void onFailed(Task task) { + failReasons.add(task.getInfo() + ": " + (task.getFailReason() == null ? "No exception" : task.getFailReason().getLocalizedMessage())); + pgsTotal.setMaximum(taskList.taskCount()); + pgsTotal.setValue(pgsTotal.getValue() + 1); + SwingUtils.replaceLast(lstDownload, task.getFailReason()); + SwingUtils.moveEnd(srlDownload); + } + + @Override + public void onProgressProviderDone() { + + } + + @Override + public void setStatus(String sta) { + SwingUtils.replaceLast(lstDownload, sta); + } +} diff --git a/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/tasks/communication/DefaultPreviousResult.java b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/tasks/communication/DefaultPreviousResult.java new file mode 100644 index 000000000..7d62b8784 --- /dev/null +++ b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/tasks/communication/DefaultPreviousResult.java @@ -0,0 +1,24 @@ +/* + * 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.tasks.communication; + +/** + * + * @author huangyuhui + */ +public class DefaultPreviousResult implements PreviousResult{ + T a; + + public DefaultPreviousResult(T a) { + this.a = a; + } + + @Override + public T getResult() { + return a; + } + +} diff --git a/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/tasks/communication/PreviousResult.java b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/tasks/communication/PreviousResult.java new file mode 100644 index 000000000..0f0e55f00 --- /dev/null +++ b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/tasks/communication/PreviousResult.java @@ -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.tasks.communication; + +/** + * + * @author hyh + * @param Task result type + */ +public interface PreviousResult { + + T getResult(); + +} diff --git a/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/tasks/communication/PreviousResultRegistrator.java b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/tasks/communication/PreviousResultRegistrator.java new file mode 100644 index 000000000..bdbbecb97 --- /dev/null +++ b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/tasks/communication/PreviousResultRegistrator.java @@ -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.tasks.communication; + +import org.jackhuang.hellominecraft.tasks.Task; + +/** + * + * @author hyh + * @param Previous task result type + */ +public interface PreviousResultRegistrator { + + /** + * + * @param pr previous task handler + * @return task self instance + */ + Task registerPreviousResult(PreviousResult pr); +} diff --git a/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/tasks/download/ContentGetAndShowTask.java b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/tasks/download/ContentGetAndShowTask.java new file mode 100644 index 000000000..756647c8d --- /dev/null +++ b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/tasks/download/ContentGetAndShowTask.java @@ -0,0 +1,43 @@ +/* + * 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.tasks.download; + +import org.jackhuang.hellominecraft.utils.functions.Consumer; +import org.jackhuang.hellominecraft.utils.Event; +import org.jackhuang.hellominecraft.views.LogWindow; + +/** + * + * @author hyh + */ +public class ContentGetAndShowTask extends HTTPGetTask implements Event { + + public ContentGetAndShowTask(String info, String changeLogUrl) { + super(changeLogUrl); + this.info = info; + } + + @Override + public boolean executeTask() { + tdtsl.register(this); + return super.executeTask(); + } + + String info; + + @Override + public String getInfo() { + return info; + } + + @Override + public boolean call(Object sender, String value) { + LogWindow.instance.clean(); + LogWindow.instance.log(value); + LogWindow.instance.setVisible(true); + return true; + } +} diff --git a/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/tasks/download/DownloadListener.java b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/tasks/download/DownloadListener.java new file mode 100644 index 000000000..ab297dc13 --- /dev/null +++ b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/tasks/download/DownloadListener.java @@ -0,0 +1,17 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package org.jackhuang.hellominecraft.tasks.download; + +import org.jackhuang.hellominecraft.tasks.ProgressProviderListener; + +/** + * + * @author hyh + */ +public interface DownloadListener extends ProgressProviderListener { + + boolean OnFailed(); + void OnFailedMoreThan5Times(String url); +} \ No newline at end of file diff --git a/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/tasks/download/FileDownloadTask.java b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/tasks/download/FileDownloadTask.java new file mode 100644 index 000000000..b171034c3 --- /dev/null +++ b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/tasks/download/FileDownloadTask.java @@ -0,0 +1,247 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package org.jackhuang.hellominecraft.tasks.download; + +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.io.RandomAccessFile; +import java.net.HttpURLConnection; +import java.net.URL; +import java.security.GeneralSecurityException; +import java.security.cert.X509Certificate; +import java.util.ArrayList; +import javax.net.ssl.HostnameVerifier; +import javax.net.ssl.HttpsURLConnection; +import javax.net.ssl.SSLContext; +import javax.net.ssl.SSLSession; +import javax.net.ssl.X509TrustManager; +import 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.utils.IOUtils; + +/** + * + * @author hyh + */ +// This class downloads a file from a URL. +public class FileDownloadTask extends Task implements PreviousResult, PreviousResultRegistrator { + + private static final X509TrustManager xtm = new X509TrustManager() { + @Override + public void checkClientTrusted(X509Certificate[] chain, String authType) { + } + + @Override + public void checkServerTrusted(X509Certificate[] chain, String authType) { + } + + @Override + public X509Certificate[] getAcceptedIssuers() { + return null; + } + }; + private static final HostnameVerifier hnv = new HostnameVerifier() { + @Override + public boolean verify(String hostname, SSLSession session) { + return true; + } + }; + + static { + SSLContext sslContext = null; + + try { + sslContext = SSLContext.getInstance("TLS"); + X509TrustManager[] xtmArray = new X509TrustManager[]{xtm}; + sslContext.init(null, xtmArray, new java.security.SecureRandom()); + } catch (GeneralSecurityException gse) { + } + if (sslContext != null) { + HttpsURLConnection.setDefaultSSLSocketFactory(sslContext.getSocketFactory()); + } + + HttpsURLConnection.setDefaultHostnameVerifier(hnv); + } + + // Max size of download buffer. + private static final int MAX_BUFFER_SIZE = 2048; + + private URL url; // download URL + private int size; // size of download in bytes + private int downloaded; // number of bytes downloaded + private final File filePath; + + public FileDownloadTask(File filePath) { + this((URL) null, filePath); + } + + public FileDownloadTask(String url, File filePath) { + this(IOUtils.parseURL(url), filePath); + } + + // Constructor for Download. + public FileDownloadTask(URL url, File filePath) { + this.url = url; + size = -1; + downloaded = 0; + this.filePath = filePath; + } + + // Get this download's URL. + public String getUrl() { + return url.toString(); + } + + RandomAccessFile file = null; + InputStream stream = null; + boolean shouldContinue = true, aborted = false; + + private void closeFiles() { + // Close file. + if (file != null) { + try { + file.close(); + file = null; + } catch (IOException e) { + HMCLog.warn("Failed to close file", e); + } + } + + // Close connection to server. + if (stream != null) { + try { + stream.close(); + stream = null; + } catch (IOException e) { + HMCLog.warn("Failed to close stream", e); + } + } + } + + // Download file. + @Override + public boolean executeTask() { + for (PreviousResult p : al) { + this.url = IOUtils.parseURL(p.getResult()); + } + + for (int repeat = 0; repeat < 6; repeat++) { + if (repeat > 0) { + HMCLog.warn("Failed to download, repeat: " + repeat); + } + try { + + // Open connection to URL. + HttpURLConnection connection + = (HttpURLConnection) url.openConnection(); + + connection.setConnectTimeout(5000); + connection.setRequestProperty("User-Agent", "Hello Minecraft! Launcher"); + + // Connect to server. + connection.connect(); + + // Make sure response code is in the 200 range. + if (connection.getResponseCode() / 100 != 2) { + setFailReason(new NetException(C.i18n("download.not_200") + " " + connection.getResponseCode())); + return false; + } + + // Check for valid content length. + int contentLength = connection.getContentLength(); + if (contentLength < 1) { + setFailReason(new NetException("The content length is invalid.")); + return false; + } + + // Set the size for this download if it hasn't been already set. + if (size == -1) { + size = contentLength; + } + + filePath.getParentFile().mkdirs(); + + File tempFile = new File(filePath.getAbsolutePath() + ".hmd"); + if (!tempFile.exists()) { + tempFile.createNewFile(); + } + + // Open file and seek to the end of it. + file = new RandomAccessFile(tempFile, "rw"); + file.seek(downloaded); + + stream = connection.getInputStream(); + while (true) { + // Size buffer according to how much of the file is left to download. + if (!shouldContinue) { + closeFiles(); + filePath.delete(); + break; + } + + byte buffer[] = new byte[MAX_BUFFER_SIZE]; + + // Read from server into buffer. + int read = stream.read(buffer); + if (read == -1) { + break; + } + + // Write buffer to file. + file.write(buffer, 0, read); + downloaded += read; + + if (ppl != null) { + ppl.setProgress(downloaded, size); + } + } + closeFiles(); + tempFile.renameTo(filePath); + if (ppl != null) { + ppl.onProgressProviderDone(); + } + return true; + } catch (Exception e) { + setFailReason(new NetException(C.i18n("download.failed") + " " + url, e)); + } finally { + closeFiles(); + } + } + return false; + } + + public static void download(String url, String file, DownloadListener dl) { + ((Task) new FileDownloadTask(url, new File(file)).setProgressProviderListener(dl)).executeTask(); + } + + @Override + public boolean abort() { + shouldContinue = false; + aborted = true; + return true; + } + + @Override + public String getInfo() { + return C.i18n("download") + ": " + url + " " + filePath; + } + + @Override + public File getResult() { + return filePath; + } + + ArrayList> al = new ArrayList(); + + @Override + public Task registerPreviousResult(PreviousResult pr) { + al.add(pr); + return this; + } +} diff --git a/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/tasks/download/HTTPGetTask.java b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/tasks/download/HTTPGetTask.java new file mode 100644 index 000000000..32a27da5b --- /dev/null +++ b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/tasks/download/HTTPGetTask.java @@ -0,0 +1,85 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package org.jackhuang.hellominecraft.tasks.download; + +import java.io.ByteArrayOutputStream; +import java.io.InputStream; +import java.net.URL; +import java.net.URLConnection; +import org.jackhuang.hellominecraft.HMCLog; +import org.jackhuang.hellominecraft.tasks.TaskInfo; +import org.jackhuang.hellominecraft.tasks.communication.PreviousResult; +import org.jackhuang.hellominecraft.utils.EventHandler; + +/** + * + * @author hyh + */ +public class HTTPGetTask extends TaskInfo implements PreviousResult { + + String url, encoding, result; + EventHandler tdtsl = new EventHandler<>(this); + boolean shouldContinue = true; + + public HTTPGetTask(String url) { + this(null, url); + } + + public HTTPGetTask(String info, String url) { + this(info, url, "UTF-8"); + } + + public HTTPGetTask(String info, String url, String encoding) { + super(info); + this.url = url; + this.encoding = encoding; + } + + @Override + public boolean executeTask() { + for (int repeat = 0; repeat < 6; repeat++) { + if (repeat > 0) HMCLog.warn("Failed to download, repeat: " + repeat); + try { + URLConnection conn = new URL(url).openConnection(); + InputStream is = conn.getInputStream(); + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + int i; + int size = conn.getContentLength(), read = 0; + while ((i = is.read()) != -1) { + baos.write(i); + if (ppl != null) { + ppl.setProgress(++read, size); + } + if (!shouldContinue) { + return true; + } + } + result = baos.toString(); + tdtsl.execute(result); + return true; + } catch (Exception ex) { + setFailReason(new NetException("Failed to get " + url, ex)); + } + } + return false; + } + + @Override + public boolean abort() { + shouldContinue = false; + return true; + } + + @Override + public String getInfo() { + return super.getInfo() != null ? super.getInfo() : "Get: " + url; + } + + @Override + public String getResult() { + return result; + } + +} diff --git a/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/tasks/download/NetException.java b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/tasks/download/NetException.java new file mode 100644 index 000000000..8b5afe29a --- /dev/null +++ b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/tasks/download/NetException.java @@ -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.tasks.download; + +/** + * + * @author hyh + */ +public class NetException extends RuntimeException { + + public NetException(String message) { + super(message); + } + + public NetException(String message, Exception e) { + super(message, e); + } + +} diff --git a/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/utils/ArrayUtils.java b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/utils/ArrayUtils.java new file mode 100644 index 000000000..30e72553c --- /dev/null +++ b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/utils/ArrayUtils.java @@ -0,0 +1,122 @@ +/* + * 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.utils; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +/** + * + * @author hyh + */ +public class ArrayUtils { + + public static boolean isEmpty(T[] array) { + return array == null || array.length <= 0; + } + + public static boolean isNotEmpty(T[] array) { + return !isEmpty(array); + } + + public static boolean contains(T[] array, T objectToFind) { + return indexOf(array, objectToFind) != -1; + } + + public static int indexOf(T[] array, T valueToFind) { + return indexOf(array, valueToFind, 0); + } + + public static int indexOf(T[] array, T valueToFind, int startIndex) { + if (array == null) { + return -1; + } + if (startIndex < 0) { + startIndex = 0; + } + for (int i = startIndex; i < array.length; i++) { + if (valueToFind.equals(array[i])) { + return i; + } + } + return -1; + } + + public static int lastIndexOf(T[] array, T valueToFind) { + return lastIndexOf(array, valueToFind, 2147483647); + } + + public static int lastIndexOf(T[] array, T valueToFind, int startIndex) { + if (array == null) { + return -1; + } + if (startIndex < 0) { + return -1; + } + if (startIndex >= array.length) { + startIndex = array.length - 1; + } + for (int i = startIndex; i >= 0; i--) { + if (valueToFind.equals(array[i])) { + return i; + } + } + return -1; + } + + public static ArrayList merge(List a, List b) { + ArrayList al = new ArrayList(a.size() + b.size()); + al.addAll(a); al.addAll(b); + return al; + } + + public static K getEnd(K[] k) { + if(k == null) return null; + else return k[k.length-1]; + } + + public static List tryGetMapWithList(Map map, String key) { + List l = (List)map.get(key); + if(l == null) + map.put(key, l = new ArrayList()); + return l; + } + + public static int matchArray(T[] a, T[] b) { + for (int i = 0; i < a.length - b.length; i++) { + int j = 1; + for (int k = 0; k < b.length; k++) { + if (b[k].equals(a[(i + k)])) { + continue; + } + j = 0; + break; + } + if (j != 0) { + return i; + } + } + return -1; + } + + public static int matchArray(byte[] a, byte[] b) { + for (int i = 0; i < a.length - b.length; i++) { + int j = 1; + for (int k = 0; k < b.length; k++) { + if (b[k] == a[(i + k)]) { + continue; + } + j = 0; + break; + } + if (j != 0) { + return i; + } + } + return -1; + } +} diff --git a/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/utils/Base64.java b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/utils/Base64.java new file mode 100644 index 000000000..e2d20f85e --- /dev/null +++ b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/utils/Base64.java @@ -0,0 +1,100 @@ +/* + * 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.utils; + +import java.io.UnsupportedEncodingException; + +/** + * + * @author hyh + */ +public class Base64 { + + public static char[] encode(byte[] data) { + char[] out = new char[((data.length + 2) / 3) * 4]; + for (int i = 0, index = 0; i < data.length; i += 3, index += 4) { + boolean quad = false; + boolean trip = false; + int val = (0xFF & (int) data[i]); + val <<= 8; + if ((i + 1) < data.length) { + val |= (0xFF & (int) data[i + 1]); + trip = true; + } + val <<= 8; + if ((i + 2) < data.length) { + val |= (0xFF & (int) data[i + 2]); + quad = true; + } + out[index + 3] = alphabet[(quad ? (val & 0x3F) : 64)]; + val >>= 6; + out[index + 2] = alphabet[(trip ? (val & 0x3F) : 64)]; + val >>= 6; + out[index + 1] = alphabet[val & 0x3F]; + val >>= 6; + out[index + 0] = alphabet[val & 0x3F]; + } + return out; + } + + public static char[] encode(String s, String charset) throws UnsupportedEncodingException { + return encode(s.getBytes(charset)); + } + + public static char[] encode(String s) { + return encode(s.getBytes()); + } + + public static byte[] decode(char[] data) { + int len = ((data.length + 3) / 4) * 3; + if (data.length > 0 && data[data.length - 1] == '=') { + --len; + } + if (data.length > 1 && data[data.length - 2] == '=') { + --len; + } + byte[] out = new byte[len]; + int shift = 0; + int accum = 0; + int index = 0; + for (int ix = 0; ix < data.length; ix++) { + int value = codes[data[ix] & 0xFF]; + if (value >= 0) { + accum <<= 6; + shift += 6; + accum |= value; + if (shift >= 8) { + shift -= 8; + out[index++] = (byte) ((accum >> shift) & 0xff); + } + } + } + if (index != out.length) { + throw new Error("miscalculated data length!"); + } + return out; + } + private static final char[] alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=" + .toCharArray(); + private static final byte[] codes = new byte[256]; + + static { + for (int i = 0; i < 256; i++) { + codes[i] = -1; + } + for (int i = 'A'; i <= 'Z'; i++) { + codes[i] = (byte) (i - 'A'); + } + for (int i = 'a'; i <= 'z'; i++) { + codes[i] = (byte) (26 + i - 'a'); + } + for (int i = '0'; i <= '9'; i++) { + codes[i] = (byte) (52 + i - '0'); + } + codes['+'] = 62; + codes['/'] = 63; + } +} diff --git a/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/utils/BaseLauncherProfile.java b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/utils/BaseLauncherProfile.java new file mode 100644 index 000000000..f3f5a3b27 --- /dev/null +++ b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/utils/BaseLauncherProfile.java @@ -0,0 +1,21 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package org.jackhuang.hellominecraft.utils; + +import java.io.File; +import java.io.IOException; + +/** + * + * @author hyh + */ +public class BaseLauncherProfile { + public static String profile = "{\"selectedProfile\": \"(Default)\",\"profiles\": {\"(Default)\": {\"name\": \"(Default)\"}},\"clientToken\": \"88888888-8888-8888-8888-888888888888\"}"; + public static void tryWriteProfile(File gameDir) throws IOException { + File file = new File(gameDir, "launcher_profiles.json"); + if(!file.exists()) + FileUtils.writeStringToFile(file, profile); + } +} diff --git a/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/utils/Bytes.java b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/utils/Bytes.java new file mode 100644 index 000000000..49e173941 --- /dev/null +++ b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/utils/Bytes.java @@ -0,0 +1,21 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package org.jackhuang.hellominecraft.utils; + +/** + * + * @author hyh + */ +public class Bytes { + + public static String substring(String src, int start_idx, int end_idx) { + byte[] b = src.getBytes(); + String tgt = ""; + for (int i = start_idx; i <= end_idx; i++) { + tgt += (char) b[i]; + } + return tgt; + } +} \ No newline at end of file diff --git a/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/utils/Charsets.java b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/utils/Charsets.java new file mode 100644 index 000000000..f19955454 --- /dev/null +++ b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/utils/Charsets.java @@ -0,0 +1,31 @@ +/* + * 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.utils; + +import java.nio.charset.Charset; + +public class Charsets { + + public static final Charset ISO_8859_1 = Charset.forName("ISO-8859-1"); + + public static final Charset US_ASCII = Charset.forName("US-ASCII"); + + public static final Charset UTF_16 = Charset.forName("UTF-16"); + + public static final Charset UTF_16BE = Charset.forName("UTF-16BE"); + + public static final Charset UTF_16LE = Charset.forName("UTF-16LE"); + + public static final Charset UTF_8 = Charset.forName("UTF-8"); + + public static Charset toCharset(Charset charset) { + return charset == null ? Charset.defaultCharset() : charset; + } + + public static Charset toCharset(String charset) { + return charset == null ? Charset.defaultCharset() : Charset.forName(charset); + } +} diff --git a/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/utils/Compressor.java b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/utils/Compressor.java new file mode 100644 index 000000000..86e19a3d7 --- /dev/null +++ b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/utils/Compressor.java @@ -0,0 +1,183 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package org.jackhuang.hellominecraft.utils; + +import java.io.BufferedInputStream; +import java.io.BufferedOutputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.util.zip.ZipEntry; +import java.util.zip.ZipFile; +import java.util.zip.ZipOutputStream; + +/** + * 鏂囦欢鍘嬬缉/瑙e帇绫 + * + * @author hyh + */ +public class Compressor { + + public static void zip(String sourceDir, String zipFile) throws IOException { + zip(new File(sourceDir), new File(zipFile)); + } + + /** + * 鍔熻兘锛氭妸 sourceDir 鐩綍涓嬬殑鎵鏈夋枃浠惰繘琛 zip 鏍煎紡鐨勫帇缂╋紝淇濆瓨涓烘寚瀹 zip 鏂囦欢 + * + * @param sourceDir + * @param zipFile + */ + public static void zip(File sourceDir, File zipFile) throws IOException { + FileOutputStream os; + os = new FileOutputStream(zipFile); + BufferedOutputStream bos = new BufferedOutputStream(os); + try (ZipOutputStream zos = new ZipOutputStream(bos)) { + String basePath; + if (sourceDir.isDirectory()) { + basePath = sourceDir.getPath(); + } else {//鐩存帴鍘嬬缉鍗曚釜鏂囦欢鏃讹紝鍙栫埗鐩綍 + basePath = sourceDir.getParent(); + } + zipFile(sourceDir, basePath, zos); + zos.closeEntry(); + } + } + + /** + * 灏嗘枃浠跺帇缂╂垚zip鏂囦欢 + * + * @param source zip鏂囦欢璺緞 + * @param basePath 寰呭帇缂╂枃浠舵牴鐩綍 + * @param zos + */ + private static void zipFile(File source, String basePath, + ZipOutputStream zos) throws IOException { + File[] files; + if (source.isDirectory()) { + files = source.listFiles(); + } else { + files = new File[1]; + files[0] = source; + } + String pathName;//瀛樼浉瀵硅矾寰(鐩稿浜庡緟鍘嬬缉鐨勬牴鐩綍) + byte[] buf = new byte[1024]; + int length; + for (File file : files) { + if (file.isDirectory()) { + pathName = file.getPath().substring(basePath.length() + 1) + + "/"; + if (file.getName().toLowerCase().contains("meta-inf")) { + continue; + } + zos.putNextEntry(new ZipEntry(pathName)); + zipFile(file, basePath, zos); + } else { + pathName = file.getPath().substring(basePath.length() + 1); + try (InputStream is = new FileInputStream(file)) { + BufferedInputStream bis = new BufferedInputStream(is); + zos.putNextEntry(new ZipEntry(pathName)); + while ((length = bis.read(buf)) > 0) { + zos.write(buf, 0, length); + } + } + } + } + } + + public static void unzip(String zipFileName, String extPlace) throws IOException { + unzip(new File(zipFileName), new File(extPlace)); + } + + public static void unzip(File zipFileName, File extPlace) throws IOException { + unzip(zipFileName, extPlace, new String[0]); + } + + /** + * 灏嗘枃浠跺帇缂╂垚zip鏂囦欢 + * + * @param zipFileName zip鏂囦欢璺緞 + * @param extPlace 寰呭帇缂╂枃浠舵牴鐩綍 + * @param without 甯﹀墠缂鐨勪笉瑙e帇 + */ + public static void unzip(File zipFileName, File extPlace, String[] without) throws IOException { + extPlace.mkdirs(); + try (ZipFile zipFile = new ZipFile(zipFileName)) { + if (zipFileName.exists()) { + String strPath, gbkPath, strtemp; + strPath = extPlace.getAbsolutePath(); + java.util.Enumeration e = zipFile.entries(); + while (e.hasMoreElements()) { + ZipEntry zipEnt = (ZipEntry) e.nextElement(); + gbkPath = zipEnt.getName(); + if(StrUtils.startsWithOne(without, gbkPath)) continue; + if (zipEnt.isDirectory()) { + strtemp = strPath + File.separator + gbkPath; + File dir = new File(strtemp); + dir.mkdirs(); + } else { + //璇诲啓鏂囦欢 + InputStream is = zipFile.getInputStream(zipEnt); + BufferedInputStream bis = new BufferedInputStream(is); + gbkPath = zipEnt.getName(); + strtemp = strPath + File.separator + gbkPath; + //寤虹洰褰 + String strsubdir = gbkPath; + for (int i = 0; i < strsubdir.length(); i++) { + if (strsubdir.substring(i, i + 1).equalsIgnoreCase("/")) { + String temp = strPath + File.separator + strsubdir.substring(0, i); + File subdir = new File(temp); + if (!subdir.exists()) { + subdir.mkdir(); + } + } + } + try (FileOutputStream fos = new FileOutputStream(strtemp); BufferedOutputStream bos = new BufferedOutputStream(fos)) { + int c; + while ((c = bis.read()) != -1) + bos.write((byte) c); + } + } + } + } + } + } + + /** + * 灏唞ip1鍚堝苟鍒皕ip2閲岄潰锛屽嵆淇濈暀zip2 + * + * @param destFile zip1 + * @param srcFile zip2 + */ + public static void merge(File destFile, File srcFile) throws IOException { + try (ZipOutputStream os = new ZipOutputStream(new FileOutputStream(destFile))) { + if (destFile.exists()) { + File extPlace = new File(IOUtils.currentDir(), "HMCL-MERGE-TEMP"); + unzip(srcFile, extPlace); + ZipFile zipFile = new ZipFile(srcFile); + if (srcFile.exists()) { + String gbkPath;//, strtemp, strPath; + //strPath = extPlace.getAbsolutePath(); + java.util.Enumeration e = zipFile.entries(); + while (e.hasMoreElements()) { + ZipEntry zipEnt = (ZipEntry) e.nextElement(); + //gbkPath = zipEnt.getName(); + if (zipEnt.isDirectory()) { + //strtemp = strPath + File.separator + gbkPath; + } else { + gbkPath = zipEnt.getName(); + //strtemp = strPath + File.separator + gbkPath; + os.putNextEntry(zipEnt); + os.write(gbkPath.getBytes("UTF-8")); + } + } + } + } + os.closeEntry(); + } + } +} diff --git a/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/utils/DigestUtils.java b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/utils/DigestUtils.java new file mode 100644 index 000000000..4ffbdacf4 --- /dev/null +++ b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/utils/DigestUtils.java @@ -0,0 +1,273 @@ +/* + * 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.utils; + +import java.io.IOException; +import java.io.InputStream; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; + +/** + * + * @author hyh + */ +public class DigestUtils { + + private static final int STREAM_BUFFER_LENGTH = 1024; + + private static byte[] digest(MessageDigest digest, InputStream data) + throws IOException { + return updateDigest(digest, data).digest(); + } + + public static MessageDigest getDigest(String algorithm) { + try { + return MessageDigest.getInstance(algorithm); + } catch (NoSuchAlgorithmException e) { + throw new IllegalArgumentException(e); + } + } + + public static MessageDigest getMd2Digest() { + return getDigest("MD2"); + } + + public static MessageDigest getMd5Digest() { + return getDigest("MD5"); + } + + public static MessageDigest getSha1Digest() { + return getDigest("SHA-1"); + } + + public static MessageDigest getSha256Digest() { + return getDigest("SHA-256"); + } + + public static MessageDigest getSha384Digest() { + return getDigest("SHA-384"); + } + + public static MessageDigest getSha512Digest() { + return getDigest("SHA-512"); + } + + @Deprecated + public static MessageDigest getShaDigest() { + return getSha1Digest(); + } + + public static byte[] md2(byte[] data) { + return getMd2Digest().digest(data); + } + + public static byte[] md2(InputStream data) + throws IOException { + return digest(getMd2Digest(), data); + } + + public static byte[] md2(String data) { + return md2(data.getBytes(Charsets.UTF_8)); + } + + public static String md2Hex(byte[] data) { + return Hex.encodeHexString(md2(data)); + } + + public static String md2Hex(InputStream data) + throws IOException { + return Hex.encodeHexString(md2(data)); + } + + public static String md2Hex(String data) { + return Hex.encodeHexString(md2(data)); + } + + public static byte[] md5(byte[] data) { + return getMd5Digest().digest(data); + } + + public static byte[] md5(InputStream data) + throws IOException { + return digest(getMd5Digest(), data); + } + + public static byte[] md5(String data) { + return md5(data.getBytes(Charsets.UTF_8)); + } + + public static String md5Hex(byte[] data) { + return Hex.encodeHexString(md5(data)); + } + + public static String md5Hex(InputStream data) + throws IOException { + return Hex.encodeHexString(md5(data)); + } + + public static String md5Hex(String data) { + return Hex.encodeHexString(md5(data)); + } + + @Deprecated + public static byte[] sha(byte[] data) { + return sha1(data); + } + + @Deprecated + public static byte[] sha(InputStream data) + throws IOException { + return sha1(data); + } + + @Deprecated + public static byte[] sha(String data) { + return sha1(data); + } + + public static byte[] sha1(byte[] data) { + return getSha1Digest().digest(data); + } + + public static byte[] sha1(InputStream data) + throws IOException { + return digest(getSha1Digest(), data); + } + + public static byte[] sha1(String data) { + return sha1(data.getBytes(Charsets.UTF_8)); + } + + public static String sha1Hex(byte[] data) { + return Hex.encodeHexString(sha1(data)); + } + + public static String sha1Hex(InputStream data) + throws IOException { + return Hex.encodeHexString(sha1(data)); + } + + public static String sha1Hex(String data) { + return Hex.encodeHexString(sha1(data)); + } + + public static byte[] sha256(byte[] data) { + return getSha256Digest().digest(data); + } + + public static byte[] sha256(InputStream data) + throws IOException { + return digest(getSha256Digest(), data); + } + + public static byte[] sha256(String data) { + return sha256(data.getBytes(Charsets.UTF_8)); + } + + public static String sha256Hex(byte[] data) { + return Hex.encodeHexString(sha256(data)); + } + + public static String sha256Hex(InputStream data) + throws IOException { + return Hex.encodeHexString(sha256(data)); + } + + public static String sha256Hex(String data) { + return Hex.encodeHexString(sha256(data)); + } + + public static byte[] sha384(byte[] data) { + return getSha384Digest().digest(data); + } + + public static byte[] sha384(InputStream data) + throws IOException { + return digest(getSha384Digest(), data); + } + + public static byte[] sha384(String data) { + return sha384(data.getBytes(Charsets.UTF_8)); + } + + public static String sha384Hex(byte[] data) { + return Hex.encodeHexString(sha384(data)); + } + + public static String sha384Hex(InputStream data) + throws IOException { + return Hex.encodeHexString(sha384(data)); + } + + public static String sha384Hex(String data) { + return Hex.encodeHexString(sha384(data)); + } + + public static byte[] sha512(byte[] data) { + return getSha512Digest().digest(data); + } + + public static byte[] sha512(InputStream data) + throws IOException { + return digest(getSha512Digest(), data); + } + + public static byte[] sha512(String data) { + return sha512(data.getBytes(Charsets.UTF_8)); + } + + public static String sha512Hex(byte[] data) { + return Hex.encodeHexString(sha512(data)); + } + + public static String sha512Hex(InputStream data) + throws IOException { + return Hex.encodeHexString(sha512(data)); + } + + public static String sha512Hex(String data) { + return Hex.encodeHexString(sha512(data)); + } + + @Deprecated + public static String shaHex(byte[] data) { + return sha1Hex(data); + } + + @Deprecated + public static String shaHex(InputStream data) + throws IOException { + return sha1Hex(data); + } + + @Deprecated + public static String shaHex(String data) { + return sha1Hex(data); + } + + public static MessageDigest updateDigest(MessageDigest messageDigest, byte[] valueToDigest) { + messageDigest.update(valueToDigest); + return messageDigest; + } + + public static MessageDigest updateDigest(MessageDigest digest, InputStream data) + throws IOException { + byte[] buffer = new byte[STREAM_BUFFER_LENGTH]; + int read = data.read(buffer, 0, STREAM_BUFFER_LENGTH); + + while (read > -1) { + digest.update(buffer, 0, read); + read = data.read(buffer, 0, STREAM_BUFFER_LENGTH); + } + + return digest; + } + + public static MessageDigest updateDigest(MessageDigest messageDigest, String valueToDigest) { + messageDigest.update(valueToDigest.getBytes(Charsets.UTF_8)); + return messageDigest; + } +} diff --git a/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/utils/DoubleOutputStream.java b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/utils/DoubleOutputStream.java new file mode 100644 index 000000000..b162d4378 --- /dev/null +++ b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/utils/DoubleOutputStream.java @@ -0,0 +1,91 @@ +/* + * 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.utils; + +import java.io.IOException; +import java.io.OutputStream; + +/** + * + * @author hyh + */ +public class DoubleOutputStream extends OutputStream { + + private OutputStream a = null; + private OutputStream b = null; + private boolean c = true; + + public DoubleOutputStream(OutputStream paramOutputStream1, OutputStream paramOutputStream2) { + this(paramOutputStream1, paramOutputStream2, true); + } + + private DoubleOutputStream(OutputStream paramOutputStream1, OutputStream paramOutputStream2, boolean paramBoolean) { + this.a = paramOutputStream1; + this.b = paramOutputStream2; + this.c = true; + } + + @Override + public final void write(byte[] arr, int off, int len) throws IOException { + if (this.a != null) { + this.a.write(arr, off, len); + } + if (this.b != null) { + this.b.write(arr, off, len); + } + if (this.c) { + flush(); + } + } + + @Override + public final void write(byte[] paramArrayOfByte) throws IOException { + if (this.a != null) { + this.a.write(paramArrayOfByte); + } + if (this.b != null) { + this.b.write(paramArrayOfByte); + } + if (this.c) { + flush(); + } + } + + @Override + public final void write(int paramInt) throws IOException { + if (this.a != null) { + this.a.write(paramInt); + } + if (this.b != null) { + this.b.write(paramInt); + } + if (this.c) { + flush(); + } + } + + @Override + public final void close() throws IOException { + flush(); + + if (this.a != null) { + this.a.close(); + } + if (this.b != null) { + this.b.close(); + } + } + + @Override + public final void flush() throws IOException { + if (this.a != null) { + this.a.flush(); + } + if (this.b != null) { + this.b.flush(); + } + } +} diff --git a/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/utils/Event.java b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/utils/Event.java new file mode 100644 index 000000000..6499968ad --- /dev/null +++ b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/utils/Event.java @@ -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.utils; + +/** + * + * @author huangyuhui + * @param EventArgs + */ +public interface Event { + boolean call(Object sender, T t); +} diff --git a/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/utils/EventHandler.java b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/utils/EventHandler.java new file mode 100644 index 000000000..a01f72f62 --- /dev/null +++ b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/utils/EventHandler.java @@ -0,0 +1,39 @@ +/* + * 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.utils; + +import java.util.HashSet; + +/** + * + * @author huangyuhui + * @param EventArgs + */ +public class EventHandler { + HashSet> handlers; + Object sender; + + public EventHandler(Object sender) { + handlers = new HashSet<>(); + this.sender = sender; + } + + public void register(Event t) { + handlers.add(t); + } + + public void unregister(Event t) { + handlers.remove(t); + } + + public boolean execute(T x) { + boolean flag = true; + for(Event t : handlers) + if(!t.call(sender, x)) flag = false; + return flag; + } + +} diff --git a/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/utils/FileUtils.java b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/utils/FileUtils.java new file mode 100644 index 000000000..d3aafae32 --- /dev/null +++ b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/utils/FileUtils.java @@ -0,0 +1,463 @@ +/* + * 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.utils; + +import java.io.File; +import java.io.FileFilter; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.nio.channels.FileChannel; +import java.util.ArrayList; +import java.util.List; +import org.jackhuang.hellominecraft.HMCLog; + +/** + * + * @author hyh + */ +public class FileUtils { + + public static void deleteDirectory(File directory) + throws IOException { + if (!directory.exists()) { + return; + } + + if (!isSymlink(directory)) { + cleanDirectory(directory); + } + + if (!directory.delete()) { + String message = "Unable to delete directory " + directory + "."; + + throw new IOException(message); + } + } + + public static boolean deleteDirectoryQuietly(File directory) { + try { + deleteDirectory(directory); + return true; + } catch(Exception e) { + HMCLog.err("Failed to delete directory " + directory, e); + return false; + } + } + + public static boolean cleanDirectoryQuietly(File directory) { + try { + cleanDirectory(directory); + return true; + } catch(Exception e) { + HMCLog.err("Failed to clean directory " + directory, e); + return false; + } + } + + public static void cleanDirectory(File directory) + throws IOException { + if (!directory.exists()) { + //String message = directory + " does not exist"; + //throw new IllegalArgumentException(message); + directory.mkdirs(); + return; + } + + if (!directory.isDirectory()) { + String message = directory + " is not a directory"; + throw new IllegalArgumentException(message); + } + + File[] files = directory.listFiles(); + if (files == null) { + throw new IOException("Failed to list contents of " + directory); + } + + IOException exception = null; + for (File file : files) { + try { + forceDelete(file); + } catch (IOException ioe) { + exception = ioe; + } + } + + if (null != exception) { + throw exception; + } + } + + public static void forceDelete(File file) + throws IOException { + if (file.isDirectory()) { + deleteDirectory(file); + } else { + boolean filePresent = file.exists(); + if (!file.delete()) { + if (!filePresent) { + throw new FileNotFoundException("File does not exist: " + file); + } + String message = "Unable to delete file: " + file; + + throw new IOException(message); + } + } + } + + public static boolean isSymlink(File file) + throws IOException { + if (file == null) { + throw new NullPointerException("File must not be null"); + } + if (File.separatorChar == '\\') { + return false; + } + File fileInCanonicalDir; + if (file.getParent() == null) { + fileInCanonicalDir = file; + } else { + File canonicalDir = file.getParentFile().getCanonicalFile(); + fileInCanonicalDir = new File(canonicalDir, file.getName()); + } + + return !fileInCanonicalDir.getCanonicalFile().equals(fileInCanonicalDir.getAbsoluteFile()); + } + + public static void copyDirectory(File srcDir, File destDir) + throws IOException { + copyDirectory(srcDir, destDir, true); + } + + public static void copyDirectory(File srcDir, File destDir, boolean preserveFileDate) + throws IOException { + copyDirectory(srcDir, destDir, null, preserveFileDate); + } + + public static void copyDirectory(File srcDir, File destDir, FileFilter filter) + throws IOException { + copyDirectory(srcDir, destDir, filter, true); + } + + public static void copyDirectory(File srcDir, File destDir, FileFilter filter, boolean preserveFileDate) + throws IOException { + if (srcDir == null) { + throw new NullPointerException("Source must not be null"); + } + if (destDir == null) { + throw new NullPointerException("Destination must not be null"); + } + if (!srcDir.exists()) { + throw new FileNotFoundException("Source '" + srcDir + "' does not exist"); + } + if (!srcDir.isDirectory()) { + throw new IOException("Source '" + srcDir + "' exists but is not a directory"); + } + if (srcDir.getCanonicalPath().equals(destDir.getCanonicalPath())) { + throw new IOException("Source '" + srcDir + "' and destination '" + destDir + "' are the same"); + } + + List exclusionList = null; + if (destDir.getCanonicalPath().startsWith(srcDir.getCanonicalPath())) { + File[] srcFiles = filter == null ? srcDir.listFiles() : srcDir.listFiles(filter); + if ((srcFiles != null) && (srcFiles.length > 0)) { + exclusionList = new ArrayList(srcFiles.length); + for (File srcFile : srcFiles) { + File copiedFile = new File(destDir, srcFile.getName()); + exclusionList.add(copiedFile.getCanonicalPath()); + } + } + } + doCopyDirectory(srcDir, destDir, filter, preserveFileDate, exclusionList); + } + + private static void doCopyDirectory(File srcDir, File destDir, FileFilter filter, boolean preserveFileDate, List exclusionList) + throws IOException { + File[] srcFiles = filter == null ? srcDir.listFiles() : srcDir.listFiles(filter); + if (srcFiles == null) { + throw new IOException("Failed to list contents of " + srcDir); + } + if (destDir.exists()) { + if (!destDir.isDirectory()) { + throw new IOException("Destination '" + destDir + "' exists but is not a directory"); + } + } else if ((!destDir.mkdirs()) && (!destDir.isDirectory())) { + throw new IOException("Destination '" + destDir + "' directory cannot be created"); + } + + if (!destDir.canWrite()) { + throw new IOException("Destination '" + destDir + "' cannot be written to"); + } + for (File srcFile : srcFiles) { + File dstFile = new File(destDir, srcFile.getName()); + if ((exclusionList == null) || (!exclusionList.contains(srcFile.getCanonicalPath()))) { + if (srcFile.isDirectory()) { + doCopyDirectory(srcFile, dstFile, filter, preserveFileDate, exclusionList); + } else { + doCopyFile(srcFile, dstFile, preserveFileDate); + } + } + + } + + if (preserveFileDate) { + destDir.setLastModified(srcDir.lastModified()); + } + } + + public static String readFileToString(File file) + throws IOException { + return NetUtils.getStreamContent(IOUtils.openInputStream(file)); + } + + public static String readFileToStringQuietly(File file) { + try { + return NetUtils.getStreamContent(IOUtils.openInputStream(file)); + } catch (IOException ex) { + HMCLog.err("Failed to read file: " + file, ex); + return null; + } + } + + public static String readFileToString(File file, String charset) + throws IOException { + return NetUtils.getStreamContent(IOUtils.openInputStream(file), charset); + } + + public static String readFileToStringIgnoreFileNotFound(File file) throws IOException { + try { + return NetUtils.getStreamContent(IOUtils.openInputStream(file)); + } catch (FileNotFoundException ex) { + return ""; + } + } + + public static void copyFile(File srcFile, File destFile) + throws IOException { + copyFile(srcFile, destFile, true); + } + + public static void copyFile(File srcFile, File destFile, boolean preserveFileDate) + throws IOException { + if (srcFile == null) { + throw new NullPointerException("Source must not be null"); + } + if (destFile == null) { + throw new NullPointerException("Destination must not be null"); + } + if (!srcFile.exists()) { + throw new FileNotFoundException("Source '" + srcFile + "' does not exist"); + } + if (srcFile.isDirectory()) { + throw new IOException("Source '" + srcFile + "' exists but is a directory"); + } + if (srcFile.getCanonicalPath().equals(destFile.getCanonicalPath())) { + throw new IOException("Source '" + srcFile + "' and destination '" + destFile + "' are the same"); + } + File parentFile = destFile.getParentFile(); + if ((parentFile != null) + && (!parentFile.mkdirs()) && (!parentFile.isDirectory())) { + throw new IOException("Destination '" + parentFile + "' directory cannot be created"); + } + + if ((destFile.exists()) && (!destFile.canWrite())) { + throw new IOException("Destination '" + destFile + "' exists but is read-only"); + } + doCopyFile(srcFile, destFile, preserveFileDate); + } + + private static void doCopyFile(File srcFile, File destFile, boolean preserveFileDate) + throws IOException { + if ((destFile.exists()) && (destFile.isDirectory())) { + throw new IOException("Destination '" + destFile + "' exists but is a directory"); + } + + FileInputStream fis = null; + FileOutputStream fos = null; + FileChannel input = null; + FileChannel output = null; + try { + fis = new FileInputStream(srcFile); + fos = new FileOutputStream(destFile); + input = fis.getChannel(); + output = fos.getChannel(); + long size = input.size(); + long pos = 0L; + long count; + while (pos < size) { + count = size - pos > 31457280L ? 31457280L : size - pos; + pos += output.transferFrom(input, pos, count); + } + } finally { + IOUtils.closeQuietly(output); + IOUtils.closeQuietly(fos); + IOUtils.closeQuietly(input); + IOUtils.closeQuietly(fis); + } + + if (srcFile.length() != destFile.length()) { + throw new IOException("Failed to copy full contents from '" + srcFile + "' to '" + destFile + "'"); + } + + if (preserveFileDate) { + destFile.setLastModified(srcFile.lastModified()); + } + } + + public static int indexOfLastSeparator(String filename) { + if (filename == null) { + return -1; + } + int lastUnixPos = filename.lastIndexOf(47); + int lastWindowsPos = filename.lastIndexOf(92); + return Math.max(lastUnixPos, lastWindowsPos); + } + + public static int indexOfExtension(String filename) { + if (filename == null) { + return -1; + } + int extensionPos = filename.lastIndexOf(46); + int lastSeparator = indexOfLastSeparator(filename); + return lastSeparator > extensionPos ? -1 : extensionPos; + } + + public static String getName(String filename) { + if (filename == null) { + return null; + } + int index = indexOfLastSeparator(filename); + return filename.substring(index + 1); + } + + public static String getBaseName(String filename) { + return removeExtension(getName(filename)); + } + + public static String getExtension(String filename) { + if (filename == null) { + return null; + } + int index = indexOfExtension(filename); + if (index == -1) { + return ""; + } + return filename.substring(index + 1); + } + + public static String removeExtension(String filename) { + if (filename == null) { + return null; + } + int index = indexOfExtension(filename); + if (index == -1) { + return filename; + } + return filename.substring(0, index); + } + + public static void writeQuietly(File file, CharSequence data) { + try { + write(file, data); + } catch(IOException e) { + HMCLog.warn("Failed to write data to file: " + file, e); + } + } + + public static void write(File file, CharSequence data) + throws IOException { + write(file, data, "UTF-8", false); + } + + public static void write(File file, CharSequence data, boolean append) + throws IOException { + write(file, data, "UTF-8", append); + } + + public static void write(File file, CharSequence data, String encoding) + throws IOException { + write(file, data, encoding, false); + } + + public static void write(File file, CharSequence data, String encoding, boolean append) + throws IOException { + String str = data == null ? null : data.toString(); + writeStringToFile(file, str, encoding, append); + } + + public static void writeStringToFile(File file, String data) + throws IOException { + writeStringToFile(file, data, "UTF-8", false); + } + + public static void writeStringToFile(File file, String data, String encoding) + throws IOException { + writeStringToFile(file, data, encoding, false); + } + + public static void writeStringToFile(File file, String data, String encoding, boolean append) + throws IOException { + OutputStream out = null; + try { + out = openOutputStream(file, append); + IOUtils.write(data, out, encoding); + out.close(); + } finally { + IOUtils.closeQuietly(out); + } + } + + public static FileInputStream openInputStream(File file) + throws IOException { + if (file.exists()) { + if (file.isDirectory()) { + throw new IOException("File '" + file + "' exists but is a directory"); + } + if (!file.canRead()) { + throw new IOException("File '" + file + "' cannot be read"); + } + } else { + throw new FileNotFoundException("File '" + file + "' does not exist"); + } + return new FileInputStream(file); + } + + public static FileOutputStream openOutputStream(File file) + throws IOException { + return openOutputStream(file, false); + } + + public static FileOutputStream openOutputStream(File file, boolean append) + throws IOException { + if (file.exists()) { + if (file.isDirectory()) { + throw new IOException("File '" + file + "' exists but is a directory"); + } + if (!file.canWrite()) { + throw new IOException("File '" + file + "' cannot be written to"); + } + } else { + File parent = file.getParentFile(); + if ((parent != null) + && (!parent.mkdirs()) && (!parent.isDirectory())) { + throw new IOException("Directory '" + parent + "' could not be created"); + } + file.createNewFile(); + } + + return new FileOutputStream(file, append); + } + + public static File[] searchSuffix(File dir, String suffix) { + ArrayList al = new ArrayList(); + File[] files = dir.listFiles(); + for(File f : files) + if(f.getName().endsWith(suffix)) al.add(f); + return al.toArray(new File[0]); + } +} diff --git a/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/utils/Hex.java b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/utils/Hex.java new file mode 100644 index 000000000..016ad0a80 --- /dev/null +++ b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/utils/Hex.java @@ -0,0 +1,124 @@ +/* + * 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.utils; + +import java.nio.charset.Charset; + +public class Hex { + + public static final Charset DEFAULT_CHARSET = Charsets.UTF_8; + public static final String DEFAULT_CHARSET_NAME = "UTF-8"; + private static final char[] DIGITS_LOWER = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'}; + + private static final char[] DIGITS_UPPER = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'}; + private final Charset charset; + + public static byte[] decodeHex(char[] data) throws Exception { + int len = data.length; + + if ((len & 0x1) != 0) { + throw new Exception("Odd number of characters."); + } + + byte[] out = new byte[len >> 1]; + + int i = 0; + for (int j = 0; j < len; i++) { + int f = toDigit(data[j], j) << 4; + j++; + f |= toDigit(data[j], j); + j++; + out[i] = (byte) (f & 0xFF); + } + + return out; + } + + public static char[] encodeHex(byte[] data) { + return encodeHex(data, true); + } + + public static char[] encodeHex(byte[] data, boolean toLowerCase) { + return encodeHex(data, toLowerCase ? DIGITS_LOWER : DIGITS_UPPER); + } + + protected static char[] encodeHex(byte[] data, char[] toDigits) { + int l = data.length; + char[] out = new char[l << 1]; + + int i = 0; + for (int j = 0; i < l; i++) { + out[(j++)] = toDigits[((0xF0 & data[i]) >>> 4)]; + out[(j++)] = toDigits[(0xF & data[i])]; + } + return out; + } + + public static String encodeHexString(byte[] data) { + return new String(encodeHex(data)); + } + + protected static int toDigit(char ch, int index) throws Exception { + int digit = Character.digit(ch, 16); + if (digit == -1) { + throw new Exception("Illegal hexadecimal character " + ch + " at index " + index); + } + return digit; + } + + public Hex() { + this.charset = DEFAULT_CHARSET; + } + + public Hex(Charset charset) { + this.charset = charset; + } + + public Hex(String charsetName) { + this(Charset.forName(charsetName)); + } + + public byte[] decode(byte[] array) throws Exception { + return decodeHex(new String(array, getCharset()).toCharArray()); + } + + public Object decode(Object object) throws Exception { + try { + char[] charArray = (object instanceof String) ? ((String) object).toCharArray() : (char[]) (char[]) object; + return decodeHex(charArray); + } catch (ClassCastException e) { + throw new Exception(e.getMessage(), e); + } + } + + public byte[] encode(byte[] array) { + return encodeHexString(array).getBytes(getCharset()); + } + + public Object encode(Object object) + throws Exception { + try { + byte[] byteArray = (object instanceof String) ? ((String) object).getBytes(getCharset()) : (byte[]) (byte[]) object; + + return encodeHex(byteArray); + } catch (ClassCastException e) { + throw new Exception(e.getMessage(), e); + } + } + + public Charset getCharset() { + return this.charset; + } + + public String getCharsetName() { + return this.charset.name(); + } + + @Override + public String toString() { + return super.toString() + "[charsetName=" + this.charset + "]"; + } +} diff --git a/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/utils/IOUtils.java b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/utils/IOUtils.java new file mode 100644 index 000000000..eea97c40a --- /dev/null +++ b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/utils/IOUtils.java @@ -0,0 +1,282 @@ +/* + * 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.utils; + +import java.io.ByteArrayOutputStream; +import java.io.Closeable; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.Reader; +import java.io.Writer; +import java.net.InetAddress; +import java.net.MalformedURLException; +import java.net.NetworkInterface; +import java.net.SocketException; +import java.net.URL; +import java.net.UnknownHostException; +import java.util.ArrayList; +import org.jackhuang.hellominecraft.HMCLog; + +/** + * + * @author huang + */ +public class IOUtils { + + public static String addSeparator(String path) { + if (path == null || path.trim().length() == 0) { + return ""; + } + if (isSeparator(path.charAt(path.length() - 1))) { + return path; + } else { + return path + File.separatorChar; + } + } + + public static boolean isSeparator(char ch) { + return ch == File.separatorChar || ch == '/' || ch == '\\'; + } + + public static String removeLastSeparator(String dir) { + String t = dir.trim(); + char ch = t.charAt(t.length() - 1); + if (isSeparator(ch)) { + return t.substring(0, t.length() - 1); + } + return t; + } + + public static String extractLastDirectory(String dir) { + String t = removeLastSeparator(dir); + int i = t.length() - 1; + while (i >= 0 && !isSeparator(dir.charAt(i))) { + i--; + } + if (i < 0) { + return t; + } + return t.substring(i + 1, (t.length() - i) + (i + 1) - 1); + } + + public static ArrayList findAllFile(File f) { + ArrayList arr = new ArrayList<>(); + if (f.isDirectory()) { + File[] f1 = f.listFiles(); + int len = f1.length; + for (int i = 0; i < len; i++) { + if (f1[i].isFile()) { + arr.add(f1[i].getName()); + } + } + } + return arr; + } + + public static ArrayList findAllFileWithFullName(File f) { + ArrayList arr = new ArrayList<>(); + if (f.isDirectory()) { + File[] f1 = f.listFiles(); + int len = f1.length; + for (int i = 0; i < len; i++) { + if (f1[i].isFile()) { + arr.add(addSeparator(f.getAbsolutePath()) + f1[i].getName()); + } + } + } + return arr; + } + + public static ArrayList findAllDir(File f) { + ArrayList arr = new ArrayList<>(); + if (f.isDirectory()) { + File[] f1 = f.listFiles(); + int len = f1.length; + for (int i = 0; i < len; i++) { + if (f1[i].isDirectory()) { + arr.add(f1[i].getName()); + } + } + } + return arr; + } + + public static File currentDir() { + return new File("."); + } + + public static String currentDirWithSeparator() { + return addSeparator(currentDir().getAbsolutePath()); + } + + public static String getLocalMAC() { + InetAddress addr; + try { + addr = InetAddress.getLocalHost(); + String ip = addr.getHostAddress(); + return getMacAddress(ip); + } catch (UnknownHostException e) { + HMCLog.warn("Failed to get local mac address because of the unknown host.", e); + } + return "ERROR"; + } + + public static String getMacAddress(String host) { + String mac; + StringBuilder sb = new StringBuilder(); + + try { + NetworkInterface ni = NetworkInterface.getByInetAddress(InetAddress.getByName(host)); + + byte[] macs = ni.getHardwareAddress(); + + for (int i = 0; i < macs.length; i++) { + mac = Integer.toHexString(macs[i] & 0xFF); + + if (mac.length() == 1) { + mac = '0' + mac; + } + + sb.append(mac).append("-"); + } + + } catch (SocketException e) { + HMCLog.warn("Failed to get mac address because the socket has thrown an exception.", e); + } catch (UnknownHostException e) { + HMCLog.warn("Failed to get mac address because of the unknown host.", e); + } + + mac = sb.toString(); + mac = mac.substring(0, mac.length() - 1); + + return mac; + } + + public static String extractFileName(String fileName) { + File file = new File(fileName); + return file.getName(); + } + + public static String getJavaDir() { + String path = System.getProperty("java.home") + File.separatorChar + "bin" + File.separatorChar; + path = addSeparator(path); + if (OS.os() == OS.WINDOWS && new File(path + "javaw.exe").isFile()) { + return path + "javaw.exe"; + } else { + return path + "java"; + } + } + + public static byte[] readFully(InputStream stream) throws IOException { + byte[] data = new byte[4096]; + ByteArrayOutputStream entryBuffer = new ByteArrayOutputStream(); + int len; + do { + len = stream.read(data); + if (len <= 0) { + continue; + } + entryBuffer.write(data, 0, len); + } while (len != -1); + + return entryBuffer.toByteArray(); + } + + public static void closeQuietly(Reader input) { + closeQuietly((Closeable) input); + } + + public static void closeQuietly(Writer output) { + closeQuietly((Closeable) output); + } + + public static void closeQuietly(InputStream input) { + closeQuietly((Closeable) input); + } + + public static void closeQuietly(OutputStream output) { + closeQuietly((Closeable) output); + } + + public static void closeQuietly(Closeable closeable) { + try { + if (closeable != null) { + closeable.close(); + } + } catch (IOException ioe) { + } + } + + public static void write(byte[] data, OutputStream output) + throws IOException { + if (data != null) { + output.write(data); + } + } + + public static void write(String data, OutputStream output, String encoding) + throws IOException { + if (data != null) { + output.write(data.getBytes(encoding)); + } + } + + public static FileInputStream openInputStream(File file) + throws IOException { + if (file.exists()) { + if (file.isDirectory()) { + throw new IOException("File '" + file + "' exists but is a directory"); + } + if (!file.canRead()) { + throw new IOException("File '" + file + "' cannot be read"); + } + } else { + throw new FileNotFoundException("File '" + file + "' does not exist"); + } + return new FileInputStream(file); + } + + public static String tryGetCanonicalFolderPath(File file) { + try { + return IOUtils.addSeparator(file.getCanonicalPath()); + } catch (IOException ex) { + return IOUtils.addSeparator(file.getAbsolutePath()); + } + } + + public static File tryGetCanonicalFile(File file) { + try { + return file.getCanonicalFile(); + } catch (IOException ex) { + return file.getAbsoluteFile(); + } + } + + public static File tryGetCanonicalFile(String file) { + return tryGetCanonicalFile(new File(file)); + } + + public static String tryGetCanonicalFilePath(File file) { + try { + return file.getCanonicalPath(); + } catch (IOException ex) { + return file.getAbsolutePath(); + } + } + + public static URL parseURL(String str) { + try { + return new URL(str); + } catch (MalformedURLException ex) { + HMCLog.warn("Failed to parse URL:" + str); + return null; + } + } +} diff --git a/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/utils/JavaProcess.java b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/utils/JavaProcess.java new file mode 100644 index 000000000..133c676d8 --- /dev/null +++ b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/utils/JavaProcess.java @@ -0,0 +1,79 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package org.jackhuang.hellominecraft.utils; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +/** + * + * @author hyh + */ +public class JavaProcess { + + private final List commands; + private final Process process; + private final ArrayList stdOutLines = new ArrayList<>(); + private final ArrayList stdErrLines = new ArrayList<>(); + + public JavaProcess(List commands, Process process, ProcessManager pm) { + this.commands = commands; + this.process = process; + if(pm != null) pm.registerProcess(this); + } + + public JavaProcess(String[] commands, Process process, ProcessManager pm) { + this(Arrays.asList(commands), process, pm); + } + + public Process getRawProcess() { + return this.process; + } + + public List getStartupCommands() { + return this.commands; + } + + public String getStartupCommand() { + return this.process.toString(); + } + + public ArrayList getStdOutLines() { + return this.stdOutLines; + } + + public ArrayList getStdErrLines() { + return this.stdErrLines; + } + + public boolean isRunning() { + try { + this.process.exitValue(); + } catch (IllegalThreadStateException ex) { + return true; + } + + return false; + } + + public int getExitCode() { + try { + return this.process.exitValue(); + } catch (IllegalThreadStateException ex) { + ex.fillInStackTrace(); + throw ex; + } + } + + @Override + public String toString() { + return "JavaProcess[commands=" + this.commands + ", isRunning=" + isRunning() + "]"; + } + + public void stop() { + this.process.destroy(); + } +} \ No newline at end of file diff --git a/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/utils/JdkVersion.java b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/utils/JdkVersion.java new file mode 100644 index 000000000..1fc2db6e2 --- /dev/null +++ b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/utils/JdkVersion.java @@ -0,0 +1,180 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package org.jackhuang.hellominecraft.utils; + +import java.io.BufferedReader; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import org.jackhuang.hellominecraft.HMCLog; + +/** + * + * @author hyh + */ +public final class JdkVersion { + + public String ver; + /** + * -1 - unkown 0 - 32Bit 1 - 64Bit + */ + public int is64Bit; + + public JdkVersion(String ver, int is64Bit) { + this.ver = ver; + this.is64Bit = is64Bit; + } + + /** + * Constant identifying the 1.5 JVM (Java 5). + */ + public static final int UNKOWN = 2; + /** + * Constant identifying the 1.5 JVM (Java 5). + */ + public static final int JAVA_15 = 2; + /** + * Constant identifying the 1.6 JVM (Java 6). + */ + public static final int JAVA_16 = 3; + /** + * Constant identifying the 1.7 JVM (Java 7). + */ + public static final int JAVA_17 = 4; + /** + * Constant identifying the 1.8 JVM (Java 8). + */ + public static final int JAVA_18 = 5; + /** + * Constant identifying the 1.9 JVM (Java 9). + */ + public static final int JAVA_19 = 6; + + private static final String javaVersion; + private static final int majorJavaVersion; + + static { + javaVersion = System.getProperty("java.version"); + // version String should look like "1.4.2_10" + if (javaVersion.contains("1.9.")) { + majorJavaVersion = JAVA_18; + } else if (javaVersion.contains("1.8.")) { + majorJavaVersion = JAVA_18; + } else if (javaVersion.contains("1.7.")) { + majorJavaVersion = JAVA_17; + } else if (javaVersion.contains("1.6.")) { + majorJavaVersion = JAVA_16; + } else { + // else leave 1.5 as default (it's either 1.5 or unknown) + majorJavaVersion = JAVA_15; + } + } + + /** + * Return the full Java version string, as returned by + * System.getProperty("java.version"). + * + * @return the full Java version string + * @see System#getProperty(String) + */ + public static String getJavaVersion() { + return javaVersion; + } + + /** + * Get the major version code. This means we can do things like + * if (getMajorJavaVersion() < JAVA_14). @retu + * + * + * rn a code comparable to the JAVA_XX codes in this class + * @return + * @see #JAVA_13 + * @see #JAVA_14 + * @see #JAVA_15 + * @see #JAVA_16 + * @see #JAVA_17 + */ + public static int getMajorJavaVersion() { + return majorJavaVersion; + } + + /** + * Convenience method to determine if the current JVM is at least Java 1.6 + * (Java 6). + * + * @return true if the current JVM is at least Java 1.6 + * @deprecated as of Spring 3.0, in favor of reflective checks for the + * specific Java 1.6 classes of interest + * @see #getMajorJavaVersion() + * @see #JAVA_16 + * @see #JAVA_17 + */ + @Deprecated + public static boolean isAtLeastJava16() { + return (majorJavaVersion >= JAVA_16); + } + + public static boolean isJava64Bit() { + String jdkBit = System.getProperty("sun.arch.data.model"); + return jdkBit.contains("64"); + } + + static Pattern p = Pattern.compile("java version \"[1-9]*\\.[1-9]*\\.[0-9]*(.*?)\""); + + public static JdkVersion getJavaVersionFromExecutable(String file) throws IOException { + String[] str = new String[]{file, "-version"}; + ProcessBuilder pb = new ProcessBuilder(str); + JavaProcess jp = new JavaProcess(str, pb.start(), null); + InputStream is = jp.getRawProcess().getErrorStream(); + BufferedReader br = null; + int lineNumber = 0; + String ver = null; + int is64Bit = -1; + try { + br = new BufferedReader(new InputStreamReader(is)); + String line; + jp.getRawProcess().waitFor(); + while ((line = br.readLine()) != null) { + lineNumber++; + switch (lineNumber) { + case 1: + Matcher m = p.matcher(line); + if (m.find()) { + ver = m.group(); + ver = ver.substring("java version \"".length(), ver.length() - 1); + } + break; + case 3: + if (line.contains("64-Bit")) { + is64Bit = 1; + } else { + is64Bit = 0; + } + break; + } + } + } catch (InterruptedException | IOException e) { + HMCLog.warn("Failed to get java version", e); + } finally { + if (br != null) { + br.close(); + } + } + return new JdkVersion(ver, is64Bit); + } + + public void write(File f) throws IOException { + if (ver != null && is64Bit != -1) { + FileUtils.write(f, ver + "\n" + is64Bit); + } + } + + public boolean isEarlyAccess() { + return ver != null && ver.endsWith("-ea"); + } +} diff --git a/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/utils/LauncherPrintStream.java b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/utils/LauncherPrintStream.java new file mode 100644 index 000000000..a5089d773 --- /dev/null +++ b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/utils/LauncherPrintStream.java @@ -0,0 +1,37 @@ +/* + * 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.utils; + +import org.jackhuang.hellominecraft.utils.functions.Consumer; +import java.io.OutputStream; +import java.io.PrintStream; +import java.util.ArrayList; + +/** + * + * @author hyh + */ +public class LauncherPrintStream extends PrintStream { + + private final ArrayList> printListeners = new ArrayList<>(); + + public LauncherPrintStream(OutputStream paramOutputStream) { + super(paramOutputStream); + } + + @Override + public final void println(String paramString) { + super.println(paramString); + + for (Consumer a1 : printListeners) { + a1.accept(paramString); + } + } + + public final void addPrintListener(Consumer paraml) { + this.printListeners.add(paraml); + } +} diff --git a/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/utils/MD5Utils.java b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/utils/MD5Utils.java new file mode 100644 index 000000000..2763ff530 --- /dev/null +++ b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/utils/MD5Utils.java @@ -0,0 +1,43 @@ +/* + * 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.utils; + +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import org.jackhuang.hellominecraft.HMCLog; + +/** + * + * @author huang + */ +public class MD5Utils { + + private static final char e[] = { + '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', + 'a', 'b', 'c', 'd', 'e', 'f' + }; + + public static String hash(String type, String source) { + try { + StringBuilder stringbuilder; + MessageDigest md = MessageDigest.getInstance(type); + md.update(source.getBytes()); + byte[] bytes = md.digest(); + int s2 = bytes.length; + stringbuilder = new StringBuilder(s2 << 1); + for (int i1 = 0; i1 < s2; i1++) { + stringbuilder.append(e[bytes[i1] >> 4 & 0xf]); + stringbuilder.append(e[bytes[i1] & 0xf]); + } + + return stringbuilder.toString(); + } catch (NoSuchAlgorithmException e) { + HMCLog.err("Failed to get md5", e); + return ""; + } + } +} diff --git a/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/utils/MathUtils.java b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/utils/MathUtils.java new file mode 100644 index 000000000..d185266dc --- /dev/null +++ b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/utils/MathUtils.java @@ -0,0 +1,43 @@ +/* + * 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.utils; + +/** + * + * @author huang + */ +public class MathUtils { + + public static int parseInt(String s, int def) { + try { + return Integer.parseInt(s); + } catch (Exception e) { + return def; + } + } + + public static boolean canParseInt(String s) { + try { + Integer.parseInt(s); + return true; + } catch (Exception e) { + return false; + } + } + + public static int parseMemory(String s, int def) { + try { + return Integer.parseInt(s); + } catch (Exception e) { + int a = parseInt(s.substring(0, s.length() - 1), def); + if(s.endsWith("g")) return a * 1024; + else if(s.endsWith("k")) return a / 1024; + else return a; + } + } + +} diff --git a/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/utils/MessageBox.java b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/utils/MessageBox.java new file mode 100644 index 000000000..9d6e00d1d --- /dev/null +++ b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/utils/MessageBox.java @@ -0,0 +1,114 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package org.jackhuang.hellominecraft.utils; + +import javax.swing.JOptionPane; +import org.jackhuang.hellominecraft.C; + +/** + * @author hyh + */ +public class MessageBox +{ + private static String Title = C.i18n("message.info"); + /** + * Buttons: OK + */ + public static final int DEFAULT_OPTION = -1; + /** + * Buttons: Yes No + */ + public static final int YES_NO_OPTION = 10; + /** + * Buttons: Yes No Cancel + */ + public static final int YES_NO_CANCEL_OPTION =11; + /** + * Buttons: OK Cancel + */ + public static final int OK_CANCEL_OPTION = 12; + /** + * User Operation: Yes + */ + public static final int YES_OPTION = 0; + /** + * User Operation: No + */ + public static final int NO_OPTION = 1; + /** + * User Operation: Cancel + */ + public static final int CANCEL_OPTION = 2; + /** + * User Operation: OK + */ + public static final int OK_OPTION = 0; + /** + * User Operation: Closed Message Box + */ + public static final int CLOSED_OPTION = -1; + /** + * Message Box Type: Error + */ + public static final int ERROR_MESSAGE = 0; + /** + * Message Box Type: Info + */ + public static final int INFORMATION_MESSAGE = 1; + /** + * Message Box Type: Warning + */ + public static final int WARNING_MESSAGE = 2; + /** + * Message Box Type: Question + */ + public static final int QUESTION_MESSAGE = 3; + /** + * Message Box Type: Plain + */ + public static final int PLAIN_MESSAGE = -1; + + /** + * Show MsgBox with title and options + * @param Msg The Message + * @param Title The title of MsgBox. + * @param Option The type of MsgBox. + * @return user operation. + */ + public static int Show(String Msg, String Title, int Option) + { + switch(Option) + { + case YES_NO_OPTION: + case YES_NO_CANCEL_OPTION: + case OK_CANCEL_OPTION: + return JOptionPane.showConfirmDialog(null, Msg, Title, Option - 10); + default: + JOptionPane.showMessageDialog(null, Msg, Title, Option); + } + return 0; + } + + /** + * Show MsgBox with options + * @param Msg The Message + * @param Option The type of MsgBox. + * @return User Operation + */ + public static int Show(String Msg, int Option) + { + return Show(Msg, Title, Option); + } + + /** + * Show Default MsgBox + * @param Msg The Message + * @return User Operation + */ + public static int Show(String Msg) + { + return Show(Msg, Title, INFORMATION_MESSAGE); + } +} \ No newline at end of file diff --git a/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/utils/MinecraftVersionRequest.java b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/utils/MinecraftVersionRequest.java new file mode 100644 index 000000000..ee8c26e92 --- /dev/null +++ b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/utils/MinecraftVersionRequest.java @@ -0,0 +1,48 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package org.jackhuang.hellominecraft.utils; + +import org.jackhuang.hellominecraft.C; + +/** + * @author hyh + */ +public class MinecraftVersionRequest { + public static final int Unkown = 0, Invaild = 1, InvaildJar = 2, + Modified = 3, OK = 4, NotFound = 5, NotReadable = 6, NotAFile = 7; + public int type; + public String version; + + public static String getResponse(MinecraftVersionRequest minecraftVersion) { + String text = ""; + switch (minecraftVersion.type) { + case MinecraftVersionRequest.Invaild: + text = C.i18n("minecraft.invalid"); + break; + case MinecraftVersionRequest.InvaildJar: + text = C.i18n("minecraft.invalid_jar"); + break; + case MinecraftVersionRequest.NotAFile: + text = C.i18n("minecraft.not_a_file"); + break; + case MinecraftVersionRequest.NotFound: + text = C.i18n("minecraft.not_found"); + break; + case MinecraftVersionRequest.NotReadable: + text = C.i18n("minecraft.not_readable"); + break; + case MinecraftVersionRequest.Modified: + text = C.i18n("minecraft.modified") + " "; + case MinecraftVersionRequest.OK: + text += minecraftVersion.version; + break; + case MinecraftVersionRequest.Unkown: + default: + text = "???"; + break; + } + return text; + } +} diff --git a/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/utils/NetUtils.java b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/utils/NetUtils.java new file mode 100644 index 000000000..179734ea5 --- /dev/null +++ b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/utils/NetUtils.java @@ -0,0 +1,175 @@ +/* + * 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.utils; + +import java.io.BufferedReader; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.OutputStreamWriter; +import java.net.HttpURLConnection; +import java.net.MalformedURLException; +import java.net.URL; +import java.net.URLConnection; +import java.util.Map; +import org.jackhuang.hellominecraft.HMCLog; + +/** + * + * @author huang + */ +public final class NetUtils { + + public static byte[] getBytesFromStream(InputStream is) throws IOException { + ByteArrayOutputStream localByteArrayOutputStream = new ByteArrayOutputStream(); + byte[] arrayOfByte1 = new byte[1024]; + int i; + while ((i = is.read(arrayOfByte1)) >= 0) { + localByteArrayOutputStream.write(arrayOfByte1, 0, i); + } + is.close(); + return localByteArrayOutputStream.toByteArray(); + } + + public static String getStreamContent(InputStream is) throws IOException { + return getStreamContent(is, DEFAULT_CHARSET); + } + + public static String getStreamContent(InputStream is, String encoding) + throws IOException { + BufferedReader br = new BufferedReader(new InputStreamReader(is, encoding)); + String result = ""; + String line; + while ((line = br.readLine()) != null) { + result += line + "\n"; + } + br.close(); + if(result.length() < 1) return ""; + else return result.substring(0, result.length() - 1); + } + + public static String doGet(String url, String encoding) throws IOException { + return getStreamContent(new URL(url).openConnection().getInputStream()); + } + + public static String doGet(String url) throws IOException { + return doGet(url, DEFAULT_CHARSET); + } + + /** + * Sends an HTTP GET request to a url + * + * @param endpoint - The URL of the server. (Example: " + * http://www.yahoo.com/search") + * @param requestParameters - all the request parameters (Example: + * "param1=val1¶m2=val2"). Note: This method will add the question mark + * (?) to the request - DO NOT add it yourself + * @return - The response from the end point + */ + public static String sendGetRequest(String endpoint, + String requestParameters) { + String result = null; + if (endpoint.startsWith("http://")) { + // Send a GET request to the servlet + try { + // Construct data + StringBuilder data = new StringBuilder(); + // Send data + String urlStr = endpoint; + if (requestParameters != null && requestParameters.length() > 0) { + urlStr += "?" + requestParameters; + } + URL url = new URL(urlStr); + URLConnection conn = url.openConnection(); + + // Get the response + InputStreamReader r = new InputStreamReader(conn.getInputStream()); + StringBuffer sb; + BufferedReader rd = new BufferedReader(r); + sb = new StringBuffer(); + String line; + while ((line = rd.readLine()) != null) + sb.append(line); + result = sb.toString(); + } catch (Exception e) { + HMCLog.warn("Failed to send get request.", e); + } + } + return result; + } + + public static String post(String url, Map params) { + URL u = null; + HttpURLConnection con = null; + StringBuilder sb = new StringBuilder(); + if (params != null) { + for (Map.Entry e : params.entrySet()) { + sb.append(e.getKey()); + sb.append("="); + sb.append(e.getValue()); + sb.append("&"); + } + sb = new StringBuilder(sb.substring(0, sb.length() - 1)); + } + System.out.println("send_url:" + url); + System.out.println("send_data:" + sb.toString()); + try { + u = new URL(url); + con = (HttpURLConnection) u.openConnection(); + con.setRequestMethod(METHOD_POST); + con.setDoOutput(true); + con.setDoInput(true); + con.setUseCaches(false); + con.setRequestProperty("Content-Type", "application/x-www-form-urlencoded"); + OutputStreamWriter osw = new OutputStreamWriter(con.getOutputStream(), DEFAULT_CHARSET); + osw.write(sb.toString()); + osw.flush(); + osw.close(); + } catch (Exception e) { + HMCLog.warn("Failed to post.", e); + } + StringBuilder buffer = new StringBuilder(); + try { + BufferedReader br = new BufferedReader(new InputStreamReader(con + .getInputStream(), DEFAULT_CHARSET)); + String temp; + while ((temp = br.readLine()) != null) { + buffer.append(temp); + buffer.append("\n"); + } + } catch (Exception e) { + e.printStackTrace(); + } + + con.disconnect(); + + return buffer.toString(); + } + private static final String METHOD_POST = "POST"; + private static final String DEFAULT_CHARSET = "UTF-8"; + + public static URL constantURL(String url) { + try { + return new URL(url); + } catch (MalformedURLException ex) { + HMCLog.err("Failed to get url instance: " + url, ex); + return null; + } + } + + public static URL concatenateURL(URL url, String query) { + try { + if ((url.getQuery() != null) && (url.getQuery().length() > 0)) { + return new URL(url.getProtocol(), url.getHost(), url.getPort(), new StringBuilder().append(url.getFile()).append("&").append(query).toString()); + } + return new URL(url.getProtocol(), url.getHost(), url.getPort(), new StringBuilder().append(url.getFile()).append("?").append(query).toString()); + } catch (MalformedURLException ex) { + throw new IllegalArgumentException("Could not concatenate given URL with GET arguments!", ex); + } + } +} diff --git a/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/utils/OS.java b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/utils/OS.java new file mode 100644 index 000000000..f48157fe5 --- /dev/null +++ b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/utils/OS.java @@ -0,0 +1,63 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package org.jackhuang.hellominecraft.utils; + +import com.sun.management.OperatingSystemMXBean; +import java.lang.management.ManagementFactory; +import org.jackhuang.hellominecraft.HMCLog; + +/** + * @author hyh + */ +public enum OS { + + LINUX, + WINDOWS, + OSX, + UNKOWN; + + public static OS os() { + String str; + if ((str = System.getProperty("os.name").toLowerCase()) + .contains("win")) { + return OS.WINDOWS; + } + if (str.contains("mac")) { + return OS.OSX; + } + if (str.contains("solaris")) { + return OS.LINUX; + } + if (str.contains("sunos")) { + return OS.LINUX; + } + if (str.contains("linux")) { + return OS.LINUX; + } + if (str.contains("unix")) { + return OS.LINUX; + } + return OS.UNKOWN; + } + + public static boolean is64Bit() { + String arch = System.getProperty("os.arch"); + return arch.contains("64"); + } + + /** + * @return Free Physical Memory Size (Byte) + */ + public static long getTotalPhysicalMemory() { + try { + OperatingSystemMXBean o = (OperatingSystemMXBean) ManagementFactory.getOperatingSystemMXBean(); + return o.getTotalPhysicalMemorySize(); + } catch(Throwable t) { + HMCLog.warn("Failed to get total physical memory size", t); + return -1; + } + } + +} diff --git a/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/utils/Pair.java b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/utils/Pair.java new file mode 100644 index 000000000..f0b3644fe --- /dev/null +++ b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/utils/Pair.java @@ -0,0 +1,20 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package org.jackhuang.hellominecraft.utils; + +/** + * + * @author hyh + */ +public class Pair { + public K key; + public V value; + + public Pair(K k, V v) { + key = k; + value = v; + } + +} diff --git a/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/utils/ProcessManager.java b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/utils/ProcessManager.java new file mode 100644 index 000000000..8ed34a30f --- /dev/null +++ b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/utils/ProcessManager.java @@ -0,0 +1,32 @@ +/* + * 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.utils; + +import java.util.HashSet; + +/** + * + * @author huangyuhui + */ +public class ProcessManager { + + private static final HashSet gameProcesses = new HashSet(); + + public void registerProcess(JavaProcess jp) { + gameProcesses.add(jp); + } + + public void stopAllProcesses() { + for(JavaProcess jp : gameProcesses) { + jp.stop(); + } + gameProcesses.clear(); + } + + public void onProcessStopped(JavaProcess p) { + gameProcesses.remove(p); + } +} diff --git a/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/utils/ProcessThread.java b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/utils/ProcessThread.java new file mode 100644 index 000000000..f8e9e4a37 --- /dev/null +++ b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/utils/ProcessThread.java @@ -0,0 +1,92 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package org.jackhuang.hellominecraft.utils; + +import java.io.BufferedReader; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.UnsupportedEncodingException; +import org.jackhuang.hellominecraft.HMCLog; + +/** + * + * @author hyh + */ +public class ProcessThread extends Thread { + + JavaProcess p; + boolean readError = false, enableReading = true; + + public final EventHandler printlnEvent = new EventHandler(this); + public final EventHandler stopEvent = new EventHandler(this); + + public ProcessThread(JavaProcess process, boolean readError, boolean enableReading) { + p = process; + this.readError = readError; + this.enableReading = enableReading; + } + + public JavaProcess getProcess() { + return p; + } + + @Override + public void run() { + InputStream in = null; + BufferedReader br = null; + if (enableReading) { + in = readError ? p.getRawProcess().getErrorStream() : p.getRawProcess().getInputStream(); + } + try { + if (enableReading) { + try { + br = new BufferedReader(new InputStreamReader(in, System.getProperty("sun.jnu.encoding", "UTF-8"))); + } catch (UnsupportedEncodingException ex) { + HMCLog.warn("Unsupported encoding: " + System.getProperty("sun.jnu.encoding", "UTF-8"), ex); + br = new BufferedReader(new InputStreamReader(in)); + } + } + + String line; + while (p.isRunning()) { + if (enableReading) { + while ((line = br.readLine()) != null) { + printlnEvent.execute(line); + if (readError) { + System.err.println(line); + p.getStdErrLines().add(line); + } else { + System.out.println(line); + p.getStdOutLines().add(line); + } + } + } else { + try { + Thread.sleep(1); + } catch (Exception e) { + } + } + } + if (enableReading) { + while ((line = br.readLine()) != null) { + printlnEvent.execute(line); + if (readError) { + System.err.println(line); + p.getStdErrLines().add(line); + } else { + System.out.println(line); + p.getStdOutLines().add(line); + } + } + } + stopEvent.execute(p); + } catch (Exception e) { + e.printStackTrace(); + } + } + + private void stopped() { + } +} diff --git a/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/utils/ReflectUtils.java b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/utils/ReflectUtils.java new file mode 100644 index 000000000..478393df9 --- /dev/null +++ b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/utils/ReflectUtils.java @@ -0,0 +1,29 @@ +/* + * 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.utils; + +import java.util.Arrays; +import java.util.HashSet; +import java.util.Set; + +/** + * + * @author hyh + */ +public class ReflectUtils { + + public static Set> getClasses(Class c) { + HashSet set = new HashSet(); + set.addAll(Arrays.asList(c.getInterfaces())); + while(c != Object.class) { + set.add(c); + c = c.getSuperclass(); + } + return set; + } + +} diff --git a/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/utils/StrUtils.java b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/utils/StrUtils.java new file mode 100644 index 000000000..3c8757a43 --- /dev/null +++ b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/utils/StrUtils.java @@ -0,0 +1,214 @@ +/* + * 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.utils; + +import java.awt.Dimension; +import java.io.PrintWriter; +import java.io.StringWriter; +import java.lang.reflect.Array; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.StringTokenizer; + +/** + * + * @author huang + */ +public final class StrUtils { + + public static String makeCommand(List cmd) { + StringBuilder cmdbuf = new StringBuilder(120); + for (int i = 0; i < cmd.size(); i++) { + if (i > 0) { + cmdbuf.append(' '); + } + String s = cmd.get(i); + if (s.indexOf(' ') >= 0 || s.indexOf('\t') >= 0) { + if (s.charAt(0) != '"') { + cmdbuf.append('"'); + cmdbuf.append(s); + if (s.endsWith("\\")) { + cmdbuf.append("\\"); + } + cmdbuf.append('"'); + } else if (s.endsWith("\"")) { + /* The argument has already been quoted. */ + cmdbuf.append(s); + } else { + /* Unmatched quote for the argument. */ + throw new IllegalArgumentException(); + } + } else { + cmdbuf.append(s); + } + } + String str = cmdbuf.toString(); + + return str; + } + + public static boolean startsWith(String base, String match) { + return base != null && base.startsWith(match); + } + + public static boolean startsWithOne(String[] a, String match) { + if (a == null) { + return false; + } + for (String b : a) { + if (startsWith(match, b)) { + return true; + } + } + return false; + } + + public static boolean equalsOne(String base, String... a) { + for (String s : a) { + if (base.equals(s)) { + return true; + } + } + return false; + } + + public static boolean containsOne(List base, List match) { + for (String a : base) { + for (String b : match) { + if (a.toLowerCase().contains(b.toLowerCase())) { + return true; + } + } + } + return false; + } + + public static int getCharShowTime(String s, char c) { + int res = 0; + for (int i = 0; i < s.length(); i++) { + if (s.charAt(i) == c) { + res++; + } + } + return res; + } + + public static String formatVersion(String ver) { + if (isBlank(ver)) { + return null; + } else { + for(char ch : ver.toCharArray()) { + if((ch < '0' || ch > '9') && ch != '.') return null; + } + } + int i = getCharShowTime(ver, '.'); + if (i == 1) { + return ver + ".0"; + } else { + return ver; + } + } + + public static String parseParams(String addBefore, Collection paramArrayOfObject, String paramString) { + return parseParams(addBefore, paramArrayOfObject.toArray(), paramString); + } + + public static String parseParams(String addBefore, Object[] paramArrayOfObject, String paramString) { + if (paramArrayOfObject == null) { + return ""; + } + StringBuilder localStringBuffer = new StringBuilder(); + for (int i = 0; i < paramArrayOfObject.length; i++) { + Object localObject = paramArrayOfObject[i]; + if (i > 0) { + localStringBuffer.append(addBefore).append(paramString); + } + if (localObject == null) { + localStringBuffer.append("null"); + } else if (localObject.getClass().isArray()) { + localStringBuffer.append("["); + + if ((localObject instanceof Object[])) { + Object[] arrayOfObject = (Object[]) localObject; + localStringBuffer.append(parseParams(addBefore, arrayOfObject, paramString)); + } else { + for (int j = 0; j < Array.getLength(localObject); j++) { + if (j > 0) { + localStringBuffer.append(paramString); + } + localStringBuffer.append(addBefore).append(Array.get(localObject, j)); + } + } + localStringBuffer.append("]"); + } else { + localStringBuffer.append(addBefore).append(paramArrayOfObject[i]); + } + } + return localStringBuffer.toString(); + } + + public static boolean isEquals(String base, String to) { + if (base == null) { + return (to == null); + } else { + return base.equals(to); + } + } + + public static Dimension parseDimension(String str) { + String[] tokenized = tokenize(str, "x,"); + if (tokenized.length != 2) { + return null; + } + int i = MathUtils.parseInt(tokenized[0], -1); + int j = MathUtils.parseInt(tokenized[1], -1); + if ((i < 0) || (j < 0)) { + return null; + } + return new Dimension(i, j); + } + + public static String[] tokenize(String paramString1) { + return tokenize(paramString1, " \t\n\r\f"); + } + + public static String[] tokenize(String paramString1, String paramString2) { + ArrayList localArrayList = new ArrayList(); + StringTokenizer tokenizer = new StringTokenizer(paramString1, paramString2); + while (tokenizer.hasMoreTokens()) { + paramString2 = tokenizer.nextToken(); + localArrayList.add(paramString2); + } + + return (String[]) localArrayList.toArray(new String[localArrayList.size()]); + } + + public static String trimExtension(String filename) { + if ((filename != null) && (filename.length() > 0)) { + int i = filename.lastIndexOf('.'); + if ((i > -1) && (i < (filename.length()))) { + return filename.substring(0, i); + } + } + return filename; + } + + public static boolean isBlank(String s) { + return s == null || s.trim().length() <= 0; + } + + public static boolean isNotBlank(String s) { + return !isBlank(s); + } + + public static String getStackTrace(Throwable t) { + StringWriter trace = new StringWriter(); + PrintWriter writer = new PrintWriter(trace); + t.printStackTrace(writer); + return trace.toString(); + } +} diff --git a/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/utils/SwingUtils.java b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/utils/SwingUtils.java new file mode 100644 index 000000000..594868a90 --- /dev/null +++ b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/utils/SwingUtils.java @@ -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.utils; + +import java.awt.Dimension; +import java.awt.Toolkit; +import java.awt.Window; +import java.net.URI; +import javax.swing.DefaultListModel; +import javax.swing.JList; +import javax.swing.JScrollBar; +import javax.swing.JScrollPane; +import javax.swing.JTable; +import javax.swing.JTextArea; +import javax.swing.table.DefaultTableModel; +import org.jackhuang.hellominecraft.HMCLog; + +/** + * + * @author huang + */ +public class SwingUtils { + + public static DefaultTableModel makeDefaultTableModel(String[] titleA, final Class[] typesA, final boolean[] canEditA) { + return new javax.swing.table.DefaultTableModel( + new Object[][]{}, + titleA) { + Class[] types = typesA; + boolean[] canEdit = canEditA; + + @Override + public Class getColumnClass(int columnIndex) { + return types[columnIndex]; + } + + @Override + public boolean isCellEditable(int rowIndex, int columnIndex) { + return canEdit[columnIndex]; + } + }; + } + + public static void openLink(URI link) { + try { + java.awt.Desktop.getDesktop().browse(link); + } catch (Throwable e) { + HMCLog.warn("Failed to open link: " + link, e); + } + } + + public static void moveEnd(JTextArea tf) { + int position = tf.getText().length(); + tf.setCaretPosition(position); + } + + public static void moveEnd(JScrollPane pane) { + JScrollBar bar = pane.getVerticalScrollBar(); + bar.setValue(bar.getMaximum()); + } + + public static DefaultListModel getDefaultListModel(JList list) { + return (DefaultListModel)list.getModel(); + } + + public static void appendLast(JList list, Object element) { + getDefaultListModel(list).addElement(element); + } + + public static void replaceLast(JList list, Object element) { + DefaultListModel model = getDefaultListModel(list); + model.set(model.getSize()-1, element); + } + + public static void clear(JList list) { + list.setModel(new DefaultListModel()); + } + + public static void clearDefaultTable(JTable table) { + DefaultTableModel model = (DefaultTableModel)table.getModel(); + while(model.getRowCount() > 0) { + model.removeRow(0); + } + table.updateUI(); + } + +} diff --git a/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/utils/TextComponentOutputStream.java b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/utils/TextComponentOutputStream.java new file mode 100644 index 000000000..128bb3a32 --- /dev/null +++ b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/utils/TextComponentOutputStream.java @@ -0,0 +1,54 @@ +/* + * 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.utils; + +import java.io.OutputStream; +import javax.swing.SwingUtilities; +import javax.swing.text.JTextComponent; +import org.jackhuang.hellominecraft.HMCLog; + +/** + * + * @author hyh + */ +public class TextComponentOutputStream extends OutputStream { + + private JTextComponent txt; + + public TextComponentOutputStream(JTextComponent paramJTextComponent) { + txt = paramJTextComponent; + } + + @Override + public final void write(byte[] paramArrayOfByte) { + write(paramArrayOfByte, 0, paramArrayOfByte.length); + } + + @Override + public final void write(byte[] paramArrayOfByte, int off, int len) { + append(new String(paramArrayOfByte, off, len)); + } + + private void append(final String newString) { + try { + SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { + String t = txt.getText() + newString.replace("\t", " "); + txt.setText(t); + txt.setCaretPosition(t.length()); + } + }); + } catch (Throwable e) { + e.printStackTrace(); + } + } + + @Override + public final void write(int paramInt) { + append(new String(new byte[]{(byte) paramInt})); + } +} diff --git a/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/utils/UpdateChecker.java b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/utils/UpdateChecker.java new file mode 100644 index 000000000..5a7e21472 --- /dev/null +++ b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/utils/UpdateChecker.java @@ -0,0 +1,68 @@ +/* + * 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.utils; + +import org.jackhuang.hellominecraft.C; +import org.jackhuang.hellominecraft.utils.functions.DoneListener0; +import org.jackhuang.hellominecraft.HMCLog; + +/** + * + * @author hyh + */ +public final class UpdateChecker extends Thread { + public static boolean OUT_DATED = false; + public VersionNumber base; + public String type; + public boolean continueUpdate; + public DoneListener0 dl; + + public UpdateChecker(VersionNumber base, String type, boolean continueUpdate, DoneListener0 dl) { + super("UpdateChecker"); + this.base = base; + this.type = type; + this.continueUpdate = continueUpdate; + this.dl = dl; + } + + VersionNumber value; + + @Override + public void run() { + + String url = "http://huangyuhui.duapp.com/info.php?type=" + type, version; + try { + version = NetUtils.doGet(url); + } catch (Exception e) { + HMCLog.warn("Failed to get update url.", e); + return; + } + value = VersionNumber.check(version); + if (!continueUpdate) { + return; + } + process(false); + } + + public void process(boolean showMessage) { + if (value == null) { + HMCLog.warn("Failed to check update..."); + if(showMessage) { + MessageBox.Show(C.i18n("update.failed")); + } + } else { + if (VersionNumber.isOlder(base, value)) { + OUT_DATED = true; + dl.onDone(); + } + } + } + + public VersionNumber getNewVersion() { + return value; + } + +} diff --git a/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/utils/Utils.java b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/utils/Utils.java new file mode 100644 index 000000000..26ffa2d5a --- /dev/null +++ b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/utils/Utils.java @@ -0,0 +1,179 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package org.jackhuang.hellominecraft.utils; + +import com.google.gson.GsonBuilder; +import com.sun.management.OperatingSystemMXBean; +import java.awt.Desktop; +import java.awt.Image; +import java.awt.Toolkit; +import java.awt.datatransfer.StringSelection; +import java.io.File; +import java.io.IOException; +import java.io.UnsupportedEncodingException; +import java.lang.management.ManagementFactory; +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.net.MalformedURLException; +import java.net.URI; +import java.net.URL; +import java.net.URLClassLoader; +import java.net.URLDecoder; +import java.util.Random; +import javax.swing.ImageIcon; +import org.jackhuang.hellominecraft.C; +import org.jackhuang.hellominecraft.HMCLog; + +/** + * @author hyh + */ +public final class Utils { + + private static final GsonBuilder gsonBuilder = new GsonBuilder().setPrettyPrinting(); + public static GsonBuilder getDefaultGsonBuilder() { + return gsonBuilder; + } + + public static String[] getURL() { + URL[] urls = ((URLClassLoader) Utils.class.getClassLoader()).getURLs(); + String[] urlStrings = new String[urls.length]; + for (int i = 0; i < urlStrings.length; i++) { + try { + urlStrings[i] = URLDecoder.decode(urls[i].getPath(), "UTF-8"); + } catch (UnsupportedEncodingException ex) { + HMCLog.warn("Unsupported UTF-8 encoding", ex); + } + } + return urlStrings; + } + + public static void addDir(String s) throws IOException { + try { + Field field = ClassLoader.class.getDeclaredField("usr_paths"); + field.setAccessible(true); + String[] paths = (String[]) field.get(null); + for (int i = 0; i < paths.length; i++) { + if (s.equals(paths[i])) { + return; + } + } + String[] tmp = new String[paths.length + 1]; + System.arraycopy(paths, 0, tmp, 0, paths.length); + tmp[paths.length] = s; + field.set(null, tmp); + } catch (IllegalAccessException e) { + throw new IOException("Failed to get permissions to set library path"); + } catch (NoSuchFieldException e) { + throw new IOException("Failed to get field handle to set library path"); + } + } + + public static int getSuggestedMemorySize() { + try { + OperatingSystemMXBean osmb = (OperatingSystemMXBean) ManagementFactory.getOperatingSystemMXBean(); + int memory = (int)(osmb.getTotalPhysicalMemorySize() / 1024 / 1024) / 4; + memory = Math.round((float)memory/128.0f)*128; + return memory; + } catch(Throwable t) { + HMCLog.warn("Failed to get total memory size, use 1024MB.", t); + return 1024; + } + } + + public static void setClipborad(String text) { + Toolkit.getDefaultToolkit().getSystemClipboard().setContents(new StringSelection(text), null); + } + + public static boolean openLink(String url) { + try { + Desktop.getDesktop().browse(new URI(url)); + return true; + } catch (Exception ex) { + HMCLog.warn("Failed to open link:" + url, ex); + return false; + } + } + + public static void openFolder(File f) { + try { + f.mkdirs(); + java.awt.Desktop.getDesktop().open(f); + } catch (Exception ex) { + MessageBox.Show(C.i18n("message.cannot_open_explorer") + ex.getMessage()); + HMCLog.warn("Failed to open folder:" + f, ex); + } + } + + public static ImageIcon scaleImage(ImageIcon i, int x, int y) { + return new ImageIcon(i.getImage().getScaledInstance(x, y, Image.SCALE_SMOOTH)); + } + + public static ImageIcon searchBackgroundImage(ImageIcon background, String bgpath, int width, int height) { + Random r = new Random(); + boolean loaded = false; + + // bgpath + if (StrUtils.isNotBlank(bgpath) && !loaded) { + String[] backgroundPath = bgpath.split(";"); + if(backgroundPath.length > 0) { + int index = r.nextInt(backgroundPath.length); + background = new ImageIcon(Toolkit.getDefaultToolkit().getImage(backgroundPath[index]).getScaledInstance(width, height, Image.SCALE_DEFAULT)); + HMCLog.log("Prepared background image in bgpath."); + loaded = true; + } + } + + // bgskin + if (!loaded) { + File backgroundImageFile = new File("bg"); + if (backgroundImageFile.exists() && backgroundImageFile.isDirectory()) { + String[] backgroundPath = backgroundImageFile.list(); + if(backgroundPath.length > 0) { + int index = r.nextInt(backgroundPath.length); + background = new ImageIcon(Toolkit.getDefaultToolkit().getImage("bg" + File.separator + backgroundPath[index]).getScaledInstance(width, height, Image.SCALE_DEFAULT)); + HMCLog.log("Prepared background image in bgskin folder."); + loaded = true; + } + } + } + + // background.png + if (!loaded) { + File backgroundImageFile = new File("background.png"); + if (backgroundImageFile.exists()) { + loaded = true; + background = new ImageIcon(Toolkit.getDefaultToolkit().getImage(backgroundImageFile.getAbsolutePath()).getScaledInstance(width, height, Image.SCALE_DEFAULT)); + HMCLog.log("Prepared background image in background.png."); + } + } + + // background.jpg + if (!loaded) { + File backgroundImageFile = new File("background.jpg"); + if (backgroundImageFile.exists()) { + loaded = true; + background = new ImageIcon(Toolkit.getDefaultToolkit().getImage(backgroundImageFile.getAbsolutePath()).getScaledInstance(width, height, Image.SCALE_DEFAULT)); + HMCLog.log("Prepared background image in background.jpg."); + } + } + + return background; + } + + /** + * In order to fight against the permission manager. + */ + public static void shutdownForcely() { + try { + Class z = Class.forName("java.lang.Shutdown"); + Method exit = z.getDeclaredMethod("exit", int.class); + exit.setAccessible(true); + exit.invoke(z, 0); + } catch(Exception e) { + MessageBox.Show(C.i18n("launcher.exit_failed")); + e.printStackTrace(); + } + } +} diff --git a/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/utils/Validate.java b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/utils/Validate.java new file mode 100644 index 000000000..87f56c4cf --- /dev/null +++ b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/utils/Validate.java @@ -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.utils; + +/** + * + * @author hyh + */ +public final class Validate { + + public static T notNull(T o) { + if(o == null) { + throw new IllegalArgumentException("The validated object is null"); + } + return o; + } + +} diff --git a/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/utils/VersionNumber.java b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/utils/VersionNumber.java new file mode 100644 index 000000000..773f11224 --- /dev/null +++ b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/utils/VersionNumber.java @@ -0,0 +1,67 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package org.jackhuang.hellominecraft.utils; + +import org.jackhuang.hellominecraft.HMCLog; + +/** + * + * @author hyh + */ +public final class VersionNumber implements Comparable { + + public byte firstVer, secondVer, thirdVer; + + public VersionNumber(byte a, byte b, byte c) { + firstVer = a; secondVer = b; thirdVer = c; + } + + public static VersionNumber check(String data) { + while (!data.isEmpty() && ((data.charAt(0) < '0' || data.charAt(0) > '9') && data.charAt(0) != '.')) { + data = data.substring(1); + } + if (data.isEmpty()) { + return null; + } + VersionNumber ur = null; + String[] ver = data.split("\\."); + if (ver.length == 3) { + byte v1, v2, v3; + try { + v1 = Byte.parseByte(ver[0]); + v2 = Byte.parseByte(ver[1]); + v3 = Byte.parseByte(ver[2]); + ur = new VersionNumber(v1, v2, v3); + return ur; + } catch (Exception e) { + HMCLog.warn("Failed to parse the version", e); + } + } + return null; + } + + public static boolean isOlder(VersionNumber a, VersionNumber b) { + if (a.firstVer < b.firstVer) { + return true; + } else if (a.firstVer == b.firstVer) { + if (a.secondVer < b.secondVer) { + return true; + } else if (a.secondVer == b.secondVer) { + if (a.thirdVer < b.thirdVer) { + return true; + } + } + } + return false; + } + + @Override + public int compareTo(VersionNumber o) { + if(isOlder(this, o)) return -1; + else if(isOlder(o, this)) return 1; + else return 0; + } + +} diff --git a/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/utils/functions/BiFunction.java b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/utils/functions/BiFunction.java new file mode 100644 index 000000000..7d3aac131 --- /dev/null +++ b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/utils/functions/BiFunction.java @@ -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.utils.functions; + +/** + * + * @author huangyuhui + */ +public interface BiFunction { + C apply(A a, B b); +} diff --git a/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/utils/functions/Consumer.java b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/utils/functions/Consumer.java new file mode 100644 index 000000000..34bc7fdf4 --- /dev/null +++ b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/utils/functions/Consumer.java @@ -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.utils.functions; + +/** + * + * @author huangyuhui + */ +public interface Consumer { + void accept(T t); +} diff --git a/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/utils/functions/DoneListener0.java b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/utils/functions/DoneListener0.java new file mode 100644 index 000000000..58bf079e5 --- /dev/null +++ b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/utils/functions/DoneListener0.java @@ -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.utils.functions; + +/** + * + * @author hyh + */ +public interface DoneListener0 { + void onDone(); +} diff --git a/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/utils/functions/DoneListener0Return.java b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/utils/functions/DoneListener0Return.java new file mode 100644 index 000000000..7af71ccbf --- /dev/null +++ b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/utils/functions/DoneListener0Return.java @@ -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.utils.functions; + +/** + * + * @author hyh + */ +public interface DoneListener0Return { + T onDone(); +} diff --git a/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/utils/functions/DoneListener2.java b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/utils/functions/DoneListener2.java new file mode 100644 index 000000000..711267e40 --- /dev/null +++ b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/utils/functions/DoneListener2.java @@ -0,0 +1,12 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package org.jackhuang.hellominecraft.utils.functions; + +/** + * @author hyh + */ +public interface DoneListener2 { + void onDone(V value, V2 value2); +} diff --git a/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/utils/functions/DoneListener3.java b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/utils/functions/DoneListener3.java new file mode 100644 index 000000000..7170f96f3 --- /dev/null +++ b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/utils/functions/DoneListener3.java @@ -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.utils.functions; + +/** + * + * @author hyh + */ +public interface DoneListener3 { + void onDone(V1 v1, V2 v2, V3 v3); +} diff --git a/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/utils/functions/FalseDoneListener.java b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/utils/functions/FalseDoneListener.java new file mode 100644 index 000000000..6005240c5 --- /dev/null +++ b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/utils/functions/FalseDoneListener.java @@ -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.utils.functions; + +/** + * + * @author hyh + */ +public class FalseDoneListener implements DoneListener0Return { + + @Override + public Boolean onDone() { + return Boolean.FALSE; + } + +} diff --git a/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/utils/functions/Function.java b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/utils/functions/Function.java new file mode 100644 index 000000000..5b0eea76e --- /dev/null +++ b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/utils/functions/Function.java @@ -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.utils.functions; + +/** + * + * @author huangyuhui + */ +public interface Function { + R apply(T t); +} diff --git a/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/utils/functions/Predicate.java b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/utils/functions/Predicate.java new file mode 100644 index 000000000..f5ac8ab46 --- /dev/null +++ b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/utils/functions/Predicate.java @@ -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.utils.functions; + +/** + * + * @author hyh + */ +public interface Predicate { + boolean apply(T t); +} diff --git a/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/utils/functions/TrueDoneListener.java b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/utils/functions/TrueDoneListener.java new file mode 100644 index 000000000..db8d3b2af --- /dev/null +++ b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/utils/functions/TrueDoneListener.java @@ -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.utils.functions; + +/** + * + * @author hyh + */ +public class TrueDoneListener implements DoneListener0Return { + + public static final TrueDoneListener instance = new TrueDoneListener(); + + private TrueDoneListener(){} + + @Override + public Boolean onDone() { + return Boolean.TRUE; + } + +} diff --git a/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/utils/tinystream/CollectionUtils.java b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/utils/tinystream/CollectionUtils.java new file mode 100644 index 000000000..53247deed --- /dev/null +++ b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/utils/tinystream/CollectionUtils.java @@ -0,0 +1,39 @@ +/* + * 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.utils.tinystream; + +import org.jackhuang.hellominecraft.utils.functions.Consumer; +import org.jackhuang.hellominecraft.utils.functions.Predicate; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Iterator; + +/** + * + * @author hyh + */ +public final class CollectionUtils { + public static void forEach(Collection coll, Consumer p) { + for(T t : coll) p.accept(t); + } + + public static Collection sortOut(Collection coll, Predicate p) { + ArrayList newColl = new ArrayList<>(); + forEach(coll, t -> { if(p.apply(t)) newColl.add(t); }); + return newColl; + } + + public static boolean removeIf(Collection coll, Predicate p) { + boolean removed = false; + final Iterator each = coll.iterator(); + while (each.hasNext()) + if (p.apply(each.next())) { + each.remove(); + removed = true; + } + return removed; + } +} diff --git a/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/utils/tinystream/Stream.java b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/utils/tinystream/Stream.java new file mode 100644 index 000000000..d94b3ea4a --- /dev/null +++ b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/utils/tinystream/Stream.java @@ -0,0 +1,91 @@ +/* + * 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.utils.tinystream; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.Comparator; +import java.util.HashSet; +import java.util.List; +import org.jackhuang.hellominecraft.utils.functions.BiFunction; +import org.jackhuang.hellominecraft.utils.functions.Consumer; +import org.jackhuang.hellominecraft.utils.functions.Function; +import org.jackhuang.hellominecraft.utils.functions.Predicate; + +/** + * + * @author huangyuhui + */ +public class Stream { + + List internal; + + public Stream(Collection internal) { + this.internal = new ArrayList<>(internal); + } + + protected Stream() { + } + + protected static Stream of(List a) { + Stream b = new Stream<>(); + b.internal = a; + return b; + } + + public Stream forEach(Consumer p) { + for (T t : internal) p.accept(t); + return this; + } + + public Stream filter(Predicate p) { + ArrayList newList = new ArrayList<>(); + forEach(a -> { + if (p.apply(a)) newList.add(a); + }); + internal = newList; + return this; + } + + public int count() { + return internal.size(); + } + + public Stream distinct() { + internal = new ArrayList<>(new HashSet<>(internal)); + return this; + } + + public Stream map(Function func) { + List newList = new ArrayList<>(internal.size()); + forEach(a -> newList.add(func.apply(a))); + return of(newList); + } + + public Stream sorted(Comparator c) { + Collections.sort(internal, c); + return this; + } + + public U reduce(U identity, BiFunction accumulator) { + for (T t : internal) identity = accumulator.apply(identity, t); + return identity; + } + + public boolean anyMatch(Predicate p) { + return map(t -> p.apply(t)).reduce(false, (accumulator, _item) -> accumulator | _item); + } + + public boolean allMatch(Predicate p) { + return map(t -> p.apply(t)).reduce(true, (accumulator, _item) -> accumulator & _item); + } + + public T findFirst() { + return internal.isEmpty() ? null : internal.get(0); + } + +} diff --git a/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/version/MinecraftRemoteLatestVersion.java b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/version/MinecraftRemoteLatestVersion.java new file mode 100644 index 000000000..71cc44530 --- /dev/null +++ b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/version/MinecraftRemoteLatestVersion.java @@ -0,0 +1,15 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package org.jackhuang.hellominecraft.version; + +/** + * + * @author hyh + */ +public class MinecraftRemoteLatestVersion { + + public String snapshot, release; + +} diff --git a/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/version/MinecraftRemoteVersion.java b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/version/MinecraftRemoteVersion.java new file mode 100644 index 000000000..98f879413 --- /dev/null +++ b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/version/MinecraftRemoteVersion.java @@ -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.version; + +/** + * + * @author hyh + */ +public class MinecraftRemoteVersion { + + public String id, time, releaseTime, type; +} diff --git a/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/version/MinecraftRemoteVersions.java b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/version/MinecraftRemoteVersions.java new file mode 100644 index 000000000..6eed696ac --- /dev/null +++ b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/version/MinecraftRemoteVersions.java @@ -0,0 +1,23 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package org.jackhuang.hellominecraft.version; + +import java.util.ArrayList; +import org.jackhuang.hellominecraft.C; + +/** + * + * @author hyh + */ +public class MinecraftRemoteVersions { + + public ArrayList versions; + public MinecraftRemoteLatestVersion latest; + + public static MinecraftRemoteVersions fromJson(String s) { + return C.gson.fromJson(s, MinecraftRemoteVersions.class); + } + +} diff --git a/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/views/AbstractFilter.java b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/views/AbstractFilter.java new file mode 100644 index 000000000..79c293065 --- /dev/null +++ b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/views/AbstractFilter.java @@ -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.views; + +import java.awt.Rectangle; +import java.awt.RenderingHints; +import java.awt.geom.Point2D; +import java.awt.geom.Rectangle2D; +import java.awt.image.BufferedImage; +import java.awt.image.BufferedImageOp; +import java.awt.image.ColorModel; +import java.awt.image.Raster; +import java.awt.image.WritableRaster; + +public abstract class AbstractFilter + implements BufferedImageOp +{ + public abstract BufferedImage filter(BufferedImage paramBufferedImage1, BufferedImage paramBufferedImage2); + + public Rectangle2D getBounds2D(BufferedImage src) + { + return new Rectangle(0, 0, src.getWidth(), src.getHeight()); + } + + public BufferedImage createCompatibleDestImage(BufferedImage src, ColorModel destCM) + { + if (destCM == null) { + destCM = src.getColorModel(); + } + + return new BufferedImage(destCM, destCM.createCompatibleWritableRaster(src.getWidth(), src.getHeight()), destCM.isAlphaPremultiplied(), null); + } + + public Point2D getPoint2D(Point2D srcPt, Point2D dstPt) + { + return (Point2D)srcPt.clone(); + } + + public RenderingHints getRenderingHints() + { + return null; + } + + protected int[] getPixels(BufferedImage img, int x, int y, int w, int h, int[] pixels) + { + if ((w == 0) || (h == 0)) { + return new int[0]; + } + + if (pixels == null) + pixels = new int[w * h]; + else if (pixels.length < w * h) { + throw new IllegalArgumentException("pixels array must have a length >= w*h"); + } + + int imageType = img.getType(); + if ((imageType == 2) || (imageType == 1)) + { + Raster raster = img.getRaster(); + return (int[])(int[])raster.getDataElements(x, y, w, h, pixels); + } + + return img.getRGB(x, y, w, h, pixels, 0, w); + } + + protected void setPixels(BufferedImage img, int x, int y, int w, int h, int[] pixels) + { + if ((pixels == null) || (w == 0) || (h == 0)) + return; + if (pixels.length < w * h) { + throw new IllegalArgumentException("pixels array must have a length >= w*h"); + } + + int imageType = img.getType(); + if ((imageType == 2) || (imageType == 1)) + { + WritableRaster raster = img.getRaster(); + raster.setDataElements(x, y, w, h, pixels); + } + else { + img.setRGB(x, y, w, h, pixels, 0, w); + } + } +} diff --git a/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/views/BasicColors.java b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/views/BasicColors.java new file mode 100644 index 000000000..89ee20050 --- /dev/null +++ b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/views/BasicColors.java @@ -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.views; + +import java.awt.Color; + +/** + * + * @author hyh + */ +public class BasicColors { + + private static Color getWebColor(String c){ + return new Color( + Integer.parseInt(c.substring(0,2),16), + Integer.parseInt(c.substring(2,4),16), + Integer.parseInt(c.substring(4,6),16) + ); + } + + public static final Color COLOR_RED = new Color(229, 0, 0); + public static final Color COLOR_RED_DARKER = new Color(157, 41, 51); + public static final Color COLOR_GREEN = new Color(90, 184, 96); + public static final Color COLOR_BLUE = new Color(16, 108, 163); + public static final Color COLOR_BLUE_DARKER = new Color(12, 94, 145); + public static final Color COLOR_WHITE_TEXT = new Color(254, 254, 254); + public static final Color COLOR_CENTRAL_BACK = new Color(25, 30, 34, 160); + + public static final Color bgcolors[] = new Color[] { + COLOR_BLUE, + getWebColor("1ABC9C"), + getWebColor("9B59B6"), + getWebColor("34495E"), + getWebColor("E67E22"), + getWebColor("E74C3C") + }; + public static final Color bgcolors_darker[] = new Color[] { + COLOR_BLUE_DARKER, + getWebColor("16A085"), + getWebColor("8E44AD"), + getWebColor("2C3E50"), + getWebColor("D35400"), + getWebColor("C0392B") + }; +} diff --git a/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/views/DropShadowBorder.java b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/views/DropShadowBorder.java new file mode 100644 index 000000000..e15e93250 --- /dev/null +++ b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/views/DropShadowBorder.java @@ -0,0 +1,75 @@ +/* + * 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.views; + +import java.awt.AlphaComposite; +import java.awt.Color; +import java.awt.Component; +import java.awt.Composite; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.Insets; +import java.awt.RenderingHints; +import java.awt.image.BufferedImage; +import javax.swing.border.AbstractBorder; + +public class DropShadowBorder extends AbstractBorder { + + private Color color; + private int thickness = 1; + private Insets insets = null; + RenderingHints hints; + + public DropShadowBorder(Color color) { + this(color, 3); + } + + public DropShadowBorder(Color color, int thickness) { + this.thickness = thickness; + this.color = color; + this.hints = new RenderingHints(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); + + this.insets = new Insets(thickness * 4, thickness * 4, thickness * 4, thickness * 4); + } + + public void setColor(Color c) { + color = c; + } + + public Insets getBorderInsets(Component c) { + return this.insets; + } + + @Override + public Insets getBorderInsets(Component c, Insets insets) { + return getBorderInsets(c); + } + + public void paintBorder(Component c, Graphics g, int x, int y, int width, int height) { + BufferedImage shadow = new BufferedImage(width, height, 2); + + Graphics2D g2 = shadow.createGraphics(); + g2.setRenderingHints(this.hints); + Composite oldComposite = g2.getComposite(); + AlphaComposite composite = AlphaComposite.getInstance(1, 0.0F); + g2.setComposite(composite); + g2.setColor(new Color(0, 0, 0, 0)); + g2.fillRect(0, 0, width, height); + g2.setComposite(oldComposite); + g2.setColor(this.color); + int border = (int) (this.thickness * 4); + g2.fillRect(border, border + border / 6, width - border * 2, height - border * 2); + g2.dispose(); + + FastBlurFilter blur = new FastBlurFilter(this.thickness); + shadow = blur.filter(shadow, null); + shadow = blur.filter(shadow, null); + shadow = blur.filter(shadow, null); + shadow = blur.filter(shadow, null); + + g.drawImage(shadow, x, y, width, height, null); + } +} diff --git a/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/views/FastBlurFilter.java b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/views/FastBlurFilter.java new file mode 100644 index 000000000..e54099f56 --- /dev/null +++ b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/views/FastBlurFilter.java @@ -0,0 +1,132 @@ +/* + * 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.views; + +import java.awt.image.BufferedImage; + +public class FastBlurFilter extends AbstractFilter { + + private final int radius; + + public FastBlurFilter() { + this(3); + } + + public FastBlurFilter(int radius) { + if (radius < 1) { + radius = 1; + } + + this.radius = radius; + } + + public int getRadius() { + return this.radius; + } + + public BufferedImage filter(BufferedImage src, BufferedImage dst) { + int width = src.getWidth(); + int height = src.getHeight(); + + if (dst == null) { + dst = createCompatibleDestImage(src, null); + } + + int[] srcPixels = new int[width * height]; + int[] dstPixels = new int[width * height]; + + getPixels(src, 0, 0, width, height, srcPixels); + + blur(srcPixels, dstPixels, width, height, this.radius); + + blur(dstPixels, srcPixels, height, width, this.radius); + + setPixels(dst, 0, 0, width, height, srcPixels); + + return dst; + } + + static void blur(int[] srcPixels, int[] dstPixels, int width, int height, int radius) { + int windowSize = radius * 2 + 1; + int radiusPlusOne = radius + 1; + + int srcIndex = 0; + + int[] sumLookupTable = new int[256 * windowSize]; + for (int i = 0; i < sumLookupTable.length; i++) { + sumLookupTable[i] = (i / windowSize); + } + + int[] indexLookupTable = new int[radiusPlusOne]; + if (radius < width) { + for (int i = 0; i < indexLookupTable.length; i++) { + indexLookupTable[i] = i; + } + } else { + for (int i = 0; i < width; i++) { + indexLookupTable[i] = i; + } + for (int i = width; i < indexLookupTable.length; i++) { + indexLookupTable[i] = (width - 1); + } + } + + for (int y = 0; y < height; y++) { + int sumBlue; + int sumGreen; + int sumRed; + int sumAlpha = sumRed = sumGreen = sumBlue = 0; + int dstIndex = y; + + int pixel = srcPixels[srcIndex]; + sumAlpha += radiusPlusOne * (pixel >> 24 & 0xFF); + sumRed += radiusPlusOne * (pixel >> 16 & 0xFF); + sumGreen += radiusPlusOne * (pixel >> 8 & 0xFF); + sumBlue += radiusPlusOne * (pixel & 0xFF); + + for (int i = 1; i <= radius; i++) { + pixel = srcPixels[(srcIndex + indexLookupTable[i])]; + sumAlpha += (pixel >> 24 & 0xFF); + sumRed += (pixel >> 16 & 0xFF); + sumGreen += (pixel >> 8 & 0xFF); + sumBlue += (pixel & 0xFF); + } + + for (int x = 0; x < width; x++) { + dstPixels[dstIndex] = (sumLookupTable[sumAlpha] << 24 | sumLookupTable[sumRed] << 16 | sumLookupTable[sumGreen] << 8 | sumLookupTable[sumBlue]); + + dstIndex += height; + + int nextPixelIndex = x + radiusPlusOne; + if (nextPixelIndex >= width) { + nextPixelIndex = width - 1; + } + + int previousPixelIndex = x - radius; + if (previousPixelIndex < 0) { + previousPixelIndex = 0; + } + + int nextPixel = srcPixels[(srcIndex + nextPixelIndex)]; + int previousPixel = srcPixels[(srcIndex + previousPixelIndex)]; + + sumAlpha += (nextPixel >> 24 & 0xFF); + sumAlpha -= (previousPixel >> 24 & 0xFF); + + sumRed += (nextPixel >> 16 & 0xFF); + sumRed -= (previousPixel >> 16 & 0xFF); + + sumGreen += (nextPixel >> 8 & 0xFF); + sumGreen -= (previousPixel >> 8 & 0xFF); + + sumBlue += (nextPixel & 0xFF); + sumBlue -= (previousPixel & 0xFF); + } + + srcIndex += width; + } + } +} diff --git a/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/views/LogWindow.form b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/views/LogWindow.form new file mode 100644 index 000000000..2e5783db0 --- /dev/null +++ b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/views/LogWindow.form @@ -0,0 +1,168 @@ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/views/LogWindow.java b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/views/LogWindow.java new file mode 100644 index 000000000..388936a58 --- /dev/null +++ b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/views/LogWindow.java @@ -0,0 +1,286 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package org.jackhuang.hellominecraft.views; + +import org.jackhuang.hellominecraft.C; +import org.jackhuang.hellominecraft.utils.functions.DoneListener0; +import org.jackhuang.hellominecraft.utils.functions.DoneListener0Return; +import org.jackhuang.hellominecraft.utils.DoubleOutputStream; +import org.jackhuang.hellominecraft.utils.LauncherPrintStream; +import org.jackhuang.hellominecraft.utils.StrUtils; +import org.jackhuang.hellominecraft.utils.SwingUtils; +import org.jackhuang.hellominecraft.utils.TextComponentOutputStream; +import org.jackhuang.hellominecraft.utils.Utils; + +/** + * + * @author hyh + */ +public class LogWindow extends javax.swing.JFrame { + + boolean movingEnd; + DoneListener0Return listener; + DoneListener0 terminateGameListener; + + /** + * Creates new form LogWindow + */ + public LogWindow() { + initComponents(); + + movingEnd = true; + + setLocationRelativeTo(null); + + TextComponentOutputStream tc = new TextComponentOutputStream(txtLog); + DoubleOutputStream out = new DoubleOutputStream(tc, System.out); + System.setOut(new LauncherPrintStream(out)); + DoubleOutputStream err = new DoubleOutputStream(tc, System.err); + System.setErr(new LauncherPrintStream(err)); + } + + public static LogWindow instance = new LogWindow(); + + /** + * This method is called from within the constructor to initialize the form. + * WARNING: Do NOT modify this code. The content of this method is always + * regenerated by the Form Editor. + */ + @SuppressWarnings("unchecked") + // //GEN-BEGIN:initComponents + private void initComponents() { + + jScrollPane1 = new javax.swing.JScrollPane(); + txtLog = new javax.swing.JTextArea(); + btnClear = new javax.swing.JButton(); + btnClose = new javax.swing.JButton(); + btnCopy = new javax.swing.JButton(); + lblCrash = new javax.swing.JLabel(); + btnMCBBS = new javax.swing.JButton(); + btnTieBa = new javax.swing.JButton(); + btnMCF = new javax.swing.JButton(); + btnTerminateGame = new javax.swing.JButton(); + + setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE); + setTitle("Log"); + addWindowListener(new java.awt.event.WindowAdapter() { + public void windowClosed(java.awt.event.WindowEvent evt) { + formWindowClosed(evt); + } + }); + + txtLog.setEditable(false); + txtLog.setColumns(20); + txtLog.setRows(5); + jScrollPane1.setViewportView(txtLog); + + java.util.ResourceBundle bundle = java.util.ResourceBundle.getBundle("org/jackhuang/hellominecraft/launcher/I18N"); // NOI18N + btnClear.setText(bundle.getString("ui.button.clear")); // NOI18N + btnClear.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + btnClearActionPerformed(evt); + } + }); + + btnClose.setText(bundle.getString("ui.button.close")); // NOI18N + btnClose.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + btnCloseActionPerformed(evt); + } + }); + + btnCopy.setText(bundle.getString("ui.button.copy")); // NOI18N + btnCopy.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + btnCopyActionPerformed(evt); + } + }); + + lblCrash.setText(C.I18N.getString("ui.label.crashing")); // NOI18N + + btnMCBBS.setText("MCBBS"); + btnMCBBS.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + btnMCBBSActionPerformed(evt); + } + }); + + btnTieBa.setText(bundle.getString("logwindow.tieba")); // NOI18N + btnTieBa.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + btnTieBaActionPerformed(evt); + } + }); + + btnMCF.setText("Minecraft Forum"); + btnMCF.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + btnMCFActionPerformed(evt); + } + }); + + btnTerminateGame.setText(bundle.getString("logwindow.terminate_game")); // NOI18N + btnTerminateGame.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + btnTerminateGameActionPerformed(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) + .addComponent(jScrollPane1) + .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup() + .addComponent(btnTieBa) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(btnMCBBS) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(btnMCF) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(btnTerminateGame) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(btnCopy) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(btnClear) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(btnClose)) + .addComponent(lblCrash, javax.swing.GroupLayout.DEFAULT_SIZE, 639, Short.MAX_VALUE)) + .addContainerGap()) + ); + layout.setVerticalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(layout.createSequentialGroup() + .addContainerGap() + .addComponent(lblCrash, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 375, Short.MAX_VALUE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(btnClear) + .addComponent(btnClose) + .addComponent(btnCopy) + .addComponent(btnMCBBS) + .addComponent(btnTieBa) + .addComponent(btnMCF) + .addComponent(btnTerminateGame)) + .addContainerGap()) + ); + + pack(); + }// //GEN-END:initComponents + + private void btnCloseActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnCloseActionPerformed + this.dispose(); + }//GEN-LAST:event_btnCloseActionPerformed + + private void btnClearActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnClearActionPerformed + this.txtLog.setText(""); + }//GEN-LAST:event_btnClearActionPerformed + + private void formWindowClosed(java.awt.event.WindowEvent evt) {//GEN-FIRST:event_formWindowClosed + if(listener != null && listener.onDone()) Utils.shutdownForcely(); + }//GEN-LAST:event_formWindowClosed + + private void btnCopyActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnCopyActionPerformed + Utils.setClipborad(this.txtLog.getText()); + }//GEN-LAST:event_btnCopyActionPerformed + + private void btnMCBBSActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnMCBBSActionPerformed + Utils.openLink(C.URL_PUBLISH); + }//GEN-LAST:event_btnMCBBSActionPerformed + + private void btnTieBaActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnTieBaActionPerformed + Utils.openLink(C.URL_TIEBA); + }//GEN-LAST:event_btnTieBaActionPerformed + + private void btnMCFActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnMCFActionPerformed + Utils.openLink(C.URL_MINECRAFTFORUM); + }//GEN-LAST:event_btnMCFActionPerformed + + private void btnTerminateGameActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnTerminateGameActionPerformed + if(terminateGameListener != null) + terminateGameListener.onDone(); + }//GEN-LAST:event_btnTerminateGameActionPerformed + + public void log(String status) { + String text = txtLog.getText(); + text += status + System.getProperty("line.separator"); + txtLog.setText(text); + + if(movingEnd) { + int position = text.length(); + txtLog.setCaretPosition(position); + } + } + + public void log(String status, Throwable t) { + log(status); + log(StrUtils.getStackTrace(t)); + } + + public void setExit(DoneListener0Return exit) { + this.listener = exit; + } + + public void setTerminateGame(DoneListener0 l) { + this.terminateGameListener = l; + } + + public void clean() { + txtLog.setText(""); + } + + public boolean getMovingEnd() { + return movingEnd; + } + + public void setMovingEnd(boolean b) { + movingEnd = b; + } + + @Override + public void setVisible(boolean b) { + lblCrash.setVisible(false); + btnMCBBS.setVisible(false); + btnTieBa.setVisible(false); + btnMCF.setVisible(false); + super.setVisible(b); + } + + public void showAsCrashWindow(boolean out_date) { + if(out_date) { + lblCrash.setVisible(false); + btnMCBBS.setVisible(false); + btnTieBa.setVisible(false); + btnMCF.setVisible(false); + lblCrash.setText(C.i18n("ui.label.crashing_out_dated")); + } else { + lblCrash.setVisible(true); + btnMCBBS.setVisible(true); + btnTieBa.setVisible(true); + btnMCF.setVisible(true); + lblCrash.setText(C.i18n("ui.label.crashing")); + } + + super.setVisible(true); + } + + // Variables declaration - do not modify//GEN-BEGIN:variables + private javax.swing.JButton btnClear; + private javax.swing.JButton btnClose; + private javax.swing.JButton btnCopy; + private javax.swing.JButton btnMCBBS; + private javax.swing.JButton btnMCF; + private javax.swing.JButton btnTerminateGame; + private javax.swing.JButton btnTieBa; + private javax.swing.JScrollPane jScrollPane1; + private javax.swing.JLabel lblCrash; + private javax.swing.JTextArea txtLog; + // End of variables declaration//GEN-END:variables +} diff --git a/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/views/Selector.form b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/views/Selector.form new file mode 100644 index 000000000..a43542b6e --- /dev/null +++ b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/views/Selector.form @@ -0,0 +1,101 @@ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/views/Selector.java b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/views/Selector.java new file mode 100644 index 000000000..c718c006c --- /dev/null +++ b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/views/Selector.java @@ -0,0 +1,127 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package org.jackhuang.hellominecraft.views; + +import org.jackhuang.hellominecraft.utils.SwingUtils; + +/** + * The frame given to choose things. + * @author hyh + */ +public class Selector extends javax.swing.JDialog { + String[] selList; + String msg; + /** + * The index of the chosen in select list. + */ + public int sel; + public static int failedToSel = -1; + + /** + * @param parent null + * @param selList Selection List + * @param msg Message + */ + public Selector(java.awt.Frame parent, String[] selList, String msg) { + super(parent, true); + initComponents(); + + setLocationRelativeTo(null); + + this.selList = selList; + this.sel = failedToSel; + this.msg = msg; + jLabel1.setText(msg); + for(String s : selList) + jComboBox1.addItem(s); + } + + /** + * 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") + // //GEN-BEGIN:initComponents + private void initComponents() { + + jLabel1 = new javax.swing.JLabel(); + jComboBox1 = new javax.swing.JComboBox(); + jButton1 = new javax.swing.JButton(); + btnCancel = 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 + jLabel1.setText(bundle.getString("selector.choose")); // NOI18N + + jButton1.setText(bundle.getString("button.ok")); // NOI18N + jButton1.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + jButton1ActionPerformed(evt); + } + }); + + btnCancel.setText(bundle.getString("button.cancel")); // NOI18N + btnCancel.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + btnCancelActionPerformed(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(jComboBox1, 0, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addContainerGap()) + .addGroup(layout.createSequentialGroup() + .addComponent(jLabel1) + .addGap(0, 0, Short.MAX_VALUE)))) + .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup() + .addContainerGap(212, Short.MAX_VALUE) + .addComponent(btnCancel) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(jButton1) + .addContainerGap()) + ); + layout.setVerticalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(layout.createSequentialGroup() + .addContainerGap() + .addComponent(jLabel1) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(jComboBox1, 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(jButton1) + .addComponent(btnCancel)) + .addContainerGap()) + ); + + pack(); + }// //GEN-END:initComponents + + private void btnCancelActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnCancelActionPerformed + sel = failedToSel; + this.dispose(); + }//GEN-LAST:event_btnCancelActionPerformed + + private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton1ActionPerformed + sel = jComboBox1.getSelectedIndex(); + this.dispose(); + }//GEN-LAST:event_jButton1ActionPerformed + + // Variables declaration - do not modify//GEN-BEGIN:variables + private javax.swing.JButton btnCancel; + private javax.swing.JButton jButton1; + private javax.swing.JComboBox jComboBox1; + private javax.swing.JLabel jLabel1; + // End of variables declaration//GEN-END:variables +} diff --git a/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/views/TintablePanel.java b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/views/TintablePanel.java new file mode 100644 index 000000000..a3043e9d9 --- /dev/null +++ b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/views/TintablePanel.java @@ -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.views; + +/** + * + * @author huangyuhui + */ +import java.awt.Color; +import java.awt.EventQueue; +import java.awt.Graphics; +import javax.swing.ImageIcon; +import javax.swing.JLabel; +import javax.swing.JPanel; + +public class TintablePanel extends JPanel { + + private Color tintColor; + private boolean tintActive; + private JLabel overIcon = null; + + public TintablePanel() { + this.tintColor = new Color(0, 0, 0, 0); + } + + public Color getTintColor() { + return this.tintColor; + } + + public void setTintColor(Color color) { + this.tintColor = color; + } + + public void setOverIcon(ImageIcon image) { + if (this.overIcon != null) { + remove(this.overIcon); + } + + this.overIcon = new JLabel(image); + this.overIcon.setVisible(false); + add(this.overIcon); + revalidate(); + } + + public boolean isTintActive() { + return this.tintActive; + } + + public void setTintActive(boolean tintActive) { + this.tintActive = tintActive; + + if (this.overIcon != null) { + this.overIcon.setVisible(tintActive); + EventQueue.invokeLater(new Runnable() { + @Override + public void run() { + TintablePanel.this.revalidate(); + } + }); + } + EventQueue.invokeLater(new Runnable() { + @Override + public void run() { + TintablePanel.this.repaint(); + } + }); + } + + @Override + public void doLayout() { + super.doLayout(); + + if (this.overIcon != null) { + int width = this.overIcon.getIcon().getIconWidth(); + int height = this.overIcon.getIcon().getIconHeight(); + this.overIcon.setBounds(getWidth() / 2 - width / 2, getHeight() / 2 - height / 2, width, height); + } + } + + @Override + public void paint(Graphics graphics) { + super.paint(graphics); + + if (this.tintActive) { + graphics.setColor(getTintColor()); + graphics.fillRect(0, 0, getWidth(), getHeight()); + } + } +} diff --git a/HMCLAPI/src/main/resources/org/jackhuang/hellominecraft/launcher/I18N.properties b/HMCLAPI/src/main/resources/org/jackhuang/hellominecraft/launcher/I18N.properties new file mode 100644 index 000000000..a459c26d7 --- /dev/null +++ b/HMCLAPI/src/main/resources/org/jackhuang/hellominecraft/launcher/I18N.properties @@ -0,0 +1,278 @@ +launch.failed=\u542f\u52a8\u5931\u8d25 +launch.failed_creating_process=\u542f\u52a8\u5931\u8d25\uff0c\u5728\u521b\u5efa\u65b0\u8fdb\u7a0b\u65f6\u53d1\u751f\u9519\u8bef\uff0c\u53ef\u80fd\u662fJava\u8def\u5f84\u9519\u8bef\u3002 +launch.failed_sh_permission=\u4e3a\u542f\u52a8\u6587\u4ef6\u6dfb\u52a0\u6743\u9650\u65f6\u53d1\u751f\u9519\u8bef +launch.failed_packing_jar=\u5728\u6253\u5305jar\u65f6\u53d1\u751f\u9519\u8bef +launch.unsupported_launcher_version=\u5bf9\u4e0d\u8d77\uff0c\u672c\u542f\u52a8\u5668\u73b0\u5728\u53ef\u80fd\u4e0d\u80fd\u542f\u52a8\u8fd9\u4e2a\u7248\u672c\u7684Minecraft\uff0c\u4f46\u542f\u52a8\u5668\u8fd8\u662f\u4f1a\u5c1d\u8bd5\u542f\u52a8\uff0c\u8bf7\u5c3d\u5feb\u5c06\u6b64\u95ee\u9898\u62a5\u544a\u7ed9\u4f5c\u8005\u3002 +launch.too_big_memory_alloc_64bit=\u60a8\u8bbe\u7f6e\u7684\u5185\u5b58\u5927\u5c0f\u8fc7\u5927\uff0c\u7531\u4e8e\u53ef\u80fd\u8d85\u8fc7\u4e8632\u4f4dJava\u7684\u5185\u5b58\u5206\u914d\u9650\u5236\uff0c\u6240\u4ee5\u53ef\u80fd\u65e0\u6cd5\u542f\u52a8\u6e38\u620f\uff0c\u8bf7\u5c06\u5185\u5b58\u8c03\u81f31024MB\u6216\u66f4\u5c0f\uff0c\u542f\u52a8\u5668\u4ecd\u4f1a\u5c1d\u8bd5\u542f\u52a8\u3002 +launch.too_big_memory_alloc_free_space_too_low=\u60a8\u8bbe\u7f6e\u7684\u5185\u5b58\u5927\u5c0f\u8fc7\u5927\uff0c\u7531\u4e8e\u8d85\u8fc7\u4e86\u7cfb\u7edf\u5185\u5b58\u5927\u5c0f%dMB\uff0c\u6240\u4ee5\u53ef\u80fd\u5f71\u54cd\u6e38\u620f\u4f53\u9a8c\u6216\u65e0\u6cd5\u542f\u52a8\u6e38\u620f\uff0c\u542f\u52a8\u5668\u4ecd\u4f1a\u5c1d\u8bd5\u542f\u52a8\u3002 +launch.cannot_create_jvm=\u622a\u83b7\u5230\u65e0\u6cd5\u521b\u5efaJava\u865a\u62df\u673a\uff0c\u53ef\u80fd\u662fJava\u53c2\u6570\u6709\u95ee\u9898\uff0c\u53ef\u4ee5\u5728\u8bbe\u7f6e\u4e2d\u5f00\u542f\u65e0\u53c2\u6570\u6a21\u5f0f\u542f\u52a8 +launch.circular_dependency_versions=\u53d1\u73b0\u6e38\u620f\u7248\u672c\u5faa\u73af\u5f15\u7528\uff0c\u8bf7\u786e\u8ba4\u60a8\u7684\u5ba2\u6237\u7aef\u672a\u88ab\u4fee\u6539\u6216\u4fee\u6539\u5bfc\u81f4\u51fa\u73b0\u6b64\u95ee\u9898\u3002 +launch.not_finished_downloading_libraries=\u672a\u5b8c\u6210\u6e38\u620f\u4f9d\u8d56\u5e93\u7684\u4e0b\u8f7d\uff0c\u8fd8\u8981\u7ee7\u7eed\u542f\u52a8\u6e38\u620f\u5417\uff1f +launch.not_finished_decompressing_natives=\u672a\u80fd\u89e3\u538b\u6e38\u620f\u672c\u5730\u5e93\uff0c\u8fd8\u8981\u7ee7\u7eed\u542f\u52a8\u6e38\u620f\u5417\uff1f + +install.no_version=\u672a\u627e\u5230\u8981\u5b89\u88c5\u7684\u5bf9\u5e94MC\u7248\u672c +install.no_version_if_intall=\u672a\u627e\u5230\u8981\u5b89\u88c5\u7684\u5bf9\u5e94MC\u7248\u672c\uff0c\u662f\u5426\u81ea\u52a8\u5b89\u88c5\u9700\u8981\u7684MC\u7248\u672c\uff1f +install.not_refrehsed=\u672a\u5237\u65b0\u5217\u8868 +install.download_list=\u4e0b\u8f7d\u5217\u8868 + +install.liteloader.get_list=\u83b7\u53d6LiteLoader\u5217\u8868 +install.liteloader.install=\u5b89\u88c5LiteLoader + +install.forge.get_list=\u83b7\u53d6Forge\u5217\u8868 +install.forge.install=\u5b89\u88c5Forge +install.forge.get_changelogs=\u83b7\u53d6Forge\u66f4\u65b0\u8bb0\u5f55 + +install.optifine.install=\u5b89\u88c5Optifine +install.optifine.get_list=\u83b7\u53d6Optifine\u5217\u8868 + +install.failed_forge=\u5b89\u88c5Forge\u5931\u8d25 +install.failed_optifine=\u5b89\u88c5Optifine\u5931\u8d25 +install.failed_liteloader=\u5b89\u88c5LiteLoader\u5931\u8d25 +install.failed_download_forge=\u4e0b\u8f7dForge\u5931\u8d25 +install.failed_download_optifine=\u4e0b\u8f7dOptifine\u5931\u8d25 +install.failed=\u5b89\u88c5\u5931\u8d25 +install.success=\u5b89\u88c5\u6210\u529f +install.no_forge=\u6ca1\u6709\u5b89\u88c5Forge +install.choose_forge=\u9009\u62e9\u4f60\u5b89\u88c5\u7684Forge\u7248\u672c +install.version=\u7248\u672c +install.mcversion=\u6e38\u620f\u7248\u672c +install.time=\u65f6\u95f4 +install.release_time=\u91ca\u653e\u65f6\u95f4 +install.type=\u7c7b\u578b + +crash.launcher=\u542f\u52a8\u5668\u5d29\u6e83\u4e86\uff01 +crash.minecraft=Minecraft\u5d29\u6e83\u4e86\uff01 + +login.choose_charactor=\u8bf7\u9009\u62e9\u60a8\u8981\u4f7f\u7528\u7684\u89d2\u8272 +login.no_charactor=\u8be5\u5e10\u53f7\u6ca1\u6709\u89d2\u8272 +login.your_password=\u60a8\u7684\u5bc6\u7801 +login.failed=\u767b\u5f55\u5931\u8d25\uff1a +login.no_Player007=\u4f60\u8fd8\u672a\u8bbe\u7f6e\u7528\u6237\u540d\uff01 +login.wrong_password=\u53ef\u80fd\u662f\u60a8\u7684\u7528\u6237\u540d\u6216\u5bc6\u7801\u9519\u8bef +login.invalid_username=\u65e0\u6548\u7684\u7528\u6237\u540d +login.invalid_uuid_and_username=\u65e0\u6548\u7684UUID\u548c\u7528\u6237\u540d +login.invalid_password=\u65e0\u6548\u7684\u5bc6\u7801 +login.invalid_access_token=\u65e0\u6548\u7684\u8bbf\u95ee\u4ee4\u724c +login.changed_client_token=\u670d\u52a1\u5668\u56de\u5e94\u5df2\u7ecf\u4fee\u6539\u5ba2\u6237\u7aef\u4ee4\u724c +login.not_email=\u7528\u6237\u540d\u5fc5\u987b\u662f\u90ae\u7bb1 +login.type=\u767b\u5f55 +login.username=\u540d\u5b57 +login.account=\u90ae\u7bb1 + +login.failed.connect_authentication_server=\u65e0\u6cd5\u8fde\u63a5\u8ba4\u8bc1\u670d\u52a1\u5668,\u53ef\u80fd\u662f\u7f51\u7edc\u95ee\u9898 + +login.profile.not_logged_in=\u65e0\u6cd5\u4fee\u6539\u6e38\u620f\u8d44\u6599\u540c\u65f6\u672a\u767b\u5f55 +login.profile.selected=\u65e0\u6cd5\u4fee\u6539\u6e38\u620f\u8d44\u6599. \u4f60\u5fc5\u987b\u767b\u51fa\u518d\u8fd4\u56de. + +login.methods.yggdrasil=\u6b63\u7248\u767b\u5f55 +login.methods.offline=\u79bb\u7ebf\u6a21\u5f0f +login.methods.no_method=\u6ca1\u6709\u767b\u5165\u65b9\u5f0f... + +log.playername_null=\u73a9\u5bb6\u540d\u4e3a\u7a7a\uff0c\u8fd9\u4ee3\u8868\u7740\u767b\u5f55\u65b9\u6cd5\u51fa\u73b0\u95ee\u9898 + +minecraft.no_selected_version=\u6ca1\u6709\u9009\u62e9\u4efb\u4f55\u4e00\u4e2aMinecraft\u7248\u672c +minecraft.wrong_path=\u9519\u8bef\u7684Minecraft\u8def\u5f84\uff0c\u542f\u52a8\u5668\u672a\u627e\u5230\u8bbe\u5b9a\u7684Minecraft\u8def\u5f84\uff0c\u8bf7\u68c0\u67e5\u3002 + +operation.stopped=\u64cd\u4f5c\u88ab\u5f3a\u884c\u7ec8\u6b62 +operation.confirm_stop=\u771f\u7684\u8981\u7ec8\u6b62\u64cd\u4f5c\u5417\uff1f + +ui.login.password=\u5bc6\u7801 +ui.more=\u66f4\u591a + +crash.advice.UnsupportedClassVersionError=\u8fd9\u53ef\u80fd\u662f\u56e0\u4e3a\u60a8\u7684Java\u7248\u672c\u8fc7\u4e8e\u8001\u65e7\uff0c\u53ef\u4ee5\u5c1d\u8bd5\u66f4\u6362\u6700\u65b0Java\u5e76\u5728\u7248\u672c\u8bbe\u7f6e\u7684Java\u8def\u5f84\u4e2d\u8bbe\u7f6e. +crash.advice.ConcurrentModificationException=\u8fd9\u53ef\u80fd\u662f\u56e0\u4e3a\u60a8\u7684Java\u7248\u672c\u9ad8\u4e8eJava 1.8.0_11\u5bfc\u81f4\u7684,\u53ef\u4ee5\u5c1d\u8bd5\u5378\u8f7dJava8\u5b89\u88c5Java7\u3002 +crash.advice.ClassNotFoundException=Minecraft\u4e0d\u5b8c\u6574\u6216Mod\u51b2\u7a81\u3002\u53ef\u4ee5\u4e0b\u8f7d\u6574\u5408\u5305\u89e3\u51b3\u95ee\u9898\u3002 +crash.advice.NoSuchFieldError=Minecraft\u4e0d\u5b8c\u6574\u6216Mod\u51b2\u7a81\u3002\u53ef\u4ee5\u901a\u8fc7\u4e0b\u8f7d\u6574\u5408\u5305\u89e3\u51b3\u95ee\u9898\u3002 +crash.advice.SecurityException=\u53ef\u80fd\u662f\u60a8\u4fee\u6539\u4e86minecraft.jar\u4f46\u672a\u5220\u9664META-INF\u6587\u4ef6\u5939\u7684\u539f\u56e0\u3002\u8bf7\u901a\u8fc7\u538b\u7f29\u8f6f\u4ef6\u5220\u9664jar\u4e2d\u7684META-INF\u6587\u4ef6\u5939\u3002 +crash.advice.otherwise=\u53ef\u80fd\u662fMod\u6216\u5176\u4ed6\u95ee\u9898\u3002 + +crash.advice.OpenGL=\u53ef\u80fd\u662f\u663e\u5361/\u58f0\u5361\u9a71\u52a8\u95ee\u9898\uff0c\u4e5f\u53ef\u80fd\u662fMod\u5bfc\u81f4\u7684\u95ee\u9898\u3002 +crash.advice.no_lwjgl=\u53ef\u80fd\u662f\u6e38\u620f\u4f9d\u8d56\u5e93\u4e0d\u5b8c\u6574\u6216\u89e3\u538b\u4f9d\u8d56\u5e93\u65f6\u51fa\u9519\u3002\u53ef\u4ee5\u901a\u8fc7\u4e0b\u8f7d\u6574\u5408\u5305\u89e3\u51b3\u95ee\u9898\u3002 + +crash.advice.no=\u65e0\u5efa\u8bae\u3002 + +crash.error=\u60a8\u7684Minecraft\u5d29\u6e83\u4e86\u3002 +crash.main_class_not_found=\u627e\u4e0d\u5230\u4e3b\u7c7b\uff0c\u53ef\u80fd\u662f\u60a8\u7684JSON\u6587\u4ef6\u586b\u5199\u9519\u8bef\u3002\u65e0\u6cd5\u542f\u52a8\u6e38\u620f\u3002\u53ef\u4ee5\u901a\u8fc7\u4e0b\u8f7d\u6574\u5408\u5305\u89e3\u51b3\u95ee\u9898\u3002 +crash.class_path_wrong=\u89e3\u6790Class Path\u65f6\u51fa\u73b0\u9519\u8bef\uff0c\u6b64\u9519\u8bef\u672c\u4e0d\u5e94\u8be5\u53d1\u751f\u3002\u53ef\u80fd\u662f\u542f\u52a8\u811a\u672c\u9519\u8bef\uff0c\u8bf7\u4ed4\u7ec6\u68c0\u67e5\u542f\u52a8\u811a\u672c\u3002 + +ui.label.newProfileWindow.new_profile_name=\u65b0\u914d\u7f6e\u540d: +ui.label.newProfileWindow.copy_from=\u590d\u5236\u914d\u7f6e: +ui.newProfileWindow.title=\u65b0\u5efa\u914d\u7f6e + +ui.button.ok=\u786e\u8ba4 +ui.button.refresh=\u5237\u65b0 +ui.button.run=\u542f\u52a8Minecraft +ui.button.settings= +ui.button.about=\u5173\u4e8e +ui.button.others=\u5176\u4ed6 +ui.button.logout=\u767b\u51fa +ui.button.download=\u4e0b\u8f7d +ui.button.retry=\u91cd\u8bd5 +ui.button.delete=\u5220\u9664 +ui.button.install=\u5b89\u88c5 +ui.button.info=\u4fe1\u606f +ui.button.save=\u4fdd\u5b58 +ui.button.copy=\u590d\u5236 +ui.button.clear=\u6e05\u9664 +ui.button.close=\u5173\u95ed +ui.button.explore=\u6d4f\u89c8 +button.cancel=\u53d6\u6d88 +button.ok=\u786e\u5b9a + +ui.label.version=\u7248\u672c +ui.label.password=\u5bc6\u7801 +ui.label.profile=\u914d\u7f6e + +ui.message.first_load=\u8bf7\u5728\u5de6\u8fb9\u8f93\u5165\u60a8\u7684\u8d26\u53f7 +ui.message.enter_password=\u8bf7\u5728\u5de6\u8fb9\u8f93\u5165\u60a8\u7684\u5bc6\u7801 +ui.message.launching=\u542f\u52a8\u4e2d +ui.message.making=\u751f\u6210\u4e2d +ui.message.sure_remove=\u771f\u7684\u8981\u5220\u9664\u914d\u7f6e%s\u5417\uff1f + +ui.label.settings=\u9009\u9879 +ui.label.crashing=Hello Minecraft! Launcher\u9047\u5230\u4e86\u65e0\u6cd5\u5904\u7406\u7684\u9519\u8bef\uff0c\u8bf7\u590d\u5236\u4e0b\u5217\u5185\u5bb9\u5e76\u901a\u8fc7mcbbs\u3001\u8d34\u5427\u6216Minecraft Forum\u53cd\u9988bug\u3002 +ui.label.crashing_out_dated=Hello Minecraft! Launcher\u9047\u5230\u4e86\u65e0\u6cd5\u5904\u7406\u7684\u9519\u8bef\uff0c\u5df2\u68c0\u6d4b\u5230\u60a8\u7684\u542f\u52a8\u5668\u4e0d\u662f\u6700\u65b0\u7248\u672c\uff0c\u8bf7\u66f4\u65b0\u540e\u518d\u8bd5\uff01 +ui.label.failed_set=\u8bbe\u7f6e\u5931\u8d25\uff1a + +download=\u4e0b\u8f7d +download.mojang=\u5b98\u65b9 +download.BMCL=BMCLAPI (bangbang93, http://bmclapi.bangbang93.com/) +download.not_200=\u4e0b\u8f7d\u5931\u8d25\uff0c\u56de\u590d\u7801 +download.failed=\u4e0b\u8f7d\u5931\u8d25 +download.successfully=\u4e0b\u8f7d\u5b8c\u6210 + +message.error=\u9519\u8bef +message.cannot_open_explorer=\u65e0\u6cd5\u6253\u5f00\u6587\u4ef6\u7ba1\u7406\u5668: +message.cancelled=\u5df2\u53d6\u6d88 +message.info=\u63d0\u793a + +folder.game=\u6e38\u620f\u6587\u4ef6\u5939 +folder.mod=MOD\u6587\u4ef6\u5939 +folder.coremod=\u6838\u5fc3MOD\u6587\u4ef6\u5939 +folder.config=\u914d\u7f6e\u6587\u4ef6\u5939 +folder.resourcepacks=\u8d44\u6e90\u5305\u6587\u4ef6\u5939 +folder.screenshots=\u622a\u56fe\u6587\u4ef6\u5939 +folder.saves=\u5b58\u6863\u6587\u4ef6\u5939 + +settings.tabs.game_download=\u6e38\u620f\u4e0b\u8f7d +settings.tabs.installers=\u81ea\u52a8\u5b89\u88c5 +settings.tabs.assets_downloads=\u8d44\u6e90\u4e0b\u8f7d + +settings=\u666e\u901a\u8bbe\u7f6e +settings.explore=\u6d4f\u89c8 +settings.manage=\u7ba1\u7406 +settings.cannot_remove_default_config=\u4e0d\u80fd\u5220\u9664\u9ed8\u8ba4\u914d\u7f6e +settings.max_memory=\u6700\u5927\u5185\u5b58/MB +settings.java_dir=Java\u8def\u5f84 +settings.game_directory=\u6e38\u620f\u8def\u5f84 +settings.dimension=\u5206\u8fa8\u7387 +settings.fullscreen=\u5168\u5c4f +settings.update_version=\u66f4\u65b0\u7248\u672c\u6587\u4ef6 +settings.physical_memory=\u7269\u7406\u5185\u5b58\u5927\u5c0f + +settings.failed_load=\u8bbe\u7f6e\u6587\u4ef6\u52a0\u8f7d\u5931\u8d25\uff0c\u53ef\u80fd\u662f\u5347\u7ea7\u4e86\u542f\u52a8\u5668\u6216\u88ab\u4eba\u5de5\u4fee\u6539\u9020\u6210\u9519\u8bef\uff0c\u662f\u5426\u6e05\u9664\uff1f + +advancedsettings=\u9ad8\u7ea7\u8bbe\u7f6e +advancedsettings.launcher_visible=\u542f\u52a8\u5668\u53ef\u89c1\u6027 +advancedsettings.run_directory=\u8fd0\u884c\u8def\u5f84 +advencedsettings.debug_mode=\u8c03\u8bd5\u6a21\u5f0f +advancedsettings.java_permanent_generation_space=\u5185\u5b58\u6c38\u4e45\u4fdd\u5b58\u533a\u57df(\u4e0d\u5fc5\u586b\u5199,MB) +advancedsettings.jvm_args=Java\u865a\u62df\u673a\u53c2\u6570(\u4e0d\u5fc5\u586b\u5199) +advancedsettings.Minecraft_arguments=Minecraft\u989d\u5916\u53c2\u6570(\u4e0d\u5fc5\u586b\u5199) +advancedsettings.launcher_visibility.close=\u6e38\u620f\u542f\u52a8\u540e\u7ed3\u675f\u542f\u52a8\u5668 +advancedsettings.launcher_visibility.hide=\u6e38\u620f\u542f\u52a8\u540e\u9690\u85cf\u542f\u52a8\u5668 +advancedsettings.launcher_visibility.keep=\u4fdd\u6301\u542f\u52a8\u5668\u53ef\u89c1 +advancedsettings.game_dir.default=\u9ed8\u8ba4(.minecraft/) +advancedsettings.game_dir.independent=\u5404\u7248\u672c\u72ec\u7acb(.minecraft/versions/<\u7248\u672c\u540d>/,\u9664assets,libraries) +advancedsettings.no_jvm_args=\u4e0d\u6dfb\u52a0JVM\u53c2\u6570(\u4f7f\u7528Java9\u65f6\u5fc5\u52fe) +advancedsettings.java_args_default=\u542f\u52a8\u5668\u9ed8\u8ba4\u6dfb\u52a0\u7684\u53c2\u6570\uff08\u8bf7\u4e0d\u8981\u91cd\u590d\u6dfb\u52a0\uff09\uff1a-XX:+UseConcMarkSweepGC -XX:+CMSIncrementalMode -XX:-UseAdaptiveSizePolicy -XX:MaxPermSize=???m -Xmx???m -Dfml.ignoreInvalidMinecraftCertificates=true -Dfml.ignorePatchDiscrepancies=true + +mainwindow.show_log=\u67e5\u770b\u65e5\u5fd7 +mainwindow.make_launch_script=\u751f\u6210\u542f\u52a8\u811a\u672c +mainwindow.make_launch_script_failed=\u751f\u6210\u542f\u52a8\u811a\u672c\u5931\u8d25 +mainwindow.enter_script_name=\u8f93\u5165\u8981\u751f\u6210\u811a\u672c\u7684\u6587\u4ef6\u540d +mainwindow.make_launch_succeed=\u542f\u52a8\u811a\u672c\u5df2\u751f\u6210\u5b8c\u6bd5: +mainwindow.no_version=\u672a\u627e\u5230\u4efb\u4f55\u7248\u672c\uff0c\u60a8\u53ef\u4ee5\u5230[\u8bbe\u7f6e]->[\u6e38\u620f\u4e0b\u8f7d]\u4e2d\u4e0b\u8f7d\u6e38\u620f\u3002 + +launcher.about=\u9ed8\u8ba4\u80cc\u666f\u56fe\u6765\u81eaLiberty Dome\u670d\u52a1\u5668\u3002
\u5173\u4e8e\u4f5c\u8005\uff1a
\n\u767e\u5ea6ID\uff1ahuanghongxun20
\nmcbbs\uff1ahuanghongxun
\n\u90ae\u7bb1\uff1ahuanghongxun2008@126.com
\nMinecraft Forum ID: klkl6523
\n\u6b22\u8fce\u63d0\u4ea4Bug\u54e6
\nCopyright (c) 2013-2015 huangyuhui.
\u514d\u8d23\u58f0\u660e\uff1aMinecraft\u8f6f\u4ef6\u7248\u6743\u5f52Mojang AB\u6240\u6709\uff0c\u6e38\u620f\u7531\u4e8e\u8bef\u64cd\u4f5c\u672c\u542f\u52a8\u5668\u800c\u4e22\u5931\u6570\u636e\u7684\u6982\u4e0d\u8d1f\u8d23\u3002 +launcher.download_source=\u4e0b\u8f7d\u6e90 +launcher.background_location=\u80cc\u666f\u5730\u5740 +launcher.exit_failed=\u5f3a\u5236\u9000\u51fa\u5931\u8d25\uff0c\u53ef\u80fd\u662fForge 1.7.10\u53ca\u66f4\u9ad8\u7248\u672c\u5bfc\u81f4\u7684\uff0c\u65e0\u6cd5\u89e3\u51b3\u3002 +launcher.versions_json_not_matched=\u7248\u672c%s\u683c\u5f0f\u4e0d\u89c4\u8303\uff01\u8be5\u7248\u672c\u6587\u4ef6\u5939\u4e0b\u6709json:%s\uff0c\u662f\u5426\u66f4\u540d\u8fd9\u4e2a\u6587\u4ef6\u6765\u89c4\u8303\u683c\u5f0f\uff1f +launcher.versions_json_not_matched_needs_auto_completion=\u7248\u672c%s\u7f3a\u5931\u5fc5\u8981\u7684\u7248\u672c\u4fe1\u606f(JSON)\u6587\u4ef6\uff0c\u662f\u5426\u81ea\u52a8\u8865\u5168\uff1f +launcher.versions_json_not_matched_cannot_auto_completion=\u7248\u672c%s\u7f3a\u5931\u5fc5\u8981\u7684\u7248\u672c\u4fe1\u606f(JSON)\u6587\u4ef6\uff0c\u4f46\u662f\u4f3c\u4e4e\u4e0d\u662f\u539f\u7248\uff0c\u65e0\u6cd5\u81ea\u52a8\u8865\u5168\uff0c\u662f\u5426\u5220\u9664\u8be5\u7248\u672c\uff1f +launcher.versions_json_not_formatted=\u7248\u672c%s\u4fe1\u606f\u6587\u4ef6\u683c\u5f0f\u9519\u8bef\uff0c\u662f\u5426\u91cd\u65b0\u4e0b\u8f7d\uff1f +launcher.choose_bgpath=\u9009\u62e9\u80cc\u666f\u8def\u5f84 +launcher.background_tooltip=\n\n\u542f\u52a8\u5668\u9ed8\u8ba4\u4f7f\u7528\u81ea\u5e26\u7684\u80cc\u666f
\n\u5982\u679c\u5f53\u524d\u76ee\u5f55\u6709background.png\uff0c\u5219\u4f1a\u4f7f\u7528\u8be5\u6587\u4ef6\u4f5c\u4e3a\u80cc\u666f
\n\u5982\u679c\u5f53\u524d\u76ee\u5f55\u6709bgskin\u5b50\u76ee\u5f55\uff0c\u5219\u4f1a\u968f\u673a\u4f7f\u7528\u91cc\u9762\u7684\u4e00\u5f20\u56fe\u4f5c\u4e3a\u80cc\u666f
\n\u5982\u679c\u8be5\u80cc\u666f\u5730\u5740\u88ab\u4fee\u6539\uff0c\u5219\u4f1a\u4f7f\u7528\u80cc\u666f\u5730\u5740\u91cc\u7684\u4e00\u5f20\u56fe\u4f5c\u4e3a\u80cc\u666f
\n\u80cc\u666f\u5730\u5740\u5141\u8bb8\u6709\u591a\u4e2a\u5730\u5740\uff0c\u4f7f\u7528\u534a\u89d2\u5206\u53f7";"(\u4e0d\u5305\u542b\u53cc\u5f15\u53f7)\u5206\u9694\n\n +launcher.update_launcher=\u68c0\u67e5\u66f4\u65b0 +launcher.enable_shadow=\u542f\u7528\u7a97\u53e3\u9634\u5f71(\u91cd\u542f\u542f\u52a8\u5668\u751f\u6548,\u53ef\u52a0\u5feb\u6e32\u67d3\u901f\u5ea6) +launcher.theme=\u4e3b\u9898 + +launcher.title.game=\u6e38\u620f\u8bbe\u7f6e +launcher.title.main=\u4e3b\u9875 +launcher.title.launcher=\u542f\u52a8\u5668\u8bbe\u7f6e + +versions.release=\u7a33\u5b9a\u7248 +versions.snapshot=\u5feb\u7167\u7248 +versions.old_beta=\u6d4b\u8bd5\u7248 +versions.old_alpha=\u8fdc\u53e4\u7248 + +versions.manage.rename=\u91cd\u547d\u540d\u8be5\u7248\u672c +versions.manage.rename.message=\u8bf7\u8f93\u5165\u8981\u6539\u6210\u7684\u540d\u5b57 +versions.manage.remove=\u5220\u9664\u8be5\u7248\u672c +versions.manage.remove.confirm=\u771f\u7684\u8981\u5220\u9664\u7248\u672c +versions.manage.redownload_json=\u91cd\u65b0\u4e0b\u8f7d\u7248\u672c\u914d\u7f6e(minecraft.json) +versions.manage.redownload_assets_index=\u91cd\u65b0\u4e0b\u8f7d\u8d44\u6e90\u914d\u7f6e(assets_index.json) + +advice.os64butjdk32=\u60a8\u7684\u7cfb\u7edf\u662f64\u4f4d\u7684\u4f46\u662fJava\u662f32\u4f4d\u7684\uff0c\u63a8\u8350\u60a8\u5b89\u88c564\u4f4dJava. + +assets.download_all=\u4e0b\u8f7d\u8d44\u6e90\u6587\u4ef6 +assets.not_refreshed=\u8d44\u6e90\u5217\u8868\u672a\u5237\u65b0\uff0c\u8bf7\u5237\u65b0\u4e00\u6b21\u3002 +assets.failed=\u83b7\u53d6\u5217\u8868\u5931\u8d25\uff0c\u8bf7\u5237\u65b0\u91cd\u8bd5\u3002 +assets.list.1_7_3_after=1.7.3\u53ca\u4ee5\u540e +assets.list.1_6=1.6(BMCLAPI) +assets.unkown_type_select_one=\u65e0\u6cd5\u89e3\u6790\u6e38\u620f\u7248\u672c\uff1a%s\uff0c\u8bf7\u9009\u62e9\u4e00\u79cd\u8d44\u6e90\u7c7b\u578b\u4e0b\u8f7d\u3002 +assets.type=\u8d44\u6e90\u7c7b\u578b +assets.download=\u4e0b\u8f7d\u8d44\u6e90 +assets.no_assets=\u672a\u68c0\u6d4b\u5230assets\u6587\u4ef6\u5939\uff0c\u542f\u52a8\u6e38\u620f\u540e\u5c06\u6ca1\u6709\u58f0\u97f3\u548c\u8bed\u8a00\u6587\u4ef6\uff0c\u8bf7\u5230\u6e38\u620f\u8bbe\u7f6e->\u8d44\u6e90\u4e0b\u8f7d\u4e0b\u8f7d\u8d44\u6e90\u3002 + +gamedownload.not_refreshed=\u6e38\u620f\u4e0b\u8f7d\u5217\u8868\u672a\u5237\u65b0\uff0c\u8bf7\u518d\u5237\u65b0\u4e00\u6b21\u3002 + +taskwindow.title=\u4efb\u52a1 +taskwindow.single_progress=\u5355\u9879\u8fdb\u5ea6 +taskwindow.total_progress=\u603b\u8fdb\u5ea6 +taskwindow.cancel=\u53d6\u6d88 +taskwindow.no_more_instance=\u53ef\u80fd\u540c\u65f6\u6253\u5f00\u4e86\u591a\u4e2a\u4efb\u52a1\u7a97\u53e3\uff0c\u8bf7\u4e0d\u8981\u591a\u6b21\u6253\u5f00\uff01 + +setupwindow.include_minecraft=\u5bfc\u5165\u6e38\u620f\u6587\u4ef6\u5939 +setupwindow.find_in_configurations=\u5bfc\u5165\u5b8c\u6210\uff0c\u5feb\u5230\u914d\u7f6e\u4e0b\u62c9\u6846\u4e2d\u627e\u65b0\u6e38\u620f\u8def\u5f84\u5427\uff01 +setupwindow.give_a_name=\u7ed9\u65b0\u6e38\u620f\u8def\u5f84\u8d77\u4e2a\u540d\u5b57\u5427 +setupwindow.new=\u65b0\u5efa +setupwindow.no_empty_name=\u540d\u5b57\u4e0d\u53ef\u4e3a\u7a7a + +update.no_browser=\u65e0\u6cd5\u6253\u5f00\u6d4f\u89c8\u5668\uff0c\u7f51\u5740\u5df2\u7ecf\u590d\u5236\u5230\u526a\u8d34\u677f\u4e86\uff0c\u60a8\u53ef\u4ee5\u624b\u52a8\u7c98\u8d34\u7f51\u5740\u6253\u5f00\u9875\u9762 +update.should_open_link=\u662f\u5426\u524d\u5f80\u53d1\u5e03\u9875\u9762\u66f4\u65b0\uff1f +update.newest_version=\u6700\u65b0\u7248\u672c\u4e3a\uff1a +update.failed=\u68c0\u67e5\u66f4\u65b0\u5931\u8d25 +update.found=(\u53d1\u73b0\u66f4\u65b0!) + +logwindow.terminate_game=\u7ed3\u675f\u6e38\u620f\u8fdb\u7a0b +logwindow.tieba=\u8d34\u5427 + +selector.choose=\u9009\u62e9 + +minecraft.invalid=\u65e0\u6548\u7684 +minecraft.invalid_jar=\u65e0\u6548\u7684jar\u5305 +minecraft.not_a_file=\u4e0d\u662f\u6587\u4ef6 +minecraft.not_found=\u627e\u4e0d\u5230minecraft.jar +minecraft.not_readable=minecraft.jar\u4e0d\u53ef\u8bfb +minecraft.modified=(\u4fee\u6539\u7684!) + +color.red=\u7ea2\u8272 +color.blue=\u84dd\u8272 +color.green=\u7eff\u8272 +color.orange=\u6a59\u8272 +color.dark_blue=\u6df1\u84dd\u8272 +color.purple=\u7d2b\u8272 +advancedsettings.wrapper_launcher=\u524d\u7f6e\u542f\u52a8\u6307\u4ee4(\u4e0d\u5fc5\u586b\u5199\uff0c\u5185\u5bb9\u5c06\u52a0\u5728\u542f\u52a8\u811a\u672c\u6700\u524d\uff0c\u5982optirun...) +advancedsettings.server_ip=\u76f4\u5165\u670d\u52a1\u5668ip\u5730\u5740(\u4e0d\u5fc5\u586b\u5199\uff0c\u542f\u52a8\u6e38\u620f\u540e\u76f4\u63a5\u8fdb\u5165\u5bf9\u5e94\u670d\u52a1\u5668) diff --git a/HMCLAPI/src/main/resources/org/jackhuang/hellominecraft/launcher/I18N_en_US.properties b/HMCLAPI/src/main/resources/org/jackhuang/hellominecraft/launcher/I18N_en_US.properties new file mode 100644 index 000000000..7c67a94dd --- /dev/null +++ b/HMCLAPI/src/main/resources/org/jackhuang/hellominecraft/launcher/I18N_en_US.properties @@ -0,0 +1,274 @@ +launch.failed=Failed to launch +launch.failed_creating_process=Failed to create process, maybe your java path is wrong, please modify your java path. +launch.failed_sh_permission=Failed to add permission to the launch script +launch.failed_packing_jar=Failed to pack jar +launch.unsupported_launcher_version=Sorry, this launcher cannot launch this minecraft, but the launcher will try to launch it. +launch.too_big_memory_alloc_64bit=You have allocated too much memory, because of your 32-Bit Java Runtime Environment, your game probably crash. The maximum memory is 1024MB. The launcher will try to launch it. +launch.too_big_memory_alloc_free_space_too_low=You have allocated too much memory, because the physical memory size is %dMB, your game probably crash. The launcher will try to launch it. +launch.cannot_create_jvm=We find that it cannot create java virutal machine. The Java argements may have problems. You can enable the no args mode in the settings. +launch.circular_dependency_versions=Found circular dependency versions, please check if your client has been modified. +launch.not_finished_downloading_libraries=Did not finish downloading libraries, continue launching game? +launch.not_finished_decompressing_natives=Did not finish decompressing native libraries, continue launching game? + +install.no_version=The version is not found. +install.no_version_if_intall=The needed version is not found, should install the version automatically? +install.not_refrehsed=The installer list is not refreshed. +install.download_list=Download List + +install.liteloader.get_list=Get LiteLoader List +install.liteloader.install=Install LiteLoader + +install.forge.get_list=Get Forge List +install.forge.install=Install Forge +install.forge.get_changelogs=Get Forge Changelogs + +install.optifine.install=Install Optifine +install.optifine.get_list=Get OptifineList + +install.failed_forge=Failed to Install Forge +install.failed_optifine=Failed to Install Optifine +install.failed_liteloader=Failed to Install LiteLoader +install.failed_download_forge=Failed to Download Forge +install.failed_download_optifine=Failed to Download Optifine +install.failed=Failed to install +install.success=Install successfully +install.no_forge=No Forge +install.choose_forge=Choose the version you want to install Forge +install.version=Version +install.mcversion=Game Version +install.time=Time +install.release_time=Release Time +install.type=Type + +crash.launcher=Launcher has crashed! +crash.minecraft=Minecraft has crashed! + +login.choose_charactor=Please choose the charactor you want +login.no_charactor=No charactor in this account. +login.your_password=Your password +login.failed=Failed to login +login.no_Player007=You have not set username! +login.wrong_password=Wrong password or username +login.invalid_username=Invalid username +login.invalid_uuid_and_username=Invalid UUID and username +login.invalid_password=Invalid password +login.invalid_access_token=Invalid Access Token +login.changed_client_token=The server response has changed the client token. +login.not_email=The username must be a e-mail. +login.type=Login +login.username=Name +login.account=Email + +login.failed.connect_authentication_server=Cannot connect the authentication server. Check your network. + +login.profile.not_logged_in=Not Logged In and Cannot modify the profile. +login.profile.selected=Cannot modify the profile, you must logout and go back. + +login.methods.yggdrasil=Mojang +login.methods.offline=Offline +login.methods.no_method=No login method + +log.playername_null=The player name is empty. + +minecraft.no_selected_version=No selected Minecraft version +minecraft.wrong_path=Wrong Minecraft path, the launcher could not find the path. + +operation.stopped=The operation was aborted. +operation.confirm_stop=Terminate the operations? + +ui.login.password=Password +ui.more=More + +crash.advice.UnsupportedClassVersionError=Maybe your java is too old, try to update the java. +crash.advice.ConcurrentModificationException=Maybe your Java is newer than 1.8.0_11, you could downgrade to Java 7. +crash.advice.ClassNotFoundException=Minecraft or mods are incomplete. Update your game and mods! +crash.advice.NoSuchFieldError=Minecraft or mods are incomplete. Update your game and mods! +crash.advice.SecurityException=Maybe you have modified minecraft.jar but have not remove the META-INF.\u8bf7\u901a\u8fc7\u538b\u7f29\u8f6f\u4ef6\u5220\u9664jar\u4e2d\u7684META-INF\u6587\u4ef6\u5939\u3002 +crash.advice.otherwise=Maybe mods caused problems. + +crash.advice.OpenGL=Maybe drivers caused problems. +crash.advice.no_lwjgl=Maybe drivers caused problems. + +crash.advice.no=No advice. + +crash.error=Minecraft has crashed. +crash.main_class_not_found=Main Class is not found, may be your mc has been broken. +crash.class_path_wrong=Maybe the launch script is malformed. + +ui.label.newProfileWindow.new_profile_name=New Profile Name: +ui.label.newProfileWindow.copy_from=Copy From: +ui.newProfileWindow.title=New Config + +ui.button.ok=OK +ui.button.refresh=Refresh +ui.button.run=Play +ui.button.settings=Settings +ui.button.about=About +ui.button.others=Others +ui.button.logout=LogOut +ui.button.download=Download +ui.button.retry=Retry +ui.button.delete=Delete +ui.button.install=Install +ui.button.info=Info +ui.button.save=Save +ui.button.copy=Copy +ui.button.clear=Clear +ui.button.close=Close +ui.button.explore=Explore +button.cancel=Cancel +button.ok=OK + +ui.label.version=Version +ui.label.password=Password +ui.label.profile=Profile + +ui.message.first_load=Please enter your name. +ui.message.enter_password=Please enter your password. +ui.message.launching=Launching... +ui.message.making=Generating... +ui.message.sure_remove=Sure to remove profile %s? + +ui.label.settings=Settings +ui.label.crashing=Hello Minecraft! Launcher has crashed! +ui.label.crashing_out_dated=Hello Minecraft! Launcher has crashed! And your launcher is not the latest version. Update it! +ui.label.failed_set=Failed to set: + +download=Download +download.mojang=Mojang +download.BMCL=BMCLAPI (bangbang93, http://bmclapi.bangbang93.com/) +download.not_200=Failed to download, the response code +download.failed=Failed to download +download.successfully=Download Successfully + +message.error=Error +message.cannot_open_explorer=Cannot open explorer: +message.cancelled=Cancelled +message.info=Info + +folder.game=Game Dir +folder.mod=Mod +folder.coremod=Core Mod +folder.config=Configs +folder.resourcepacks=Resourcepacks +folder.screenshots=Screenshots +folder.saves=Saves + +settings.tabs.game_download=Games +settings.tabs.installers=Installers +settings.tabs.assets_downloads=Assets + +settings=Settings +settings.explore=Explore +settings.manage=Manage +settings.cannot_remove_default_config=Cannot remove the default configution. +settings.max_memory=Max Memory/MB +settings.java_dir=Java Dir +settings.game_directory=Game Dir +settings.dimension=Dimension +settings.fullscreen=Fullscreen +settings.update_version=Update version json. +settings.physical_memory=Physical Memory Size + +settings.failed_load=Failed to load settings file. Remove it? + +advancedsettings=Advanced +advancedsettings.launcher_visible=Launcher Visibility +advancedsettings.run_directory=Run Directory +advencedsettings.debug_mode=Debug Mode +advancedsettings.java_permanent_generation_space=Permanent Generation Space/MB +advancedsettings.jvm_args=Java VM Arguments +advancedsettings.Minecraft_arguments=Minecraft Arguments +advancedsettings.launcher_visibility.close=Close the launcher when the game launched. +advancedsettings.launcher_visibility.hide=Hide the launcher when the game launched. +advancedsettings.launcher_visibility.keep=Keep the launcher visible. +advancedsettings.game_dir.default=Default (.minecraft/) +advancedsettings.game_dir.independent=Independent (.minecraft/versions//,\u9664assets,libraries) +advancedsettings.no_jvm_args=No JVM Args +advancedsettings.java_args_default=Default java args: -XX:+UseConcMarkSweepGC -XX:+CMSIncrementalMode -XX:-UseAdaptiveSizePolicy -XX:MaxPermSize=???m -Xmx???m -Dfml.ignoreInvalidMinecraftCertificates=true -Dfml.ignorePatchDiscrepancies=true + +mainwindow.show_log=Show Logs +mainwindow.make_launch_script=Make Launching Script. +mainwindow.make_launch_script_failed=Failed to make script. +mainwindow.enter_script_name=Enter the script name. +mainwindow.make_launch_succeed=Finished script creation. +mainwindow.no_version=No version found. You could download the game in the game settings. + +launcher.about=About Author
\nEmail\uff1ahuanghongxun2008@126.com
\nMinecraft Forum ID: klkl6523
\nCopyright (c) 2013 huangyuhui +launcher.download_source=Download Source +launcher.background_location=Background Location +launcher.exit_failed=Failed to shutdown. +launcher.versions_json_not_matched=The version %s is malformed! There are a json:%s in this version. Do you want to fix this problem? +launcher.versions_json_not_matched_needs_auto_completion=The version %s lost json, needs auto completion? +launcher.versions_json_not_matched_cannot_auto_completion=The version %s lost json, but cannot auto complete it, delete it? +launcher.choose_bgpath=Choose background path. +launcher.background_tooltip=\n\n\u542f\u52a8\u5668\u9ed8\u8ba4\u4f7f\u7528\u81ea\u5e26\u7684\u80cc\u666f
\n\u5982\u679c\u5f53\u524d\u76ee\u5f55\u6709background.png\uff0c\u5219\u4f1a\u4f7f\u7528\u8be5\u6587\u4ef6\u4f5c\u4e3a\u80cc\u666f
\n\u5982\u679c\u5f53\u524d\u76ee\u5f55\u6709bgskin\u5b50\u76ee\u5f55\uff0c\u5219\u4f1a\u968f\u673a\u4f7f\u7528\u91cc\u9762\u7684\u4e00\u5f20\u56fe\u4f5c\u4e3a\u80cc\u666f
\n\u5982\u679c\u8be5\u80cc\u666f\u5730\u5740\u88ab\u4fee\u6539\uff0c\u5219\u4f1a\u4f7f\u7528\u80cc\u666f\u5730\u5740\u91cc\u7684\u4e00\u5f20\u56fe\u4f5c\u4e3a\u80cc\u666f
\n\u80cc\u666f\u5730\u5740\u5141\u8bb8\u6709\u591a\u4e2a\u5730\u5740\uff0c\u4f7f\u7528\u534a\u89d2\u5206\u53f7";"(\u4e0d\u5305\u542b\u53cc\u5f15\u53f7)\u5206\u9694\n\n +launcher.update_launcher=Check for update +launcher.enable_shadow=Enable Window Shadow +launcher.theme=Theme + +launcher.title.game=Games +launcher.title.main=Home +launcher.title.launcher=Launcher + +versions.release=Release +versions.snapshot=Snapshot +versions.old_beta=Beta +versions.old_alpha=Old Alpha + +versions.manage.rename=Rename this version +versions.manage.rename.message=Please enter the new name +versions.manage.remove=Delete this version +versions.manage.remove.confirm=Sure to remove the version +versions.manage.redownload_json=Redownload Minecraft Configuration(minecraft.json) +versions.manage.redownload_assets_index=Redownload Assets Index + +advice.os64butjdk32=Your OS is 64-Bit but your Java is 32-Bit. The 64-Bit Java is recommended. + +assets.download_all=Download Assets Files +assets.not_refreshed=The assets list is not refreshed, please refresh it once. +assets.failed=Failed to get the list, try again. +assets.list.1_7_3_after=1.7.3 And Higher +assets.list.1_6=1.6(BMCLAPI) +assets.type=Asset Type +assets.download=Download Assets +assets.no_assets=No assets folder found, there's no sound & language file gaming. You can go to Game Settings->Assets Download to download assets. + +gamedownload.not_refreshed=The game list is not refreshed, please refresh it once. + +taskwindow.title=Tasks +taskwindow.single_progress=Single progress +taskwindow.total_progress=Total progress +taskwindow.cancel=Cancel +taskwindow.no_more_instance=Maybe you opened more than one task window, dont open it again! + +setupwindow.include_minecraft=Import game +setupwindow.find_in_configurations=Finished importing. You can find it in the configuration selection bar. +setupwindow.give_a_name=Give a name to the new game. +setupwindow.new=New +setupwindow.no_empty_name=Version name cannot be empty. + +update.no_browser=Cannot open any browser. The link has been copied to the clipboard. You can paste it to the address bar. +update.should_open_link=Are you willing to open the update link? +update.newest_version=Newest version: +update.failed=Failed to check for updates. +update.found=(Found Update!) + +logwindow.terminate_game=Terminate Game +logwindow.tieba=Tieba + +selector.choose=Choose + +minecraft.invalid=Invalid +minecraft.invalid_jar=Invalid Jar +minecraft.not_a_file=Not a file +minecraft.not_found=Not found +minecraft.not_readable=Not readable +minecraft.modified=(Modified!) + +color.red=Red +color.blue=Blue +color.green=Green +color.orange=Orange +color.dark_blue=Dark Blue +color.purple=Purple \ No newline at end of file diff --git a/HMCLAPI/src/main/resources/org/jackhuang/hellominecraft/launcher/I18N_zh_CN.properties b/HMCLAPI/src/main/resources/org/jackhuang/hellominecraft/launcher/I18N_zh_CN.properties new file mode 100644 index 000000000..27df800f2 --- /dev/null +++ b/HMCLAPI/src/main/resources/org/jackhuang/hellominecraft/launcher/I18N_zh_CN.properties @@ -0,0 +1,276 @@ +launch.failed=\u542f\u52a8\u5931\u8d25 +launch.failed_creating_process=\u542f\u52a8\u5931\u8d25\uff0c\u5728\u521b\u5efa\u65b0\u8fdb\u7a0b\u65f6\u53d1\u751f\u9519\u8bef\uff0c\u53ef\u80fd\u662fJava\u8def\u5f84\u9519\u8bef\u3002 +launch.failed_sh_permission=\u4e3a\u542f\u52a8\u6587\u4ef6\u6dfb\u52a0\u6743\u9650\u65f6\u53d1\u751f\u9519\u8bef +launch.failed_packing_jar=\u5728\u6253\u5305jar\u65f6\u53d1\u751f\u9519\u8bef +launch.unsupported_launcher_version=\u5bf9\u4e0d\u8d77\uff0c\u672c\u542f\u52a8\u5668\u73b0\u5728\u53ef\u80fd\u4e0d\u80fd\u542f\u52a8\u8fd9\u4e2a\u7248\u672c\u7684Minecraft\uff0c\u4f46\u542f\u52a8\u5668\u8fd8\u662f\u4f1a\u5c1d\u8bd5\u542f\u52a8\uff0c\u8bf7\u5c3d\u5feb\u5c06\u6b64\u95ee\u9898\u62a5\u544a\u7ed9\u4f5c\u8005\u3002 +launch.too_big_memory_alloc_64bit=\u60a8\u8bbe\u7f6e\u7684\u5185\u5b58\u5927\u5c0f\u8fc7\u5927\uff0c\u7531\u4e8e\u53ef\u80fd\u8d85\u8fc7\u4e8632\u4f4dJava\u7684\u5185\u5b58\u5206\u914d\u9650\u5236\uff0c\u6240\u4ee5\u53ef\u80fd\u65e0\u6cd5\u542f\u52a8\u6e38\u620f\uff0c\u8bf7\u5c06\u5185\u5b58\u8c03\u81f31024MB\u6216\u66f4\u5c0f\uff0c\u542f\u52a8\u5668\u4ecd\u4f1a\u5c1d\u8bd5\u542f\u52a8\u3002 +launch.too_big_memory_alloc_free_space_too_low=\u60a8\u8bbe\u7f6e\u7684\u5185\u5b58\u5927\u5c0f\u8fc7\u5927\uff0c\u7531\u4e8e\u8d85\u8fc7\u4e86\u7cfb\u7edf\u5185\u5b58\u5927\u5c0f%dMB\uff0c\u6240\u4ee5\u53ef\u80fd\u5f71\u54cd\u6e38\u620f\u4f53\u9a8c\u6216\u65e0\u6cd5\u542f\u52a8\u6e38\u620f\uff0c\u542f\u52a8\u5668\u4ecd\u4f1a\u5c1d\u8bd5\u542f\u52a8\u3002 +launch.cannot_create_jvm=\u622a\u83b7\u5230\u65e0\u6cd5\u521b\u5efaJava\u865a\u62df\u673a\uff0c\u53ef\u80fd\u662fJava\u53c2\u6570\u6709\u95ee\u9898\uff0c\u53ef\u4ee5\u5728\u8bbe\u7f6e\u4e2d\u5f00\u542f\u65e0\u53c2\u6570\u6a21\u5f0f\u542f\u52a8\u3002 +launch.circular_dependency_versions=\u53d1\u73b0\u6e38\u620f\u7248\u672c\u5faa\u73af\u5f15\u7528\uff0c\u8bf7\u786e\u8ba4\u60a8\u7684\u5ba2\u6237\u7aef\u672a\u88ab\u4fee\u6539\u6216\u4fee\u6539\u5bfc\u81f4\u51fa\u73b0\u6b64\u95ee\u9898\u3002 +launch.not_finished_downloading_libraries=\u672a\u5b8c\u6210\u6e38\u620f\u4f9d\u8d56\u5e93\u7684\u4e0b\u8f7d\uff0c\u8fd8\u8981\u7ee7\u7eed\u542f\u52a8\u6e38\u620f\u5417\uff1f +launch.not_finished_decompressing_natives=\u672a\u80fd\u89e3\u538b\u6e38\u620f\u672c\u5730\u5e93\uff0c\u8fd8\u8981\u7ee7\u7eed\u542f\u52a8\u6e38\u620f\u5417\uff1f + +install.no_version=\u672a\u627e\u5230\u8981\u5b89\u88c5\u7684\u5bf9\u5e94MC\u7248\u672c +install.no_version_if_intall=\u672a\u627e\u5230\u8981\u5b89\u88c5\u7684\u5bf9\u5e94MC\u7248\u672c\uff0c\u662f\u5426\u81ea\u52a8\u5b89\u88c5\u9700\u8981\u7684MC\u7248\u672c\uff1f +install.not_refrehsed=\u672a\u5237\u65b0\u5217\u8868 +install.download_list=\u4e0b\u8f7d\u5217\u8868 + +install.liteloader.get_list=\u83b7\u53d6LiteLoader\u5217\u8868 +install.liteloader.install=\u5b89\u88c5LiteLoader + +install.forge.get_list=\u83b7\u53d6Forge\u5217\u8868 +install.forge.install=\u5b89\u88c5Forge +install.forge.get_changelogs=\u83b7\u53d6Forge\u66f4\u65b0\u8bb0\u5f55 + +install.optifine.install=\u5b89\u88c5Optifine +install.optifine.get_list=\u83b7\u53d6Optifine\u5217\u8868 + +install.failed_forge=\u5b89\u88c5Forge\u5931\u8d25 +install.failed_optifine=\u5b89\u88c5Optifine\u5931\u8d25 +install.failed_liteloader=\u5b89\u88c5LiteLoader\u5931\u8d25 +install.failed_download_forge=\u4e0b\u8f7dForge\u5931\u8d25 +install.failed_download_optifine=\u4e0b\u8f7dOptifine\u5931\u8d25 +install.failed=\u5b89\u88c5\u5931\u8d25 +install.success=\u5b89\u88c5\u6210\u529f +install.no_forge=\u6ca1\u6709\u5b89\u88c5Forge +install.choose_forge=\u9009\u62e9\u4f60\u5b89\u88c5\u7684Forge\u7248\u672c +install.version=\u7248\u672c +install.mcversion=\u6e38\u620f\u7248\u672c +install.time=\u65f6\u95f4 +install.release_time=\u91ca\u653e\u65f6\u95f4 +install.type=\u7c7b\u578b + +crash.launcher=\u542f\u52a8\u5668\u5d29\u6e83\u4e86\uff01 +crash.minecraft=Minecraft\u5d29\u6e83\u4e86\uff01 + +login.choose_charactor=\u8bf7\u9009\u62e9\u60a8\u8981\u4f7f\u7528\u7684\u89d2\u8272 +login.no_charactor=\u8be5\u5e10\u53f7\u6ca1\u6709\u89d2\u8272 +login.your_password=\u60a8\u7684\u5bc6\u7801 +login.failed=\u767b\u5f55\u5931\u8d25\uff1a +login.no_Player007=\u4f60\u8fd8\u672a\u8bbe\u7f6e\u7528\u6237\u540d\uff01 +login.wrong_password=\u53ef\u80fd\u662f\u60a8\u7684\u7528\u6237\u540d\u6216\u5bc6\u7801\u9519\u8bef +login.invalid_username=\u65e0\u6548\u7684\u7528\u6237\u540d +login.invalid_uuid_and_username=\u65e0\u6548\u7684UUID\u548c\u7528\u6237\u540d +login.invalid_password=\u65e0\u6548\u7684\u5bc6\u7801 +login.invalid_access_token=\u65e0\u6548\u7684\u8bbf\u95ee\u4ee4\u724c +login.changed_client_token=\u670d\u52a1\u5668\u56de\u5e94\u5df2\u7ecf\u4fee\u6539\u5ba2\u6237\u7aef\u4ee4\u724c +login.not_email=\u7528\u6237\u540d\u5fc5\u987b\u662f\u90ae\u7bb1 +login.type=\u767b\u5f55 +login.username=\u540d\u5b57 +login.account=\u90ae\u7bb1 + +login.failed.connect_authentication_server=\u65e0\u6cd5\u8fde\u63a5\u8ba4\u8bc1\u670d\u52a1\u5668,\u53ef\u80fd\u662f\u7f51\u7edc\u95ee\u9898 + +login.profile.not_logged_in=\u65e0\u6cd5\u4fee\u6539\u6e38\u620f\u8d44\u6599\u540c\u65f6\u672a\u767b\u5f55 +login.profile.selected=\u65e0\u6cd5\u4fee\u6539\u6e38\u620f\u8d44\u6599. \u4f60\u5fc5\u987b\u767b\u51fa\u518d\u8fd4\u56de. + +login.methods.yggdrasil=\u6b63\u7248\u767b\u5f55 +login.methods.offline=\u79bb\u7ebf\u6a21\u5f0f +login.methods.no_method=\u6ca1\u6709\u767b\u5165\u65b9\u5f0f... + +log.playername_null=\u73a9\u5bb6\u540d\u4e3a\u7a7a\uff0c\u8fd9\u4ee3\u8868\u7740\u767b\u5f55\u65b9\u6cd5\u51fa\u73b0\u95ee\u9898 + +minecraft.no_selected_version=\u6ca1\u6709\u9009\u62e9\u4efb\u4f55\u4e00\u4e2aMinecraft\u7248\u672c +minecraft.wrong_path=\u9519\u8bef\u7684Minecraft\u8def\u5f84\uff0c\u542f\u52a8\u5668\u672a\u627e\u5230\u8bbe\u5b9a\u7684Minecraft\u8def\u5f84\uff0c\u8bf7\u68c0\u67e5\u3002 + +operation.stopped=\u64cd\u4f5c\u88ab\u5f3a\u884c\u7ec8\u6b62 +operation.confirm_stop=\u771f\u7684\u8981\u7ec8\u6b62\u64cd\u4f5c\u5417\uff1f + +ui.login.password=\u5bc6\u7801 +ui.more=\u66f4\u591a + +crash.advice.UnsupportedClassVersionError=\u8fd9\u53ef\u80fd\u662f\u56e0\u4e3a\u60a8\u7684Java\u7248\u672c\u8fc7\u4e8e\u8001\u65e7\uff0c\u53ef\u4ee5\u5c1d\u8bd5\u66f4\u6362\u6700\u65b0Java\u5e76\u5728\u7248\u672c\u8bbe\u7f6e\u7684Java\u8def\u5f84\u4e2d\u8bbe\u7f6e. +crash.advice.ConcurrentModificationException=\u8fd9\u53ef\u80fd\u662f\u56e0\u4e3a\u60a8\u7684Java\u7248\u672c\u9ad8\u4e8eJava 1.8.0_11\u5bfc\u81f4\u7684,\u53ef\u4ee5\u5c1d\u8bd5\u5378\u8f7dJava8\u5b89\u88c5Java7\u3002 +crash.advice.ClassNotFoundException=Minecraft\u4e0d\u5b8c\u6574\u6216Mod\u51b2\u7a81\u3002\u53ef\u4ee5\u4e0b\u8f7d\u6574\u5408\u5305\u89e3\u51b3\u95ee\u9898\u3002 +crash.advice.NoSuchFieldError=Minecraft\u4e0d\u5b8c\u6574\u6216Mod\u51b2\u7a81\u3002\u53ef\u4ee5\u901a\u8fc7\u4e0b\u8f7d\u6574\u5408\u5305\u89e3\u51b3\u95ee\u9898\u3002 +crash.advice.SecurityException=\u53ef\u80fd\u662f\u60a8\u4fee\u6539\u4e86minecraft.jar\u4f46\u672a\u5220\u9664META-INF\u6587\u4ef6\u5939\u7684\u539f\u56e0\u3002\u8bf7\u901a\u8fc7\u538b\u7f29\u8f6f\u4ef6\u5220\u9664jar\u4e2d\u7684META-INF\u6587\u4ef6\u5939\u3002 +crash.advice.otherwise=\u53ef\u80fd\u662fMod\u6216\u5176\u4ed6\u95ee\u9898\u3002 + +crash.advice.OpenGL=\u53ef\u80fd\u662f\u663e\u5361/\u58f0\u5361\u9a71\u52a8\u95ee\u9898\uff0c\u4e5f\u53ef\u80fd\u662fMod\u5bfc\u81f4\u7684\u95ee\u9898\u3002 +crash.advice.no_lwjgl=\u53ef\u80fd\u662f\u6e38\u620f\u4f9d\u8d56\u5e93\u4e0d\u5b8c\u6574\u6216\u89e3\u538b\u4f9d\u8d56\u5e93\u65f6\u51fa\u9519\u3002\u53ef\u4ee5\u901a\u8fc7\u4e0b\u8f7d\u6574\u5408\u5305\u89e3\u51b3\u95ee\u9898\u3002 + +crash.advice.no=\u65e0\u5efa\u8bae\u3002 + +crash.error=\u60a8\u7684Minecraft\u5d29\u6e83\u4e86\u3002 +crash.main_class_not_found=\u627e\u4e0d\u5230\u4e3b\u7c7b\uff0c\u53ef\u80fd\u662f\u60a8\u7684JSON\u6587\u4ef6\u586b\u5199\u9519\u8bef\u3002\u65e0\u6cd5\u542f\u52a8\u6e38\u620f\u3002\u53ef\u4ee5\u901a\u8fc7\u4e0b\u8f7d\u6574\u5408\u5305\u89e3\u51b3\u95ee\u9898\u3002 +crash.class_path_wrong=\u89e3\u6790Class Path\u65f6\u51fa\u73b0\u9519\u8bef\uff0c\u6b64\u9519\u8bef\u672c\u4e0d\u5e94\u8be5\u53d1\u751f\u3002\u53ef\u80fd\u662f\u542f\u52a8\u811a\u672c\u9519\u8bef\uff0c\u8bf7\u4ed4\u7ec6\u68c0\u67e5\u542f\u52a8\u811a\u672c\u3002 + +ui.label.newProfileWindow.new_profile_name=\u65b0\u914d\u7f6e\u540d: +ui.label.newProfileWindow.copy_from=\u590d\u5236\u914d\u7f6e: +ui.newProfileWindow.title=\u65b0\u5efa\u914d\u7f6e + +ui.button.ok=\u786e\u8ba4 +ui.button.refresh=\u5237\u65b0 +ui.button.run=\u542f\u52a8Minecraft +ui.button.settings= +ui.button.about=\u5173\u4e8e +ui.button.others=\u5176\u4ed6 +ui.button.logout=\u767b\u51fa +ui.button.download=\u4e0b\u8f7d +ui.button.retry=\u91cd\u8bd5 +ui.button.delete=\u5220\u9664 +ui.button.install=\u5b89\u88c5 +ui.button.info=\u4fe1\u606f +ui.button.save=\u4fdd\u5b58 +ui.button.copy=\u590d\u5236 +ui.button.clear=\u6e05\u9664 +ui.button.close=\u5173\u95ed +ui.button.explore=\u6d4f\u89c8 +button.cancel=\u53d6\u6d88 +button.ok=\u786e\u5b9a + +ui.label.version=\u7248\u672c +ui.label.password=\u5bc6\u7801 +ui.label.profile=\u914d\u7f6e + +ui.message.first_load=\u8bf7\u5728\u5de6\u8fb9\u8f93\u5165\u60a8\u7684\u8d26\u53f7 +ui.message.enter_password=\u8bf7\u5728\u5de6\u8fb9\u8f93\u5165\u60a8\u7684\u5bc6\u7801 +ui.message.launching=\u542f\u52a8\u4e2d +ui.message.making=\u751f\u6210\u4e2d +ui.message.sure_remove=\u771f\u7684\u8981\u5220\u9664\u914d\u7f6e%s\u5417\uff1f + +ui.label.settings=\u9009\u9879 +ui.label.crashing=Hello Minecraft! Launcher\u9047\u5230\u4e86\u65e0\u6cd5\u5904\u7406\u7684\u9519\u8bef\uff0c\u8bf7\u590d\u5236\u4e0b\u5217\u5185\u5bb9\u5e76\u901a\u8fc7mcbbs\u3001\u8d34\u5427\u6216Minecraft Forum\u53cd\u9988bug\u3002 +ui.label.crashing_out_dated=Hello Minecraft! Launcher\u9047\u5230\u4e86\u65e0\u6cd5\u5904\u7406\u7684\u9519\u8bef\uff0c\u5df2\u68c0\u6d4b\u5230\u60a8\u7684\u542f\u52a8\u5668\u4e0d\u662f\u6700\u65b0\u7248\u672c\uff0c\u8bf7\u66f4\u65b0\u540e\u518d\u8bd5\uff01 +ui.label.failed_set=\u8bbe\u7f6e\u5931\u8d25\uff1a + +download=\u4e0b\u8f7d +download.mojang=\u5b98\u65b9 +download.BMCL=BMCLAPI (bangbang93, http://bmclapi.bangbang93.com/) +download.not_200=\u4e0b\u8f7d\u5931\u8d25\uff0c\u56de\u590d\u7801 +download.failed=\u4e0b\u8f7d\u5931\u8d25 +download.successfully=\u4e0b\u8f7d\u5b8c\u6210 + +message.error=\u9519\u8bef +message.cannot_open_explorer=\u65e0\u6cd5\u6253\u5f00\u6587\u4ef6\u7ba1\u7406\u5668: +message.cancelled=\u5df2\u53d6\u6d88 +message.info=\u63d0\u793a + +folder.game=\u6e38\u620f\u6587\u4ef6\u5939 +folder.mod=MOD\u6587\u4ef6\u5939 +folder.coremod=\u6838\u5fc3MOD\u6587\u4ef6\u5939 +folder.config=\u914d\u7f6e\u6587\u4ef6\u5939 +folder.resourcepacks=\u8d44\u6e90\u5305\u6587\u4ef6\u5939 +folder.screenshots=\u622a\u56fe\u6587\u4ef6\u5939 +folder.saves=\u5b58\u6863\u6587\u4ef6\u5939 + +settings.tabs.game_download=\u6e38\u620f\u4e0b\u8f7d +settings.tabs.installers=\u81ea\u52a8\u5b89\u88c5 +settings.tabs.assets_downloads=\u8d44\u6e90\u4e0b\u8f7d + +settings=\u666e\u901a\u8bbe\u7f6e +settings.explore=\u6d4f\u89c8 +settings.manage=\u7ba1\u7406 +settings.cannot_remove_default_config=\u4e0d\u80fd\u5220\u9664\u9ed8\u8ba4\u914d\u7f6e +settings.max_memory=\u6700\u5927\u5185\u5b58/MB +settings.java_dir=Java\u8def\u5f84 +settings.game_directory=\u6e38\u620f\u8def\u5f84 +settings.dimension=\u5206\u8fa8\u7387 +settings.fullscreen=\u5168\u5c4f +settings.update_version=\u66f4\u65b0\u7248\u672c\u6587\u4ef6 +settings.physical_memory=\u7269\u7406\u5185\u5b58\u5927\u5c0f + +settings.failed_load=\u8bbe\u7f6e\u6587\u4ef6\u52a0\u8f7d\u5931\u8d25\uff0c\u53ef\u80fd\u662f\u5347\u7ea7\u4e86\u542f\u52a8\u5668\u6216\u88ab\u4eba\u5de5\u4fee\u6539\u9020\u6210\u9519\u8bef\uff0c\u662f\u5426\u6e05\u9664\uff1f + +advancedsettings=\u9ad8\u7ea7\u8bbe\u7f6e +advancedsettings.launcher_visible=\u542f\u52a8\u5668\u53ef\u89c1\u6027 +advancedsettings.run_directory=\u8fd0\u884c\u8def\u5f84 +advencedsettings.debug_mode=\u8c03\u8bd5\u6a21\u5f0f +advancedsettings.java_permanent_generation_space=\u5185\u5b58\u6c38\u4e45\u4fdd\u5b58\u533a\u57df/MB +advancedsettings.jvm_args=Java\u865a\u62df\u673a\u53c2\u6570(\u4e0d\u5fc5\u586b\u5199) +advancedsettings.Minecraft_arguments=Minecraft\u989d\u5916\u53c2\u6570(\u4e0d\u5fc5\u586b\u5199) +advancedsettings.launcher_visibility.close=\u6e38\u620f\u542f\u52a8\u540e\u7ed3\u675f\u542f\u52a8\u5668 +advancedsettings.launcher_visibility.hide=\u6e38\u620f\u542f\u52a8\u540e\u9690\u85cf\u542f\u52a8\u5668 +advancedsettings.launcher_visibility.keep=\u4fdd\u6301\u542f\u52a8\u5668\u53ef\u89c1 +advancedsettings.game_dir.default=\u9ed8\u8ba4(.minecraft/) +advancedsettings.game_dir.independent=\u5404\u7248\u672c\u72ec\u7acb(.minecraft/versions/<\u7248\u672c\u540d>/,\u9664assets,libraries) +advancedsettings.no_jvm_args=\u4e0d\u6dfb\u52a0JVM\u53c2\u6570(\u4f7f\u7528Java9\u65f6\u5fc5\u52fe) +advancedsettings.java_args_default=\u542f\u52a8\u5668\u9ed8\u8ba4\u6dfb\u52a0\u7684\u53c2\u6570\uff08\u8bf7\u4e0d\u8981\u91cd\u590d\u6dfb\u52a0\uff09\uff1a-XX:+UseConcMarkSweepGC -XX:+CMSIncrementalMode -XX:-UseAdaptiveSizePolicy -XX:MaxPermSize=???m -Xmx???m -Dfml.ignoreInvalidMinecraftCertificates=true -Dfml.ignorePatchDiscrepancies=true + +mainwindow.show_log=\u67e5\u770b\u65e5\u5fd7 +mainwindow.make_launch_script=\u751f\u6210\u542f\u52a8\u811a\u672c +mainwindow.make_launch_script_failed=\u751f\u6210\u542f\u52a8\u811a\u672c\u5931\u8d25 +mainwindow.enter_script_name=\u8f93\u5165\u8981\u751f\u6210\u811a\u672c\u7684\u6587\u4ef6\u540d +mainwindow.make_launch_succeed=\u542f\u52a8\u811a\u672c\u5df2\u751f\u6210\u5b8c\u6bd5: +mainwindow.no_version=\u672a\u627e\u5230\u4efb\u4f55\u7248\u672c\uff0c\u60a8\u53ef\u4ee5\u5230[\u8bbe\u7f6e]->[\u6e38\u620f\u4e0b\u8f7d]\u4e2d\u4e0b\u8f7d\u6e38\u620f\u3002 + +launcher.about=\u9ed8\u8ba4\u80cc\u666f\u56fe\u6765\u81eaLiberty Dome\u670d\u52a1\u5668\u3002
\u5173\u4e8e\u4f5c\u8005\uff1a
\n\u767e\u5ea6ID\uff1ahuanghongxun20
\nmcbbs\uff1ahuanghongxun
\n\u90ae\u7bb1\uff1ahuanghongxun2008@126.com
\nMinecraft Forum ID: klkl6523
\n\u6b22\u8fce\u63d0\u4ea4Bug\u54e6
\nCopyright (c) 2013-2015 huangyuhui.
\u514d\u8d23\u58f0\u660e\uff1aMinecraft\u8f6f\u4ef6\u7248\u6743\u5f52Mojang AB\u6240\u6709\uff0c\u6e38\u620f\u7531\u4e8e\u8bef\u64cd\u4f5c\u672c\u542f\u52a8\u5668\u800c\u4e22\u5931\u6570\u636e\u7684\u6982\u4e0d\u8d1f\u8d23\u3002 +launcher.download_source=\u4e0b\u8f7d\u6e90 +launcher.background_location=\u80cc\u666f\u5730\u5740 +launcher.exit_failed=\u5f3a\u5236\u9000\u51fa\u5931\u8d25\uff0c\u53ef\u80fd\u662fForge 1.7.10\u53ca\u66f4\u9ad8\u7248\u672c\u5bfc\u81f4\u7684\uff0c\u65e0\u6cd5\u89e3\u51b3\u3002 +launcher.versions_json_not_matched=\u7248\u672c%s\u683c\u5f0f\u4e0d\u89c4\u8303\uff01\u8be5\u7248\u672c\u6587\u4ef6\u5939\u4e0b\u6709json:%s\uff0c\u662f\u5426\u66f4\u540d\u8fd9\u4e2a\u6587\u4ef6\u6765\u89c4\u8303\u683c\u5f0f\uff1f +launcher.versions_json_not_matched_needs_auto_completion=\u7248\u672c%s\u7f3a\u5931\u5fc5\u8981\u7684\u7248\u672c\u4fe1\u606f(JSON)\u6587\u4ef6\uff0c\u662f\u5426\u81ea\u52a8\u8865\u5168\uff1f +launcher.versions_json_not_matched_cannot_auto_completion=\u7248\u672c%s\u7f3a\u5931\u5fc5\u8981\u7684\u7248\u672c\u4fe1\u606f(JSON)\u6587\u4ef6\uff0c\u4f46\u662f\u4f3c\u4e4e\u4e0d\u662f\u539f\u7248\uff0c\u65e0\u6cd5\u81ea\u52a8\u8865\u5168\uff0c\u662f\u5426\u5220\u9664\u8be5\u7248\u672c\uff1f +launcher.versions_json_not_formatted=\u7248\u672c%s\u4fe1\u606f\u6587\u4ef6\u683c\u5f0f\u9519\u8bef\uff0c\u662f\u5426\u91cd\u65b0\u4e0b\u8f7d\uff1f +launcher.choose_bgpath=\u9009\u62e9\u80cc\u666f\u8def\u5f84 +launcher.background_tooltip=\n\n\u542f\u52a8\u5668\u9ed8\u8ba4\u4f7f\u7528\u81ea\u5e26\u7684\u80cc\u666f
\n\u5982\u679c\u5f53\u524d\u76ee\u5f55\u6709background.png\uff0c\u5219\u4f1a\u4f7f\u7528\u8be5\u6587\u4ef6\u4f5c\u4e3a\u80cc\u666f
\n\u5982\u679c\u5f53\u524d\u76ee\u5f55\u6709bgskin\u5b50\u76ee\u5f55\uff0c\u5219\u4f1a\u968f\u673a\u4f7f\u7528\u91cc\u9762\u7684\u4e00\u5f20\u56fe\u4f5c\u4e3a\u80cc\u666f
\n\u5982\u679c\u8be5\u80cc\u666f\u5730\u5740\u88ab\u4fee\u6539\uff0c\u5219\u4f1a\u4f7f\u7528\u80cc\u666f\u5730\u5740\u91cc\u7684\u4e00\u5f20\u56fe\u4f5c\u4e3a\u80cc\u666f
\n\u80cc\u666f\u5730\u5740\u5141\u8bb8\u6709\u591a\u4e2a\u5730\u5740\uff0c\u4f7f\u7528\u534a\u89d2\u5206\u53f7";"(\u4e0d\u5305\u542b\u53cc\u5f15\u53f7)\u5206\u9694\n\n +launcher.update_launcher=\u68c0\u67e5\u66f4\u65b0 +launcher.enable_shadow=\u542f\u7528\u7a97\u53e3\u9634\u5f71(\u91cd\u542f\u542f\u52a8\u5668\u751f\u6548,\u53ef\u52a0\u5feb\u6e32\u67d3\u901f\u5ea6) +launcher.theme=\u4e3b\u9898 + +launcher.title.game=\u6e38\u620f\u8bbe\u7f6e +launcher.title.main=\u4e3b\u9875 +launcher.title.launcher=\u542f\u52a8\u5668\u8bbe\u7f6e + +versions.release=\u7a33\u5b9a\u7248 +versions.snapshot=\u5feb\u7167\u7248 +versions.old_beta=\u6d4b\u8bd5\u7248 +versions.old_alpha=\u8fdc\u53e4\u7248 + +versions.manage.rename=\u91cd\u547d\u540d\u8be5\u7248\u672c +versions.manage.rename.message=\u8bf7\u8f93\u5165\u8981\u6539\u6210\u7684\u540d\u5b57 +versions.manage.remove=\u5220\u9664\u8be5\u7248\u672c +versions.manage.remove.confirm=\u771f\u7684\u8981\u5220\u9664\u7248\u672c +versions.manage.redownload_json=\u91cd\u65b0\u4e0b\u8f7d\u7248\u672c\u914d\u7f6e(minecraft.json) +versions.manage.redownload_assets_index=\u91cd\u65b0\u4e0b\u8f7d\u8d44\u6e90\u914d\u7f6e(assets_index.json) + +advice.os64butjdk32=\u60a8\u7684\u7cfb\u7edf\u662f64\u4f4d\u7684\u4f46\u662fJava\u662f32\u4f4d\u7684\uff0c\u63a8\u8350\u60a8\u5b89\u88c564\u4f4dJava. + +assets.download_all=\u4e0b\u8f7d\u8d44\u6e90\u6587\u4ef6 +assets.not_refreshed=\u8d44\u6e90\u5217\u8868\u672a\u5237\u65b0\uff0c\u8bf7\u5237\u65b0\u4e00\u6b21\u3002 +assets.failed=\u83b7\u53d6\u5217\u8868\u5931\u8d25\uff0c\u8bf7\u5237\u65b0\u91cd\u8bd5\u3002 +assets.list.1_7_3_after=1.7.3\u53ca\u4ee5\u540e +assets.list.1_6=1.6(BMCLAPI) +assets.unkown_type_select_one=\u65e0\u6cd5\u89e3\u6790\u6e38\u620f\u7248\u672c\uff1a%s\uff0c\u8bf7\u9009\u62e9\u4e00\u79cd\u8d44\u6e90\u7c7b\u578b\u4e0b\u8f7d\u3002 +assets.type=\u8d44\u6e90\u7c7b\u578b +assets.download=\u4e0b\u8f7d\u8d44\u6e90 +assets.no_assets=\u672a\u68c0\u6d4b\u5230assets\u6587\u4ef6\u5939\uff0c\u542f\u52a8\u6e38\u620f\u540e\u5c06\u6ca1\u6709\u58f0\u97f3\u548c\u8bed\u8a00\u6587\u4ef6\uff0c\u8bf7\u5230\u6e38\u620f\u8bbe\u7f6e->\u8d44\u6e90\u4e0b\u8f7d\u4e0b\u8f7d\u8d44\u6e90\u3002 + +gamedownload.not_refreshed=\u6e38\u620f\u4e0b\u8f7d\u5217\u8868\u672a\u5237\u65b0\uff0c\u8bf7\u518d\u5237\u65b0\u4e00\u6b21\u3002 + +taskwindow.title=\u4efb\u52a1 +taskwindow.single_progress=\u5355\u9879\u8fdb\u5ea6 +taskwindow.total_progress=\u603b\u8fdb\u5ea6 +taskwindow.cancel=\u53d6\u6d88 +taskwindow.no_more_instance=\u53ef\u80fd\u540c\u65f6\u6253\u5f00\u4e86\u591a\u4e2a\u4efb\u52a1\u7a97\u53e3\uff0c\u8bf7\u4e0d\u8981\u591a\u6b21\u6253\u5f00\uff01 + +setupwindow.include_minecraft=\u5bfc\u5165\u6e38\u620f\u6587\u4ef6\u5939 +setupwindow.find_in_configurations=\u5bfc\u5165\u5b8c\u6210\uff0c\u5feb\u5230\u914d\u7f6e\u4e0b\u62c9\u6846\u4e2d\u627e\u65b0\u6e38\u620f\u8def\u5f84\u5427\uff01 +setupwindow.give_a_name=\u7ed9\u65b0\u6e38\u620f\u8def\u5f84\u8d77\u4e2a\u540d\u5b57\u5427 +setupwindow.new=\u65b0\u5efa +setupwindow.no_empty_name=\u540d\u5b57\u4e0d\u53ef\u4e3a\u7a7a + +update.no_browser=\u65e0\u6cd5\u6253\u5f00\u6d4f\u89c8\u5668\uff0c\u7f51\u5740\u5df2\u7ecf\u590d\u5236\u5230\u526a\u8d34\u677f\u4e86\uff0c\u60a8\u53ef\u4ee5\u624b\u52a8\u7c98\u8d34\u7f51\u5740\u6253\u5f00\u9875\u9762 +update.should_open_link=\u662f\u5426\u524d\u5f80\u53d1\u5e03\u9875\u9762\u66f4\u65b0\uff1f +update.newest_version=\u6700\u65b0\u7248\u672c\u4e3a\uff1a +update.failed=\u68c0\u67e5\u66f4\u65b0\u5931\u8d25 +update.found=(\u53d1\u73b0\u66f4\u65b0!) + +logwindow.terminate_game=\u7ed3\u675f\u6e38\u620f\u8fdb\u7a0b +logwindow.tieba=\u8d34\u5427 + +selector.choose=\u9009\u62e9 + +minecraft.invalid=\u65e0\u6548\u7684 +minecraft.invalid_jar=\u65e0\u6548\u7684jar\u5305 +minecraft.not_a_file=\u4e0d\u662f\u6587\u4ef6 +minecraft.not_found=\u627e\u4e0d\u5230minecraft.jar +minecraft.not_readable=minecraft.jar\u4e0d\u53ef\u8bfb +minecraft.modified=(\u4fee\u6539\u7684!) + +color.red=\u7ea2\u8272 +color.blue=\u84dd\u8272 +color.green=\u7eff\u8272 +color.orange=\u6a59\u8272 +color.dark_blue=\u6df1\u84dd\u8272 +color.purple=\u7d2b\u8272 \ No newline at end of file diff --git a/HMCLAPI/src/main/resources/org/jackhuang/hellominecraft/launcher/I18N_zh_TW.properties b/HMCLAPI/src/main/resources/org/jackhuang/hellominecraft/launcher/I18N_zh_TW.properties new file mode 100644 index 000000000..c74290029 --- /dev/null +++ b/HMCLAPI/src/main/resources/org/jackhuang/hellominecraft/launcher/I18N_zh_TW.properties @@ -0,0 +1,274 @@ +launch.failed=\u555f\u52d5\u5931\u6557 +launch.failed_creating_process=\u555f\u52d5\u5931\u6557\uff0c\u5728\u5275\u5efa\u65b0\u9032\u7a0b\u6642\u767c\u751f\u932f\u8aa4\uff0c\u53ef\u80fd\u662fJava\u8def\u5f91\u932f\u8aa4\u3002 +launch.failed_sh_permission=\u70ba\u555f\u52d5\u6587\u4ef6\u6dfb\u52a0\u6b0a\u9650\u6642\u767c\u751f\u932f\u8aa4 +launch.failed_pa\u200b\u200bcking_jar=\u5728\u6253\u5305jar\u6642\u767c\u751f\u932f\u8aa4 +launch.unsupported_launcher_version=\u5c0d\u4e0d\u8d77\uff0c\u672c\u555f\u52d5\u5668\u73fe\u5728\u53ef\u80fd\u4e0d\u80fd\u555f\u52d5\u9019\u500b\u7248\u672c\u7684Minecraft\uff0c\u4f46\u555f\u52d5\u5668\u9084\u662f\u6703\u5617\u8a66\u555f\u52d5\uff0c\u8acb\u76e1\u5feb\u5c07\u6b64\u554f\u984c\u5831\u544a\u7d66\u4f5c\u8005\u3002 +launch.too_big_memory_alloc_64bit=\u60a8\u8bbe\u7f6e\u7684\u5185\u5b58\u5927\u5c0f\u8fc7\u5927\uff0c\u7531\u4e8e\u53ef\u80fd\u8d85\u8fc7\u4e8632\u4f4dJava\u7684\u5185\u5b58\u5206\u914d\u9650\u5236\uff0c\u6240\u4ee5\u53ef\u80fd\u65e0\u6cd5\u542f\u52a8\u6e38\u620f\uff0c\u8bf7\u5c06\u5185\u5b58\u8c03\u81f31024MB\u6216\u66f4\u5c0f\uff0c\u542f\u52a8\u5668\u4ecd\u4f1a\u5c1d\u8bd5\u542f\u52a8\u3002 +launch.too_big_memory_alloc_free_space_too_low=\u60a8\u8bbe\u7f6e\u7684\u5185\u5b58\u5927\u5c0f\u8fc7\u5927\uff0c\u7531\u4e8e\u8d85\u8fc7\u4e86\u7cfb\u7edf\u5185\u5b58\u5927\u5c0f%dMB\uff0c\u6240\u4ee5\u53ef\u80fd\u5f71\u54cd\u6e38\u620f\u4f53\u9a8c\u6216\u65e0\u6cd5\u542f\u52a8\u6e38\u620f\uff0c\u542f\u52a8\u5668\u4ecd\u4f1a\u5c1d\u8bd5\u542f\u52a8\u3002 +launch.cannot_create_jvm=\u622a\u7372\u5230\u7121\u6cd5\u5275\u5efaJava\u865b\u64ec\u6a5f\uff0c\u53ef\u80fd\u662fJava\u53c3\u6578\u6709\u554f\u984c\uff0c\u53ef\u4ee5\u5728\u8a2d\u5b9a\u4e2d\u958b\u555f\u7121\u53c3\u6578\u6a21\u5f0f\u555f\u52d5\u3002 +launch.circular_dependency_versions=\u767c\u73fe\u904a\u6232\u7248\u672c\u5faa\u74b0\u5f15\u7528\uff0c\u8acb\u78ba\u8a8d\u60a8\u7684\u5ba2\u6236\u7aef\u672a\u88ab\u4fee\u6539\u6216\u4fee\u6539\u5c0e\u81f4\u51fa\u73fe\u6b64\u554f\u984c\u3002 +launch.not_finished_downloading_libraries=\u672a\u5b8c\u6210\u904a\u6232\u4f9d\u8cf4\u5eab\u7684\u4e0b\u8f09\uff0c\u9084\u8981\u7e7c\u7e8c\u555f\u52d5\u904a\u6232\u55ce\uff1f +launch.not_finished_decompressing_natives=\u672a\u80fd\u89e3\u58d3\u904a\u6232\u672c\u5730\u5eab\uff0c\u9084\u8981\u7e7c\u7e8c\u555f\u52d5\u904a\u6232\u55ce\uff1f + +install.no_version=\u672a\u627e\u5230\u8981\u5b89\u88dd\u7684\u5c0d\u61c9MC\u7248\u672c +install.no_version_if_intall=\u672a\u627e\u5230\u8981\u5b89\u88dd\u7684\u5c0d\u61c9MC\u7248\u672c\uff0c\u662f\u5426\u81ea\u52a8\u5b89\u88c5\u9700\u8981\u7684MC\u7248\u672c\uff1f +install.not_refrehsed=\u672a\u5237\u65b0\u5217\u8868 +install.download_list=\u4e0b\u8f09\u5217\u8868 + +install.liteloader.get_list=\u7372\u53d6LiteLoader\u5217\u8868 +install.liteloader.install=\u5b89\u88ddLiteLoader + +install.forge.get_list=\u7372\u53d6Forge\u5217\u8868 +install.forge.install=\u5b89\u88ddForge +install.forge.get_changelogs=\u7372\u53d6Forge\u66f4\u65b0\u8a18\u9304 + +install.optifine.install=\u5b89\u88ddOptifine +install.optifine.get_list=\u7372\u53d6Optifine\u5217\u8868 + +install.failed_forge=\u5b89\u88ddForge\u5931\u6557 +install.failed_optifine=\u5b89\u88ddOptifine\u5931\u6557 +install.failed_liteloader=\u5b89\u88ddLiteLoader\u5931\u6557 +install.failed_download_forge=\u4e0b\u8f09Forge\u5931\u6557 +install.failed_download_optifine=\u4e0b\u8f09Optifine\u5931\u6557 +install.failed=\u5b89\u88dd\u5931\u6557 +install.success=\u5b89\u88dd\u6210\u529f +install.no_forge=\u6c92\u6709\u5b89\u88ddForge +install.choose_forge=\u9078\u64c7\u4f60\u5b89\u88dd\u7684Forge\u7248\u672c +install.version=\u7248\u672c +install.mcversion=\u904a\u6232\u7248\u672c +install.time=\u6642\u9593 +install.release_time=\u91cb\u653e\u6642\u9593 +install.type=\u985e\u578b + +crash.launcher=\u555f\u52d5\u5668\u5d29\u6f70\u4e86\uff01 +crash.minecraft=Minecraft\u5d29\u6f70\u4e86\uff01 + +login.choose_charactor=\u8acb\u9078\u64c7\u60a8\u8981\u4f7f\u7528\u7684\u89d2\u8272 +login.no_charactor=\u8a72\u5e33\u865f\u6c92\u6709\u89d2\u8272 +login.your_password=\u60a8\u7684\u5bc6\u78bc +login.failed=\u767b\u9304\u5931\u6557\uff1a +login.no_Player007=\u4f60\u9084\u672a\u8a2d\u5b9a\u7528\u6236\u540d\uff01 +login.wrong_password=\u53ef\u80fd\u662f\u60a8\u7684\u7528\u6236\u540d\u6216\u5bc6\u78bc\u932f\u8aa4 +login.invalid_username=\u7121\u6548\u7684\u7528\u6236\u540d +login.invalid_uuid_and_username=\u7121\u6548\u7684UUID\u548c\u7528\u6236\u540d +login.invalid_password=\u7121\u6548\u7684\u5bc6\u78bc +login.invalid_access_token=\u7121\u6548\u7684\u8a2a\u554f\u4ee4\u724c +login.changed_client_token=\u670d\u52d9\u5668\u56de\u61c9\u5df2\u7d93\u4fee\u6539\u5ba2\u6236\u7aef\u4ee4\u724c +login.not_email=\u7528\u6236\u540d\u5fc5\u9808\u662f\u90f5\u7bb1 +login.type=\u767b\u9304 +login.username=\u540d\u5b57 +login.account=\u90ae\u7bb1 + +login.failed.connect_authentication_server=\u7121\u6cd5\u9023\u63a5\u8a8d\u8b49\u670d\u52d9\u5668,\u53ef\u80fd\u662f\u7db2\u7d61\u554f\u984c + +login.profile.not_logged_in=\u7121\u6cd5\u4fee\u6539\u904a\u6232\u8cc7\u6599\u540c\u6642\u672a\u767b\u9304 +login.profile.selected=\u7121\u6cd5\u4fee\u6539\u904a\u6232\u8cc7\u6599. \u4f60\u5fc5\u9808\u767b\u51fa\u518d\u8fd4\u56de. + +login.methods.yggdrasil=\u6b63\u7248\u767b\u9304 +login.methods.offline=\u96e2\u7dda\u6a21\u5f0f +login.methods.no_method=\u6c92\u6709\u767b\u5165\u65b9\u5f0f... + +log.playername_null=\u73a9\u5bb6\u540d\u70ba\u7a7a\uff0c\u9019\u4ee3\u8868\u8457\u767b\u9304\u65b9\u6cd5\u51fa\u73fe\u554f\u984c + +minecraft.no_selected_version=\u6c92\u6709\u9078\u64c7\u4efb\u4f55\u4e00\u500bMinecraft\u7248\u672c +minecraft.wrong_path=\u932f\u8aa4\u7684Minecraft\u8def\u5f91\uff0c\u555f\u52d5\u5668\u672a\u627e\u5230\u8a2d\u5b9a\u7684Minecraft\u8def\u5f91\uff0c\u8acb\u6aa2\u67e5\u3002 + +operation.stopped=\u64cd\u4f5c\u88ab\u5f37\u884c\u7d42\u6b62 +operation.confirm_stop=\u771f\u7684\u8981\u7d42\u6b62\u64cd\u4f5c\u55ce\uff1f + +ui.login.password=\u5bc6\u78bc +ui.more=\u66f4\u591a + +crash.advice.UnsupportedClassVersionError=\u9019\u53ef\u80fd\u662f\u56e0\u70ba\u60a8\u7684Java\u7248\u672c\u904e\u65bc\u8001\u820a\uff0c\u53ef\u4ee5\u5617\u8a66\u66f4\u63db\u6700\u65b0Java\u4e26\u5728\u7248\u672c\u8a2d\u5b9a\u7684Java\u8def\u5f91\u4e2d\u8a2d\u5b9a. +crash.advice.ConcurrentModificationException=\u9019\u53ef\u80fd\u662f\u56e0\u70ba\u60a8\u7684Java\u7248\u672c\u9ad8\u65bcJava 1.8.0_11\u5c0e\u81f4\u7684,\u53ef\u4ee5\u5617\u8a66\u5378\u8f09Java8\u5b89\u88ddJava7\u3002 +crash.advice.ClassNotFoundException=Minecraft\u4e0d\u5b8c\u6574\u6216Mod\u885d\u7a81\u3002\u53ef\u4ee5\u4e0b\u8f09\u6574\u5408\u5305\u89e3\u6c7a\u554f\u984c\u3002 +crash.advice.NoSuchFieldError=Minecraft\u4e0d\u5b8c\u6574\u6216Mod\u885d\u7a81\u3002\u53ef\u4ee5\u901a\u904e\u4e0b\u8f09\u6574\u5408\u5305\u89e3\u6c7a\u554f\u984c\u3002 +crash.advice.SecurityException=\u53ef\u80fd\u662f\u60a8\u4fee\u6539\u4e86minecraft.jar\u4f46\u672a\u522a\u9664META-INF\u6587\u4ef6\u593e\u7684\u539f\u56e0\u3002\u8acb\u901a\u904e\u58d3\u7e2e\u8edf\u4ef6\u522a\u9664jar\u4e2d\u7684META-INF\u6587\u4ef6\u593e\u3002 +crash.advice.otherwise=\u53ef\u80fd\u662fMod\u6216\u5176\u4ed6\u554f\u984c\u3002 + +crash.advice.OpenGL=\u53ef\u80fd\u662f\u986f\u5361/\u8072\u5361\u9a45\u52d5\u554f\u984c\uff0c\u4e5f\u53ef\u80fd\u662fMod\u5c0e\u81f4\u7684\u554f\u984c\u3002 +crash.advice.no_lwjgl=\u53ef\u80fd\u662f\u904a\u6232\u4f9d\u8cf4\u5eab\u4e0d\u5b8c\u6574\u6216\u89e3\u58d3\u4f9d\u8cf4\u5eab\u6642\u51fa\u932f\u3002\u53ef\u4ee5\u901a\u904e\u4e0b\u8f09\u6574\u5408\u5305\u89e3\u6c7a\u554f\u984c\u3002 + +crash.advice.no=\u7121\u5efa\u8b70\u3002 + +crash.error=\u60a8\u7684Minecraft\u5d29\u6f70\u4e86\u3002 +crash.main_class_not_found=\u627e\u4e0d\u5230\u4e3b\u985e\uff0c\u53ef\u80fd\u662f\u60a8\u7684JSON\u6587\u4ef6\u586b\u5beb\u932f\u8aa4\u3002\u7121\u6cd5\u555f\u52d5\u904a\u6232\u3002\u53ef\u4ee5\u901a\u904e\u4e0b\u8f09\u6574\u5408\u5305\u89e3\u6c7a\u554f\u984c\u3002 +crash.class_path_wrong=\u89e3\u6790Class Path\u6642\u51fa\u73fe\u932f\u8aa4\uff0c\u6b64\u932f\u8aa4\u672c\u4e0d\u61c9\u8a72\u767c\u751f\u3002\u53ef\u80fd\u662f\u555f\u52d5\u8173\u672c\u932f\u8aa4\uff0c\u8acb\u4ed4\u7d30\u6aa2\u67e5\u555f\u52d5\u8173\u672c\u3002 + +ui.label.newProfileWindow.new_profile_name=\u65b0\u914d\u7f6e\u540d: +ui.label.newProfileWindow.copy_from=\u8907\u88fd\u914d\u7f6e: +ui.newProfileWindow.title=\u65b0\u5efa\u914d\u7f6e + +ui.button.ok=\u78ba\u8a8d +ui.button.refresh=\u5237\u65b0 +ui.button.run=\u555f\u52d5Minecraft +ui.button.settings= +ui.button.about=\u95dc\u65bc +ui.button.others=\u5176\u4ed6 +ui.button.logout=\u767b\u51fa +ui.button.download=\u4e0b\u8f09 +ui.button.retry=\u91cd\u8a66 +ui.button.delete=\u522a\u9664 +ui.button.install=\u5b89\u88dd +ui.button.info=\u4fe1\u606f +ui.button.save=\u4fdd\u5b58 +ui.button.copy=\u8907\u88fd +ui.button.clear=\u6e05\u9664 +ui.button.close=\u95dc\u9589 +ui.button.explore=\u700f\u89bd +button.cancel=\u53d6\u6d88 +button.ok=\u78ba\u5b9a + +ui.label.version=\u7248\u672c +ui.label.password=\u5bc6\u78bc +ui.label.profile=\u914d\u7f6e + +ui.message.first_load=\u8acb\u5728\u5de6\u908a\u8f38\u5165\u60a8\u7684\u8cec\u865f +ui.message.enter_password=\u8acb\u5728\u5de6\u908a\u8f38\u5165\u60a8\u7684\u5bc6\u78bc +ui.message.launching=\u555f\u52d5\u4e2d +ui.message.making=\u751f\u6210\u4e2d +ui.message.sure_remove=\u771f\u7684\u8981\u5220\u9664\u914d\u7f6e%s\u5417\uff1f + +ui.label.settings=\u9078\u9805 +ui.label.crashing=Hello Minecraft! Launcher\u9047\u5230\u4e86\u7121\u6cd5\u8655\u7406\u7684\u932f\u8aa4\uff0c\u8acb\u8907\u5236\u4e0b\u5217\u5167\u5bb9\u4e26\u901a\u904emcbbs\u3001\u8cbc\u5427\u6216Minecraft Forum\u53cd\u994bbug\u3002 +ui.label.crashing_out_dated=Hello Minecraft! Launcher\u9047\u5230\u4e86\u7121\u6cd5\u8655\u7406\u7684\u932f\u8aa4\uff0c\u5df2\u6aa2\u6e2c\u5230\u60a8\u7684\u555f\u52d5\u5668\u4e0d\u662f\u6700\u65b0\u7248\u672c\uff0c\u8acb\u66f4\u65b0\u5f8c\u518d\u8a66\uff01 +ui.label.failed_set=\u8a2d\u5b9a\u5931\u6557\uff1a + +download=\u4e0b\u8f09 +download.mojang=\u5b98\u65b9 +download.BMCL=BMCLAPI (bangbang93, http://bmclapi.bangbang93.com/) +download.not_200=\u4e0b\u8f09\u5931\u6557\uff0c\u56de\u590d\u7801 +download.failed=\u4e0b\u8f09\u5931\u6557 +download.successfully=\u4e0b\u8f09\u5b8c\u6210 + +message.error=\u932f\u8aa4 +message.cannot_open_explorer=\u7121\u6cd5\u6253\u958b\u6587\u4ef6\u7ba1\u7406\u5668: +message.cancelled=\u5df2\u53d6\u6d88 +message.info=\u63d0\u793a + +folder.game=\u904a\u6232\u6587\u4ef6\u593e +folder.mod=MOD\u6587\u4ef6\u593e +folder.coremod=\u6838\u5fc3MOD\u6587\u4ef6\u593e +folder.config=\u914d\u7f6e\u6587\u4ef6\u593e +folder.resourcepacks=\u8cc7\u6e90\u5305\u6587\u4ef6\u593e +folder.screenshots=\u622a\u5716\u6587\u4ef6\u593e +folder.saves=\u5b58\u6a94\u6587\u4ef6\u593e + +settings.tabs.game_download=\u904a\u6232\u4e0b\u8f09 +settings.tabs.installers=\u81ea\u52d5\u5b89\u88dd +settings.tabs.assets_downloads=\u8cc7\u6e90\u4e0b\u8f09 + +settings=\u666e\u901a\u8a2d\u5b9a +settings.explore=\u700f\u89bd +settings.manage=\u7ba1\u7406 +settings.cannot_remove_default_config=\u4e0d\u80fd\u522a\u9664\u9ed8\u8a8d\u914d\u7f6e +settings.max_memory=\u6700\u5927\u5167\u5b58\uff08MB\uff09 +settings.java_dir=Java\u8def\u5f91 +settings.game_directory=\u904a\u6232\u8def\u5f91 +settings.dimension=\u5206\u8fa8\u7387 +settings.fullscreen=\u5168\u5c4f +settings.update_version=\u66f4\u65b0\u7248\u672c\u6587\u4ef6 +settings.physical_memory=\u7269\u7406\u5185\u5b58\u5927\u5c0f + +settings.failed_load=\u8a2d\u5b9a\u6587\u4ef6\u52a0\u8f09\u5931\u6557\uff0c\u53ef\u80fd\u662f\u5347\u7d1a\u4e86\u555f\u52d5\u5668\u6216\u88ab\u4eba\u5de5\u4fee\u6539\u9020\u6210\u932f\u8aa4\uff0c\u662f\u5426\u6e05\u9664\uff1f + +advancedsettings=\u9ad8\u7d1a\u8a2d\u5b9a +advancedsettings.launcher_visible=\u555f\u52d5\u5668\u53ef\u898b\u6027 +advancedsettings.run_directory=\u904b\u884c\u8def\u5f91 +advencedsettings.debug_mode=\u8abf\u8a66\u6a21\u5f0f +advancedsettings.java_permanent_generation_space=\u5167\u5b58\u6c38\u4e45\u4fdd\u5b58\u5340\u57df/MB +advancedsettings.jvm_args=Java\u865b\u64ec\u6a5f\u53c3\u6578(\u4e0d\u5fc5\u586b\u5beb) +advancedsettings.Minecraft_arguments=Minecraft\u984d\u5916\u53c3\u6578(\u4e0d\u5fc5\u586b\u5beb) +advancedsettings.launcher_visibility.close=\u904a\u6232\u555f\u52d5\u5f8c\u7d50\u675f\u555f\u52d5\u5668 +advancedsettings.launcher_visibility.hide=\u904a\u6232\u555f\u52d5\u5f8c\u96b1\u85cf\u555f\u52d5\u5668 +advancedsettings.launcher_visibility.keep=\u4fdd\u6301\u555f\u52d5\u5668\u53ef\u898b +advancedsettings.game_dir.default=\u9ed8\u8a8d(.minecraft/) +advancedsettings.game_dir.independent=\u5404\u7248\u672c\u7368\u7acb(.minecraft/versions/<\u7248\u672c\u540d>/,\u9664assets,libraries) +advancedsettings.no_jvm_args=\u4e0d\u6dfb\u52a0JVM\u53c3\u6578(\u4f7f\u7528Java9\u6642\u5fc5\u52fe) +advancedsettings.java_args_default=\u555f\u52d5\u5668\u9ed8\u8a8d\u6dfb\u52a0\u7684\u53c3\u6578\uff08\u8acb\u4e0d\u8981\u91cd\u8907\u6dfb\u52a0\uff09\uff1a-XX:+UseConcMarkSweepGC -XX:+CMSIncrementalMode -XX:-UseAdaptiveSizePolicy -XX:MaxPermSize=???m -Xmx???m -Dfml. ignoreInvalidMinecraftCertificates=true -Dfml.ignorePatchDiscrepancies=true + +mainwindow.show_log=\u67e5\u770b\u65e5\u8a8c +mainwindow.make_launch_script=\u751f\u6210\u555f\u52d5\u8173\u672c +mainwindow.make_launch_script_failed=\u751f\u6210\u555f\u52d5\u8173\u672c\u5931\u6557 +mainwindow.enter_script_name=\u8f38\u5165\u8981\u751f\u6210\u8173\u672c\u7684\u6587\u4ef6\u540d +mainwindow.make_launch_succeed=\u555f\u52d5\u8173\u672c\u5df2\u751f\u6210\u5b8c\u7562: +mainwindow.no_version=\u672a\u627e\u5230\u4efb\u4f55\u7248\u672c\uff0c\u60a8\u53ef\u4ee5\u5230[\u8a2d\u5b9a]->[\u904a\u6232\u4e0b\u8f09]\u4e2d\u4e0b\u8f09\u904a\u6232\u3002 + +launcher.about=\u9ed8\u8a8d\u80cc\u666f\u5716\u4f86\u81eaLiberty Dome\u670d\u52d9\u5668\u3002
\u95dc\u65bc\u4f5c\u8005\uff1a
\n\u767e\u5ea6ID\uff1ahuanghongxun20
\nmcbbs\uff1ahuanghongxun
\n\u90f5\u7bb1\uff1ahuanghongxun2008@126.com
\nMinecraft Forum ID: klkl6523
\n\u6b61\u8fce\u63d0\u4ea4Bug\u54e6
\nCopyright (c) 2013 huangyuhui +launcher.download_source=\u4e0b\u8f09\u6e90 +launcher.background_location=\u80cc\u666f\u5730\u5740 +launcher.exit_failed=\u5f37\u5236\u9000\u51fa\u5931\u6557\uff0c\u53ef\u80fd\u662fForge 1.7.10\u53ca\u66f4\u9ad8\u7248\u672c\u5c0e\u81f4\u7684\uff0c\u7121\u6cd5\u89e3\u6c7a\u3002 +launcher.versions_json_not_matched=\u7248\u672c%s\u683c\u5f0f\u4e0d\u898f\u7bc4\uff01\u8a72\u7248\u672c\u6587\u4ef6\u593e\u4e0b\u6709json:%s\uff0c\u662f\u5426\u66f4\u540d\u9019\u500b\u6587\u4ef6\u4f86\u898f\u7bc4\u683c\u5f0f\uff1f +launcher.versions_json_not_matched_needs_auto_completion=\u7248\u672c%s\u7f3a\u5931\u5fc5\u8981\u7684\u7248\u672c\u4fe1\u606f(JSON)\u6587\u4ef6\uff0c\u662f\u5426\u81ea\u52a8\u8865\u5168\uff1f +launcher.versions_json_not_matched_cannot_auto_completion=\u7248\u672c%s\u7f3a\u5931\u5fc5\u8981\u7684\u7248\u672c\u4fe1\u606f(JSON)\u6587\u4ef6\uff0c\u4f46\u662f\u4f3c\u4e4e\u4e0d\u662f\u539f\u7248\uff0c\u65e0\u6cd5\u81ea\u52a8\u8865\u5168\uff0c\u662f\u5426\u5220\u9664\u8be5\u7248\u672c\uff1f +launcher.choose_bgpath=\u9078\u64c7\u80cc\u666f\u8def\u5f91 +launcher.background_tooltip=\n\n\u555f\u52d5\u5668\u9ed8\u8a8d\u4f7f\u7528\u81ea\u5e36\u7684\u80cc\u666f
\n\u5982\u679c\u7576\u524d\u76ee\u9304\u6709background.png\uff0c\u5247\u6703\u4f7f\u7528\u8a72\u6587\u4ef6\u4f5c\u70ba\u80cc\u666f
\n\u5982\u679c\u7576\u524d\u76ee\u9304\u6709bgskin\u5b50\u76ee\u9304\uff0c\u5247\u6703\u96a8\u6a5f\u4f7f\u7528\u88e1\u9762\u7684\u4e00\u5f35\u5716\u4f5c\u70ba\u80cc\u666f
\n\u5982\u679c\u8a72\u80cc\u666f\u5730\u5740\u88ab\u4fee\u6539\uff0c\u5247\u6703\u4f7f\u7528\u80cc\u666f\u5730\u5740\u88e1\u7684\u4e00\u5f35\u5716\u4f5c\u70ba\u80cc\u666f
\n\u80cc\u666f\u5730\u5740\u5141\u8a31\u6709\u591a\u500b\u5730\u5740\uff0c\u4f7f\u7528\u534a\u89d2\u5206\u865f";"(\u4e0d\u5305\u542b\u96d9\u5f15\u865f)\u5206\u9694\n\n +launcher.update_launcher=\u68c0\u67e5\u66f4\u65b0 +launcher.enable_shadow=\u542f\u7528\u7a97\u53e3\u9634\u5f71(\u91cd\u542f\u542f\u52a8\u5668\u751f\u6548) +launcher.theme=\u4e3b\u9898 + +launcher.title.game=\u904a\u6232\u8a2d\u5b9a +launcher.title.main=\u4e3b\u9801 +launcher.title.launcher=\u555f\u52d5\u5668\u8a2d\u5b9a + +versions.release=\u7a69\u5b9a\u7248 +versions.snapshot=\u5feb\u7167\u7248 +versions.old_beta=\u6e2c\u8a66\u7248 +versions.old_alpha=\u9060\u53e4\u7248 + +versions.manage.rename=\u91cd\u547d\u540d\u8a72\u7248\u672c +versions.manage.rename.message=\u8acb\u8f38\u5165\u8981\u6539\u6210\u7684\u540d\u5b57 +versions.manage.remove=\u522a\u9664\u8a72\u7248\u672c +versions.manage.remove.confirm=\u771f\u7684\u8981\u522a\u9664\u7248\u672c +versions.manage.redownload_json=\u91cd\u65b0\u4e0b\u8f09\u7248\u672c\u914d\u7f6e(minecraft.json) +versions.manage.redownload_assets_index=\u91cd\u65b0\u4e0b\u8f09\u8cc7\u6e90\u914d\u7f6e(assets_index.json) + +advice.os64butjdk32=\u60a8\u7684\u7cfb\u7d71\u662f64\u4f4d\u7684\u4f46\u662fJava\u662f32\u4f4d\u7684\uff0c\u63a8\u85a6\u60a8\u5b89\u88dd64\u4f4dJava. + +assets.download_all=\u4e0b\u8f7d\u8d44\u6e90\u6587\u4ef6 +assets.not_refreshed=\u8cc7\u6e90\u5217\u8868\u672a\u5237\u65b0\uff0c\u8acb\u5237\u65b0\u4e00\u6b21\u3002 +assets.failed=\u7372\u53d6\u5217\u8868\u5931\u6557\uff0c\u8acb\u5237\u65b0\u91cd\u8a66\u3002 +assets.list.1_7_3_after=1.7.3\u53ca\u4ee5\u5f8c +assets.list.1_6=1.6(BMCLAPI) +assets.type=\u8cc7\u6e90\u985e\u578b +assets.download=\u4e0b\u8f09\u8cc7\u6e90 +assets.no_assets=\u672a\u68c0\u6d4b\u5230assets\u6587\u4ef6\u5939\uff0c\u542f\u52a8\u6e38\u620f\u540e\u5c06\u6ca1\u6709\u58f0\u97f3\u548c\u8bed\u8a00\u6587\u4ef6\uff0c\u8bf7\u5230\u6e38\u620f\u8bbe\u7f6e->\u8d44\u6e90\u4e0b\u8f7d\u4e0b\u8f7d\u8d44\u6e90\u3002 + +gamedownload.not_refreshed=\u904a\u6232\u4e0b\u8f09\u5217\u8868\u672a\u5237\u65b0\uff0c\u8acb\u518d\u5237\u65b0\u4e00\u6b21\u3002 + +taskwindow.title=\u4efb\u52d9 +taskwindow.single_progress=\u55ae\u9805\u9032\u5ea6 +taskwindow.total_progress=\u7e3d\u9032\u5ea6 +taskwindow.cancel=\u53d6\u6d88 +taskwindow.no_more_instance=\u53ef\u80fd\u540c\u6642\u6253\u958b\u4e86\u591a\u500b\u4efb\u52d9\u7a97\u53e3\uff0c\u8acb\u4e0d\u8981\u591a\u6b21\u6253\u958b\uff01 + +setupwindow.include_minecraft=\u5c0e\u5165\u904a\u6232\u6587\u4ef6\u593e +setupwindow.find_in_configurations=\u5c0e\u5165\u5b8c\u6210\uff0c\u5feb\u5230\u914d\u7f6e\u4e0b\u62c9\u6846\u4e2d\u627e\u65b0\u904a\u6232\u8def\u5f91\u5427\uff01 +setupwindow.give_a_name=\u7d66\u65b0\u904a\u6232\u8def\u5f91\u8d77\u500b\u540d\u5b57\u5427 +setupwindow.new=\u65b0\u5efa +setupwindow.no_empty_name=\u540d\u5b57\u4e0d\u53ef\u70ba\u7a7a + +update.no_browser=\u7121\u6cd5\u6253\u958b\u700f\u89bd\u5668\uff0c\u7db2\u5740\u5df2\u7d93\u5fa9\u88fd\u5230\u526a\u8cbc\u677f\u4e86\uff0c\u60a8\u53ef\u4ee5\u624b\u52d5\u7c98\u8cbc\u7db2\u5740\u6253\u958b\u9801\u9762 +update.should_open_link=\u662f\u5426\u524d\u5f80\u767c\u5e03\u9801\u9762\u66f4\u65b0\uff1f +update.newest_version=\u6700\u65b0\u7248\u672c\u70ba\uff1a +update.failed=\u6aa2\u67e5\u66f4\u65b0\u5931\u6557 +update.found=(\u767c\u73fe\u66f4\u65b0!) + +logwindow.terminate_game=\u7d50\u675f\u904a\u6232\u9032\u7a0b +logwindow.tieba=\u8cbc\u5427 + +selector.choose=\u9078\u64c7 + +minecraft.invalid=\u7121\u6548\u7684 +minecraft.invalid_jar=\u7121\u6548\u7684jar\u5305 +minecraft.not_a_file=\u4e0d\u662f\u6587\u4ef6 +minecraft.not_found=\u627e\u4e0d\u5230minecraft.jar +minecraft.not_readable=minecraft.jar\u4e0d\u53ef\u8b80 +minecraft.modified=(\u4fee\u6539\u7684!) + +color.red=\u7d05\u8272 +color.blue=\u85cd\u8272 +color.green=\u7da0\u8272 +color.orange=\u6a59\u8272 +color.dark_blue=\u6df1\u85cd\u8272 +color.purple=\u7d2b\u8272 \ No newline at end of file diff --git a/HMCSM/build.gradle b/HMCSM/build.gradle new file mode 100644 index 000000000..be0317039 --- /dev/null +++ b/HMCSM/build.gradle @@ -0,0 +1,90 @@ +//apply plugin: 'execjar' +apply plugin: 'launch4j' + +if (!hasProperty('mainClass')) { + ext.mainClass = 'org.jackhuang.hellominecraft.svrmgr.Main' +} + +String mavenGroupId = 'HMCSM' +String mavenVersion = '0.8.6' +String bundleName = "Hello Minecraft! Server Manager" + +group = mavenGroupId +version = mavenVersion + +String mavenArtifactId = name + +buildscript { + repositories { + mavenCentral(); + // You may define additional repositories, or even remove "mavenCentral()". + // Read more about repositories here: + // http://www.gradle.org/docs/current/userguide/dependency_management.html#sec:repositories + /* + maven { + url uri('../../../../repo') + }*/ + dependencies { + //classpath 'org.jackhuang.gradle:ExecJar:1.0-SNAPSHOT' + classpath 'net.sf.proguard:proguard-gradle:4.10' + classpath 'edu.sc.seis.gradle:launch4j:1.0.6' + } + } +} + +configure(install.repositories.mavenInstaller) { + pom.project { + groupId = mavenGroupId + artifactId = mavenArtifactId + version = mavenVersion + } +} + +dependencies { + compile project(":HMCLAPI") + compile project(":MetroLookAndFeel") + compile files("../../../../repo/org/ho/jyaml/1.3/jyaml-1.3.jar") + compile ("org.tukaani:xz:1.5") + compile ('org.jsoup:jsoup:1.7.2') +} + +jar { + from { configurations.compile.collect { it.isDirectory() ? it : zipTree(it) } } + + manifest { + attributes 'Created-By' : 'Copyright(c) 2014 huangyuhui.', + 'Main-Class' : mainClass + } +} + +task proguard(type: proguard.gradle.ProGuardTask, dependsOn: jar) { + ext { + injar = jar.archivePath + jar.classifier = 'proguard' + outjar = jar.archivePath + jar.classifier = '' + } + + injars injar + outjars outjar + printusage "shrinking_" + version + ".map" + printmapping "obfuscate_" + version + ".map" + + configuration 'proguard.pro' +} +/* +execjar.suffix = 'proguard' +execjar.version = mavenVersion +execjar.group = mavenGroupId +execjar.mainClass = mainClass +execjar.bundleName = bundleName + +execjar.dependsOn proguard +*/ +processResources { + from(sourceSets.main.resources.srcDirs) { + exclude 'icon.icns' + } +} + +build.dependsOn proguard diff --git a/HMCSM/proguard.pro b/HMCSM/proguard.pro new file mode 100644 index 000000000..f4d2fd4fe --- /dev/null +++ b/HMCSM/proguard.pro @@ -0,0 +1,50 @@ +-libraryjars D:\Java\jdk1.6.0_45\jre\lib\rt.jar +-libraryjars D:\Java\jdk1.6.0_45\jre\lib\jce.jar +-libraryjars D:\Java\jdk1.6.0_45\jre\lib\jsse.jar + +-dontoptimize +-dontwarn +-dontshrink + +-overloadaggressively +-repackageclasses 'org.jackhuang.hellominecraft.svrmgr' +-allowaccessmodification + +-renamesourcefileattribute SourceFile + +-keepattributes *Annotation*,SourceFile,LineNumberTable,Signature + +-keep class com.** { *; } +-keep class org.jackhuang.metro.** { *; } +-keep class yaml.** { *; } +-keep class org.ho.** { *; } +-keep class org.jsoup.** { *; } + +-keep class org.jackhuang.hellominecraft.svrmgr.Main { public static void main(java.lang.String[]); } + +-keepclassmembers class org.jackhuang.hellominecraft.svrmgr.settings.Settings { public ; } +-keepclassmembers class org.jackhuang.hellominecraft.svrmgr.settings.BannedPlayers { public ; } +-keepclassmembers class org.jackhuang.hellominecraft.svrmgr.settings.Op { public ; } +-keepclassmembers class org.jackhuang.hellominecraft.svrmgr.settings.PlayerList { public ; } +-keepclassmembers class org.jackhuang.hellominecraft.svrmgr.settings.Schedule { public ; } +-keepclassmembers class org.jackhuang.hellominecraft.svrmgr.settings.WhiteList { public ; } + +-keepclassmembers class org.jackhuang.hellominecraft.svrmgr.cbplugins.Category { public ; } +-keepclassmembers class org.jackhuang.hellominecraft.svrmgr.cbplugins.BukkitPlugin { public ; } +-keepclassmembers class org.jackhuang.hellominecraft.svrmgr.cbplugins.PluginInfo { public ; } +-keepclassmembers class org.jackhuang.hellominecraft.svrmgr.cbplugins.PluginInformation { public ; } +-keepclassmembers class org.jackhuang.hellominecraft.svrmgr.cbplugins.PluginVersion { public ; } + +-keepclassmembers class org.jackhuang.hellominecraft.svrmgr.installer.cauldron.InstallProfile { public ; } +-keepclassmembers class org.jackhuang.hellominecraft.svrmgr.installer.cauldron.Install { public ; } + +-keepclassmembers class org.jackhuang.hellominecraft.version.Latest { public ; } +-keepclassmembers class org.jackhuang.hellominecraft.version.MinecraftVersion { public ; } +-keepclassmembers class org.jackhuang.hellominecraft.version.MinecraftLibrary { public ; } +-keepclassmembers class org.jackhuang.hellominecraft.version.IMinecraftLibrary { public ; } +-keepclassmembers class org.jackhuang.hellominecraft.version.MinecraftVersions { public ; } +-keepclassmembers class org.jackhuang.hellominecraft.version.Natives { public ; } +-keepclassmembers class org.jackhuang.hellominecraft.version.OS { public ; } +-keepclassmembers class org.jackhuang.hellominecraft.version.Rules { public ; } +-keepclassmembers class org.jackhuang.hellominecraft.version.AssetsObject { public ; } +-keepclassmembers class org.jackhuang.hellominecraft.version.AssetsIndex { public ; } diff --git a/HMCSM/src/main/java/org/jackhuang/hellominecraft/svrmgr/Main.java b/HMCSM/src/main/java/org/jackhuang/hellominecraft/svrmgr/Main.java new file mode 100644 index 000000000..a34a9b4e8 --- /dev/null +++ b/HMCSM/src/main/java/org/jackhuang/hellominecraft/svrmgr/Main.java @@ -0,0 +1,65 @@ +/* + * 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.svrmgr; + +import java.awt.Font; +import java.io.PrintWriter; +import java.io.StringWriter; +import javax.swing.UIManager; +import org.jackhuang.hellominecraft.utils.functions.DoneListener0; +import org.jackhuang.hellominecraft.HMCLog; +import org.jackhuang.hellominecraft.views.LogWindow; +import org.jackhuang.hellominecraft.svrmgr.settings.SettingsManager; +import org.jackhuang.hellominecraft.utils.UpdateChecker; +import org.jackhuang.hellominecraft.svrmgr.views.MainWindow; +import org.jackhuang.hellominecraft.utils.VersionNumber; +import org.jackhuang.hellominecraft.lookandfeel.HelloMinecraftLookAndFeel; + +/** + * + * @author hyh + */ +public class Main { + + public static String launcherName = "Hello Minecraft! Server Manager"; + public static final String PUBLISH_URL = "http://www.mcbbs.net/thread-171239-1-1.html"; + public static byte firstVer = 0, secondVer = 8, thirdVer = 6; + public static String makeTitle() { + return launcherName + ' ' + firstVer + '.' + secondVer + '.' + thirdVer; + } + + public static void main(String[] args) { + try { + SettingsManager.load(); + try { + javax.swing.UIManager.setLookAndFeel(new HelloMinecraftLookAndFeel()); + UIManager.getLookAndFeelDefaults().put("defaultFont", new Font("寰蒋闆呴粦", Font.PLAIN, 12)); + } catch (Throwable ex) { + HMCLog.warn("Failed to set look and feel", ex); + } + new UpdateChecker(new VersionNumber(firstVer, secondVer, thirdVer), "hmcsm", SettingsManager.settings.checkUpdate, new DoneListener0() { + + @Override + public void onDone() { + SettingsManager.settings.checkUpdate = false; + } + }).start(); + new MainWindow().setVisible(true); + } catch(Throwable t) { + HMCLog.err("There's something wrong when running server holder.", t); + + LogWindow.instance.clean(); + LogWindow.instance.log("寮鏈嶅櫒宕╂簝浜哘AQ"); + StringWriter trace = new StringWriter(); + t.printStackTrace(new PrintWriter(trace)); + LogWindow.instance.log(trace.toString()); + LogWindow.instance.setVisible(true); + + System.exit(-1); + } + } +} diff --git a/HMCSM/src/main/java/org/jackhuang/hellominecraft/svrmgr/cbplugins/BukkitPlugin.java b/HMCSM/src/main/java/org/jackhuang/hellominecraft/svrmgr/cbplugins/BukkitPlugin.java new file mode 100644 index 000000000..1e53130b0 --- /dev/null +++ b/HMCSM/src/main/java/org/jackhuang/hellominecraft/svrmgr/cbplugins/BukkitPlugin.java @@ -0,0 +1,37 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package org.jackhuang.hellominecraft.svrmgr.cbplugins; + +import java.util.List; + +/** + * + * @author hyh + */ +public class BukkitPlugin { + + public String description, plugin_name, slug; + public List versions; + + public String getLatestVersion() { + if(versions != null) { + PluginVersion v = versions.get(0); + return v.version; + } + return null; + } + + public String getLatestBukkit() { + if(versions != null) { + PluginVersion v = versions.get(0); + List al = v.game_versions; + if(al != null && !al.isEmpty()) { + return al.get(0); + } + } + return ""; + } + +} diff --git a/HMCSM/src/main/java/org/jackhuang/hellominecraft/svrmgr/cbplugins/Category.java b/HMCSM/src/main/java/org/jackhuang/hellominecraft/svrmgr/cbplugins/Category.java new file mode 100644 index 000000000..bcf3cae8d --- /dev/null +++ b/HMCSM/src/main/java/org/jackhuang/hellominecraft/svrmgr/cbplugins/Category.java @@ -0,0 +1,14 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package org.jackhuang.hellominecraft.svrmgr.cbplugins; + +/** + * + * @author hyh + */ +public class Category { + public double count; + public String name; +} diff --git a/HMCSM/src/main/java/org/jackhuang/hellominecraft/svrmgr/cbplugins/PluginInfo.java b/HMCSM/src/main/java/org/jackhuang/hellominecraft/svrmgr/cbplugins/PluginInfo.java new file mode 100644 index 000000000..af255f38a --- /dev/null +++ b/HMCSM/src/main/java/org/jackhuang/hellominecraft/svrmgr/cbplugins/PluginInfo.java @@ -0,0 +1,18 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package org.jackhuang.hellominecraft.svrmgr.cbplugins; + +import java.util.List; + +/** + * + * @author hyh + */ +public class PluginInfo { + public String website, dbo_page, description, slug, plugin_name, + link, stage, main; + public List authors, categories; + public List versions; +} diff --git a/HMCSM/src/main/java/org/jackhuang/hellominecraft/svrmgr/cbplugins/PluginInformation.java b/HMCSM/src/main/java/org/jackhuang/hellominecraft/svrmgr/cbplugins/PluginInformation.java new file mode 100644 index 000000000..461c85407 --- /dev/null +++ b/HMCSM/src/main/java/org/jackhuang/hellominecraft/svrmgr/cbplugins/PluginInformation.java @@ -0,0 +1,15 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package org.jackhuang.hellominecraft.svrmgr.cbplugins; + +/** + * + * @author hyh + */ +public class PluginInformation { + + public String name, version, author, description; + +} diff --git a/HMCSM/src/main/java/org/jackhuang/hellominecraft/svrmgr/cbplugins/PluginManager.java b/HMCSM/src/main/java/org/jackhuang/hellominecraft/svrmgr/cbplugins/PluginManager.java new file mode 100644 index 000000000..2362d9e8c --- /dev/null +++ b/HMCSM/src/main/java/org/jackhuang/hellominecraft/svrmgr/cbplugins/PluginManager.java @@ -0,0 +1,86 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package org.jackhuang.hellominecraft.svrmgr.cbplugins; + +import com.google.gson.Gson; +import com.google.gson.reflect.TypeToken; +import java.io.File; +import java.io.InputStream; +import java.util.List; +import java.util.logging.Level; +import java.util.logging.Logger; +import java.util.zip.ZipEntry; +import java.util.zip.ZipFile; +import org.ho.yaml.Yaml; +import org.jackhuang.hellominecraft.utils.NetUtils; +import org.jackhuang.hellominecraft.utils.StrUtils; + +/** + * + * @author hyh + */ +public class PluginManager { + + public static PluginInformation getPluginYML(File f) { + try { + ZipFile file = new ZipFile(f); + ZipEntry plg = file.getEntry("plugin.yml"); + InputStream is = file.getInputStream(plg); + return Yaml.loadType(is, PluginInformation.class); + } catch (Exception ex) { + Logger.getLogger(PluginManager.class.getName()).log(Level.SEVERE, null, ex); + } + return null; + } + + public static List getPlugins() throws Exception { + String result = NetUtils.doGet("http://api.bukget.org/3//plugins?fields=slug,plugin_name,description,versions.version,versions.game_versions"); + Gson gson = new Gson(); + List list = gson.fromJson(result, new TypeToken>(){}.getType()); + return list; + } + + public static final String CATEGORY_ADMIN_TOOLS = "Admin Tools", + CATEGORY_DEVELOPER_TOOLS = "Developer Tools", + CATEGORY_FUN = "Fun", + CATEGORY_GENERAL = "General", + CATEGORY_ANTI_GRIEFING_TOOLS = "Anti Griefing Tools", + CATEGORY_MECHAICS = "Mechanics", + CATEGORY_Fixes = "Fixes", + CATEGORY_ROLE_PLAYING = "Role Playing", + CATEGORY_WORLD_EDITING_AND_MANAGEMENT = "World Editing and Management", + CATEGORY_TELEPORTATION = "Teleportation", + CATEGORY_INFORMATIONAL = "Informational", + CATEGORY_ECONOMY = "Economy", + CATEGORY_CHAT_RELATED = "Chat Related", + CATEGORY_MISCELLANEOUS = "Miscellaneous", + CATEGORY_WORLD_GENERATORS = "World Generators", + CATEGORY_WEBSITE_ADMINISTRATION = "Website Administration"; + + public static List getPluginsByCategory(String category) throws Exception { + String result = NetUtils.doGet("http://api.bukget.org/3//categories/" + category + "?fields=slug,plugin_name,description,versions.version,versions.game_versions"); + Gson gson = new Gson(); + List list = gson.fromJson(result, new TypeToken>(){}.getType()); + return list; + } + public static List getCategories() throws Exception { + String result = NetUtils.doGet("http://api.bukget.org/3//categories/"); + Gson gson = new Gson(); + List list = gson.fromJson(result, new TypeToken>(){}.getType()); + return list; + } + public static PluginInfo getPluginInfo(String slug) throws Exception { + if(StrUtils.isNotBlank(slug)) { + String result = NetUtils.doGet("http://api.bukget.org/3//plugins/bukkit/" + slug.toLowerCase()); + if(StrUtils.isNotBlank(result)) { + if(!result.equals("null")) { + PluginInfo info = new Gson().fromJson(result, PluginInfo.class); + return info; + } + } + } + return null; + } +} diff --git a/HMCSM/src/main/java/org/jackhuang/hellominecraft/svrmgr/cbplugins/PluginVersion.java b/HMCSM/src/main/java/org/jackhuang/hellominecraft/svrmgr/cbplugins/PluginVersion.java new file mode 100644 index 000000000..03b236712 --- /dev/null +++ b/HMCSM/src/main/java/org/jackhuang/hellominecraft/svrmgr/cbplugins/PluginVersion.java @@ -0,0 +1,19 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package org.jackhuang.hellominecraft.svrmgr.cbplugins; + +import java.util.List; + +/** + * + * @author hyh + */ +public class PluginVersion { + public long date; + public String download, link, version; + public List game_versions; + public String filename, type; + +} diff --git a/HMCSM/src/main/java/org/jackhuang/hellominecraft/svrmgr/installer/bukkit/BukkitFormatThread.java b/HMCSM/src/main/java/org/jackhuang/hellominecraft/svrmgr/installer/bukkit/BukkitFormatThread.java new file mode 100644 index 000000000..fbca5ca6f --- /dev/null +++ b/HMCSM/src/main/java/org/jackhuang/hellominecraft/svrmgr/installer/bukkit/BukkitFormatThread.java @@ -0,0 +1,80 @@ +/* + * 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.svrmgr.installer.bukkit; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; +import org.jackhuang.hellominecraft.DoneListener1; +import org.jackhuang.hellominecraft.HMCLog; +import org.jsoup.Jsoup; +import org.jsoup.nodes.Document; +import org.jsoup.nodes.Element; +import org.jsoup.select.Elements; + +/** + * + * @author hyh + */ +public class BukkitFormatThread extends Thread { + + DoneListener1> lis; + List formattedList; + String url; + + public BukkitFormatThread(String url, DoneListener1> lis) { + this.lis = lis; + this.url = url; + } + + public void format(String url) { + + formattedList = new ArrayList(); + + try { + Document doc = Jsoup.connect(url).get(); + Elements versionsTable = doc.getElementsByClass("versionsTable"); + Elements allforge = new Elements(); + for(Element table : versionsTable) + allforge.addAll(table.getElementsByTag("tr")); + for(Element e : allforge) { + Elements tds = e.getElementsByTag("td"); + if(tds.isEmpty()) continue; + BukkitVersion v = new BukkitVersion(); + Elements ths = e.getElementsByTag("th"); + v.buildNumber = v.infoLink = null; + if(ths.size() > 0) { + Elements a = ths.get(0).getElementsByTag("a"); + if(a.size() > 0) { + v.buildNumber = a.get(0).text(); + v.infoLink = a.get(0).attr("href"); + } + } + v.version = tds.get(0).text(); + v.type = tds.get(1).text(); + if(tds.get(2).getElementsByTag("a").isEmpty()) continue; + v.downloadLink = "http://dl.bukkit.org" + tds.get(2).getElementsByTag("a").get(0).attr("href"); + formattedList.add(v); + } + } catch (IOException ex) { + HMCLog.warn("Failed to get bukkit list", ex); + BukkitVersion v = new BukkitVersion(); + v.type = v.version = "鑾峰彇澶辫触"; + v.buildNumber = v.infoLink = null; + formattedList.add(v); + } + } + + @Override + public void run() { + List al = null; + format(url); + if(lis != null) + lis.onDone(formattedList); + } + +} diff --git a/HMCSM/src/main/java/org/jackhuang/hellominecraft/svrmgr/installer/bukkit/BukkitVersion.java b/HMCSM/src/main/java/org/jackhuang/hellominecraft/svrmgr/installer/bukkit/BukkitVersion.java new file mode 100644 index 000000000..0a498bd20 --- /dev/null +++ b/HMCSM/src/main/java/org/jackhuang/hellominecraft/svrmgr/installer/bukkit/BukkitVersion.java @@ -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.svrmgr.installer.bukkit; + +/** + * + * @author hyh + */ +public class BukkitVersion { + + public String buildNumber, version, type, downloadLink, infoLink; + +} diff --git a/HMCSM/src/main/java/org/jackhuang/hellominecraft/svrmgr/installer/cauldron/ForgeFormatThread.java b/HMCSM/src/main/java/org/jackhuang/hellominecraft/svrmgr/installer/cauldron/ForgeFormatThread.java new file mode 100644 index 000000000..687066bb2 --- /dev/null +++ b/HMCSM/src/main/java/org/jackhuang/hellominecraft/svrmgr/installer/cauldron/ForgeFormatThread.java @@ -0,0 +1,97 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package org.jackhuang.hellominecraft.svrmgr.installer.cauldron; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import org.jackhuang.hellominecraft.DoneListener1; +import org.jackhuang.hellominecraft.HMCLog; +import org.jsoup.Jsoup; +import org.jsoup.nodes.Document; +import org.jsoup.nodes.Element; +import org.jsoup.select.Elements; + +/** + * + * @author hyh + */ +public class ForgeFormatThread extends Thread { + + DoneListener1>> lis; + Map> formattedList; + + public ForgeFormatThread(DoneListener1>> lis) { + this.lis = lis; + } + + public void formatNew() { + + formattedList = new HashMap(); + + try { + Document doc = Jsoup.connect("http://files.minecraftforge.net/").get(); + Elements allbuilds = doc.getElementsByClass("builds"); + Elements tables = new Elements(); + for(Element build : allbuilds) + tables.addAll(build.getElementsByTag("table")); + Elements allforge = new Elements(); + for(Element table : tables) + allforge.addAll(table.getElementsByTag("tr")); + for(Element e : allforge) { + Elements tds = e.getElementsByTag("td"); + if(tds.isEmpty()) continue; + ForgeVersion v = new ForgeVersion(); + v.ver = tds.get(0).text(); + v.mcver = tds.get(1).text(); + v.releasetime = tds.get(2).text(); + v.installer = new String[2]; + v.universal = new String[2]; + v.javadoc = new String[2]; + v.src = new String[2]; + v.userdev = new String[2]; + Elements a = tds.get(3).getElementsByTag("a"); + String prev = null; + for(Element e2 : a) { + String href = e2.attributes().get("href").toLowerCase(); + if(e2.text().toLowerCase().contains("changelog")) { + v.changelog = href; + } else if(prev != null) { + int index; + if(href.contains("adf.ly")) index = 0; + else index = 1; + if(prev.toLowerCase().contains("installer")) { + v.installer[index] = href; + } else + if(prev.toLowerCase().contains("server")) { + v.universal[index] = href; + } + } + prev = e2.text(); + } + + if(!formattedList.containsKey(v.mcver)) + formattedList.put(v.mcver, new ArrayList()); + formattedList.get(v.mcver).add(v); + } + } catch (IOException ex) { + HMCLog.warn("Failed to get forge list", ex); + ForgeVersion v = new ForgeVersion(); + v.mcver = v.ver = "鑾峰彇澶辫触"; + formattedList.put(v.mcver, new ArrayList()); + formattedList.get(v.mcver).add(v); + } + } + + @Override + public void run() { + formatNew(); + if(lis != null) + lis.onDone(formattedList); + } + +} diff --git a/HMCSM/src/main/java/org/jackhuang/hellominecraft/svrmgr/installer/cauldron/ForgeInstaller.java b/HMCSM/src/main/java/org/jackhuang/hellominecraft/svrmgr/installer/cauldron/ForgeInstaller.java new file mode 100644 index 000000000..66215b24a --- /dev/null +++ b/HMCSM/src/main/java/org/jackhuang/hellominecraft/svrmgr/installer/cauldron/ForgeInstaller.java @@ -0,0 +1,239 @@ +/* + * 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.svrmgr.installer.cauldron; + +import com.google.gson.Gson; +import java.io.BufferedOutputStream; +import java.io.ByteArrayInputStream; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.nio.charset.Charset; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.jar.JarEntry; +import java.util.jar.JarInputStream; +import java.util.jar.JarOutputStream; +import java.util.jar.Pack200; +import java.util.zip.ZipEntry; +import java.util.zip.ZipFile; +import javax.swing.JOptionPane; +import org.jackhuang.hellominecraft.HMCLog; +import org.jackhuang.hellominecraft.utils.DigestUtils; +import org.jackhuang.hellominecraft.utils.FileUtils; +import org.jackhuang.hellominecraft.utils.IOUtils; +import org.jackhuang.hellominecraft.utils.MessageBox; +import org.jackhuang.hellominecraft.utils.NetUtils; +import org.jackhuang.hellominecraft.utils.StrUtils; +import org.jackhuang.hellominecraft.tasks.TaskWindow; +import org.jackhuang.hellominecraft.tasks.download.FileDownloadTask; +import org.tukaani.xz.XZInputStream; + +/** + * + * @author hyh + */ +public class ForgeInstaller { + + private final Gson gson = new Gson(); + public File gameDir, gameLibraries; + public File forgeInstaller; + + public ForgeInstaller(File gameDir, File forgeInstaller) throws IOException { + this.gameDir = gameDir.getCanonicalFile(); + this.forgeInstaller = forgeInstaller; + } + + public void install() throws Exception { + 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); + + HMCLog.log("Extracting cauldron server pack..." + profile.install.filePath); + + entry = zipFile.getEntry(profile.install.filePath); + InputStream is = zipFile.getInputStream(entry); + + //MinecraftLibrary forge = new MinecraftLibrary(profile.install.path); + //forge.format(); + File file = new File(gameDir, profile.install.filePath); + file.getParentFile().mkdirs(); + FileOutputStream fos = new FileOutputStream(file); + BufferedOutputStream bos = new BufferedOutputStream(fos); + int c; + while ((c = is.read()) != -1) { + bos.write((byte) c); + } + bos.close(); + fos.close(); + + File minecraftserver = new File(gameDir, "minecraft_server." + profile.install.minecraft + ".jar"); + TaskWindow tw = TaskWindow.getInstance(); + if(minecraftserver.exists() && JOptionPane.showConfirmDialog(null, "宸插彂鐜板畼鏂规湇鍔$鏂囦欢锛屾槸鍚﹁閲嶆柊涓嬭浇锛") == JOptionPane.YES_OPTION) { + tw.clean(); + if(!tw.addTask(new FileDownloadTask("https://s3.amazonaws.com/Minecraft.Download/versions/{MCVER}/minecraft_server.{MCVER}.jar".replace("{MCVER}", profile.install.minecraft), + minecraftserver).setTag("minecraft_server")).start()) + MessageBox.Show("Minecraft瀹樻柟鏈嶅姟绔笅杞藉け璐ワ紒"); + } + tw.clean(); + for (MinecraftLibrary library : profile.versionInfo.libraries) { + library.init(); + File lib = new File(gameDir, "libraries" + File.separator + library.formatted + ".pack.xz"); + String libURL = "https://libraries.minecraft.net/"; + if (StrUtils.isNotBlank(library.url)) { + libURL = library.url; + } + tw.addTask(new FileDownloadTask(libURL + library.formatted.replace("\\", "/"), lib).setTag(library.name)); + } + tw.start(); + if(!tw.areTasksFinished()) + MessageBox.Show("鍘嬬缉搴撲笅杞藉け璐ワ紒"); + tw.clean(); + for (MinecraftLibrary library : profile.versionInfo.libraries) { + File packxz = new File(gameDir, "libraries" + File.separator + library.formatted + ".pack.xz"); + if(packxz.exists()) return; + File lib = new File(gameDir, "libraries" + File.separator + library.formatted); + lib.getParentFile().mkdirs(); + String libURL = "https://libraries.minecraft.net/"; + if (StrUtils.isNotBlank(library.url)) { + libURL = library.url; + } + tw.addTask(new FileDownloadTask(libURL + library.formatted.replace("\\", "/"), lib).setTag(library.name)); + } + tw.start(); + if(!tw.areTasksFinished()) + MessageBox.Show("搴撲笅杞藉け璐ワ紒"); + tw.clean(); + ArrayList badLibs = new ArrayList(); + for (MinecraftLibrary library : profile.versionInfo.libraries) { + File lib = new File(gameDir, "libraries" + File.separator + library.formatted); + File packFile = new File(gameDir, "libraries" + File.separator + library.formatted + ".pack.xz"); + if (packFile.exists() && packFile.isFile()) { + try { + unpackLibrary(lib.getParentFile(), NetUtils.getBytesFromStream(FileUtils.openInputStream(packFile))); + if(!checksumValid(lib, Arrays.asList(library.checksums))) + badLibs.add(library.name); + } catch (IOException e) { + HMCLog.warn("Failed to unpack library: " + library.name); + badLibs.add(library.name); + } + } + } + if (badLibs.size() > 0) { + MessageBox.Show("杩欎簺搴撳湪瑙e帇鐨勬椂鍊欏嚭鐜颁簡闂" + badLibs.toString()); + } + } + + public static void unpackLibrary(File output, byte[] data) + throws IOException { + if (output.exists()) { + output.delete(); + } + + byte[] decompressed = IOUtils.readFully(new XZInputStream(new ByteArrayInputStream(data))); + + String end = new String(decompressed, decompressed.length - 4, 4); + if (!end.equals("SIGN")) { + HMCLog.warn("Unpacking failed, signature missing " + end); + return; + } + + int x = decompressed.length; + int len = decompressed[(x - 8)] & 0xFF | (decompressed[(x - 7)] & 0xFF) << 8 | (decompressed[(x - 6)] & 0xFF) << 16 | (decompressed[(x - 5)] & 0xFF) << 24; + + byte[] checksums = Arrays.copyOfRange(decompressed, decompressed.length - len - 8, decompressed.length - 8); + + FileOutputStream jarBytes = new FileOutputStream(output); + JarOutputStream jos = new JarOutputStream(jarBytes); + + Pack200.newUnpacker().unpack(new ByteArrayInputStream(decompressed), jos); + + jos.putNextEntry(new JarEntry("checksums.sha1")); + jos.write(checksums); + jos.closeEntry(); + + jos.close(); + jarBytes.close(); + } + + private static boolean checksumValid(File libPath, List checksums) { + try { + byte[] fileData = NetUtils.getBytesFromStream(FileUtils.openInputStream(libPath)); + boolean valid = (checksums == null) || (checksums.isEmpty()) || (checksums.contains(DigestUtils.sha1Hex(fileData))); + if ((!valid) && (libPath.getName().endsWith(".jar"))) { + valid = validateJar(libPath, fileData, checksums); + } + return valid; + } catch (IOException e) { + HMCLog.warn("Failed to checksum valid: " + libPath, e); + } + return false; + } + + private static boolean validateJar(File libPath, byte[] data, List checksums) throws IOException { + System.out.println("Checking \"" + libPath.getAbsolutePath() + "\" internal checksums"); + + HashMap files = new HashMap(); + String[] hashes = null; + JarInputStream jar = new JarInputStream(new ByteArrayInputStream(data)); + JarEntry entry = jar.getNextJarEntry(); + while (entry != null) { + byte[] eData = IOUtils.readFully(jar); + + if (entry.getName().equals("checksums.sha1")) { + hashes = new String(eData, Charset.forName("UTF-8")).split("\n"); + } + + if (!entry.isDirectory()) { + files.put(entry.getName(), DigestUtils.sha1Hex(eData)); + } + entry = jar.getNextJarEntry(); + } + jar.close(); + + if (hashes != null) { + boolean failed = !checksums.contains(files.get("checksums.sha1")); + if (failed) { + System.out.println(" checksums.sha1 failed validation"); + } else { + System.out.println(" checksums.sha1 validated successfully"); + for (String hash : hashes) { + if ((!hash.trim().equals("")) && (hash.contains(" "))) { + String[] e = hash.split(" "); + String validChecksum = e[0]; + String target = e[1]; + String checksum = (String) files.get(target); + + if ((!files.containsKey(target)) || (checksum == null)) { + System.out.println(" " + target + " : missing"); + failed = true; + } else { + if (checksum.equals(validChecksum)) { + continue; + } + System.out.println(" " + target + " : failed (" + checksum + ", " + validChecksum + ")"); + failed = true; + } + } + } + } + if (!failed) { + System.out.println(" Jar contents validated successfully"); + } + + return !failed; + } + + System.out.println(" checksums.sha1 was not found, validation failed"); + return false; + } +} diff --git a/HMCSM/src/main/java/org/jackhuang/hellominecraft/svrmgr/installer/cauldron/ForgeVersion.java b/HMCSM/src/main/java/org/jackhuang/hellominecraft/svrmgr/installer/cauldron/ForgeVersion.java new file mode 100644 index 000000000..d307a5d73 --- /dev/null +++ b/HMCSM/src/main/java/org/jackhuang/hellominecraft/svrmgr/installer/cauldron/ForgeVersion.java @@ -0,0 +1,20 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package org.jackhuang.hellominecraft.svrmgr.installer.cauldron; + +/** + * + * @author hyh + */ +public class ForgeVersion { + public String vername, ver, mcver, releasetime, changelog; + public String[] installer, javadoc, src, universal, userdev; + public int typeint; + + @Override + public String toString() { + return "ForgeVersion{" + "vername=" + vername + ", ver=" + ver + ", mcver=" + mcver + ", releasetime=" + releasetime + ", changelog=" + changelog + ", installer=" + installer + ", javadoc=" + javadoc + ", src=" + src + ", universal=" + universal + ", userdev=" + userdev + ", typeint=" + typeint + '}'; + } +} diff --git a/HMCSM/src/main/java/org/jackhuang/hellominecraft/svrmgr/installer/cauldron/Install.java b/HMCSM/src/main/java/org/jackhuang/hellominecraft/svrmgr/installer/cauldron/Install.java new file mode 100644 index 000000000..d0618b324 --- /dev/null +++ b/HMCSM/src/main/java/org/jackhuang/hellominecraft/svrmgr/installer/cauldron/Install.java @@ -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.svrmgr.installer.cauldron; + +/** + * + * @author hyh + */ +public class Install { + public String profileName, target, path, version, filePath, welcome, minecraft, mirrorList, logo; +} diff --git a/HMCSM/src/main/java/org/jackhuang/hellominecraft/svrmgr/installer/cauldron/InstallProfile.java b/HMCSM/src/main/java/org/jackhuang/hellominecraft/svrmgr/installer/cauldron/InstallProfile.java new file mode 100644 index 000000000..dc1ab82a1 --- /dev/null +++ b/HMCSM/src/main/java/org/jackhuang/hellominecraft/svrmgr/installer/cauldron/InstallProfile.java @@ -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.svrmgr.installer.cauldron; + +/** + * + * @author hyh + */ +public class InstallProfile { + public Install install; + public MinecraftVersion versionInfo; +} diff --git a/HMCSM/src/main/java/org/jackhuang/hellominecraft/svrmgr/installer/cauldron/MinecraftLibrary.java b/HMCSM/src/main/java/org/jackhuang/hellominecraft/svrmgr/installer/cauldron/MinecraftLibrary.java new file mode 100644 index 000000000..dc57c2222 --- /dev/null +++ b/HMCSM/src/main/java/org/jackhuang/hellominecraft/svrmgr/installer/cauldron/MinecraftLibrary.java @@ -0,0 +1,29 @@ +/* + * 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.svrmgr.installer.cauldron; + +import java.io.File; + +/** + * + * @author hyh + */ +public class MinecraftLibrary { + + public String url, formatted=null, name; + //public boolean serverreq=true, clientreq=true; + public String[] checksums; + + public void init() { + String str = name; + String[] s = str.split(":"); + str = s[0]; + str = str.replace('.', File.separatorChar); + str += File.separator + s[1] + File.separator + s[2] + + File.separator + s[1] + '-' + s[2] + ".jar"; + formatted = str; + } +} diff --git a/HMCSM/src/main/java/org/jackhuang/hellominecraft/svrmgr/installer/cauldron/MinecraftVersion.java b/HMCSM/src/main/java/org/jackhuang/hellominecraft/svrmgr/installer/cauldron/MinecraftVersion.java new file mode 100644 index 000000000..0b5adc639 --- /dev/null +++ b/HMCSM/src/main/java/org/jackhuang/hellominecraft/svrmgr/installer/cauldron/MinecraftVersion.java @@ -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.svrmgr.installer.cauldron; + +import java.util.List; + +/** + * + * @author hyh + */ +public class MinecraftVersion { + + public String minecraftArguments, mainClass, time, id, type, processArguments, + releaseTime, assets, jar, inheritsFrom; + public int minimumLauncherVersion; + + public List libraries; +} diff --git a/HMCSM/src/main/java/org/jackhuang/hellominecraft/svrmgr/server/ScheduleTranslator.java b/HMCSM/src/main/java/org/jackhuang/hellominecraft/svrmgr/server/ScheduleTranslator.java new file mode 100644 index 000000000..05562bf97 --- /dev/null +++ b/HMCSM/src/main/java/org/jackhuang/hellominecraft/svrmgr/server/ScheduleTranslator.java @@ -0,0 +1,71 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package org.jackhuang.hellominecraft.svrmgr.server; + +import java.util.TimerTask; +import org.jackhuang.hellominecraft.svrmgr.server.schedules.*; +import org.jackhuang.hellominecraft.svrmgr.settings.Schedule; + +/** + * + * @author hyh + */ +public class ScheduleTranslator { + + public static TimerTask translate(Server ser, Schedule s) { + switch(s.type) { + case Schedule.TYPE_AUTO_SAVE: + return new AutoSaveSchedule(s, ser); + case Schedule.TYPE_AUTO_RESTART: + return new AutoRestartSchedule(s, ser); + case Schedule.TYPE_AUTO_BACKUP: + return new AutoBackupSchedule(s, ser); + case Schedule.TYPE_AUTO_BROADCAST: + return new AutoBroadcastSchedule(s, ser); + case Schedule.TYPE_AUTO_SEND_COMMAND: + return new AutoBroadcastSchedule(s, ser); + } + return null; + } + + public static String getName(Schedule s) { + switch(s.type) { + case Schedule.TYPE_AUTO_SAVE: + return "鑷姩淇濆瓨"; + case Schedule.TYPE_AUTO_RESTART: + return "鑷姩閲嶅惎"; + case Schedule.TYPE_AUTO_BACKUP: + return "鑷姩澶囦唤"; + case Schedule.TYPE_AUTO_BROADCAST: + return "鑷姩骞挎挱"; + case Schedule.TYPE_AUTO_SEND_COMMAND: + return "鑷姩鍙戦佸懡浠"; + } + return ""; + } + + public static String getTimeTypeName(Schedule s) { + switch(s.timeType) { + case Schedule.TIME_TYPE_PER: + return "姣弜鍒嗛挓"; + case Schedule.TIME_TYPE_PAST_HOUR: + return "鏁寸偣鍚巟鍒嗛挓"; + case Schedule.TIME_TYPE_SERVER_STARTED: + return "褰撴湇鍔″櫒鍚姩"; + case Schedule.TIME_TYPE_SERVER_STOPPED: + return "褰撴湇鍔″櫒鍏抽棴"; + case Schedule.TIME_TYPE_SERVER_CRASHED: + return "褰撴湇鍔″櫒宕╂簝"; + } + return ""; + } + + public static Object[] getRow(Schedule s) { + return new Object[] { + getName(s), getTimeTypeName(s), s.per, s.content + }; + } + +} diff --git a/HMCSM/src/main/java/org/jackhuang/hellominecraft/svrmgr/server/Server.java b/HMCSM/src/main/java/org/jackhuang/hellominecraft/svrmgr/server/Server.java new file mode 100644 index 000000000..df7fba011 --- /dev/null +++ b/HMCSM/src/main/java/org/jackhuang/hellominecraft/svrmgr/server/Server.java @@ -0,0 +1,431 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package org.jackhuang.hellominecraft.svrmgr.server; + +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.io.BufferedWriter; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStreamWriter; +import java.io.UnsupportedEncodingException; +import java.util.ArrayList; +import java.util.Calendar; +import java.util.Date; +import java.util.GregorianCalendar; +import java.util.Timer; +import java.util.TimerTask; +import java.util.logging.Level; +import java.util.logging.Logger; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import org.jackhuang.hellominecraft.utils.functions.DoneListener0; +import org.jackhuang.hellominecraft.DoneListener1; +import org.jackhuang.hellominecraft.HMCLog; +import org.jackhuang.hellominecraft.utils.IOUtils; +import org.jackhuang.hellominecraft.utils.MessageBox; +import org.jackhuang.hellominecraft.utils.Pair; +import org.jackhuang.hellominecraft.utils.StrUtils; +import org.jackhuang.hellominecraft.svrmgr.settings.Schedule; +import org.jackhuang.hellominecraft.svrmgr.settings.SettingsManager; +import org.jackhuang.hellominecraft.svrmgr.threads.MonitorThread; +import org.jackhuang.hellominecraft.svrmgr.threads.WaitForThread; +import org.jackhuang.hellominecraft.svrmgr.utils.Utilities; + +/** + * + * @author hyh + */ +public class Server implements DoneListener1, MonitorThread.MonitorThreadListener, + ActionListener { + + private static Server instance; + private static boolean disactived = false; + + public static Server getInstance() { + return instance; + } + + public static boolean isInstanceRunning() { + return instance != null && instance.isRunning; + } + + public static void init(String jar, String memory) { + instance = new Server(jar, memory); + } + + String jar, memory; + Process server; + MonitorThread threadA, threadB; + WaitForThread threadC; + DoneListener1> gettingPlayerNumber; + ArrayList listeners; + ArrayList> listenersC; + ArrayList listenersBegin, listenersDone; + ArrayList timerTasks; + ArrayList schedules; + BufferedWriter bw; + Timer timer; + javax.swing.Timer pastTimer; + public boolean isRunning, isRestart, isDone; + int isGettingPlayerNumber; + String playerNumber; + + private Server(String jar, String memory) { + this.jar = jar; + this.memory = memory; + isRestart = isDone = false; + listeners = new ArrayList(); + listenersC = new ArrayList>(); + listenersBegin = new ArrayList(); + listenersDone = new ArrayList(); + schedules = new ArrayList(); + timerTasks = new ArrayList(); + } + + public void addListener(MonitorThread.MonitorThreadListener l) { + listeners.add(l); + } + + public void addListener(DoneListener1 l) { + listenersC.add(l); + } + + public void addServerStartedListener(DoneListener0 l) { + listenersBegin.add(l); + } + + public void addServerDoneListener(DoneListener0 l) { + listenersDone.add(l); + } + + public void run() throws IOException { + String jvmPath; + if (StrUtils.isBlank(SettingsManager.settings.javaDir)) { + jvmPath = IOUtils.getJavaDir(); + } else { + jvmPath = SettingsManager.settings.javaDir; + } + String[] puts = new String[]{ + jvmPath, + "-Xmx" + memory + "m", + "-jar", + SettingsManager.settings.mainjar, + "nogui", + "-nojline" + }; + ProcessBuilder pb = new ProcessBuilder(puts); + pb.directory(new File(SettingsManager.settings.mainjar).getParentFile()); + try { + disactiveMods(SettingsManager.settings.inactiveExtMods, + SettingsManager.settings.inactiveCoreMods, + SettingsManager.settings.inactivePlugins); + server = pb.start(); + registerThread(threadA, server.getInputStream()); + registerThread(threadB, server.getErrorStream()); + registerThreadC(server); + try { + bw = new BufferedWriter(new OutputStreamWriter(server.getOutputStream(), System.getProperty("sun.jnu.encoding", "utf-8"))); + } catch (UnsupportedEncodingException ex) { + bw = new BufferedWriter(new OutputStreamWriter(server.getOutputStream())); + } + isRunning = true; + for (DoneListener0 d : listenersBegin) { + d.onDone(); + } + sendStatus("*** 鍚姩鏈嶅姟绔腑 ***"); + } catch (IOException ex) { + Logger.getLogger(Server.class.getName()).log(Level.SEVERE, null, ex); + isRunning = false; + } + } + + public void sendCommand(String cmd) { + if (isRunning) { + try { + sendStatus("鍙戦佹寚浠: " + cmd); + bw.write(cmd); + bw.newLine(); + bw.flush(); + } catch (IOException ex) { + Logger.getLogger(Server.class.getName()).log(Level.SEVERE, null, ex); + } + } + } + + public void getPlayerNumber(DoneListener1> d) { + isGettingPlayerNumber = 1; + gettingPlayerNumber = d; + sendCommand("list"); + } + + public void restart() { + isRestart = true; + stop(); + } + + public void stop() { + if (timer != null) { + timer.cancel(); + } + sendCommand("stop"); + } + + public void shutdown() { + if (timer != null) { + timer.cancel(); + } + server.destroy(); + } + + public void clearSchedule() { + schedules.clear(); + } + + public void addSchedule(Schedule s) { + schedules.add(s); + } + + public void delSchedule(Schedule s) { + int index = schedules.indexOf(s); + if (index == -1) { + return; + } + schedules.remove(index); + timerTasks.get(index).cancel(); + timerTasks.remove(index); + } + + private void registerThread(MonitorThread thread, InputStream is) { + thread = new MonitorThread(is); + for (MonitorThread.MonitorThreadListener l : listeners) { + thread.addListener(l); + } + thread.addListener(this); + thread.start(); + } + + private void registerThreadC(Process p) { + threadC = new WaitForThread(p); + for (DoneListener1 l : listenersC) { + threadC.addListener(l); + } + threadC.addListener(this); + threadC.start(); + } + + @Override + public void onDone(Integer t) { + if (t == 0) { + sendStatus("*** 鏈嶅姟绔凡鍋滄 ***"); + System.out.println("Server stopped successfully"); + } else { + sendStatus("*** 鏈嶅姟绔穿婧冧簡锛(閿欒鐮:" + t + ") ***"); + System.err.println("Server crashed(exit code: " + t + ")"); + } + isRunning = false; + for (int i = 0; i < schedules.size(); i++) { + if (schedules.get(i).timeType == Schedule.TIME_TYPE_SERVER_STOPPED) { + ScheduleTranslator.translate(this, schedules.get(i)).run(); + } + } + if (timer != null) { + timer.cancel(); + } + if (pastTimer != null) { + pastTimer.stop(); + } + restoreMods(); + if (isRestart) { + try { + run(); + } catch (IOException ex) { + MessageBox.Show("閲嶅惎澶辫触锛"); + HMCLog.warn("Failed to launch!", ex); + } + isRestart = false; + } + } + + private static void disactiveMods(ArrayList inactiveExtMods, + ArrayList inactiveCoreMods, ArrayList inactivePlugins) { + disactiveModsByType(inactiveExtMods, "mods"); + disactiveModsByType(inactiveCoreMods, "coremods"); + disactiveModsByType(inactivePlugins, "plugins"); + disactived = true; + } + + private static void disactiveModsByType(ArrayList paramArrayOfString, String paramString) { + restoreModsByType(paramString); + + System.out.println("绂佺敤涓嶆椿鍔ㄧ殑鏂囦欢: " + paramString); + if ((paramArrayOfString == null) || (paramArrayOfString.size() <= 0)) { + return; + } + File[] files = new File(Utilities.getGameDir(), paramString).listFiles(); + if (files == null) { + System.out.println("娌℃湁鏂囦欢: " + paramString); + return; + } + for (int i = 0; i < files.length; i++) { + File file = files[i]; + if (!file.isDirectory()) { + String name = file.getName(); + + if ((!paramArrayOfString.contains(name)) + || ((!name.toLowerCase().endsWith(".zip")) && (!name.toLowerCase().endsWith(".jar")))) { + continue; + } + + String newName = name + "X"; + File newFile = new File(file.getParentFile(), newName); + + if (newFile.exists()) { + newFile.delete(); + } + if (file.renameTo(newFile)) { + System.out.println("宸茬鐢: " + name + ", 鏂板悕绉: " + newFile.getName()); + } else { + System.out.println("鏃犳硶绂佺敤: " + name); + } + } + } + } + + private static void restoreModsByType(String paramString) { + System.out.println("杩樺師琚鐢ㄧ殑鏂囦欢: " + paramString); + File[] files = new File(Utilities.getGameDir(), paramString).listFiles(); + if (files == null) { + return; + } + for (int i = 0; i < files.length; i++) { + File file = files[i]; + if (file.isDirectory()) { + continue; + } + String name = file.getName(); + String lowName = name.toLowerCase(); + if ((!lowName.endsWith(".zipx")) && (!lowName.endsWith(".jarx"))) { + continue; + } + String newName = name.substring(0, name.length() - 1); + + File newFile = new File(file.getParentFile(), newName); + if (newFile.exists()) { + file.delete(); + } else { + if (!file.renameTo(newFile)) { + System.out.println("鏃犳硶閲嶅懡鍚: " + file.getName() + " 鍒: " + newFile.getName() + " 鍦: " + file.getParent()); + } + } + } + } + + static void restoreMods() { + if (disactived) { + restoreModsByType("mods"); + restoreModsByType("coremods"); + restoreModsByType("plugins"); + disactived = false; + } + } + + @Override + public void onStatus(String status) { + System.out.println(status); + if (isGettingPlayerNumber == 1) { + Pattern p = Pattern.compile("There are [0-9]*/[0-9]* players online"); + Matcher m = p.matcher(status); + if (!m.find()) { + return; + } + String s = m.group(0); + s = s.substring(10, s.length() - 15); + playerNumber = s; + isGettingPlayerNumber = 2; + return; + } else if (isGettingPlayerNumber == 2) { + try { + status = status.substring(status.lastIndexOf("]")+1); + status = status.substring(status.indexOf(":")+1); + } catch(Exception e) { + HMCLog.warn("Failed to substring status.", e); + } + String[] s; + if(StrUtils.isNotBlank(status)) { + s = status.trim().split(", "); + } else { + s = new String[0]; + } + Pair p = new Pair(playerNumber, s); + isGettingPlayerNumber = 0; + gettingPlayerNumber.onDone(p); + return; + } + if (isDone == false) { + Pattern p = Pattern.compile("\\[INFO\\] Done \\([0-9]*\\.[0-9]*s\\)! For help, type \"help\" or \"\\?\""); + Matcher m = p.matcher(status); + if (m.find()) { + for (DoneListener0 d : listenersDone) { + d.onDone(); + } + timer = new Timer(); + timerTasks.clear(); + for (int i = 0; i < schedules.size(); i++) { + if (schedules.get(i).timeType == Schedule.TIME_TYPE_SERVER_STARTED) { + ScheduleTranslator.translate(this, schedules.get(i)).run(); + continue; + } + if (schedules.get(i).timeType != Schedule.TIME_TYPE_PER) { + continue; + } + long mill = (long) Math.floor(schedules.get(i).per * 60 * 1000); + timerTasks.add(ScheduleTranslator.translate(this, schedules.get(i))); + timer.schedule(timerTasks.get(i), mill, mill); + } + pastTimer = new javax.swing.Timer(1000, this); + pastTimer.start(); + System.out.println("Server started!"); + sendStatus("*** 鏈嶅姟绔凡鍚姩瀹屾垚 ***"); + isDone = true; + } + } + if (status.length() > 20) { + if (status.substring(20).contains("[SEVERE] This crash report has been saved to: ")) { + for (int i = 0; i < schedules.size(); i++) { + if (schedules.get(i).timeType == Schedule.TIME_TYPE_SERVER_CRASHED) { + ScheduleTranslator.translate(this, schedules.get(i)).run(); + } + } + } + } + } + + GregorianCalendar c = new GregorianCalendar(); + + @Override + public void actionPerformed(ActionEvent e) { + c.setTime(new Date()); + if (c.get(Calendar.SECOND) != 0) { + return; + } + int minute = c.get(Calendar.MINUTE); + for (int i = 0; i < schedules.size(); i++) { + if (schedules.get(i).timeType != Schedule.TIME_TYPE_PAST_HOUR) { + continue; + } + if (schedules.get(i).per == minute) { + ScheduleTranslator.translate(this, schedules.get(i)).run(); + } + } + } + + private void sendStatus(String status) { + for (MonitorThread.MonitorThreadListener l : listeners) { + l.onStatus(status); + } + } +} diff --git a/HMCSM/src/main/java/org/jackhuang/hellominecraft/svrmgr/server/ServerChecker.java b/HMCSM/src/main/java/org/jackhuang/hellominecraft/svrmgr/server/ServerChecker.java new file mode 100644 index 000000000..66a9b6c2c --- /dev/null +++ b/HMCSM/src/main/java/org/jackhuang/hellominecraft/svrmgr/server/ServerChecker.java @@ -0,0 +1,35 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package org.jackhuang.hellominecraft.svrmgr.server; + +import java.io.File; +import java.io.IOException; +import java.util.zip.ZipFile; +import org.jackhuang.hellominecraft.HMCLog; + +/** + * + * @author hyh + */ +public class ServerChecker { + + public static boolean isServerJar(File f) { + ZipFile file; + try { + file = new ZipFile(f); + } catch (IOException ex) { + HMCLog.warn("", ex); + return false; + } + if(file.getEntry("org/bukkit/craftbukkit/Main.class") != null) { + return true; + } + if(file.getEntry("net/minecraft/server/MinecraftServer.class") != null) { + return true; + } + return false; + } + +} diff --git a/HMCSM/src/main/java/org/jackhuang/hellominecraft/svrmgr/server/backups/BackupManager.java b/HMCSM/src/main/java/org/jackhuang/hellominecraft/svrmgr/server/backups/BackupManager.java new file mode 100644 index 000000000..d396e6358 --- /dev/null +++ b/HMCSM/src/main/java/org/jackhuang/hellominecraft/svrmgr/server/backups/BackupManager.java @@ -0,0 +1,103 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package org.jackhuang.hellominecraft.svrmgr.server.backups; + +import java.io.File; +import java.io.IOException; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Date; +import org.jackhuang.hellominecraft.HMCLog; +import org.jackhuang.hellominecraft.utils.Compressor; +import org.jackhuang.hellominecraft.svrmgr.settings.SettingsManager; +import org.jackhuang.hellominecraft.svrmgr.utils.Utilities; + +/** + * + * @author hyh + */ +public class BackupManager { + + public static String backupDir() { + return Utilities.getGameDir() + "backups-HMCSM" + File.separator; + } + + public static ArrayList getBackupList() { + String gameDir = backupDir(); + return Utilities.findAllFile(new File(gameDir)); + } + + public static void addWorldBackup(final String folder) { + new File(backupDir()).mkdirs(); + Thread t = new Thread() { + @Override + public void run() { + try { + SimpleDateFormat f = new SimpleDateFormat("yyyy-MM-dd HH-mm-ss"); + Compressor.zip(Utilities.getGameDir() + folder + File.separator, + backupDir() + "world+" + f.format(new Date()) + "+" + folder + ".zip"); + } catch (IOException ex) { + HMCLog.warn("Failed to compress world pack.", ex); + } + } + }; + t.start(); + } + + public static ArrayList findAllWorlds() { + String gameDir = Utilities.getGameDir(); + ArrayList folders = Utilities.findAllDir(new File(gameDir)); + ArrayList result = new ArrayList(); + for(String folder : folders) { + String worldPath = gameDir + folder + File.separator; + ArrayList files = Utilities.findAllFile(new File(worldPath)); + if(files.contains("level.dat")) { + result.add(folder); + } + } + return result; + } + + public static void restoreBackup(String backupFile) { + try { + File file = new File(backupFile); + String name = Utilities.trimExtension(file.getName()); + String[] info = name.split("\\+"); + String folder = info[2]; + File world = new File(Utilities.getGameDir() + folder + File.separator); + Utilities.deleteAll(world); + world.mkdirs(); + Compressor.unzip(backupFile, world.getAbsolutePath()); + } catch (IOException ex) { + HMCLog.warn("Failed to decompress world pack.", ex); + } + } + + public static void backupAllWorlds() { + ArrayList al = findAllWorlds(); + for(String world : al) { + if(!SettingsManager.settings.inactiveWorlds.contains(world)) + addWorldBackup(world); + } + } + + public static void backupAllPlugins() { + new File(backupDir()).mkdirs(); + Thread t = new Thread() { + @Override + public void run() { + try { + SimpleDateFormat f = new SimpleDateFormat("yyyy-MM-dd HH-mm-ss"); + Compressor.zip(Utilities.getGameDir() + "plugins" + File.separator, + backupDir() + "plugin+" + f.format(new Date()) + "+plugins.zip"); + } catch (IOException ex) { + HMCLog.warn("Failed to compress world pack with plugins.", ex); + } + } + }; + t.start(); + } + +} diff --git a/HMCSM/src/main/java/org/jackhuang/hellominecraft/svrmgr/server/download/ServerDownloadPackage.java b/HMCSM/src/main/java/org/jackhuang/hellominecraft/svrmgr/server/download/ServerDownloadPackage.java new file mode 100644 index 000000000..a053af6d1 --- /dev/null +++ b/HMCSM/src/main/java/org/jackhuang/hellominecraft/svrmgr/server/download/ServerDownloadPackage.java @@ -0,0 +1,13 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package org.jackhuang.hellominecraft.svrmgr.server.download; + +/** + * + * @author hyh + */ +public class ServerDownloadPackage { + public String mcversion, version, forgeversion, majorversion, file; +} diff --git a/HMCSM/src/main/java/org/jackhuang/hellominecraft/svrmgr/server/schedules/AutoBackupSchedule.java b/HMCSM/src/main/java/org/jackhuang/hellominecraft/svrmgr/server/schedules/AutoBackupSchedule.java new file mode 100644 index 000000000..70a739216 --- /dev/null +++ b/HMCSM/src/main/java/org/jackhuang/hellominecraft/svrmgr/server/schedules/AutoBackupSchedule.java @@ -0,0 +1,33 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package org.jackhuang.hellominecraft.svrmgr.server.schedules; + +import java.util.TimerTask; +import org.jackhuang.hellominecraft.svrmgr.server.Server; +import org.jackhuang.hellominecraft.svrmgr.server.backups.BackupManager; +import org.jackhuang.hellominecraft.svrmgr.settings.Schedule; + +/** + * + * @author hyh + */ +public class AutoBackupSchedule extends TimerTask { + + Schedule main; + Server server; + + public AutoBackupSchedule(Schedule s, Server s2) { + main = s; + server = s2; + } + + @Override + public void run() { + System.out.println("Backup"); + Server.getInstance().sendCommand("say 鑷姩澶囦唤瀹屾瘯"); + BackupManager.backupAllWorlds(); + } + +} diff --git a/HMCSM/src/main/java/org/jackhuang/hellominecraft/svrmgr/server/schedules/AutoBroadcastSchedule.java b/HMCSM/src/main/java/org/jackhuang/hellominecraft/svrmgr/server/schedules/AutoBroadcastSchedule.java new file mode 100644 index 000000000..7ceb63a71 --- /dev/null +++ b/HMCSM/src/main/java/org/jackhuang/hellominecraft/svrmgr/server/schedules/AutoBroadcastSchedule.java @@ -0,0 +1,29 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package org.jackhuang.hellominecraft.svrmgr.server.schedules; + +import java.util.TimerTask; +import org.jackhuang.hellominecraft.svrmgr.server.Server; +import org.jackhuang.hellominecraft.svrmgr.settings.Schedule; + +/** + * + * @author hyh + */ +public class AutoBroadcastSchedule extends TimerTask { + + Schedule main; + Server server; + + public AutoBroadcastSchedule(Schedule s, Server s2) { + main = s; + server = s2; + } + + @Override + public void run() { + server.sendCommand("say " + main.content); + } +} diff --git a/HMCSM/src/main/java/org/jackhuang/hellominecraft/svrmgr/server/schedules/AutoExecuteSchedule.java b/HMCSM/src/main/java/org/jackhuang/hellominecraft/svrmgr/server/schedules/AutoExecuteSchedule.java new file mode 100644 index 000000000..a8678c60a --- /dev/null +++ b/HMCSM/src/main/java/org/jackhuang/hellominecraft/svrmgr/server/schedules/AutoExecuteSchedule.java @@ -0,0 +1,34 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package org.jackhuang.hellominecraft.svrmgr.server.schedules; + +import java.io.IOException; +import java.util.TimerTask; +import org.jackhuang.hellominecraft.HMCLog; +import org.jackhuang.hellominecraft.svrmgr.server.Server; +import org.jackhuang.hellominecraft.svrmgr.settings.Schedule; + +/** + * + * @author hyh + */ +public class AutoExecuteSchedule extends TimerTask { + Schedule main; + Server server; + + public AutoExecuteSchedule(Schedule s, Server s2) { + main = s; + server = s2; + } + + @Override + public void run() { + try { + Runtime.getRuntime().exec(main.content); + } catch (IOException ex) { + HMCLog.err("Failed to exec command: " + main.content, ex); + } + } +} diff --git a/HMCSM/src/main/java/org/jackhuang/hellominecraft/svrmgr/server/schedules/AutoRestartSchedule.java b/HMCSM/src/main/java/org/jackhuang/hellominecraft/svrmgr/server/schedules/AutoRestartSchedule.java new file mode 100644 index 000000000..17ac55272 --- /dev/null +++ b/HMCSM/src/main/java/org/jackhuang/hellominecraft/svrmgr/server/schedules/AutoRestartSchedule.java @@ -0,0 +1,28 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package org.jackhuang.hellominecraft.svrmgr.server.schedules; + +import java.util.TimerTask; +import org.jackhuang.hellominecraft.svrmgr.server.Server; +import org.jackhuang.hellominecraft.svrmgr.settings.Schedule; +/** + * + * @author hyh + */ +public class AutoRestartSchedule extends TimerTask { + + Schedule main; + Server server; + + public AutoRestartSchedule(Schedule s, Server s2) { + main = s; + server = s2; + } + + @Override + public void run() { + server.restart(); + } +} diff --git a/HMCSM/src/main/java/org/jackhuang/hellominecraft/svrmgr/server/schedules/AutoSaveSchedule.java b/HMCSM/src/main/java/org/jackhuang/hellominecraft/svrmgr/server/schedules/AutoSaveSchedule.java new file mode 100644 index 000000000..01e74ce1b --- /dev/null +++ b/HMCSM/src/main/java/org/jackhuang/hellominecraft/svrmgr/server/schedules/AutoSaveSchedule.java @@ -0,0 +1,31 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package org.jackhuang.hellominecraft.svrmgr.server.schedules; + +import java.util.TimerTask; +import org.jackhuang.hellominecraft.svrmgr.server.Server; +import org.jackhuang.hellominecraft.svrmgr.settings.Schedule; + +/** + * + * @author hyh + */ +public class AutoSaveSchedule extends TimerTask { + + Schedule main; + Server server; + + public AutoSaveSchedule(Schedule s, Server s2) { + main = s; + server = s2; + } + + @Override + public void run() { + System.out.println("auto save"); + server.sendCommand("save-all"); + } + +} diff --git a/HMCSM/src/main/java/org/jackhuang/hellominecraft/svrmgr/server/schedules/AutoSchedule.java b/HMCSM/src/main/java/org/jackhuang/hellominecraft/svrmgr/server/schedules/AutoSchedule.java new file mode 100644 index 000000000..966d48224 --- /dev/null +++ b/HMCSM/src/main/java/org/jackhuang/hellominecraft/svrmgr/server/schedules/AutoSchedule.java @@ -0,0 +1,23 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package org.jackhuang.hellominecraft.svrmgr.server.schedules; + +import java.util.TimerTask; +import org.jackhuang.hellominecraft.svrmgr.server.Server; +import org.jackhuang.hellominecraft.svrmgr.settings.Schedule; + +/** + * + * @author hyh + */ +public abstract class AutoSchedule extends TimerTask { + Schedule main; + Server server; + + public AutoSchedule(Schedule s, Server s2) { + main = s; + server = s2; + } +} diff --git a/HMCSM/src/main/java/org/jackhuang/hellominecraft/svrmgr/server/schedules/AutoSendCommandSchedule.java b/HMCSM/src/main/java/org/jackhuang/hellominecraft/svrmgr/server/schedules/AutoSendCommandSchedule.java new file mode 100644 index 000000000..aed4d21d2 --- /dev/null +++ b/HMCSM/src/main/java/org/jackhuang/hellominecraft/svrmgr/server/schedules/AutoSendCommandSchedule.java @@ -0,0 +1,24 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package org.jackhuang.hellominecraft.svrmgr.server.schedules; + +import org.jackhuang.hellominecraft.svrmgr.server.Server; +import org.jackhuang.hellominecraft.svrmgr.settings.Schedule; + +/** + * + * @author hyh + */ +public class AutoSendCommandSchedule extends AutoSchedule { + + public AutoSendCommandSchedule(Schedule s, Server s2) { + super(s, s2); + } + + @Override + public void run() { + server.sendCommand(main.content); + } +} diff --git a/HMCSM/src/main/java/org/jackhuang/hellominecraft/svrmgr/settings/BannedPlayers.java b/HMCSM/src/main/java/org/jackhuang/hellominecraft/svrmgr/settings/BannedPlayers.java new file mode 100644 index 000000000..49f556874 --- /dev/null +++ b/HMCSM/src/main/java/org/jackhuang/hellominecraft/svrmgr/settings/BannedPlayers.java @@ -0,0 +1,36 @@ +/* + * 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.svrmgr.settings; + +import java.text.SimpleDateFormat; +import java.util.Date; + +/** + * + * @author hyh + */ +public class BannedPlayers extends PlayerList { + + @Override + protected BannedPlayer newPlayer(String name) { + return new BannedPlayer(name); + } + + public static class BannedPlayer extends PlayerList.BasePlayer { + + public String source, expires, reason, created; + + public BannedPlayer(String name) { + super(name); + + created = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss +0800").format(new Date()); + source = "Server"; + expires = "forever"; + reason = "浣犲凡缁忚鏈嶅姟鍣ㄥ皝绂"; + } + } +} diff --git a/HMCSM/src/main/java/org/jackhuang/hellominecraft/svrmgr/settings/Op.java b/HMCSM/src/main/java/org/jackhuang/hellominecraft/svrmgr/settings/Op.java new file mode 100644 index 000000000..31f9625e7 --- /dev/null +++ b/HMCSM/src/main/java/org/jackhuang/hellominecraft/svrmgr/settings/Op.java @@ -0,0 +1,28 @@ +/* + * 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.svrmgr.settings; + +/** + * + * @author hyh + */ +public class Op extends PlayerList { + + @Override + protected Op.Operator newPlayer(String name) { + return new Op.Operator(name); + } + + public static class Operator extends PlayerList.BasePlayer { + + public int level; + + public Operator(String name) { + super(name); + level = 4; + } + } +} diff --git a/HMCSM/src/main/java/org/jackhuang/hellominecraft/svrmgr/settings/PlayerList.java b/HMCSM/src/main/java/org/jackhuang/hellominecraft/svrmgr/settings/PlayerList.java new file mode 100644 index 000000000..c309cc2b9 --- /dev/null +++ b/HMCSM/src/main/java/org/jackhuang/hellominecraft/svrmgr/settings/PlayerList.java @@ -0,0 +1,113 @@ +/* + * 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.svrmgr.settings; + +import com.google.gson.Gson; +import java.io.File; +import java.io.IOException; +import java.util.HashSet; +import java.util.UUID; +import org.jackhuang.hellominecraft.HMCLog; +import org.jackhuang.hellominecraft.utils.FileUtils; +import org.jackhuang.hellominecraft.utils.StrUtils; +import org.jackhuang.hellominecraft.svrmgr.settings.PlayerList.BasePlayer; + +/** + * + * @author hyh + * @param Player type. + */ +public abstract class PlayerList { + + public static class BasePlayer { + + public String uuid, name; + + public BasePlayer(String name) { + uuid = UUID.randomUUID().toString(); + this.name = name; + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof PlayerList.BasePlayer) { + BasePlayer player = (BasePlayer) obj; + return player.name.equals(name); + } + return false; + } + + @Override + public int hashCode() { + return this.name.hashCode(); + } + + @Override + public String toString() { + return name; + } + + } + + public HashSet op; + + protected abstract T newPlayer(String name); + + public void initByText(String s) { + String[] lines = s.split("\n"); + op = new HashSet(); + for (String l : lines) { + if(l.startsWith("#")) continue; + T player = newPlayer(l); + if (StrUtils.isBlank(l)) { + continue; + } + op.add(player); + } + } + + public void initByJson(String s) { + op = new Gson().>fromJson(s, HashSet.class); + } + + public void initByBoth(File txt, File json) { + HashSet player = new HashSet(); + /*op = null; + if(json.exists()) { + try { + initByJson(FileUtils.readFileToStringIgnoreFileNotFound(json)); + if(op != null) + player.addAll(op); + } catch(IOException e) { + HMCLLog.warn("Failed to load playerlist by json", e); + } + }*/ + op = null; + if(txt.exists()) { + try { + initByText(FileUtils.readFileToStringIgnoreFileNotFound(txt)); + if(op != null) + player.addAll(op); + } catch(IOException e) { + HMCLog.warn("Failed to load playerlist by txt", e); + } + } + op = player; + } + + public void saveAsText(File file) throws IOException { + FileUtils.write(file, StrUtils.parseParams("", op, System.getProperty("line.separator"))); + } + + public void saveAsJson(File file) throws IOException { + FileUtils.write(file, new Gson().toJson(op)); + } + + public void saveAsBoth(File txt, File json) throws IOException { + saveAsText(txt); + saveAsJson(json); + } +} diff --git a/HMCSM/src/main/java/org/jackhuang/hellominecraft/svrmgr/settings/Schedule.java b/HMCSM/src/main/java/org/jackhuang/hellominecraft/svrmgr/settings/Schedule.java new file mode 100644 index 000000000..7ba697d38 --- /dev/null +++ b/HMCSM/src/main/java/org/jackhuang/hellominecraft/svrmgr/settings/Schedule.java @@ -0,0 +1,33 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package org.jackhuang.hellominecraft.svrmgr.settings; + +/** + * + * @author hyh + */ +public class Schedule { + public static final int + TYPE_AUTO_SAVE = 0, + TYPE_AUTO_RESTART = 1, + TYPE_AUTO_BACKUP = 2, + TYPE_AUTO_BROADCAST = 3, + TYPE_AUTO_SEND_COMMAND = 4, + TYPE_AUTO_EXECUTE = 5; + public static final int + TYPE2_AUTO_BACKUP_PLUGINS = 1, + TYPE2_AUTH_BACKUP_CONFIG = 2, + TYPE3_AUTH_BACKUP_WORLD = 3; + public static final int + TIME_TYPE_PER = 0, + TIME_TYPE_PAST_HOUR = 1, + TIME_TYPE_SERVER_STARTED = 2, + TIME_TYPE_SERVER_STOPPED = 3, + TIME_TYPE_SERVER_CRASHED = 4; + + public int type, type2, timeType; + public String content; + public double per; +} diff --git a/HMCSM/src/main/java/org/jackhuang/hellominecraft/svrmgr/settings/ServerProperties.java b/HMCSM/src/main/java/org/jackhuang/hellominecraft/svrmgr/settings/ServerProperties.java new file mode 100644 index 000000000..3bcc95c19 --- /dev/null +++ b/HMCSM/src/main/java/org/jackhuang/hellominecraft/svrmgr/settings/ServerProperties.java @@ -0,0 +1,253 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package org.jackhuang.hellominecraft.svrmgr.settings; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.Properties; +import org.jackhuang.hellominecraft.HMCLog; + +/** + * + * @author jack + */ +public class ServerProperties { + + public static ServerProperties getInstance() { + return instance; + } + + private static ServerProperties instance; + + public static void init(String path) { + instance = new ServerProperties(path); + } + + String path; + InputStream is; + Properties p; + + public ServerProperties(String path) { + this.path = path; + } + + public String getProperty(String key) { + return getProperty(key, ""); + } + + public String getProperty(String key, String defaultValue) { + try { + is = new FileInputStream(new File(path, "server.properties")); + p = new Properties(); + p.load(is); + return p.getProperty(key, defaultValue); + } catch (IOException ex) { + HMCLog.warn("Failed to get property in server.properties", ex); + return ""; + } finally { + try { + if(is != null) + is.close(); + } catch (IOException ex) { + HMCLog.warn("Failed to close InputStream for server.properties", ex); + } + } + } + + public int getPropertyInt(String key, int defaultValue) { + try { + return Integer.parseInt(getProperty(key, String.valueOf(defaultValue))); + } catch(NumberFormatException e) { + return defaultValue; + } + } + + public boolean getPropertyBoolean(String key, boolean defaultValue) { + return getProperty(key, String.valueOf(defaultValue)).equals("true"); + } + + public void setProperty(String key, String value) { + try { + is = new FileInputStream(new File(path, "server.properties")); + p = new Properties(); + p.load(is); + p.setProperty(key, value); + SimpleDateFormat f = new SimpleDateFormat("E M d HH:mm:ss z y"); + p.store(new FileOutputStream(new File(path, "server.properties")), + "Minecraft server properties\n" + f.format(new Date())); + } catch (IOException ex) { + HMCLog.warn("Failed to set property in server.properties", ex); + } finally { + try { + if(is != null) + is.close(); + } catch (IOException ex) { + HMCLog.warn("Failed to close OutputStream for server.properties", ex); + } + } + } + + public void setProperty(String key, boolean value) { + setProperty(key, value ? "true" : "false"); + } + + public void setProperty(String key, int value) { + setProperty(key, String.valueOf(value)); + } + + public void setGeneratorSettings(String string) { + setProperty("generator-settings", string); + } + + public void setAllowNether(boolean bool) { + setProperty("allow-nether", bool); + } + + public void setLevelName(String string) { + setProperty("level-name", string); + } + + public void setEnableQuery(boolean bool) { + setProperty("enable-query", bool); + } + + public void setAllowFlight(boolean bool) { + setProperty("allow-flight", bool); + } + + public void setServerPort(int integer) { + setProperty("server-port", integer); + } + + public void setLevelType(String string) { + setProperty("level-type", string); + } + + public void setEnableRcon(boolean bool) { + setProperty("enable-rcon", bool); + } + + public void setForceGameMode(boolean bool) { + setProperty("force-gamemode", bool); + } + + public void setLevelSeed(String string) { + setProperty("level-seed", string); + } + + public void setServerIP(String string) { + setProperty("server-ip", string); + } + + public void setMaxBuildHeight(int integer) { + setProperty("max-build-height", integer); + } + + public void setSpawnNPCs(boolean bool) { + setProperty("spawn-npcs", bool); + } + + public void setWhiteList(boolean bool) { + setProperty("white-list", bool); + } + + public void setSpawnAnimals(boolean bool) { + setProperty("spawn-animals", bool); + } + + public void setTexturePack(String string) { + setProperty("texture-pack", string); + } + + public void setSnooperEnabled(boolean bool) { + setProperty("snooper-enabled", bool); + } + + public void setHardCore(boolean bool) { + setProperty("hardcore", bool); + } + + public void setOnlineMode(boolean bool) { + setProperty("online-mode", bool); + } + + public void setPVP(boolean bool) { + setProperty("pvp", bool); + } + + public void setDifficulty(int integer) { + setProperty("difficulty", integer); + } + + public void setServerName(String string) { + setProperty("server-name", string); + } + + public void setGameMode(int integer) { + setProperty("gamemode", integer); + } + + public void setMaxPlayers(int integer) { + setProperty("max-players", integer); + } + + public void setSpawnMonsters(boolean bool) { + setProperty("spawn-monsters", bool); + } + + public void setViewDistence(int integer) { + setProperty("view-distance", integer); + } + + public void setGenerateStructures(boolean bool) { + setProperty("generate-structures", bool); + } + + public void setMotd(String string) { + setProperty("motd", string); + } + + public static String getDefault() { + return "generator-settings=\n" + +"op-permission-level=4\n" + +"allow-nether=true\n" + +"level-name=world\n" + +"enable-query=false\n" + +"allow-flight=false\n" + +"announce-player-achievements=true\n" + +"server-port=25565\n" + +"level-type=DEFAULT\n" + +"enable-rcon=false\n" + +"force-gamemode=false\n" + +"level-seed=\n" + +"server-ip=\n" + +"max-build-height=256\n" + +"spawn-npcs=true\n" + +"white-list=false\n" + +"spawn-animals=true\n" + +"hardcore=false\n" + +"snooper-enabled=true\n" + +"online-mode=false\n" + +"resource-pack=\n" + +"pvp=true\n" + +"difficulty=1\n" + +"server-name=Unknown Server\n" + +"enable-command-block=false\n" + +"gamemode=0\n" + +"player-idle-timeout=0\n" + +"max-players=20\n" + +"spawn-monsters=true\n" + +"generate-structures=true\n" + +"view-distance=10\n" + +"spawn-protection=16\n" + +"motd=A Minecraft Server"; + } + +} diff --git a/HMCSM/src/main/java/org/jackhuang/hellominecraft/svrmgr/settings/Settings.java b/HMCSM/src/main/java/org/jackhuang/hellominecraft/svrmgr/settings/Settings.java new file mode 100644 index 000000000..dff19660f --- /dev/null +++ b/HMCSM/src/main/java/org/jackhuang/hellominecraft/svrmgr/settings/Settings.java @@ -0,0 +1,33 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package org.jackhuang.hellominecraft.svrmgr.settings; + +import java.util.ArrayList; + +/** + * + * @author hyh + */ +public class Settings { + + public boolean checkUpdate; + public String maxMemory; + public String mainjar, bgPath, javaDir, javaArgs; + public ArrayList inactiveExtMods, inactiveCoreMods, inactivePlugins, + inactiveWorlds; + public ArrayList schedules; + + public Settings() { + maxMemory = "1024"; + checkUpdate = true; + schedules = new ArrayList(); + mainjar = bgPath = javaDir = javaArgs = ""; + inactiveExtMods = new ArrayList(); + inactiveCoreMods = new ArrayList(); + inactivePlugins = new ArrayList(); + inactiveWorlds = new ArrayList(); + } + +} diff --git a/HMCSM/src/main/java/org/jackhuang/hellominecraft/svrmgr/settings/SettingsManager.java b/HMCSM/src/main/java/org/jackhuang/hellominecraft/svrmgr/settings/SettingsManager.java new file mode 100644 index 000000000..f692c5b49 --- /dev/null +++ b/HMCSM/src/main/java/org/jackhuang/hellominecraft/svrmgr/settings/SettingsManager.java @@ -0,0 +1,62 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package org.jackhuang.hellominecraft.svrmgr.settings; + +/** + * + * @author hyh + */ +import com.google.gson.Gson; +import java.io.File; +import java.io.IOException; +import org.jackhuang.hellominecraft.HMCLog; +import org.jackhuang.hellominecraft.utils.FileUtils; +import org.jackhuang.hellominecraft.utils.IOUtils; + +/** + * + * @author hyh + */ +public class SettingsManager { + + public static Settings settings; + public static boolean isFirstLoad = false; + static Gson gson; + + public static void load() { + gson = new Gson(); + File file = new File(IOUtils.currentDir(), "hmcsm.json"); + if (file.exists()) { + try { + String str = FileUtils.readFileToString(file); + if (str == null || str.trim().equals("")) { + init(); + } else { + settings = gson.fromJson(str, Settings.class); + } + } catch (IOException ex) { + init(); + } + } else { + settings = new Settings(); + save(); + } + } + + public static void init() { + settings = new Settings(); + isFirstLoad = true; + save(); + } + + public static void save() { + File f = new File(IOUtils.currentDir(), "hmcsm.json"); + try { + FileUtils.write(f, gson.toJson(settings)); + } catch (IOException ex) { + HMCLog.err("Failed to save settings.", ex); + } + } +} diff --git a/HMCSM/src/main/java/org/jackhuang/hellominecraft/svrmgr/settings/WhiteList.java b/HMCSM/src/main/java/org/jackhuang/hellominecraft/svrmgr/settings/WhiteList.java new file mode 100644 index 000000000..e420ebcf8 --- /dev/null +++ b/HMCSM/src/main/java/org/jackhuang/hellominecraft/svrmgr/settings/WhiteList.java @@ -0,0 +1,28 @@ +/* + * 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.svrmgr.settings; + +/** + * + * @author hyh + */ +public class WhiteList extends PlayerList { + + @Override + protected WhiteList.WhiteListPlayer newPlayer(String name) { + return new WhiteList.WhiteListPlayer(name); + } + + public static class WhiteListPlayer extends PlayerList.BasePlayer { + + public WhiteListPlayer(String name) { + super(name); + } + + } + +} diff --git a/HMCSM/src/main/java/org/jackhuang/hellominecraft/svrmgr/threads/MonitorThread.java b/HMCSM/src/main/java/org/jackhuang/hellominecraft/svrmgr/threads/MonitorThread.java new file mode 100644 index 000000000..5db0dce32 --- /dev/null +++ b/HMCSM/src/main/java/org/jackhuang/hellominecraft/svrmgr/threads/MonitorThread.java @@ -0,0 +1,56 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package org.jackhuang.hellominecraft.svrmgr.threads; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.UnsupportedEncodingException; +import java.util.ArrayList; +import org.jackhuang.hellominecraft.HMCLog; + +/** + * + * @author hyh + */ +public class MonitorThread extends Thread { + + public interface MonitorThreadListener { + void onStatus(String status); + } + + InputStream is; + BufferedReader br; + ArrayList listeners; + + public MonitorThread(InputStream is) { + this.listeners = new ArrayList(5); + try { + br = new BufferedReader(new InputStreamReader(is, System.getProperty("sun.jnu.encoding", "gbk"))); + } catch (UnsupportedEncodingException ex) { + br = new BufferedReader(new InputStreamReader(is)); + } + } + + public void addListener(MonitorThreadListener l) { + listeners.add(l); + } + + @Override + public void run() { + String line; + try { + while((line = br.readLine()) != null) { + for(MonitorThreadListener l : listeners) + if(l != null) + l.onStatus(line); + } + } catch (IOException ex) { + HMCLog.warn("Failed to monitor threads.", ex); + } + } + +} diff --git a/HMCSM/src/main/java/org/jackhuang/hellominecraft/svrmgr/threads/WaitForThread.java b/HMCSM/src/main/java/org/jackhuang/hellominecraft/svrmgr/threads/WaitForThread.java new file mode 100644 index 000000000..5342f5c28 --- /dev/null +++ b/HMCSM/src/main/java/org/jackhuang/hellominecraft/svrmgr/threads/WaitForThread.java @@ -0,0 +1,45 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package org.jackhuang.hellominecraft.svrmgr.threads; + +import java.util.ArrayList; +import java.util.logging.Level; +import java.util.logging.Logger; +import org.jackhuang.hellominecraft.DoneListener1; + +/** + * + * @author jack + */ +public class WaitForThread extends Thread { + + public ArrayList> al; + Process p; + + public WaitForThread(Process p) { + this.p = p; + al = new ArrayList>(); + } + + public void addListener(DoneListener1 dl) { + al.add(dl); + } + + @Override + public void run() { + try { + int exitCode = p.waitFor(); + for(DoneListener1 dl : al) + if(dl != null) + dl.onDone(exitCode); + } catch (InterruptedException ex) { + Logger.getLogger(WaitForThread.class.getName()).log(Level.SEVERE, null, ex); + for(DoneListener1 dl : al) + if(dl != null) + dl.onDone(-1); + } + } + +} diff --git a/HMCSM/src/main/java/org/jackhuang/hellominecraft/svrmgr/utils/FolderOpener.java b/HMCSM/src/main/java/org/jackhuang/hellominecraft/svrmgr/utils/FolderOpener.java new file mode 100644 index 000000000..e48374700 --- /dev/null +++ b/HMCSM/src/main/java/org/jackhuang/hellominecraft/svrmgr/utils/FolderOpener.java @@ -0,0 +1,45 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package org.jackhuang.hellominecraft.svrmgr.utils; + +import java.io.File; +import org.jackhuang.hellominecraft.utils.MessageBox; + +/** + * + * @author jack + */ +public class FolderOpener { + + public static void open(String s) { + try { + File f = new File(s); + f.mkdirs(); + java.awt.Desktop.getDesktop().open(f); + } catch (Exception ex) { + MessageBox.Show("鏃犳硶鎵撳紑璧勬簮绠$悊鍣: " + ex.getMessage()); + } + } + + public static void openResourcePacks(String gameDir) { + open(gameDir + "resourcepacks"); + } + public static void openTextutrePacks(String gameDir) { + open(gameDir + "texturepacks"); + } + public static void openMods() { + open(Utilities.try2GetPath("mods")); + } + public static void openCoreMods() { + open(Utilities.try2GetPath("coremods")); + } + public static void openPlugins() { + open(Utilities.try2GetPath("plugins")); + } + public static void openConfig() { + open(Utilities.try2GetPath("config")); + } + +} diff --git a/HMCSM/src/main/java/org/jackhuang/hellominecraft/svrmgr/utils/IMonitorService.java b/HMCSM/src/main/java/org/jackhuang/hellominecraft/svrmgr/utils/IMonitorService.java new file mode 100644 index 000000000..0e47794cf --- /dev/null +++ b/HMCSM/src/main/java/org/jackhuang/hellominecraft/svrmgr/utils/IMonitorService.java @@ -0,0 +1,20 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package org.jackhuang.hellominecraft.svrmgr.utils; + +/** + * + * @author hyh + */ +public interface IMonitorService { + + /** + * 鑾峰緱褰撳墠鐨勭洃鎺у璞. + * + * @return 杩斿洖鏋勯犲ソ鐨勭洃鎺у璞 + * @throws Exception + */ + public MonitorInfoBean getMonitorInfoBean() throws Exception; +} \ No newline at end of file diff --git a/HMCSM/src/main/java/org/jackhuang/hellominecraft/svrmgr/utils/IPGet.java b/HMCSM/src/main/java/org/jackhuang/hellominecraft/svrmgr/utils/IPGet.java new file mode 100644 index 000000000..122f3c040 --- /dev/null +++ b/HMCSM/src/main/java/org/jackhuang/hellominecraft/svrmgr/utils/IPGet.java @@ -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.svrmgr.utils; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import org.jackhuang.hellominecraft.DoneListener1; +import org.jackhuang.hellominecraft.HMCLog; +import org.jackhuang.hellominecraft.utils.NetUtils; +import org.jsoup.Jsoup; +import org.jsoup.nodes.Document; +import org.jsoup.select.Elements; + +/** + * + * @author hyh + */ +public class IPGet extends Thread { + + public DoneListener1 dl; + + @Override + public void run() { + try { + Document d = Jsoup.connect("http://www.ip138.com").get(); + Elements iframe = d.getElementsByTag("iframe"); + if(iframe.size() > 0) { + String url = iframe.get(0).attr("src"); + String s = NetUtils.doGet(url, "GBK"); + Pattern p = Pattern.compile("\\[(\\d|[1-9]\\d|1\\d\\d|2[0-4]\\d|25[0-5])(\\.(\\d|[1-9]\\d|1\\d\\d|2[0-4]\\d|25[0-5])){3}\\]"); + Matcher m = p.matcher(s); + s = ""; + while(m.find()) { + s += m.group() + ","; + } + dl.onDone(s.substring(0, s.length()-1)); + } + } catch (Exception ex) { + HMCLog.warn("Failed to get ip from ip138.", ex); + dl.onDone("鑾峰彇澶辫触"); + } + } + +} diff --git a/HMCSM/src/main/java/org/jackhuang/hellominecraft/svrmgr/utils/ModType.java b/HMCSM/src/main/java/org/jackhuang/hellominecraft/svrmgr/utils/ModType.java new file mode 100644 index 000000000..9c08af355 --- /dev/null +++ b/HMCSM/src/main/java/org/jackhuang/hellominecraft/svrmgr/utils/ModType.java @@ -0,0 +1,86 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package org.jackhuang.hellominecraft.svrmgr.utils; + +import java.io.File; +import java.io.IOException; +import java.util.logging.Level; +import java.util.logging.Logger; +import java.util.zip.ZipEntry; +import java.util.zip.ZipFile; + +/** + * 鍒ゆ柇mod绫诲瀷 + * @author hyh + */ +public class ModType { + + public static final int ForgeMod = 0; + public static final int ModLoaderMod = 1; + public static final int Forge = 2; + public static final int ModLoader = 3; + public static final int Unknown = 4; + + public static int getModType(String path) { + return getModType(new File(path)); + } + + public static int getModType(File path) { + boolean isModLoader = false; + ZipFile zipFile = null; + try { + if (path.exists()) { + zipFile = new ZipFile(path); + String gbkPath; + java.util.Enumeration e = zipFile.entries(); + while (e.hasMoreElements()) + { + ZipEntry zipEnt = (ZipEntry) e.nextElement(); + if(zipEnt.isDirectory()) continue; + gbkPath = zipEnt.getName(); + if("mcmod.info".equals(gbkPath)) + return ForgeMod; + else if("mcpmod.info".equals(gbkPath)) + return Forge; + else if("ModLoader.class".equals(gbkPath)) + isModLoader = true; + else if(gbkPath.trim().startsWith("mod_")) + return ModLoaderMod; + } + } + } catch(Exception e) { + + } finally { + try { + if(zipFile != null) + zipFile.close(); + } catch (IOException ex) { + Logger.getLogger(ModType.class.getName()).log(Level.SEVERE, null, ex); + } catch (Throwable t) { + + } + } + if(isModLoader) + return ModLoaderMod; + else + return Unknown; + } + + public static String getModTypeShowName(int type) { + java.util.ResourceBundle bundle = java.util.ResourceBundle.getBundle("org/jackhuang/hellominecraftlauncher/I18N"); // NOI18N + switch(type) { + case ForgeMod: + return bundle.getString("ForgeMod"); + case Forge: + return bundle.getString("Forge"); + case ModLoader: + return bundle.getString("ModLoader"); + case ModLoaderMod: + return bundle.getString("ModLoaderMod"); + default: + return bundle.getString("Unknown"); + } + } +} diff --git a/HMCSM/src/main/java/org/jackhuang/hellominecraft/svrmgr/utils/MonitorInfoBean.java b/HMCSM/src/main/java/org/jackhuang/hellominecraft/svrmgr/utils/MonitorInfoBean.java new file mode 100644 index 000000000..003a61761 --- /dev/null +++ b/HMCSM/src/main/java/org/jackhuang/hellominecraft/svrmgr/utils/MonitorInfoBean.java @@ -0,0 +1,121 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package org.jackhuang.hellominecraft.svrmgr.utils; + +/** + * + * @author hyh + */ +public class MonitorInfoBean { + + /** + * 鍙娇鐢ㄥ唴瀛. + */ + private long totalMemory; + /** + * 鍓╀綑鍐呭瓨. + */ + private long freeMemory; + /** + * 鏈澶у彲浣跨敤鍐呭瓨. + */ + private long maxMemory; + /** + * 鎿嶄綔绯荤粺. + */ + private String osName; + /** + * 鎬荤殑鐗╃悊鍐呭瓨. + */ + private long totalMemorySize; + /** + * 鍓╀綑鐨勭墿鐞嗗唴瀛. + */ + private long freePhysicalMemorySize; + /** + * 宸蹭娇鐢ㄧ殑鐗╃悊鍐呭瓨. + */ + private long usedMemory; + /** + * 绾跨▼鎬绘暟. + */ + private int totalThread; + /** + * cpu浣跨敤鐜. + */ + private double cpuRatio; + + public long getFreeMemory() { + return freeMemory; + } + + public void setFreeMemory(long freeMemory) { + this.freeMemory = freeMemory; + } + + public long getFreePhysicalMemorySize() { + return freePhysicalMemorySize; + } + + public void setFreePhysicalMemorySize(long freePhysicalMemorySize) { + this.freePhysicalMemorySize = freePhysicalMemorySize; + } + + public long getMaxMemory() { + return maxMemory; + } + + public void setMaxMemory(long maxMemory) { + this.maxMemory = maxMemory; + } + + public String getOsName() { + return osName; + } + + public void setOsName(String osName) { + this.osName = osName; + } + + public long getTotalMemory() { + return totalMemory; + } + + public void setTotalMemory(long totalMemory) { + this.totalMemory = totalMemory; + } + + public long getTotalMemorySize() { + return totalMemorySize; + } + + public void setTotalMemorySize(long totalMemorySize) { + this.totalMemorySize = totalMemorySize; + } + + public int getTotalThread() { + return totalThread; + } + + public void setTotalThread(int totalThread) { + this.totalThread = totalThread; + } + + public long getUsedMemory() { + return usedMemory; + } + + public void setUsedMemory(long usedMemory) { + this.usedMemory = usedMemory; + } + + public double getCpuRatio() { + return cpuRatio; + } + + public void setCpuRatio(double cpuRatio) { + this.cpuRatio = cpuRatio; + } +} \ No newline at end of file diff --git a/HMCSM/src/main/java/org/jackhuang/hellominecraft/svrmgr/utils/MonitorServiceImpl.java b/HMCSM/src/main/java/org/jackhuang/hellominecraft/svrmgr/utils/MonitorServiceImpl.java new file mode 100644 index 000000000..7003f75e1 --- /dev/null +++ b/HMCSM/src/main/java/org/jackhuang/hellominecraft/svrmgr/utils/MonitorServiceImpl.java @@ -0,0 +1,267 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package org.jackhuang.hellominecraft.svrmgr.utils; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.LineNumberReader; +import java.util.StringTokenizer; +import com.sun.management.OperatingSystemMXBean; +import org.jackhuang.hellominecraft.utils.Bytes; + +/** + * + * 鑾峰彇绯荤粺淇℃伅鐨勪笟鍔¢昏緫瀹炵幇绫. + * + * @author GuoHuang + */ +public class MonitorServiceImpl implements IMonitorService { + + private static final int CPUTIME = 30; + private static final int PERCENT = 100; + private static final int FAULTLENGTH = 10; + private static String linuxVersion = null; + + /** + * 鑾峰緱褰撳墠鐨勭洃鎺у璞. + * + * @return 杩斿洖鏋勯犲ソ鐨勭洃鎺у璞 + * @throws Exception + * @author GuoHuang + */ + public MonitorInfoBean getMonitorInfoBean() throws Exception { + int kb = 1024; + // 鍙娇鐢ㄥ唴瀛 + long totalMemory = Runtime.getRuntime().totalMemory() / kb; + // 鍓╀綑鍐呭瓨 + long freeMemory = Runtime.getRuntime().freeMemory() / kb; + // 鏈澶у彲浣跨敤鍐呭瓨 + long maxMemory = Runtime.getRuntime().maxMemory() / kb; + OperatingSystemMXBean osmxb = (OperatingSystemMXBean) java.lang.management.ManagementFactory.getOperatingSystemMXBean(); + // 鎿嶄綔绯荤粺 + String osName = System.getProperty("os.name"); + // 鎬荤殑鐗╃悊鍐呭瓨 + long totalMemorySize = osmxb.getTotalPhysicalMemorySize() / kb; + // 鍓╀綑鐨勭墿鐞嗗唴瀛 + long freePhysicalMemorySize = osmxb.getFreePhysicalMemorySize() / kb; + // 宸蹭娇鐢ㄧ殑鐗╃悊鍐呭瓨 + long usedMemory = (osmxb.getTotalPhysicalMemorySize() - osmxb.getFreePhysicalMemorySize()) / kb; + // 鑾峰緱绾跨▼鎬绘暟 + ThreadGroup parentThread; + for (parentThread = Thread.currentThread().getThreadGroup(); parentThread.getParent() != null; parentThread = parentThread.getParent()); + int totalThread = parentThread.activeCount(); + double cpuRatio = 0; + if (osName.toLowerCase().startsWith("windows")) { + cpuRatio = this.getCpuRatioForWindows(); + } else { + cpuRatio = getCpuRateForLinux(); + } + // 鏋勯犺繑鍥炲璞 + MonitorInfoBean infoBean = new MonitorInfoBean(); + infoBean.setFreeMemory(freeMemory); + infoBean.setFreePhysicalMemorySize(freePhysicalMemorySize); + infoBean.setMaxMemory(maxMemory); + infoBean.setOsName(osName); + infoBean.setTotalMemory(totalMemory); + infoBean.setTotalMemorySize(totalMemorySize); + infoBean.setTotalThread(totalThread); + infoBean.setUsedMemory(usedMemory); + infoBean.setCpuRatio(cpuRatio); + return infoBean; + } + + private static double getCpuRateForLinux() { + InputStream is = null; + InputStreamReader isr = null; + BufferedReader brStat = null; + StringTokenizer tokenStat = null; + try { + System.out.println("Getting usage rate of CPU , linux version: " + linuxVersion); + Process process = Runtime.getRuntime().exec("top -b -n 1"); + is = process.getInputStream(); + isr = new InputStreamReader(is); + brStat = new BufferedReader(isr); + if (linuxVersion == null || linuxVersion.equals("2.4")) { + brStat.readLine(); + brStat.readLine(); + brStat.readLine(); + brStat.readLine(); + tokenStat = new StringTokenizer(brStat.readLine()); + tokenStat.nextToken(); + tokenStat.nextToken(); + String user = tokenStat.nextToken(); + tokenStat.nextToken(); + String system = tokenStat.nextToken(); + tokenStat.nextToken(); + String nice = tokenStat.nextToken(); + System.out.println(user + " , " + system + " , " + nice); + user = user.substring(0, user.indexOf("%")); + system = system.substring(0, system.indexOf("%")); + nice = nice.substring(0, nice.indexOf("%")); + float userUsage = new Float(user).floatValue(); + float systemUsage = new Float(system).floatValue(); + float niceUsage = new Float(nice).floatValue(); + return (userUsage + systemUsage + niceUsage) / 100; + } else { + brStat.readLine(); + brStat.readLine(); + tokenStat = new StringTokenizer(brStat.readLine()); + tokenStat.nextToken(); + tokenStat.nextToken(); + tokenStat.nextToken(); + tokenStat.nextToken(); + tokenStat.nextToken(); + tokenStat.nextToken(); + tokenStat.nextToken(); + String cpuUsage = tokenStat.nextToken(); + System.out.println("CPU idle : " + cpuUsage); + Float usage = new Float(cpuUsage.substring(0, cpuUsage.indexOf("%"))); + return (1 - usage.floatValue() / 100); + } + } catch (IOException ioe) { + System.out.println(ioe.getMessage()); + freeResource(is, isr, brStat); + return 1; + } finally { + freeResource(is, isr, brStat); + } + } + + private static void freeResource(InputStream is, InputStreamReader isr, + BufferedReader br) { + try { + if (is != null) { + is.close(); + } + if (isr != null) { + isr.close(); + } + if (br != null) { + br.close(); + } + } catch (IOException ioe) { + System.out.println(ioe.getMessage()); + } + } + + /** + * 鑾峰緱CPU浣跨敤鐜. + * + * @return 杩斿洖cpu浣跨敤鐜 + * @author GuoHuang + */ + private double getCpuRatioForWindows() { + try { + String procCmd = System.getenv("windir") + "\\system32\\wbem\\wmic.exe process get Caption,CommandLine,KernelModeTime,ReadOperationCount,ThreadCount,UserModeTime,WriteOperationCount"; + // 鍙栬繘绋嬩俊鎭 + long[] c0 = readCpu(Runtime.getRuntime().exec(procCmd)); + Thread.sleep(CPUTIME); + long[] c1 = readCpu(Runtime.getRuntime().exec(procCmd)); + if (c0 != null && c1 != null) { + long idletime = c1[0] - c0[0]; + long busytime = c1[1] - c0[1]; + return Double.valueOf(PERCENT * (busytime) / (busytime + idletime)).doubleValue(); + } else { + return 0.0; + } + } catch (Exception ex) { + ex.printStackTrace(); + return 0.0; + } + } + + /** + * 璇诲彇CPU淇℃伅. + * + * @param proc + * @return + * @author GuoHuang + */ + private long[] readCpu(final Process proc) { + long[] retn = new long[2]; + try { + proc.getOutputStream().close(); + InputStreamReader ir = new InputStreamReader(proc.getInputStream()); + LineNumberReader input = new LineNumberReader(ir); + String line = input.readLine(); + if (line == null || line.length() < FAULTLENGTH) { + return null; + } + int capidx = line.indexOf("Caption"); + int cmdidx = line.indexOf("CommandLine"); + int rocidx = line.indexOf("ReadOperationCount"); + int umtidx = line.indexOf("UserModeTime"); + int kmtidx = line.indexOf("KernelModeTime"); + int wocidx = line.indexOf("WriteOperationCount"); + long idletime = 0; + long kneltime = 0; + long usertime = 0; + while ((line = input.readLine()) != null) { + if (line.length() < wocidx) { + continue; + } + // 瀛楁鍑虹幇椤哄簭锛欳aption,CommandLine,KernelModeTime,ReadOperationCount, + // ThreadCount,UserModeTime,WriteOperation + String caption = Bytes.substring(line, capidx, cmdidx - 1).trim(); + String cmd = Bytes.substring(line, cmdidx, kmtidx - 1).trim(); + if (cmd.indexOf("wmic.exe") >= 0) { + continue; + } + String s1 = Bytes.substring(line, kmtidx, rocidx - 1).trim(); + String s2 = Bytes.substring(line, umtidx, wocidx - 1).trim(); + if (caption.equals("System Idle Process") || caption.equals("System")) { + if (s1.length() > 0) { + idletime += Long.parseLong(s1); + } + if (s2.length() > 0) { + idletime += Long.parseLong(s2); + } + continue; + } + if (s1.length() > 0) { + kneltime += Long.parseLong(s1); + } + if (s2.length() > 0) { + usertime += Long.parseLong(s2); + } + } + retn[0] = idletime; + retn[1] = kneltime + usertime; + return retn; + } catch (Exception ex) { + ex.printStackTrace(); + } finally { + try { + proc.getInputStream().close(); + } catch (Exception e) { + e.printStackTrace(); + } + } + return null; + } + + /** + * 娴嬭瘯鏂规硶. + * + * @param args + * @throws Exception + * @author GuoHuang + */ + public static void main(String[] args) throws Exception { + IMonitorService service = new MonitorServiceImpl(); + MonitorInfoBean monitorInfo = service.getMonitorInfoBean(); + System.out.println("cpu鍗犳湁鐜=" + monitorInfo.getCpuRatio()); + System.out.println("鍙娇鐢ㄥ唴瀛=" + monitorInfo.getTotalMemory()); + System.out.println("鍓╀綑鍐呭瓨=" + monitorInfo.getFreeMemory()); + System.out.println("鏈澶у彲浣跨敤鍐呭瓨=" + monitorInfo.getMaxMemory()); + System.out.println("鎿嶄綔绯荤粺=" + monitorInfo.getOsName()); + System.out.println("鎬荤殑鐗╃悊鍐呭瓨=" + monitorInfo.getTotalMemorySize() + "kb"); + System.out.println("鍓╀綑鐨勭墿鐞嗗唴瀛=" + monitorInfo.getFreeMemory() + "kb"); + System.out.println("宸蹭娇鐢ㄧ殑鐗╃悊鍐呭瓨=" + monitorInfo.getUsedMemory() + "kb"); + System.out.println("绾跨▼鎬绘暟=" + monitorInfo.getTotalThread() + "kb"); + } +} \ No newline at end of file diff --git a/HMCSM/src/main/java/org/jackhuang/hellominecraft/svrmgr/utils/Utilities.java b/HMCSM/src/main/java/org/jackhuang/hellominecraft/svrmgr/utils/Utilities.java new file mode 100644 index 000000000..ce88f9c4b --- /dev/null +++ b/HMCSM/src/main/java/org/jackhuang/hellominecraft/svrmgr/utils/Utilities.java @@ -0,0 +1,195 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package org.jackhuang.hellominecraft.svrmgr.utils; + +import java.io.File; +import java.util.ArrayList; +import org.jackhuang.hellominecraft.svrmgr.settings.SettingsManager; + +/** + * + * @author hyh + */ +public class Utilities { + + public static String addSeparator(String path) { + if (path == null || path.trim().length() == 0) { + return ""; + } + if (path.charAt(path.length() - 1) == File.separatorChar) { + return path; + } else { + return path + File.separatorChar; + } + } + + public static boolean isSeparator(char ch) { + return ch == File.separatorChar || ch == '/' || ch == '\\'; + } + + public static String removeLastSeparator(String dir) { + String t = dir.trim(); + char ch = t.charAt(t.length() - 1); + if (isSeparator(ch)) { + return t.substring(0, t.length() - 1); + } + return t; + } + + public static String extractLastDirectory(String dir) { + String t = removeLastSeparator(dir); + int i = t.length() - 1; + while (i >= 0 && !isSeparator(dir.charAt(i))) { + i--; + } + if (i < 0) { + return t; + } + return t.substring(i + 1, (t.length() - i) + (i + 1) - 1); + } + + public static ArrayList findAllFile(File f) { + ArrayList arr = new ArrayList(); + if (!f.exists()) { + return arr; + } + if (f.isDirectory()) { + File[] f1 = f.listFiles(); + int len = f1.length; + for (int i = 0; i < len; i++) { + if (f1[i].isFile()) { + arr.add(f1[i].getName()); + } + } + } + return arr; + } + + public static ArrayList findAllDir(File f) { + ArrayList arr = new ArrayList(); + if (f.isDirectory()) { + File[] f1 = f.listFiles(); + int len = f1.length; + for (int i = 0; i < len; i++) { + if (f1[i].isDirectory()) { + arr.add(f1[i].getName()); + } + } + } + return arr; + } + + public static void deleteAll(File f) { + if (f == null || !f.exists()) { + return; + } + if (f.isFile()) { + f.delete(); + } else { + File f1[] = f.listFiles(); + int len = f1.length; + for (int i = 0; i < len; i++) { + deleteAll(f1[i]); + } + f.delete(); + } + } + + public static String extractFileName(String fileName) { + File file = new File(fileName); + return file.getName(); + } + + public static boolean is16Folder(String path) { + path = Utilities.addSeparator(path); + if (new File(path + "versions").exists()) { + return true; + } + return false; + } + + public static boolean isEmpty(String s) { + return s == null || s.trim().equals(""); + } + + public static int parseInt(String s, int def) { + try { + return Integer.parseInt(s); + } catch (Exception e) { + return def; + } + } + public static int tryParseInteger(String integer, int def) { + try { + return Integer.parseInt(integer); + } catch (NumberFormatException localNumberFormatException) { + return def; + } + } + + public static boolean isEquals(String base, String to) { + if (base == null) { + return (to == null); + } else { + return base.equals(to); + } + } + + public static String getGameDir() { + String path = new File(SettingsManager.settings.mainjar).getParent(); + path = Utilities.addSeparator(path); + return path; + } + + public static String getPath(String lastFolder) { + String path = getGameDir(); + File file = new File((new StringBuilder()).append(path).append(lastFolder).toString()); + if (file.exists()) { + return file.getPath(); + } else { + return null; + } + } + + public static String try2GetPath(String lastFolder) { + String path = getGameDir(); + return (new StringBuilder()).append(path).append(lastFolder).toString(); + + } + + public static String trimExtension(String filename) { + if ((filename != null) && (filename.length() > 0)) { + int i = filename.lastIndexOf('.'); + if ((i > -1) && (i < (filename.length()))) { + return filename.substring(0, i); + } + } + return filename; + } + + public static boolean openLink(String url) { + boolean isBrowsed = false; + //鍒ゆ柇褰撳墠绯荤粺鏄惁鏀寔Java AWT Desktop鎵╁睍 + if (java.awt.Desktop.isDesktopSupported()) { + try { +//鍒涘缓涓涓猆RI瀹炰緥 + java.net.URI uri = java.net.URI.create(url); +//鑾峰彇褰撳墠绯荤粺妗岄潰鎵╁睍 + java.awt.Desktop dp = java.awt.Desktop.getDesktop(); +//鍒ゆ柇绯荤粺妗岄潰鏄惁鏀寔瑕佹墽琛岀殑鍔熻兘 + if (dp.isSupported(java.awt.Desktop.Action.BROWSE)) { +//鑾峰彇绯荤粺榛樿娴忚鍣ㄦ墦寮閾炬帴 + dp.browse(uri); + isBrowsed = true; + } + } catch (java.lang.NullPointerException e) { +//姝や负uri涓虹┖鏃舵姏鍑哄紓甯 + } catch (java.io.IOException e) { +//姝や负鏃犳硶鑾峰彇绯荤粺榛樿娴忚鍣 + } + } + return isBrowsed; + } +} diff --git a/HMCSM/src/main/java/org/jackhuang/hellominecraft/svrmgr/views/CommandsWindow.form b/HMCSM/src/main/java/org/jackhuang/hellominecraft/svrmgr/views/CommandsWindow.form new file mode 100644 index 000000000..ee12f0b03 --- /dev/null +++ b/HMCSM/src/main/java/org/jackhuang/hellominecraft/svrmgr/views/CommandsWindow.form @@ -0,0 +1,53 @@ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/HMCSM/src/main/java/org/jackhuang/hellominecraft/svrmgr/views/CommandsWindow.java b/HMCSM/src/main/java/org/jackhuang/hellominecraft/svrmgr/views/CommandsWindow.java new file mode 100644 index 000000000..3eb0d4a29 --- /dev/null +++ b/HMCSM/src/main/java/org/jackhuang/hellominecraft/svrmgr/views/CommandsWindow.java @@ -0,0 +1,58 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package org.jackhuang.hellominecraft.svrmgr.views; + +/** + * + * @author hyh + */ +public class CommandsWindow extends javax.swing.JDialog { + + /** + * Creates new form CommandsWindow + */ + public CommandsWindow(java.awt.Frame parent, boolean modal) { + super(parent, modal); + initComponents(); + } + + /** + * 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") + // //GEN-BEGIN:initComponents + private void initComponents() { + + jScrollPane1 = new javax.swing.JScrollPane(); + jTextArea1 = new javax.swing.JTextArea(); + + setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE); + + jTextArea1.setColumns(20); + jTextArea1.setRows(5); + jTextArea1.setText("--鍩烘湰\n/register [瀵嗙爜] [纭瀵嗙爜]:娉ㄥ唽 (Authme鎻掍欢)\n/login [瀵嗙爜]:鐧诲綍 (Authme鎻掍欢)\n/sethome:璁剧疆浣犺嚜宸辩殑瀹 (Esentials鎻掍欢)\n/home:鍥炲埌浣犺嚜宸辩殑瀹 (Esentials鎻掍欢)\n/money:鏌ョ湅浣犳湁鐨勯挶 (iConmey缁忔祹鎻掍欢)\n/back:鍥炲埌涓婁竴涓綅缃 (Esentials鎻掍欢)\n/tp [鐜╁鍚嶅瓧]:浼犻佸埌璇ョ帺瀹 闇姹侽P\n/gamemode [鐜╁濮撳悕] [娓告垙妯″紡]:缁欐煇鐜╁鏇存崲娓告垙妯″紡\n/ban [鐜╁鍚嶅瓧]:灏佺鐜╁\n/ban-ip [鐜╁鍚嶅瓧]:灏佺鐜╁IP\n/kick [鐜╁鍚嶅瓧]:T鍑虹帺瀹禱n/setspawn:璁剧疆鍑虹敓鐐 (Esentials鎻掍欢)\n/spawn:鏌ョ湅鍑虹敓鐐 (Esentials鎻掍欢)\n/whitelist add [鐜╁鍚嶅瓧]:娣诲姞鐧藉悕鍗昞n/whitelist remove [鐜╁鍚嶅瓧]:绉婚櫎鐧藉悕鍗昞n/op [鐜╁鍚嶅瓧]:缁欐煇浜簅p\n/unban [鐜╁鍚嶅瓧]:瑙i櫎鐜╁ban (Essentials鎻掍欢)\n/unbanip [鐜╁鍚嶅瓧]:瑙i櫎鐜╁ban-ip (Essentials鎻掍欢)\n/pardon [鐜╁鍚嶅瓧]:鍚寀nban (鍘熺増craftbukkit)\n/pardon-ip [鐜╁鍚嶅瓧]:鍚寀nbanip (鍘熺増craftbukkit)\n/pay [鐜╁] [閽辨暟] 鎶婅嚜宸辩殑娓告垙甯佽浆鍒板叾浠栫帺瀹 (iConmey缁忔祹鎻掍欢)\n/delwarp [鍦版爣] :鍒犻櫎浼犻佹爣 (Essentials鎻掍欢)\n/give [鐜╁鍚嶅瓧] [鐗╁搧ID] [鏁伴噺]:缁欐煇浜虹墿鍝乗n/petrelease 鏀剧敓瀹犵墿 (MyPet鎻掍欢)\n/reload 閲嶅惎鏈嶅姟鍣╘n\n--鍏朵粬\n/help: 鏌ョ湅甯姪鍛戒护鍒楄〃.\n/helpop: 鍚戝湪绾縊P鍙戦佹眰鍔╀俊鎭.\n/heroicderp: 閲嶆柊鍔犺浇閰嶇疆\n/home: 浼犻佸洖瀹.\n/ignore: 蹇界暐鏌愮帺瀹.\n/info: 鏂瑰潡淇℃伅宸ュ叿\n/invsee: 鏌ョ湅鏌愮帺瀹惰儗鍖.\n/item: 鐢熸垚涓涓墿鍝.\n/itemdb: 鎼滅储鐗╁搧.\n/jails: 鏄剧ず鎵鏈夌洃鐙辩殑鍒楄〃.\n/jump: 浼犻佸埌瑙嗛噹灏藉ご.\n/jumpto: 璺宠浆鍒颁竴涓湴鏂筡n/kick: 鎶婃煇鐜╁浠ユ煇鐞嗙敱浠庢湇鍔″櫒韪㈠嚭.\n/kickall: 鎶婃墍鏈夌帺瀹惰涪鍑烘湇鍔″櫒,闄や簡OP.\n/kill: 鏉姝绘煇涓帺瀹.\n/killall: 鏉姝昏繖涓笘鐣岀殑鎵鏈夌敓鐗.\n/kit: 鑾峰緱鎸囧畾鐨勫伐鍏峰寘,鎴栨煡鐪嬪彲鐢ㄧ殑宸ュ叿鍖.\n/kittycannon: 鍚戜綘鐨勫鎵嬫墧鍑轰竴涓垎鐐哥殑灏忕尗.\n/lift: 妫鏌ョ數姊痋n/lightning: 绁炵殑鍔涢噺锛佽闂數鍔堝埌鍑嗘槦澶勬垨鐜╁澶撮《.\n/list: 鏌ョ湅鎵鏈夊湪绾跨殑鐜╁.\n/listchunks: List chunks that your selection includes\n/listgroups: List the groups available.\n/lockette: Access to the Lockette plugin via commands.\n/login: Authenticate yourself as the owner of this player.\n/logout: Manually end your login session.\n/lrbuild: - Long-range buil\n/mail: 鏌ョ湅/娓呴櫎/鍙戦 閭欢.\n/manclear: Clear world selection. Next commands will work on you\n/mandemote: Demote a player in the same heritage line to a lower\n/mangadd: Add group to the system.\n/mangaddi: Add a group to another group inheritance list.\n/mangaddp: Add permissions to a group.\n/mangaddv: Add, or replaces, a variable to a group (like prefix\n/mangcheckp: Check if group has a permissions, and where it come\n/mangcheckv: Verify a value of a variable of group, and where it\n/mangdel: Removes group from the system(all it's users become de\n/mangdeli: Remove a group from another group inheritance list.\n/mangdelp: Removes permissions from a group.\n/mangdelv: Remove a variable from a group.\n/manglistp: Lists all permissionss from a group.\n/manglistv: List variables a group has (like prefix or suffix).\n/manload: Reload current world and config.yml. Or load given wor\n/manpromote: Promote a player in the same heritage line to a hig\n/mansave: Save all permissionss on file.\n/manselect: Select a world to work with next commands.\n/mantogglesave: Toggle on/off the autosave.\n/mantogglevalidate: Toggle on/off the validating if player is on\n/manuadd: Move a player to desired group.(Adds to the file if no\n/manuaddp: Add permissions diretly to the player.\n/manuaddsub: Add a group to a player's subgroup list.\n/manuaddv: Add, or replaces, a variable to a user (like prefix o\n/manucheckp: Verify if user has a permissions, and where it come\n/manucheckv: Verify a value of a variable of user, and where it\n/manudel: Remove any user specific configuration. Make him defau\n/manudelp: Removes permissions diretly from the player.\n/manudelsub: Remove a group to a player's subgroup list.\n/manudelv: Remove a variable from a user.\n/manulistp: List all permissionss from a player.\n/manulistv: List variables a user has (like prefix or suffix).\n/manwhois: Tell the group that user belongs.\n/manworld: Prints the selected world name\n/mask: [mask] - Set the brush mask\n/mat: [pattern] - Set the brush material\n/me: 鍦ㄦ帴涓嬫潵璇寸殑璇濅腑娣诲姞鏄熷彿鍓嶇紑.\n/mobbounty: Allows user to see MobBountyReloaded information.\n/mobbountycheck: Allows user to check the values for creatures.\n/mobbountydropscheck: Reloads the MobBountyReloadedDrops configs\n/mobbountydropsdrops: Allows the user to modify drop strings for\n/mobbountydropsload: Reloads the MobBountyReloadedDrops configs./mobbountydropssave: Reloads the MobBountyReloadedDrops configs./mobbountydropsworlddrops: Allows the user to modify drop string.\n/mobbountyenvmulti: Allows user to change an environment multipl\n/mobbountyexploitsload: Reloads the plugin's configs.\n/mobbountyexploitsmodify: Modifies the plugin's configs.\n/mobbountyexploitssave: Saves the plugin's configs.\n/mobbountygeneral: Allows user to change values of creatures.\n/mobbountygroupmulti: Allows user to change a group multiplier.\n/mobbountyload: Allows user to reload the MBR configs.\n/mobbountyreward: Allows user to change values of creatures.\n/mobbountysave: Allows user to reload the MBR configs.\n/mobbountytimemulti: Allows user to change a time multiplier.\n/mobbountyusermulti: Allows user to change a user multiplier.\n/mobbountyworldreward: Allows user to change values of creatures\n/mobhealth: Root command for all MobHealth Commands.\n/money: Distrobute, Check, Use Currency.\n/more: 璁╂墜涓墿鍝佽揪鍒版渶澶у爢鍙.\n/motd: 鏌ョ湅浠婃棩鏈嶅姟鍣ㄦ秷鎭.\n/msg: 鍙戦佷竴鏉″瘑璇粰鏌愮帺瀹.\n/mute: 绂佽█鎴栬В绂 鐜╁.\n/mv: Generic Multiverse Command\n/mvc: Display World, Coordinates, Direction & Compression for a\n/mvclone: World clone command\n/mvco: Displays the player's coordinates.\n/mvconfirm: Confirms sensitive decisions like deleting a world.\n/mvcoord: Display World, Coordinates, Direction & Compression fo\n/mvcreate: World create command\n/mvdebug: Turns on debugging.\n/mvdelete: World delete command\n/mvenv: Tells the user all possible environment types.\n/mvgenerators: Displays all found world generators.\n/mvgens: Displays all found world generators.\n/mvh: Displays the Multiverse Help.\n/mvhelp: Displays the Multiverse Help.\n/mvi: Gets world info.\n/mvim: World import command\n/mvimport: World import command\n/mvinfo: Gets world info.\n/mvl: Print list of loaded Worlds\n/mvlist: Print list of loaded Worlds\n/mvload: Loads a world into Multiverse.\n/mvm: Modify the settings of an existing world\n/mvmadd: Modify the settings of an existing world\n/mvmclear: Modify the settings of an existing world\n/mvmodify: Modify the settings of an existing world\n/mvmremove: Modify the settings of an existing world\n/mvmset: Modify the settings of an existing world\n/mvpurge: Purge the targetted world of creatures.\n/mvr: Reload Configuration files.\n/mvregen: Regenerates a world Multiverse already knows about.\n/mvreload: Reload Configuration files.\n/mvremove: World remove command\n/mvs: Teleport to the spawn area\n/mvscript: Runs a script from the Multiverse scripts directory.\n/mvsearch: Displays the Multiverse Help.\n/mvset: Set the spawn area for a particular world\n/mvsetspawn: Set the spawn area for a particular world\n/mvsilent: Reduces startup messages\n/mvspawn: Teleport to the spawn area\n/mvss: Set the spawn area for a particular world\n/mvtp: Command to teleport between Worlds\n/mvunload: World unload command\n/mvv: Prints out version info.\n/mvversion: Prints out version info.\n/mvw: Display online users per world.\n/mvwho: Display online users per world.\n/mypet: Help for all MyPet commands.\n/near: 鍒楀嚭鑷繁韬竟鐨勭帺瀹,鎴栧垪鍑烘煇鐜╁闄勮繎鐨勫叾瀹冪帺瀹.\n/nick: 鏀瑰彉鑷繁鐨勬樀绉,鎴栬呭埆浜虹殑鏄电О<绠$悊鍛>.\n/none: Unbind a bound tool from your current item\n/nuke: 鍙戝皠鏍告鍣.\n/op: Gives the specified player operator status\n/packet: Add or remove a simple packet listener.\n/pardon-ip: Allows the specified IP address to use this server\n/pay: 浠庝綘鐨勮处鎴蜂腑杞处浠樿垂缁欐煇鐜╁.\n/petadmin: Set the Exp or Name of a MyPet\n/petbeacon: Beacon!\n/petbehavior: Switch the behavior mode of your MyPet.\n/petcall: Call your MyPet.\n/petchooseskilltree: Chooses a skilltree.\n/petinfo: Shows HP and Exp of your MyPet\n/petinventory: Open the inventory of your MyPet.\n/petname: Set the name of your MyPet\n/petpickup: Toogles pickup of your MyPet.\n/petrelease: Release your MyPet.\n/petsendaway: Send your MyPet away.\n/petskill: Shows the skill-levels of a online MyPet\n/petskilltree: Shows a fully configured skilltree\n/petstop: your MyPet stop attacking.\n/ping: 鍟暘鍟暘鍟暘鍟暘鍟!\n/pistonjump: To see the PistonJump help.\n/plugin: Load, unload or reload the specified plugins.\n/plugins: Gets a list of plugins running on the server\n/powertool: 缁欐墜涓墿鍝佹寚瀹氫竴涓懡浠.\n/powertooltoggle: 寮鍚垨鍏抽棴褰撳墠鎵鏈夌殑powertool.\n/protocol: Performs administrative tasks regarding ProtocolLib.\n/ptime: 涓撻棬璋冩暣鏌愮帺瀹跺鎴风鐨勬椂闂. 娣诲姞 @ 鍓嶇紑鏉ヤ慨澶.\n/pumpkins: [size] - Generate pumpkin patches\n/quit: Manually quit your session.\n/r: 蹇熷洖澶嶅埆浜哄彂缁欎綘鐨勪俊鎭(閭欢/绉佷俊).\n/range: [pattern] - Set the brush range\n/rc: Chat in current residence channel.\n/realname: 鏌ョ湅鏌愮帺瀹剁殑鐪熷悕(nick涔嬪墠鐨勫悕瀛).\n/region: Region management commands\n/register: Register your player with the supplied password.\n/reload: Reloads the server configuration and plugins\n/remove: - Remove all entities of a type\n/repair: 淇<鎵嬩腑|鎵鏈>鐨勭墿鍝.\n/repl: - Block replacer tool\n/res: Manage Residences\n/resadmin: Residence admin functions.\n/residence: Manage Residences\n/resload: Load the save file again after you have made modificat\n/resreload: Reload the entire residence plugin.\n/restore: [snapshot] - Restore the selection from a snapshot\n/resworld: Removes every residence in a world.\n/rules: 鏌ョ湅鏈嶅姟鍣ㄨ鍒.\n/save-all: Saves the server to disk\n/save-off: Disables server autosaving\n/save-on: Enables server autosaving\n/say: Broadcasts the given message as the console\n/sbackup: Run the map backup\n/seed: Shows the world seed\n/seen: 鏌ョ湅鏈鍚庝竴浣嶇帺瀹剁櫥鍑虹殑鏃堕棿.\n/sell: 鎶婃墜涓殑鐗╁搧鍑哄敭缁欑郴缁.\n/serverstate: Show the server stats using a command\n/sethome: 鎶婁綘鐨勫璁剧疆鍦ㄨ繖涓綅缃.\n/setjail: 鍦ㄤ綘鎵鍦ㄤ綅缃缃竴涓洃鐙,鍚嶇О鍙 [鐩戠嫳鍚嶇О]\n/setspawn: Set the spawnpoint to your current position.\n/setwarp: 鍒涘缓涓涓柊鐨勫湴鏍.\n/setworth: 璁剧疆鏌愪釜鐗╁搧鐨勪环鍊.\n/sg: Used to reload the plugin. Console use only.\n/shelfit: Lists ShelfIt's commands and uses.\n/showcasestandalone: Access to all ShowCaseStandalone related co\n/signedit: Allows you to edit a sign\n/size: [pattern] - Set the brush size\n/snapshot: Snapshot commands\n/socialspy: 鍒囨崲浣犳槸鍚﹀彲浠ョ湅鍒板叾浠栫帺瀹剁殑绉佽亰鍜岄偖浠.\n/spawn: Teleport to the spawnpoint.\n/spawner: 鏀瑰彉涓涓埛鎬鐨勭被鍨.\n/spawnmob: 鐢熸垚涓涓敓鐗.\n/spawnpoint: Sets a player's spawn point\n/speed: 鏀瑰彉绉诲姩閫熷害.\n/ss: Short-Command for serverstate\n/stop: Stops the server with optional reason\n/stopfire: [] - Disables all fire spread temporarily\n/sudo: 璁╂煇鐜╁寮哄埗鎵ц涓涓懡浠.\n/suicide: 鑷潃.\n/superpickaxe: Select super pickaxe mode\n/tempadd: Creates a temporary permissions copy for that user.\n/tempban: 涓存椂灏佺涓涓帺瀹.\n/tempdel: Remove the temporary permissions copy for player.\n/tempdelall: Remove all overrides made by command /tempadd.\n/templist: List players in overload-permissionss mode made by /t\n/thru: Passthrough walls\n/thunder: 鍏佽/绂佹 鑷劧闆峰嚮.\n/time: 鏄剧ず/鏀瑰彉涓栫晫鐨勬椂闂,榛樿褰撳墠涓栫晫.\n/timeismoney: Give connection time and earned money\n/timeismoney:reload: Give connection time and earned money\n/timings: Records timings for all plugin events\n/togglechop: Toggle ChopTree\n/toggledownfall: Toggles rain on/off on a given world\n/toggleeditwand: Toggle functionality of the edit wand\n/togglejail: 鐩戠/瑙g涓涓帺瀹,骞朵紶閫佷粬鍒扮洃鐙.\n/tool: Select a tool to bind\n/top: 浼犻佸埌浣犳墍绔欏潗鏍囦笂鐨勬渶楂樻柟鍧楀.\n/tp: 寮鸿浼犻佸埌鏌愮帺瀹.\n/tpa: 鍙戦佷竴鏉′紶閫佽姹,璁╀綘浼犻佸埌瀵硅薄鐜╁鐨勫湴鐐.\n/tpaall: 鍙戦佷竴鏉′紶閫佽姹,璁╂墍鏈夌帺瀹堕兘浼犻佸埌浣犺繖閲.\n/tpaccept: 鎺ュ彈浼犻佽姹.\n/tpahere: 鍙戦佷竴鏉′紶閫佽姹,璁╁璞$帺瀹朵紶閫佸埌浣犳墍鍦ㄧ殑鍦扮偣.\n/tpall: 寮哄埗鎶婃墍鏈夊湪绾跨帺瀹朵紶閫佸埌鑷繁鐨勪綅缃.\n/tpdeny: 鎷掔粷浼犻佽姹.\n/tphere: 寮哄埗鎶婁竴涓帺瀹朵紶閫佸埌鑷繁鐨勪綅缃.\n/tpo: 寮鸿浼犻佸埌鏌愮帺瀹,鏃犺鎷掔粷浼犻.\n/tpohere: 寮哄埗鎶婁竴涓帺瀹朵紶閫佸埌鑷繁鐨勪綅缃,鏃犺鎷掔粷浼犻.\n/tppos: 鎶婅嚜宸变紶閫佸埌鏌愪釜鍧愭爣.\n/tptoggle: 鎷掔粷鎵鏈変紶閫.\n/tree: [type] - Tree generator tool\n/unban: 瑙i櫎灏佺鐜╁.\n/unbanip: 瑙i櫎灏佺IP鍦板潃.\n/undisguise: Remove a disguise.\n/unlimited: 鍏佽鏌愮帺瀹舵棤闄愭斁缃煇鏂瑰潡.\n/unstuck: Escape from being stuck inside a block\n/up: - Go upwards some distance\n/vanish: 杩涘叆闅愯韩妯″紡,鍏朵粬鐜╁灏嗘棤娉曠湅鍒颁綘.\n/vault-convert: Converts all data in economy1 and dumps it into\n/vault-info: Displays information about Vault\n/version: Gets the version of this server including any plugins\n/warp: 鍒楀嚭鎵鏈夌殑鍦版爣,鎴栦紶閫佸埌璇ュ湴鏍.\n/we: WorldEdit commands\n/weather: 璁剧疆鎵鍦ㄤ笘鐣岀殑澶╂皵.\n/whitelist: Prevents the specified player from using this server/whois: 鍦ㄦ樀绉板悗闈㈡樉绀虹湡鍚,骞跺垪鍑虹帺瀹朵俊鎭.\n/workbench: 闅忔椂闅忓湴寮鍚竴涓伐浣滃彴\n/world: 鍦ㄥ悇涓笘鐣岄棿杞崲.\n/worldguard: WorldGuard commands\n/worth: 鏌ョ湅鏌愮墿鍝佺殑浠峰."); + jScrollPane1.setViewportView(jTextArea1); + + javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane()); + getContentPane().setLayout(layout); + layout.setHorizontalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 400, Short.MAX_VALUE) + ); + layout.setVerticalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 300, Short.MAX_VALUE) + ); + + pack(); + }// //GEN-END:initComponents + + // Variables declaration - do not modify//GEN-BEGIN:variables + private javax.swing.JScrollPane jScrollPane1; + private javax.swing.JTextArea jTextArea1; + // End of variables declaration//GEN-END:variables +} diff --git a/HMCSM/src/main/java/org/jackhuang/hellominecraft/svrmgr/views/InputDialog.form b/HMCSM/src/main/java/org/jackhuang/hellominecraft/svrmgr/views/InputDialog.form new file mode 100644 index 000000000..bdd51861b --- /dev/null +++ b/HMCSM/src/main/java/org/jackhuang/hellominecraft/svrmgr/views/InputDialog.form @@ -0,0 +1,147 @@ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/HMCSM/src/main/java/org/jackhuang/hellominecraft/svrmgr/views/InputDialog.java b/HMCSM/src/main/java/org/jackhuang/hellominecraft/svrmgr/views/InputDialog.java new file mode 100644 index 000000000..c3b77138f --- /dev/null +++ b/HMCSM/src/main/java/org/jackhuang/hellominecraft/svrmgr/views/InputDialog.java @@ -0,0 +1,234 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package org.jackhuang.hellominecraft.svrmgr.views; + +import java.awt.Dimension; +import java.awt.Toolkit; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.util.ArrayList; +import javax.swing.GroupLayout; +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.JTextField; + +/** + * + * @author hyh + */ +public class InputDialog extends javax.swing.JDialog { + + ArrayList textFields; + ArrayList panels; + public String[] result; + + /** + * Creates new form InputDialog + */ + public InputDialog(java.awt.Frame parent, boolean modal, String[] messages) { + super(parent, modal); + setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE); + + textFields = new ArrayList(); + panels = new ArrayList(); + jButton1 = new javax.swing.JButton(); + jButton1.setText("纭"); + jButton1.addActionListener(new ActionListener() { + + @Override + public void actionPerformed(ActionEvent e) { + result = new String[textFields.size()]; + for(int i = 0; i < textFields.size(); i++) + result[i] = textFields.get(i).getText(); + InputDialog.this.dispose(); + } + }); + for(String s : messages) { + makeNewField(s); + } + makeLayout(); + Dimension scrSize = Toolkit.getDefaultToolkit().getScreenSize(); + setLocation((scrSize.width - this.getWidth()) / 2, + (scrSize.height - this.getHeight()) / 2); + } + + void makeNewField(String message) { + JLabel label = new JLabel(); + label.setText(message); + JTextField textField = new JTextField(); + textField.setText(""); + JPanel panel = new JPanel(); + + javax.swing.GroupLayout jPanelLayout = new javax.swing.GroupLayout(panel); + panel.setLayout(jPanelLayout); + jPanelLayout.setHorizontalGroup( + jPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jPanelLayout.createSequentialGroup() + .addContainerGap() + .addGroup(jPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jPanelLayout.createSequentialGroup() + .addComponent(label) + .addGap(0, 0, Short.MAX_VALUE)) + .addComponent(textField)) + .addContainerGap()) + ); + jPanelLayout.setVerticalGroup( + jPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jPanelLayout.createSequentialGroup() + .addContainerGap() + .addComponent(label) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(textField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addContainerGap(GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) + ); + textFields.add(textField); + panels.add(panel); + } + + void makeLayout() { + javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane()); + getContentPane().setLayout(layout); + GroupLayout.ParallelGroup g = layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING); + for(JPanel p : panels) + g.addComponent(p, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE); + g.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup() + .addGap(0, 0, Short.MAX_VALUE) + .addComponent(jButton1)); + layout.setHorizontalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(layout.createSequentialGroup() + .addContainerGap() + .addGroup(g) + .addContainerGap()) + ); + GroupLayout.SequentialGroup g2 = layout.createSequentialGroup() + .addContainerGap(); + for(JPanel p : panels) + g2 = g2.addComponent(p, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED); + g2 = g2.addComponent(jButton1) + .addContainerGap(); + layout.setVerticalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(g2) + ); + + pack(); + } + + /** + * 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") + // //GEN-BEGIN:initComponents + private void initComponents() { + + jPanel1 = new javax.swing.JPanel(); + jLabel1 = new javax.swing.JLabel(); + jTextField1 = new javax.swing.JTextField(); + jPanel2 = new javax.swing.JPanel(); + jLabel2 = new javax.swing.JLabel(); + jTextField2 = new javax.swing.JTextField(); + jButton1 = new javax.swing.JButton(); + + setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE); + + jLabel1.setText("jLabel1"); + + jTextField1.setText("jTextField1"); + + javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1); + jPanel1.setLayout(jPanel1Layout); + jPanel1Layout.setHorizontalGroup( + jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jPanel1Layout.createSequentialGroup() + .addContainerGap() + .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jPanel1Layout.createSequentialGroup() + .addComponent(jLabel1) + .addGap(0, 0, Short.MAX_VALUE)) + .addComponent(jTextField1)) + .addContainerGap()) + ); + jPanel1Layout.setVerticalGroup( + jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jPanel1Layout.createSequentialGroup() + .addContainerGap() + .addComponent(jLabel1) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(jTextField1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) + ); + + jLabel2.setText("jLabel1"); + + jTextField2.setText("jTextField1"); + + javax.swing.GroupLayout jPanel2Layout = new javax.swing.GroupLayout(jPanel2); + jPanel2.setLayout(jPanel2Layout); + jPanel2Layout.setHorizontalGroup( + jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jPanel2Layout.createSequentialGroup() + .addContainerGap() + .addGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jPanel2Layout.createSequentialGroup() + .addComponent(jLabel2) + .addGap(0, 0, Short.MAX_VALUE)) + .addComponent(jTextField2, javax.swing.GroupLayout.DEFAULT_SIZE, 360, Short.MAX_VALUE)) + .addContainerGap()) + ); + jPanel2Layout.setVerticalGroup( + jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jPanel2Layout.createSequentialGroup() + .addContainerGap() + .addComponent(jLabel2) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(jTextField2, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) + ); + + jButton1.setText("jButton1"); + + 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) + .addComponent(jPanel1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(jPanel2, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup() + .addGap(0, 0, Short.MAX_VALUE) + .addComponent(jButton1))) + .addContainerGap()) + ); + layout.setVerticalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(layout.createSequentialGroup() + .addContainerGap() + .addComponent(jPanel1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(jPanel2, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 107, Short.MAX_VALUE) + .addComponent(jButton1) + .addContainerGap()) + ); + + pack(); + }// //GEN-END:initComponents + + // Variables declaration - do not modify//GEN-BEGIN:variables + private javax.swing.JButton jButton1; + private javax.swing.JLabel jLabel1; + private javax.swing.JLabel jLabel2; + private javax.swing.JPanel jPanel1; + private javax.swing.JPanel jPanel2; + private javax.swing.JTextField jTextField1; + private javax.swing.JTextField jTextField2; + // End of variables declaration//GEN-END:variables +} diff --git a/HMCSM/src/main/java/org/jackhuang/hellominecraft/svrmgr/views/MainWindow.form b/HMCSM/src/main/java/org/jackhuang/hellominecraft/svrmgr/views/MainWindow.form new file mode 100644 index 000000000..6e0ccc789 --- /dev/null +++ b/HMCSM/src/main/java/org/jackhuang/hellominecraft/svrmgr/views/MainWindow.form @@ -0,0 +1,3484 @@ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + + + + <Editor/> + <Renderer/> + </Column> + <Column maxWidth="-1" minWidth="-1" prefWidth="-1" resizable="true"> + <Title/> + <Editor/> + <Renderer/> + </Column> + <Column maxWidth="-1" minWidth="-1" prefWidth="-1" resizable="true"> + <Title/> + <Editor/> + <Renderer/> + </Column> + <Column maxWidth="-1" minWidth="-1" prefWidth="-1" resizable="true"> + <Title/> + <Editor/> + <Renderer/> + </Column> + <Column maxWidth="-1" minWidth="-1" prefWidth="-1" resizable="true"> + <Title/> + <Editor/> + <Renderer/> + </Column> + <Column maxWidth="-1" minWidth="-1" prefWidth="-1" resizable="true"> + <Title/> + <Editor/> + <Renderer/> + </Column> + </TableColumnModel> + </Property> + <Property name="tableHeader" type="javax.swing.table.JTableHeader" editor="org.netbeans.modules.form.editors2.JTableHeaderEditor"> + <TableHeader reorderingAllowed="true" resizingAllowed="true"/> + </Property> + </Properties> + </Component> + </SubComponents> + </Container> + <Component class="javax.swing.JButton" name="btnManagePlugins"> + <Properties> + <Property name="text" type="java.lang.String" value="管理"/> + </Properties> + <Events> + <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="btnManagePluginsActionPerformed"/> + </Events> + <AuxValues> + <AuxValue name="JavaCodeGenerator_CreateCodeCustom" type="java.lang.String" value="new ConstomButton()"/> + </AuxValues> + </Component> + <Component class="javax.swing.JButton" name="btnAddPlugins"> + <Properties> + <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor"> + <ResourceString bundle="org/jackhuang/hellominecraftlauncher/VersionSettingsWindow.properties" key="增加" replaceFormat="java.util.ResourceBundle.getBundle("{bundleNameSlashes}").getString("{key}")"/> + </Property> + </Properties> + <Events> + <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="btnAddPluginsActionPerformed"/> + </Events> + <AuxValues> + <AuxValue name="JavaCodeGenerator_CreateCodeCustom" type="java.lang.String" value="new ConstomButton()"/> + </AuxValues> + </Component> + <Component class="javax.swing.JButton" name="btnDeletePlugins"> + <Properties> + <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor"> + <ResourceString bundle="org/jackhuang/hellominecraftlauncher/VersionSettingsWindow.properties" key="删除" replaceFormat="java.util.ResourceBundle.getBundle("{bundleNameSlashes}").getString("{key}")"/> + </Property> + </Properties> + <Events> + <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="btnDeletePluginsActionPerformed"/> + </Events> + <AuxValues> + <AuxValue name="JavaCodeGenerator_CreateCodeCustom" type="java.lang.String" value="new ConstomButton()"/> + </AuxValues> + </Component> + <Component class="javax.swing.JButton" name="btnSavePlugins"> + <Properties> + <Property name="text" type="java.lang.String" value="保存"/> + </Properties> + <Events> + <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="btnSavePluginsActionPerformed"/> + </Events> + <AuxValues> + <AuxValue name="JavaCodeGenerator_CreateCodeCustom" type="java.lang.String" value="new ConstomButton()"/> + </AuxValues> + </Component> + </SubComponents> + </Container> + </SubComponents> + </Container> + </SubComponents> + </Container> + <Container class="javax.swing.JPanel" name="jPanel13"> + <Constraints> + <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.support.JTabbedPaneSupportLayout" value="org.netbeans.modules.form.compat2.layouts.support.JTabbedPaneSupportLayout$JTabbedPaneConstraintsDescription"> + <JTabbedPaneConstraints tabName="计划任务"> + <Property name="tabTitle" type="java.lang.String" value="计划任务"/> + </JTabbedPaneConstraints> + </Constraint> + </Constraints> + + <Layout> + <DimensionLayout dim="0"> + <Group type="103" groupAlignment="0" attributes="0"> + <Component id="jPanel14" max="32767" attributes="0"/> + <Component id="jScrollPane9" alignment="0" max="32767" attributes="0"/> + </Group> + </DimensionLayout> + <DimensionLayout dim="1"> + <Group type="103" groupAlignment="0" attributes="0"> + <Group type="102" alignment="1" attributes="0"> + <Component id="jScrollPane9" pref="356" max="32767" attributes="0"/> + <EmptySpace max="-2" attributes="0"/> + <Component id="jPanel14" min="-2" max="-2" attributes="0"/> + </Group> + </Group> + </DimensionLayout> + </Layout> + <SubComponents> + <Container class="javax.swing.JPanel" name="jPanel14"> + + <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"> + <Group type="103" groupAlignment="0" attributes="0"> + <Component id="cboTimerTask" alignment="0" min="-2" pref="95" max="-2" attributes="0"/> + <Component id="jLabel21" alignment="0" min="-2" max="-2" attributes="0"/> + </Group> + <EmptySpace max="-2" attributes="0"/> + <Group type="103" groupAlignment="0" attributes="0"> + <Component id="jLabel28" min="-2" max="-2" attributes="0"/> + <Component id="cboTimeType" min="-2" max="-2" attributes="0"/> + </Group> + <EmptySpace max="32767" attributes="0"/> + <Group type="103" groupAlignment="0" attributes="0"> + <Component id="txtTimerTaskPeriod" alignment="1" min="-2" pref="96" max="-2" attributes="0"/> + <Component id="jLabel22" alignment="1" min="-2" max="-2" attributes="0"/> + </Group> + </Group> + <Component id="jLabel13" min="-2" max="-2" attributes="0"/> + <Component id="txtTimerTaskContent" alignment="0" min="-2" pref="197" max="-2" attributes="0"/> + </Group> + <Group type="103" groupAlignment="0" attributes="0"> + <Group type="102" attributes="0"> + <EmptySpace min="-2" pref="73" max="-2" attributes="0"/> + <Component id="btnNewTask" min="-2" max="-2" attributes="0"/> + </Group> + <Group type="102" alignment="1" attributes="0"> + <EmptySpace max="-2" attributes="0"/> + <Component id="btnDelSelectedSchedule" 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="0" attributes="0"> + <Group type="102" alignment="0" attributes="0"> + <Group type="103" groupAlignment="3" attributes="0"> + <Component id="jLabel21" alignment="3" min="-2" max="-2" attributes="0"/> + <Component id="jLabel22" alignment="3" min="-2" max="-2" attributes="0"/> + <Component id="jLabel28" alignment="3" min="-2" max="-2" attributes="0"/> + </Group> + <EmptySpace max="-2" attributes="0"/> + <Group type="103" groupAlignment="3" attributes="0"> + <Component id="cboTimerTask" alignment="3" min="-2" max="-2" attributes="0"/> + <Component id="txtTimerTaskPeriod" alignment="3" min="-2" max="-2" attributes="0"/> + <Component id="cboTimeType" alignment="3" min="-2" max="-2" attributes="0"/> + </Group> + <EmptySpace max="-2" attributes="0"/> + <Component id="jLabel13" min="-2" max="-2" attributes="0"/> + <EmptySpace max="-2" attributes="0"/> + <Component id="txtTimerTaskContent" min="-2" max="-2" attributes="0"/> + </Group> + <Group type="102" alignment="0" attributes="0"> + <Component id="btnNewTask" min="-2" max="-2" attributes="0"/> + <EmptySpace max="-2" attributes="0"/> + <Component id="btnDelSelectedSchedule" min="-2" max="-2" attributes="0"/> + </Group> + </Group> + <EmptySpace max="32767" attributes="0"/> + </Group> + </Group> + </DimensionLayout> + </Layout> + <SubComponents> + <Component class="javax.swing.JLabel" name="jLabel21"> + <Properties> + <Property name="text" type="java.lang.String" value="新建计划任务"/> + </Properties> + </Component> + <Component class="javax.swing.JComboBox" name="cboTimerTask"> + <Properties> + <Property name="model" type="javax.swing.ComboBoxModel" editor="org.netbeans.modules.form.editors2.ComboBoxModelEditor"> + <StringArray count="5"> + <StringItem index="0" value="自动保存"/> + <StringItem index="1" value="自动重启"/> + <StringItem index="2" value="自动备份"/> + <StringItem index="3" value="自动广播"/> + <StringItem index="4" value="自动发送命令"/> + </StringArray> + </Property> + </Properties> + </Component> + <Component class="javax.swing.JTextField" name="txtTimerTaskPeriod"> + </Component> + <Component class="javax.swing.JLabel" name="jLabel22"> + <Properties> + <Property name="text" type="java.lang.String" value="间隔时间(分钟)"/> + </Properties> + </Component> + <Component class="javax.swing.JButton" name="btnNewTask"> + <Properties> + <Property name="text" type="java.lang.String" value="新建计划任务"/> + </Properties> + <Events> + <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="btnNewTaskActionPerformed"/> + </Events> + <AuxValues> + <AuxValue name="JavaCodeGenerator_CreateCodeCustom" type="java.lang.String" value="new ConstomButton()"/> + </AuxValues> + </Component> + <Component class="javax.swing.JLabel" name="jLabel13"> + <Properties> + <Property name="text" type="java.lang.String" value="内容"/> + </Properties> + </Component> + <Component class="javax.swing.JTextField" name="txtTimerTaskContent"> + </Component> + <Component class="javax.swing.JLabel" name="jLabel28"> + <Properties> + <Property name="text" type="java.lang.String" value="时间类型"/> + </Properties> + </Component> + <Component class="javax.swing.JComboBox" name="cboTimeType"> + <Properties> + <Property name="model" type="javax.swing.ComboBoxModel" editor="org.netbeans.modules.form.editors2.ComboBoxModelEditor"> + <StringArray count="5"> + <StringItem index="0" value="每x分钟"/> + <StringItem index="1" value="整点过去x分钟"/> + <StringItem index="2" value="服务器启动"/> + <StringItem index="3" value="服务器关闭"/> + <StringItem index="4" value="服务器崩溃"/> + </StringArray> + </Property> + </Properties> + </Component> + <Component class="javax.swing.JButton" name="btnDelSelectedSchedule"> + <Properties> + <Property name="text" type="java.lang.String" value="删除选中"/> + </Properties> + <Events> + <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="btnDelSelectedScheduleActionPerformed"/> + </Events> + <AuxValues> + <AuxValue name="JavaCodeGenerator_CreateCodeCustom" type="java.lang.String" value="new ConstomButton()"/> + </AuxValues> + </Component> + </SubComponents> + </Container> + <Container class="javax.swing.JScrollPane" name="jScrollPane9"> + <AuxValues> + <AuxValue name="autoScrollPane" type="java.lang.Boolean" value="true"/> + </AuxValues> + + <Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/> + <SubComponents> + <Component class="javax.swing.JTable" name="lstSchedules"> + <Properties> + <Property name="model" type="javax.swing.table.TableModel" editor="org.netbeans.modules.form.editors2.TableModelEditor"> + <Table columnCount="4" rowCount="0"> + <Column editable="true" title="类型" type="java.lang.String"/> + <Column editable="false" title="时间类型" type="java.lang.String"/> + <Column editable="false" title="间隔时间(分钟)" type="java.lang.Double"/> + <Column editable="true" title="内容" type="java.lang.String"/> + </Table> + </Property> + <Property name="columnModel" type="javax.swing.table.TableColumnModel" editor="org.netbeans.modules.form.editors2.TableColumnModelEditor"> + <TableColumnModel selectionModel="0"> + <Column maxWidth="-1" minWidth="-1" prefWidth="-1" resizable="true"> + <Title/> + <Editor/> + <Renderer/> + </Column> + <Column maxWidth="-1" minWidth="-1" prefWidth="-1" resizable="true"> + <Title/> + <Editor/> + <Renderer/> + </Column> + <Column maxWidth="-1" minWidth="-1" prefWidth="-1" resizable="true"> + <Title/> + <Editor/> + <Renderer/> + </Column> + <Column maxWidth="-1" minWidth="-1" prefWidth="-1" resizable="true"> + <Title/> + <Editor/> + <Renderer/> + </Column> + </TableColumnModel> + </Property> + <Property name="tableHeader" type="javax.swing.table.JTableHeader" editor="org.netbeans.modules.form.editors2.JTableHeaderEditor"> + <TableHeader reorderingAllowed="true" resizingAllowed="true"/> + </Property> + </Properties> + </Component> + </SubComponents> + </Container> + </SubComponents> + </Container> + <Container class="javax.swing.JPanel" name="jPanel15"> + <Constraints> + <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.support.JTabbedPaneSupportLayout" value="org.netbeans.modules.form.compat2.layouts.support.JTabbedPaneSupportLayout$JTabbedPaneConstraintsDescription"> + <JTabbedPaneConstraints tabName="备份"> + <Property name="tabTitle" type="java.lang.String" value="备份"/> + </JTabbedPaneConstraints> + </Constraint> + </Constraints> + + <Layout> + <DimensionLayout dim="0"> + <Group type="103" groupAlignment="0" attributes="0"> + <Group type="102" alignment="0" attributes="0"> + <Component id="jPanel16" min="-2" max="-2" attributes="0"/> + <EmptySpace max="-2" attributes="0"/> + <Component id="jScrollPane11" pref="391" max="32767" attributes="0"/> + <EmptySpace max="-2" attributes="0"/> + </Group> + </Group> + </DimensionLayout> + <DimensionLayout dim="1"> + <Group type="103" groupAlignment="0" attributes="0"> + <Component id="jPanel16" max="32767" attributes="0"/> + <Group type="102" alignment="1" attributes="0"> + <EmptySpace max="-2" attributes="0"/> + <Component id="jScrollPane11" pref="0" max="32767" attributes="0"/> + <EmptySpace max="-2" attributes="0"/> + </Group> + </Group> + </DimensionLayout> + </Layout> + <SubComponents> + <Container class="javax.swing.JPanel" name="jPanel16"> + + <Layout> + <DimensionLayout dim="0"> + <Group type="103" groupAlignment="0" attributes="0"> + <Component id="jPanel17" alignment="0" max="32767" attributes="0"/> + <Group type="102" attributes="0"> + <EmptySpace max="-2" attributes="0"/> + <Group type="103" groupAlignment="0" attributes="0"> + <Component id="jButton1" alignment="0" min="-2" max="-2" attributes="0"/> + <Component id="btnDeleteBackup" alignment="0" min="-2" max="-2" attributes="0"/> + <Component id="btnRestoreBackup" alignment="0" min="-2" max="-2" attributes="0"/> + </Group> + <EmptySpace max="32767" attributes="0"/> + </Group> + </Group> + </DimensionLayout> + <DimensionLayout dim="1"> + <Group type="103" groupAlignment="0" attributes="0"> + <Group type="102" alignment="0" attributes="0"> + <Component id="jPanel17" min="-2" max="-2" attributes="0"/> + <EmptySpace pref="272" max="32767" attributes="0"/> + <Component id="btnRestoreBackup" min="-2" max="-2" attributes="0"/> + <EmptySpace max="-2" attributes="0"/> + <Component id="btnDeleteBackup" min="-2" max="-2" attributes="0"/> + <EmptySpace max="-2" attributes="0"/> + <Component id="jButton1" min="-2" max="-2" attributes="0"/> + <EmptySpace max="-2" attributes="0"/> + </Group> + </Group> + </DimensionLayout> + </Layout> + <SubComponents> + <Container class="javax.swing.JPanel" name="jPanel17"> + + <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="jLabel23" min="-2" max="-2" attributes="0"/> + <EmptySpace min="0" pref="0" max="32767" attributes="0"/> + </Group> + <Component id="cboBackupTypes" max="32767" attributes="0"/> + <Group type="102" alignment="1" attributes="0"> + <EmptySpace min="0" pref="0" max="32767" attributes="0"/> + <Component id="btnBackup" 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"/> + <Component id="jLabel23" min="-2" max="-2" attributes="0"/> + <EmptySpace max="-2" attributes="0"/> + <Component id="cboBackupTypes" min="-2" max="-2" attributes="0"/> + <EmptySpace max="32767" attributes="0"/> + <Component id="btnBackup" min="-2" max="-2" attributes="0"/> + <EmptySpace max="-2" attributes="0"/> + </Group> + </Group> + </DimensionLayout> + </Layout> + <SubComponents> + <Component class="javax.swing.JLabel" name="jLabel23"> + <Properties> + <Property name="text" type="java.lang.String" value="新建备份"/> + </Properties> + </Component> + <Component class="javax.swing.JComboBox" name="cboBackupTypes"> + <Properties> + <Property name="model" type="javax.swing.ComboBoxModel" editor="org.netbeans.modules.form.editors2.ComboBoxModelEditor"> + <StringArray count="2"> + <StringItem index="0" value="地图备份"/> + <StringItem index="1" value="插件备份"/> + </StringArray> + </Property> + </Properties> + </Component> + <Component class="javax.swing.JButton" name="btnBackup"> + <Properties> + <Property name="text" type="java.lang.String" value="备份"/> + </Properties> + <Events> + <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="btnBackupActionPerformed"/> + </Events> + <AuxValues> + <AuxValue name="JavaCodeGenerator_CreateCodeCustom" type="java.lang.String" value="new ConstomButton()"/> + </AuxValues> + </Component> + </SubComponents> + </Container> + <Component class="javax.swing.JButton" name="jButton1"> + <Properties> + <Property name="text" type="java.lang.String" value="刷新备份列表"/> + </Properties> + <Events> + <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="jButton1ActionPerformed"/> + </Events> + <AuxValues> + <AuxValue name="JavaCodeGenerator_CreateCodeCustom" type="java.lang.String" value="new ConstomButton()"/> + </AuxValues> + </Component> + <Component class="javax.swing.JButton" name="btnDeleteBackup"> + <Properties> + <Property name="text" type="java.lang.String" value="删除选中备份"/> + </Properties> + <Events> + <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="btnDeleteBackupActionPerformed"/> + </Events> + <AuxValues> + <AuxValue name="JavaCodeGenerator_CreateCodeCustom" type="java.lang.String" value="new ConstomButton()"/> + </AuxValues> + </Component> + <Component class="javax.swing.JButton" name="btnRestoreBackup"> + <Properties> + <Property name="text" type="java.lang.String" value="恢复选中备份"/> + </Properties> + <Events> + <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="btnRestoreBackupActionPerformed"/> + </Events> + <AuxValues> + <AuxValue name="JavaCodeGenerator_CreateCodeCustom" type="java.lang.String" value="new ConstomButton()"/> + </AuxValues> + </Component> + </SubComponents> + </Container> + <Container class="javax.swing.JScrollPane" name="jScrollPane11"> + <AuxValues> + <AuxValue name="autoScrollPane" type="java.lang.Boolean" value="true"/> + </AuxValues> + + <Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/> + <SubComponents> + <Component class="javax.swing.JTable" name="lstBackups"> + <Properties> + <Property name="model" type="javax.swing.table.TableModel" editor="org.netbeans.modules.form.editors2.TableModelEditor"> + <Table columnCount="3" rowCount="0"> + <Column editable="true" title="类型" type="java.lang.String"/> + <Column editable="true" title="时间" type="java.lang.String"/> + <Column editable="true" title="名称" type="java.lang.String"/> + </Table> + </Property> + <Property name="columnModel" type="javax.swing.table.TableColumnModel" editor="org.netbeans.modules.form.editors2.TableColumnModelEditor"> + <TableColumnModel selectionModel="0"> + <Column maxWidth="-1" minWidth="-1" prefWidth="-1" resizable="true"> + <Title/> + <Editor/> + <Renderer/> + </Column> + <Column maxWidth="-1" minWidth="-1" prefWidth="-1" resizable="true"> + <Title/> + <Editor/> + <Renderer/> + </Column> + <Column maxWidth="-1" minWidth="-1" prefWidth="-1" resizable="true"> + <Title/> + <Editor/> + <Renderer/> + </Column> + </TableColumnModel> + </Property> + <Property name="tableHeader" type="javax.swing.table.JTableHeader" editor="org.netbeans.modules.form.editors2.JTableHeaderEditor"> + <TableHeader reorderingAllowed="true" resizingAllowed="true"/> + </Property> + </Properties> + </Component> + </SubComponents> + </Container> + </SubComponents> + </Container> + <Container class="javax.swing.JPanel" name="jPanel18"> + <Constraints> + <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.support.JTabbedPaneSupportLayout" value="org.netbeans.modules.form.compat2.layouts.support.JTabbedPaneSupportLayout$JTabbedPaneConstraintsDescription"> + <JTabbedPaneConstraints tabName="地图管理"> + <Property name="tabTitle" type="java.lang.String" value="地图管理"/> + </JTabbedPaneConstraints> + </Constraint> + </Constraints> + + <Layout> + <DimensionLayout dim="0"> + <Group type="103" groupAlignment="0" attributes="0"> + <Group type="102" attributes="0"> + <EmptySpace max="-2" attributes="0"/> + <Group type="103" groupAlignment="0" attributes="0"> + <Component id="jScrollPane10" alignment="0" pref="521" max="32767" attributes="0"/> + <Group type="102" alignment="0" attributes="0"> + <Component id="btnRefreshWorlds" min="-2" max="-2" attributes="0"/> + <EmptySpace max="32767" attributes="0"/> + <Component id="btnSaveWorld" 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"/> + <Component id="jScrollPane10" pref="431" max="32767" attributes="0"/> + <EmptySpace max="-2" attributes="0"/> + <Group type="103" groupAlignment="3" attributes="0"> + <Component id="btnRefreshWorlds" alignment="3" min="-2" max="-2" attributes="0"/> + <Component id="btnSaveWorld" alignment="3" min="-2" max="-2" attributes="0"/> + </Group> + <EmptySpace max="-2" attributes="0"/> + </Group> + </Group> + </DimensionLayout> + </Layout> + <SubComponents> + <Container class="javax.swing.JScrollPane" name="jScrollPane10"> + <AuxValues> + <AuxValue name="autoScrollPane" type="java.lang.Boolean" value="true"/> + </AuxValues> + + <Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/> + <SubComponents> + <Component class="javax.swing.JTable" name="lstWorlds"> + <Properties> + <Property name="model" type="javax.swing.table.TableModel" editor="org.netbeans.modules.form.editors2.TableModelEditor"> + <Table columnCount="3" rowCount="0"> + <Column editable="true" title="地图名" type="java.lang.String"/> + <Column editable="true" title="路径" type="java.lang.String"/> + <Column editable="true" title="是否允许备份" type="java.lang.Boolean"/> + </Table> + </Property> + <Property name="columnModel" type="javax.swing.table.TableColumnModel" editor="org.netbeans.modules.form.editors2.TableColumnModelEditor"> + <TableColumnModel selectionModel="0"> + <Column maxWidth="-1" minWidth="-1" prefWidth="-1" resizable="true"> + <Title/> + <Editor/> + <Renderer/> + </Column> + <Column maxWidth="-1" minWidth="-1" prefWidth="-1" resizable="true"> + <Title/> + <Editor/> + <Renderer/> + </Column> + <Column maxWidth="-1" minWidth="-1" prefWidth="-1" resizable="true"> + <Title/> + <Editor/> + <Renderer/> + </Column> + </TableColumnModel> + </Property> + <Property name="tableHeader" type="javax.swing.table.JTableHeader" editor="org.netbeans.modules.form.editors2.JTableHeaderEditor"> + <TableHeader reorderingAllowed="true" resizingAllowed="true"/> + </Property> + </Properties> + </Component> + </SubComponents> + </Container> + <Component class="javax.swing.JButton" name="btnRefreshWorlds"> + <Properties> + <Property name="text" type="java.lang.String" value="刷新"/> + </Properties> + <Events> + <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="btnRefreshWorldsActionPerformed"/> + </Events> + <AuxValues> + <AuxValue name="JavaCodeGenerator_CreateCodeCustom" type="java.lang.String" value="new ConstomButton()"/> + </AuxValues> + </Component> + <Component class="javax.swing.JButton" name="btnSaveWorld"> + <Properties> + <Property name="text" type="java.lang.String" value="保存修改"/> + </Properties> + <Events> + <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="btnSaveWorldActionPerformed"/> + </Events> + <AuxValues> + <AuxValue name="JavaCodeGenerator_CreateCodeCustom" type="java.lang.String" value="new ConstomButton()"/> + </AuxValues> + </Component> + </SubComponents> + </Container> + <Container class="javax.swing.JPanel" name="jPanel19"> + <Constraints> + <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.support.JTabbedPaneSupportLayout" value="org.netbeans.modules.form.compat2.layouts.support.JTabbedPaneSupportLayout$JTabbedPaneConstraintsDescription"> + <JTabbedPaneConstraints tabName="下载中心"> + <Property name="tabTitle" type="java.lang.String" value="下载中心"/> + </JTabbedPaneConstraints> + </Constraint> + </Constraints> + + <Layout> + <DimensionLayout dim="0"> + <Group type="103" groupAlignment="0" attributes="0"> + <Component id="jTabbedPane5" alignment="1" max="32767" attributes="0"/> + </Group> + </DimensionLayout> + <DimensionLayout dim="1"> + <Group type="103" groupAlignment="0" attributes="0"> + <Component id="jTabbedPane5" alignment="0" max="32767" attributes="0"/> + </Group> + </DimensionLayout> + </Layout> + <SubComponents> + <Container class="javax.swing.JTabbedPane" name="jTabbedPane5"> + <AccessibilityProperties> + <Property name="AccessibleContext.accessibleName" type="java.lang.String" value="CraftBukkit"/> + </AccessibilityProperties> + + <Layout class="org.netbeans.modules.form.compat2.layouts.support.JTabbedPaneSupportLayout"/> + <SubComponents> + <Container class="javax.swing.JPanel" name="jPanel20"> + <Constraints> + <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.support.JTabbedPaneSupportLayout" value="org.netbeans.modules.form.compat2.layouts.support.JTabbedPaneSupportLayout$JTabbedPaneConstraintsDescription"> + <JTabbedPaneConstraints tabName="CraftBukkit"> + <Property name="tabTitle" type="java.lang.String" value="CraftBukkit"/> + </JTabbedPaneConstraints> + </Constraint> + </Constraints> + + <Layout> + <DimensionLayout dim="0"> + <Group type="103" groupAlignment="0" attributes="0"> + <Group type="102" alignment="0" attributes="0"> + <EmptySpace max="-2" attributes="0"/> + <Group type="103" groupAlignment="0" attributes="0"> + <Group type="102" attributes="0"> + <Component id="jLabel39" min="-2" max="-2" attributes="0"/> + <EmptySpace max="-2" attributes="0"/> + <Component id="cboBukkitType" pref="442" max="32767" attributes="0"/> + </Group> + <Group type="102" attributes="0"> + <Component id="jScrollPane18" pref="450" max="32767" attributes="0"/> + <EmptySpace max="-2" attributes="0"/> + <Group type="103" groupAlignment="0" attributes="0"> + <Component id="btnDownloadCraftbukkit" alignment="1" min="-2" max="-2" attributes="0"/> + <Component id="lstRefreshCraftbukkit" alignment="1" min="-2" max="-2" 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="jLabel39" alignment="3" min="-2" max="-2" attributes="0"/> + <Component id="cboBukkitType" alignment="3" min="-2" max="-2" attributes="0"/> + </Group> + <EmptySpace max="-2" attributes="0"/> + <Group type="103" groupAlignment="0" attributes="0"> + <Group type="102" attributes="0"> + <Component id="btnDownloadCraftbukkit" min="-2" max="-2" attributes="0"/> + <EmptySpace max="-2" attributes="0"/> + <Component id="lstRefreshCraftbukkit" min="-2" max="-2" attributes="0"/> + <EmptySpace min="0" pref="0" max="32767" attributes="0"/> + </Group> + <Component id="jScrollPane18" pref="402" max="32767" attributes="0"/> + </Group> + <EmptySpace max="-2" attributes="0"/> + </Group> + </Group> + </DimensionLayout> + </Layout> + <SubComponents> + <Container class="javax.swing.JScrollPane" name="jScrollPane18"> + <AuxValues> + <AuxValue name="autoScrollPane" type="java.lang.Boolean" value="true"/> + </AuxValues> + + <Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/> + <SubComponents> + <Component class="javax.swing.JTable" name="lstCraftbukkit"> + <Properties> + <Property name="model" type="javax.swing.table.TableModel" editor="org.netbeans.modules.form.editors2.TableModelEditor"> + <Table columnCount="2" rowCount="0"> + <Column editable="true" title="编译号" type="java.lang.String"/> + <Column editable="true" title="版本" type="java.lang.String"/> + </Table> + </Property> + <Property name="columnModel" type="javax.swing.table.TableColumnModel" editor="org.netbeans.modules.form.editors2.TableColumnModelEditor"> + <TableColumnModel selectionModel="0"> + <Column maxWidth="-1" minWidth="-1" prefWidth="-1" resizable="true"> + <Title/> + <Editor/> + <Renderer/> + </Column> + <Column maxWidth="-1" minWidth="-1" prefWidth="-1" resizable="true"> + <Title/> + <Editor/> + <Renderer/> + </Column> + </TableColumnModel> + </Property> + <Property name="selectionModel" type="javax.swing.ListSelectionModel" editor="org.netbeans.modules.form.editors2.JTableSelectionModelEditor"> + <JTableSelectionModel selectionMode="0"/> + </Property> + <Property name="tableHeader" type="javax.swing.table.JTableHeader" editor="org.netbeans.modules.form.editors2.JTableHeaderEditor"> + <TableHeader reorderingAllowed="true" resizingAllowed="true"/> + </Property> + </Properties> + </Component> + </SubComponents> + </Container> + <Component class="javax.swing.JButton" name="btnDownloadCraftbukkit"> + <Properties> + <Property name="text" type="java.lang.String" value="下载"/> + </Properties> + <Events> + <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="btnDownloadCraftbukkitActionPerformed"/> + </Events> + <AuxValues> + <AuxValue name="JavaCodeGenerator_CreateCodeCustom" type="java.lang.String" value="new ConstomButton()"/> + </AuxValues> + </Component> + <Component class="javax.swing.JButton" name="lstRefreshCraftbukkit"> + <Properties> + <Property name="text" type="java.lang.String" value="刷新"/> + <Property name="toolTipText" type="java.lang.String" value=""/> + </Properties> + <Events> + <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="lstRefreshCraftbukkitActionPerformed"/> + </Events> + <AuxValues> + <AuxValue name="JavaCodeGenerator_CreateCodeCustom" type="java.lang.String" value="new ConstomButton()"/> + </AuxValues> + </Component> + <Component class="javax.swing.JComboBox" name="cboBukkitType"> + <Properties> + <Property name="model" type="javax.swing.ComboBoxModel" editor="org.netbeans.modules.form.editors2.ComboBoxModelEditor"> + <StringArray count="3"> + <StringItem index="0" value="稳定版"/> + <StringItem index="1" value="测试版"/> + <StringItem index="2" value="最新开发版"/> + </StringArray> + </Property> + </Properties> + <Events> + <EventHandler event="itemStateChanged" listener="java.awt.event.ItemListener" parameters="java.awt.event.ItemEvent" handler="cboBukkitTypeItemStateChanged"/> + </Events> + </Component> + <Component class="javax.swing.JLabel" name="jLabel39"> + <Properties> + <Property name="text" type="java.lang.String" value="Bukkit类型"/> + </Properties> + </Component> + </SubComponents> + </Container> + <Container class="javax.swing.JPanel" name="jPanel30"> + <Constraints> + <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.support.JTabbedPaneSupportLayout" value="org.netbeans.modules.form.compat2.layouts.support.JTabbedPaneSupportLayout$JTabbedPaneConstraintsDescription"> + <JTabbedPaneConstraints tabName="Cauldron"> + <Property name="tabTitle" type="java.lang.String" value="Cauldron"/> + </JTabbedPaneConstraints> + </Constraint> + </Constraints> + + <Layout> + <DimensionLayout dim="0"> + <Group type="103" groupAlignment="0" attributes="0"> + <Group type="102" attributes="0"> + <EmptySpace max="-2" attributes="0"/> + <Group type="103" groupAlignment="0" attributes="0"> + <Group type="102" alignment="0" attributes="0"> + <Component id="jScrollPane19" pref="450" max="32767" attributes="0"/> + <EmptySpace max="-2" attributes="0"/> + <Group type="103" groupAlignment="0" attributes="0"> + <Group type="103" groupAlignment="0" attributes="0"> + <Component id="lstRefreshMCPC" min="-2" max="-2" attributes="0"/> + <Component id="btnInstallMCPC" alignment="1" min="-2" max="-2" attributes="0"/> + </Group> + <Component id="btnDownloadMCPC" alignment="1" min="-2" max="-2" attributes="0"/> + </Group> + </Group> + <Group type="102" alignment="0" attributes="0"> + <Component id="jLabel38" min="-2" max="-2" attributes="0"/> + <EmptySpace max="-2" attributes="0"/> + <Component id="cboCauldronMinecraft" max="32767" attributes="0"/> + </Group> + </Group> + <EmptySpace max="-2" attributes="0"/> + </Group> + </Group> + </DimensionLayout> + <DimensionLayout dim="1"> + <Group type="103" groupAlignment="0" attributes="0"> + <Group type="102" alignment="1" attributes="0"> + <EmptySpace max="-2" attributes="0"/> + <Group type="103" groupAlignment="3" attributes="0"> + <Component id="jLabel38" alignment="3" min="-2" max="-2" attributes="0"/> + <Component id="cboCauldronMinecraft" alignment="3" min="-2" max="-2" attributes="0"/> + </Group> + <EmptySpace max="-2" attributes="0"/> + <Group type="103" groupAlignment="0" attributes="0"> + <Component id="jScrollPane19" pref="402" max="32767" attributes="0"/> + <Group type="102" attributes="0"> + <Component id="lstRefreshMCPC" min="-2" max="-2" attributes="0"/> + <EmptySpace max="-2" attributes="0"/> + <Component id="btnDownloadMCPC" min="-2" max="-2" attributes="0"/> + <EmptySpace max="-2" attributes="0"/> + <Component id="btnInstallMCPC" min="-2" max="-2" attributes="0"/> + <EmptySpace min="0" pref="0" max="32767" attributes="0"/> + </Group> + </Group> + <EmptySpace max="-2" attributes="0"/> + </Group> + </Group> + </DimensionLayout> + </Layout> + <SubComponents> + <Container class="javax.swing.JScrollPane" name="jScrollPane19"> + <AuxValues> + <AuxValue name="autoScrollPane" type="java.lang.Boolean" value="true"/> + </AuxValues> + + <Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/> + <SubComponents> + <Component class="javax.swing.JTable" name="lstMCPC"> + <Properties> + <Property name="model" type="javax.swing.table.TableModel" editor="org.netbeans.modules.form.editors2.TableModelEditor"> + <Table columnCount="3" rowCount="0"> + <Column editable="false" title="MC版本" type="java.lang.String"/> + <Column editable="false" title="Cauldron版本" type="java.lang.String"/> + <Column editable="false" title="释放时间" type="java.lang.String"/> + </Table> + </Property> + <Property name="columnModel" type="javax.swing.table.TableColumnModel" editor="org.netbeans.modules.form.editors2.TableColumnModelEditor"> + <TableColumnModel selectionModel="0"> + <Column maxWidth="-1" minWidth="-1" prefWidth="-1" resizable="true"> + <Title/> + <Editor/> + <Renderer/> + </Column> + <Column maxWidth="-1" minWidth="-1" prefWidth="-1" resizable="true"> + <Title/> + <Editor/> + <Renderer/> + </Column> + <Column maxWidth="-1" minWidth="-1" prefWidth="-1" resizable="true"> + <Title/> + <Editor/> + <Renderer/> + </Column> + </TableColumnModel> + </Property> + <Property name="selectionModel" type="javax.swing.ListSelectionModel" editor="org.netbeans.modules.form.editors2.JTableSelectionModelEditor"> + <JTableSelectionModel selectionMode="0"/> + </Property> + <Property name="tableHeader" type="javax.swing.table.JTableHeader" editor="org.netbeans.modules.form.editors2.JTableHeaderEditor"> + <TableHeader reorderingAllowed="true" resizingAllowed="true"/> + </Property> + </Properties> + </Component> + </SubComponents> + </Container> + <Component class="javax.swing.JButton" name="btnDownloadMCPC"> + <Properties> + <Property name="label" type="java.lang.String" value="下载"/> + </Properties> + <Events> + <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="btnDownloadMCPCActionPerformed"/> + </Events> + <AuxValues> + <AuxValue name="JavaCodeGenerator_CreateCodeCustom" type="java.lang.String" value="new ConstomButton()"/> + </AuxValues> + </Component> + <Component class="javax.swing.JButton" name="lstRefreshMCPC"> + <Properties> + <Property name="toolTipText" type="java.lang.String" value=""/> + <Property name="label" type="java.lang.String" value="刷新"/> + </Properties> + <Events> + <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="lstRefreshMCPCActionPerformed"/> + </Events> + <AuxValues> + <AuxValue name="JavaCodeGenerator_CreateCodeCustom" type="java.lang.String" value="new ConstomButton()"/> + </AuxValues> + </Component> + <Component class="javax.swing.JLabel" name="jLabel38"> + <Properties> + <Property name="text" type="java.lang.String" value="Minecraft版本"/> + </Properties> + </Component> + <Component class="javax.swing.JComboBox" name="cboCauldronMinecraft"> + <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="cboCauldronMinecraftItemStateChanged"/> + </Events> + </Component> + <Component class="javax.swing.JButton" name="btnInstallMCPC"> + <Properties> + <Property name="text" type="java.lang.String" value="重试"/> + </Properties> + <Events> + <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="btnInstallMCPCActionPerformed"/> + </Events> + <AuxValues> + <AuxValue name="JavaCodeGenerator_CreateCodeCustom" type="java.lang.String" value="new ConstomButton()"/> + </AuxValues> + </Component> + </SubComponents> + </Container> + <Container class="javax.swing.JPanel" name="jPanel21"> + <Constraints> + <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.support.JTabbedPaneSupportLayout" value="org.netbeans.modules.form.compat2.layouts.support.JTabbedPaneSupportLayout$JTabbedPaneConstraintsDescription"> + <JTabbedPaneConstraints tabName="官方服务器"> + <Property name="tabTitle" type="java.lang.String" value="官方服务器"/> + </JTabbedPaneConstraints> + </Constraint> + </Constraints> + + <Layout> + <DimensionLayout dim="0"> + <Group type="103" groupAlignment="0" attributes="0"> + <Group type="102" alignment="0" attributes="0"> + <EmptySpace max="-2" attributes="0"/> + <Component id="jScrollPane12" pref="450" max="32767" attributes="0"/> + <EmptySpace max="-2" attributes="0"/> + <Group type="103" groupAlignment="0" max="-2" attributes="0"> + <Component id="btnRefreshDownloads" max="32767" attributes="0"/> + <Component id="btnMinecraftServerDownload" max="32767" attributes="0"/> + </Group> + <EmptySpace max="-2" attributes="0"/> + </Group> + </Group> + </DimensionLayout> + <DimensionLayout dim="1"> + <Group type="103" groupAlignment="0" attributes="0"> + <Group type="102" alignment="0" attributes="0"> + <EmptySpace max="-2" attributes="0"/> + <Group type="103" groupAlignment="0" attributes="0"> + <Component id="jScrollPane12" pref="435" max="32767" attributes="0"/> + <Group type="102" attributes="0"> + <Component id="btnRefreshDownloads" min="-2" max="-2" attributes="0"/> + <EmptySpace max="-2" attributes="0"/> + <Component id="btnMinecraftServerDownload" min="-2" max="-2" attributes="0"/> + <EmptySpace min="0" pref="0" max="32767" attributes="0"/> + </Group> + </Group> + <EmptySpace max="-2" attributes="0"/> + </Group> + </Group> + </DimensionLayout> + </Layout> + <SubComponents> + <Component class="javax.swing.JButton" name="btnRefreshDownloads"> + <Properties> + <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor"> + <ResourceString bundle="org/jackhuang/hellominecraftlauncher/I18N.properties" key="刷新" replaceFormat="java.util.ResourceBundle.getBundle("{bundleNameSlashes}").getString("{key}")"/> + </Property> + </Properties> + <Events> + <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="btnRefreshDownloadsActionPerformed"/> + </Events> + <AuxValues> + <AuxValue name="JavaCodeGenerator_CreateCodeCustom" type="java.lang.String" value="new ConstomButton()"/> + </AuxValues> + </Component> + <Container class="javax.swing.JScrollPane" name="jScrollPane12"> + <AuxValues> + <AuxValue name="autoScrollPane" type="java.lang.Boolean" value="true"/> + </AuxValues> + + <Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/> + <SubComponents> + <Component class="javax.swing.JTable" name="lstDownloads"> + <Properties> + <Property name="model" type="javax.swing.table.TableModel" editor="org.netbeans.modules.form.editors2.TableModelEditor"> + <Table columnCount="4" rowCount="0"> + <Column editable="false" title="版本" type="java.lang.String"/> + <Column editable="false" title="发布时间" type="java.lang.String"/> + <Column editable="false" title="释放时间" type="java.lang.String"/> + <Column editable="false" title="类型" type="java.lang.String"/> + </Table> + </Property> + <Property name="toolTipText" type="java.lang.String" value=""/> + <Property name="columnModel" type="javax.swing.table.TableColumnModel" editor="org.netbeans.modules.form.editors2.TableColumnModelEditor"> + <TableColumnModel selectionModel="0"> + <Column maxWidth="-1" minWidth="-1" prefWidth="-1" resizable="true"> + <Title/> + <Editor/> + <Renderer/> + </Column> + <Column maxWidth="-1" minWidth="-1" prefWidth="-1" resizable="true"> + <Title/> + <Editor/> + <Renderer/> + </Column> + <Column maxWidth="-1" minWidth="-1" prefWidth="-1" resizable="true"> + <Title/> + <Editor/> + <Renderer/> + </Column> + <Column maxWidth="-1" minWidth="-1" prefWidth="-1" resizable="true"> + <Title/> + <Editor/> + <Renderer/> + </Column> + </TableColumnModel> + </Property> + <Property name="tableHeader" type="javax.swing.table.JTableHeader" editor="org.netbeans.modules.form.editors2.JTableHeaderEditor"> + <TableHeader reorderingAllowed="true" resizingAllowed="true"/> + </Property> + </Properties> + </Component> + </SubComponents> + </Container> + <Component class="javax.swing.JButton" name="btnMinecraftServerDownload"> + <Properties> + <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor"> + <ResourceString bundle="org/jackhuang/hellominecraftlauncher/I18N.properties" key="下载" replaceFormat="java.util.ResourceBundle.getBundle("{bundleNameSlashes}").getString("{key}")"/> + </Property> + </Properties> + <Events> + <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="btnMinecraftServerDownloadActionPerformed"/> + </Events> + <AuxValues> + <AuxValue name="JavaCodeGenerator_CreateCodeCustom" type="java.lang.String" value="new ConstomButton()"/> + </AuxValues> + </Component> + </SubComponents> + </Container> + <Container class="javax.swing.JPanel" name="jPanel23"> + <Constraints> + <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.support.JTabbedPaneSupportLayout" value="org.netbeans.modules.form.compat2.layouts.support.JTabbedPaneSupportLayout$JTabbedPaneConstraintsDescription"> + <JTabbedPaneConstraints tabName="服务器插件"> + <Property name="tabTitle" type="java.lang.String" value="服务器插件"/> + </JTabbedPaneConstraints> + </Constraint> + </Constraints> + + <Layout> + <DimensionLayout dim="0"> + <Group type="103" groupAlignment="0" attributes="0"> + <Group type="102" attributes="0"> + <EmptySpace max="-2" attributes="0"/> + <Group type="103" groupAlignment="0" attributes="0"> + <Component id="jScrollPane15" alignment="0" pref="516" max="32767" attributes="0"/> + <Group type="102" alignment="1" attributes="0"> + <Component id="btnShowPluginInfo" min="-2" max="-2" attributes="0"/> + <EmptySpace max="-2" attributes="0"/> + <Component id="jButton11" min="-2" max="-2" attributes="0"/> + <EmptySpace max="32767" attributes="0"/> + <Component id="jLabel24" min="-2" max="-2" attributes="0"/> + <EmptySpace max="-2" attributes="0"/> + <Component id="cboCategory" 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="1" attributes="0"> + <EmptySpace max="-2" attributes="0"/> + <Group type="103" groupAlignment="3" attributes="0"> + <Component id="cboCategory" alignment="3" min="-2" max="-2" attributes="0"/> + <Component id="jLabel24" alignment="3" min="-2" max="-2" attributes="0"/> + <Component id="btnShowPluginInfo" alignment="3" min="-2" max="-2" attributes="0"/> + <Component id="jButton11" alignment="3" min="-2" max="-2" attributes="0"/> + </Group> + <EmptySpace max="-2" attributes="0"/> + <Component id="jScrollPane15" pref="401" max="32767" attributes="0"/> + <EmptySpace max="-2" attributes="0"/> + </Group> + </Group> + </DimensionLayout> + </Layout> + <SubComponents> + <Container class="javax.swing.JScrollPane" name="jScrollPane15"> + <AuxValues> + <AuxValue name="autoScrollPane" type="java.lang.Boolean" value="true"/> + </AuxValues> + + <Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/> + <SubComponents> + <Component class="javax.swing.JTable" name="lstBukkitPlugins"> + <Properties> + <Property name="model" type="javax.swing.table.TableModel" editor="org.netbeans.modules.form.editors2.TableModelEditor"> + <Table columnCount="4" rowCount="0"> + <Column editable="false" title="名字" type="java.lang.String"/> + <Column editable="false" title="描述" type="java.lang.String"/> + <Column editable="false" title="版本" type="java.lang.String"/> + <Column editable="false" title="Bukkit版本" type="java.lang.String"/> + </Table> + </Property> + <Property name="columnModel" type="javax.swing.table.TableColumnModel" editor="org.netbeans.modules.form.editors2.TableColumnModelEditor"> + <TableColumnModel selectionModel="0"> + <Column maxWidth="-1" minWidth="-1" prefWidth="-1" resizable="true"> + <Title/> + <Editor/> + <Renderer/> + </Column> + <Column maxWidth="-1" minWidth="-1" prefWidth="-1" resizable="true"> + <Title/> + <Editor/> + <Renderer/> + </Column> + <Column maxWidth="-1" minWidth="-1" prefWidth="-1" resizable="true"> + <Title/> + <Editor/> + <Renderer/> + </Column> + <Column maxWidth="-1" minWidth="-1" prefWidth="-1" resizable="true"> + <Title/> + <Editor/> + <Renderer/> + </Column> + </TableColumnModel> + </Property> + <Property name="tableHeader" type="javax.swing.table.JTableHeader" editor="org.netbeans.modules.form.editors2.JTableHeaderEditor"> + <TableHeader reorderingAllowed="true" resizingAllowed="true"/> + </Property> + </Properties> + </Component> + </SubComponents> + </Container> + <Component class="javax.swing.JComboBox" name="cboCategory"> + <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="cboCategoryItemStateChanged"/> + </Events> + </Component> + <Component class="javax.swing.JLabel" name="jLabel24"> + <Properties> + <Property name="text" type="java.lang.String" value="分类"/> + </Properties> + </Component> + <Component class="javax.swing.JButton" name="btnShowPluginInfo"> + <Properties> + <Property name="text" type="java.lang.String" value="选中插件信息"/> + </Properties> + <Events> + <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="btnShowPluginInfoActionPerformed"/> + </Events> + <AuxValues> + <AuxValue name="JavaCodeGenerator_CreateCodeCustom" type="java.lang.String" value="new ConstomButton()"/> + </AuxValues> + </Component> + <Component class="javax.swing.JButton" name="jButton11"> + <Properties> + <Property name="text" type="java.lang.String" value="刷新"/> + </Properties> + <Events> + <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="jButton11ActionPerformed"/> + </Events> + </Component> + </SubComponents> + </Container> + </SubComponents> + </Container> + </SubComponents> + </Container> + <Container class="javax.swing.JPanel" name="jPanel22"> + <Constraints> + <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.support.JTabbedPaneSupportLayout" value="org.netbeans.modules.form.compat2.layouts.support.JTabbedPaneSupportLayout$JTabbedPaneConstraintsDescription"> + <JTabbedPaneConstraints tabName="信息记录"> + <Property name="tabTitle" type="java.lang.String" value="信息记录"/> + </JTabbedPaneConstraints> + </Constraint> + </Constraints> + + <Layout> + <DimensionLayout dim="0"> + <Group type="103" groupAlignment="0" attributes="0"> + <Group type="102" attributes="0"> + <EmptySpace max="-2" attributes="0"/> + <Group type="103" groupAlignment="0" max="-2" attributes="0"> + <Group type="102" attributes="0"> + <Component id="btnRefreshInfos" min="-2" max="-2" attributes="0"/> + <EmptySpace max="32767" attributes="0"/> + <Component id="btnShowInfo" min="-2" max="-2" attributes="0"/> + </Group> + <Component id="jScrollPane13" min="-2" pref="141" max="-2" attributes="0"/> + </Group> + <EmptySpace max="-2" attributes="0"/> + <Component id="jScrollPane14" pref="374" max="32767" attributes="0"/> + <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="0" attributes="0"> + <Component id="jScrollPane14" pref="465" max="32767" attributes="0"/> + <Group type="102" attributes="0"> + <Component id="jScrollPane13" pref="0" max="32767" attributes="0"/> + <EmptySpace max="-2" attributes="0"/> + <Group type="103" groupAlignment="3" attributes="0"> + <Component id="btnRefreshInfos" alignment="3" min="-2" max="-2" attributes="0"/> + <Component id="btnShowInfo" alignment="3" min="-2" max="-2" attributes="0"/> + </Group> + </Group> + </Group> + <EmptySpace max="-2" attributes="0"/> + </Group> + </Group> + </DimensionLayout> + </Layout> + <SubComponents> + <Container class="javax.swing.JScrollPane" name="jScrollPane13"> + <AuxValues> + <AuxValue name="autoScrollPane" type="java.lang.Boolean" value="true"/> + </AuxValues> + + <Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/> + <SubComponents> + <Component class="javax.swing.JTable" name="lstInfos"> + <Properties> + <Property name="model" type="javax.swing.table.TableModel" editor="org.netbeans.modules.form.editors2.TableModelEditor"> + <Table columnCount="2" rowCount="0"> + <Column editable="false" title="名字" type="java.lang.String"/> + <Column editable="false" title="时间" type="java.lang.String"/> + </Table> + </Property> + <Property name="columnModel" type="javax.swing.table.TableColumnModel" editor="org.netbeans.modules.form.editors2.TableColumnModelEditor"> + <TableColumnModel selectionModel="0"> + <Column maxWidth="-1" minWidth="-1" prefWidth="-1" resizable="true"> + <Title/> + <Editor/> + <Renderer/> + </Column> + <Column maxWidth="-1" minWidth="-1" prefWidth="-1" resizable="true"> + <Title/> + <Editor/> + <Renderer/> + </Column> + </TableColumnModel> + </Property> + <Property name="tableHeader" type="javax.swing.table.JTableHeader" editor="org.netbeans.modules.form.editors2.JTableHeaderEditor"> + <TableHeader reorderingAllowed="true" resizingAllowed="true"/> + </Property> + </Properties> + </Component> + </SubComponents> + </Container> + <Component class="javax.swing.JButton" name="btnRefreshInfos"> + <Properties> + <Property name="text" type="java.lang.String" value="刷新"/> + </Properties> + <Events> + <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="btnRefreshInfosActionPerformed"/> + </Events> + <AuxValues> + <AuxValue name="JavaCodeGenerator_CreateCodeCustom" type="java.lang.String" value="new ConstomButton()"/> + </AuxValues> + </Component> + <Container class="javax.swing.JScrollPane" name="jScrollPane14"> + <AuxValues> + <AuxValue name="autoScrollPane" type="java.lang.Boolean" value="true"/> + </AuxValues> + + <Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/> + <SubComponents> + <Component class="javax.swing.JTextArea" name="txtInfo"> + <Properties> + <Property name="editable" type="boolean" value="false"/> + <Property name="columns" type="int" value="20"/> + <Property name="rows" type="int" value="5"/> + </Properties> + </Component> + </SubComponents> + </Container> + <Component class="javax.swing.JButton" name="btnShowInfo"> + <Properties> + <Property name="text" type="java.lang.String" value="显示"/> + </Properties> + <Events> + <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="btnShowInfoActionPerformed"/> + </Events> + <AuxValues> + <AuxValue name="JavaCodeGenerator_CreateCodeCustom" type="java.lang.String" value="new ConstomButton()"/> + </AuxValues> + </Component> + </SubComponents> + </Container> + <Container class="javax.swing.JPanel" name="jPanel26"> + <Constraints> + <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.support.JTabbedPaneSupportLayout" value="org.netbeans.modules.form.compat2.layouts.support.JTabbedPaneSupportLayout$JTabbedPaneConstraintsDescription"> + <JTabbedPaneConstraints tabName="崩溃记录"> + <Property name="tabTitle" type="java.lang.String" value="崩溃记录"/> + </JTabbedPaneConstraints> + </Constraint> + </Constraints> + + <Layout> + <DimensionLayout dim="0"> + <Group type="103" groupAlignment="0" attributes="0"> + <Group type="102" alignment="0" attributes="0"> + <EmptySpace max="-2" attributes="0"/> + <Group type="103" groupAlignment="0" max="-2" attributes="0"> + <Group type="102" attributes="0"> + <Component id="btnRefreshReports" min="-2" max="-2" attributes="0"/> + <EmptySpace min="-2" pref="27" max="-2" attributes="0"/> + <Component id="btnShowReport" min="-2" max="-2" attributes="0"/> + </Group> + <Component id="jScrollPane8" pref="0" max="32767" attributes="0"/> + </Group> + <EmptySpace max="-2" attributes="0"/> + <Component id="jScrollPane17" pref="368" max="32767" attributes="0"/> + <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="0" attributes="0"> + <Component id="jScrollPane17" pref="465" max="32767" attributes="0"/> + <Group type="102" attributes="0"> + <Component id="jScrollPane8" max="32767" attributes="0"/> + <EmptySpace max="-2" attributes="0"/> + <Group type="103" groupAlignment="3" attributes="0"> + <Component id="btnRefreshReports" alignment="3" min="-2" max="-2" attributes="0"/> + <Component id="btnShowReport" alignment="3" min="-2" max="-2" attributes="0"/> + </Group> + </Group> + </Group> + <EmptySpace max="-2" attributes="0"/> + </Group> + </Group> + </DimensionLayout> + </Layout> + <SubComponents> + <Component class="javax.swing.JButton" name="btnRefreshReports"> + <Properties> + <Property name="text" type="java.lang.String" value="刷新"/> + </Properties> + <Events> + <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="btnRefreshReportsActionPerformed"/> + </Events> + <AuxValues> + <AuxValue name="JavaCodeGenerator_CreateCodeCustom" type="java.lang.String" value="new ConstomButton()"/> + </AuxValues> + </Component> + <Container class="javax.swing.JScrollPane" name="jScrollPane17"> + <AuxValues> + <AuxValue name="autoScrollPane" type="java.lang.Boolean" value="true"/> + </AuxValues> + + <Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/> + <SubComponents> + <Component class="javax.swing.JTextArea" name="txtCrashReport"> + <Properties> + <Property name="editable" type="boolean" value="false"/> + <Property name="columns" type="int" value="20"/> + <Property name="rows" type="int" value="5"/> + </Properties> + </Component> + </SubComponents> + </Container> + <Component class="javax.swing.JButton" name="btnShowReport"> + <Properties> + <Property name="text" type="java.lang.String" value="显示"/> + </Properties> + <Events> + <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="btnShowReportActionPerformed"/> + </Events> + <AuxValues> + <AuxValue name="JavaCodeGenerator_CreateCodeCustom" type="java.lang.String" value="new ConstomButton()"/> + </AuxValues> + </Component> + <Container class="javax.swing.JScrollPane" name="jScrollPane8"> + <AuxValues> + <AuxValue name="autoScrollPane" type="java.lang.Boolean" value="true"/> + </AuxValues> + + <Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/> + <SubComponents> + <Component class="javax.swing.JList" name="lstReports"> + <Properties> + <Property name="model" type="javax.swing.ListModel" editor="org.netbeans.modules.form.editors2.ListModelEditor"> + <StringArray count="0"/> + </Property> + </Properties> + </Component> + </SubComponents> + </Container> + </SubComponents> + </Container> + <Container class="javax.swing.JPanel" name="jPanel27"> + <Constraints> + <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.support.JTabbedPaneSupportLayout" value="org.netbeans.modules.form.compat2.layouts.support.JTabbedPaneSupportLayout$JTabbedPaneConstraintsDescription"> + <JTabbedPaneConstraints tabName="在线玩家"> + <Property name="tabTitle" type="java.lang.String" value="在线玩家"/> + </JTabbedPaneConstraints> + </Constraint> + </Constraints> + + <Layout> + <DimensionLayout dim="0"> + <Group type="103" groupAlignment="0" attributes="0"> + <Group type="102" attributes="0"> + <EmptySpace max="-2" attributes="0"/> + <Group type="103" groupAlignment="0" attributes="0"> + <Component id="jScrollPane16" pref="521" max="32767" attributes="0"/> + <Group type="102" attributes="0"> + <Component id="lblPlayers" min="-2" max="-2" attributes="0"/> + <EmptySpace max="32767" attributes="0"/> + <Component id="btnRefreshPlayers" min="-2" max="-2" attributes="0"/> + </Group> + <Group type="102" alignment="0" attributes="0"> + <Component id="jLabel27" min="-2" max="-2" attributes="0"/> + <EmptySpace min="0" pref="0" max="32767" attributes="0"/> + </Group> + </Group> + <EmptySpace max="-2" attributes="0"/> + </Group> + </Group> + </DimensionLayout> + <DimensionLayout dim="1"> + <Group type="103" groupAlignment="0" attributes="0"> + <Group type="102" alignment="0" attributes="0"> + <EmptySpace max="-2" attributes="0"/> + <Group type="103" groupAlignment="3" attributes="0"> + <Component id="lblPlayers" alignment="3" min="-2" max="-2" attributes="0"/> + <Component id="btnRefreshPlayers" alignment="3" min="-2" max="-2" attributes="0"/> + </Group> + <EmptySpace max="-2" attributes="0"/> + <Component id="jScrollPane16" pref="407" max="32767" attributes="0"/> + <EmptySpace max="-2" attributes="0"/> + <Component id="jLabel27" min="-2" max="-2" attributes="0"/> + <EmptySpace max="-2" attributes="0"/> + </Group> + </Group> + </DimensionLayout> + </Layout> + <SubComponents> + <Component class="javax.swing.JLabel" name="lblPlayers"> + <Properties> + <Property name="text" type="java.lang.String" value="在线人数"/> + </Properties> + </Component> + <Component class="javax.swing.JButton" name="btnRefreshPlayers"> + <Properties> + <Property name="text" type="java.lang.String" value="刷新在线人数"/> + </Properties> + <Events> + <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="btnRefreshPlayersActionPerformed"/> + </Events> + <AuxValues> + <AuxValue name="JavaCodeGenerator_CreateCodeCustom" type="java.lang.String" value="new ConstomButton()"/> + </AuxValues> + </Component> + <Container class="javax.swing.JScrollPane" name="jScrollPane16"> + <AuxValues> + <AuxValue name="autoScrollPane" type="java.lang.Boolean" value="true"/> + </AuxValues> + + <Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/> + <SubComponents> + <Component class="javax.swing.JList" name="lstPlayers"> + <Properties> + <Property name="model" type="javax.swing.ListModel" editor="org.netbeans.modules.form.editors2.ListModelEditor"> + <StringArray count="0"/> + </Property> + </Properties> + </Component> + </SubComponents> + </Container> + <Component class="javax.swing.JLabel" name="jLabel27"> + <Properties> + <Property name="text" type="java.lang.String" value="此列表每一分钟刷新一次"/> + </Properties> + </Component> + </SubComponents> + </Container> + <Container class="javax.swing.JPanel" name="jPanel28"> + <Constraints> + <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.support.JTabbedPaneSupportLayout" value="org.netbeans.modules.form.compat2.layouts.support.JTabbedPaneSupportLayout$JTabbedPaneConstraintsDescription"> + <JTabbedPaneConstraints tabName="应用中心"> + <Property name="tabTitle" type="java.lang.String" value="应用中心"/> + </JTabbedPaneConstraints> + </Constraint> + </Constraints> + + <Layout> + <DimensionLayout dim="0"> + <Group type="103" groupAlignment="0" attributes="0"> + <Group type="102" attributes="0"> + <EmptySpace max="-2" attributes="0"/> + <Group type="103" groupAlignment="0" attributes="0"> + <Component id="jButton2" alignment="0" min="-2" max="-2" attributes="0"/> + <Group type="102" alignment="0" attributes="0"> + <Component id="jButton4" min="-2" max="-2" attributes="0"/> + <EmptySpace max="-2" attributes="0"/> + <Component id="jButton5" min="-2" max="-2" attributes="0"/> + <EmptySpace max="-2" attributes="0"/> + <Component id="jButton6" min="-2" max="-2" attributes="0"/> + <EmptySpace max="-2" attributes="0"/> + <Component id="jButton7" min="-2" max="-2" attributes="0"/> + </Group> + <Group type="102" alignment="0" attributes="0"> + <Component id="jButton8" min="-2" max="-2" attributes="0"/> + <EmptySpace max="-2" attributes="0"/> + <Component id="jButton9" min="-2" max="-2" attributes="0"/> + </Group> + <Component id="jButton10" alignment="0" min="-2" max="-2" attributes="0"/> + </Group> + <EmptySpace pref="100" max="32767" attributes="0"/> + </Group> + </Group> + </DimensionLayout> + <DimensionLayout dim="1"> + <Group type="103" groupAlignment="0" attributes="0"> + <Group type="102" alignment="0" attributes="0"> + <EmptySpace max="-2" attributes="0"/> + <Component id="jButton2" min="-2" max="-2" attributes="0"/> + <EmptySpace max="-2" attributes="0"/> + <Component id="jButton10" min="-2" max="-2" attributes="0"/> + <EmptySpace pref="341" max="32767" attributes="0"/> + <Group type="103" groupAlignment="3" attributes="0"> + <Component id="jButton8" alignment="3" min="-2" max="-2" attributes="0"/> + <Component id="jButton9" alignment="3" min="-2" max="-2" attributes="0"/> + </Group> + <EmptySpace max="-2" attributes="0"/> + <Group type="103" groupAlignment="3" attributes="0"> + <Component id="jButton4" alignment="3" min="-2" max="-2" attributes="0"/> + <Component id="jButton5" alignment="3" min="-2" max="-2" attributes="0"/> + <Component id="jButton6" alignment="3" min="-2" max="-2" attributes="0"/> + <Component id="jButton7" alignment="3" min="-2" max="-2" attributes="0"/> + </Group> + <EmptySpace max="-2" attributes="0"/> + </Group> + </Group> + </DimensionLayout> + </Layout> + <SubComponents> + <Component class="javax.swing.JButton" name="jButton2"> + <Properties> + <Property name="text" type="java.lang.String" value="花生壳6.5工程版(无需公网IP,无需路由端口映射)"/> + </Properties> + <Events> + <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="jButton2ActionPerformed"/> + </Events> + <AuxValues> + <AuxValue name="JavaCodeGenerator_CreateCodeCustom" type="java.lang.String" value="new ConstomButton()"/> + </AuxValues> + </Component> + <Component class="javax.swing.JButton" name="jButton4"> + <Properties> + <Property name="text" type="java.lang.String" value="mcbbs"/> + </Properties> + <Events> + <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="jButton4ActionPerformed"/> + </Events> + <AuxValues> + <AuxValue name="JavaCodeGenerator_CreateCodeCustom" type="java.lang.String" value="new ConstomButton()"/> + </AuxValues> + </Component> + <Component class="javax.swing.JButton" name="jButton5"> + <Properties> + <Property name="text" type="java.lang.String" value="minecraft贴吧"/> + </Properties> + <Events> + <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="jButton5ActionPerformed"/> + </Events> + <AuxValues> + <AuxValue name="JavaCodeGenerator_CreateCodeCustom" type="java.lang.String" value="new ConstomButton()"/> + </AuxValues> + </Component> + <Component class="javax.swing.JButton" name="jButton6"> + <Properties> + <Property name="text" type="java.lang.String" value="mcbbs发布帖"/> + </Properties> + <Events> + <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="jButton6ActionPerformed"/> + </Events> + <AuxValues> + <AuxValue name="JavaCodeGenerator_CreateCodeCustom" type="java.lang.String" value="new ConstomButton()"/> + </AuxValues> + </Component> + <Component class="javax.swing.JButton" name="jButton7"> + <Properties> + <Property name="text" type="java.lang.String" value="minecraft官网"/> + </Properties> + <Events> + <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="jButton7ActionPerformed"/> + </Events> + <AuxValues> + <AuxValue name="JavaCodeGenerator_CreateCodeCustom" type="java.lang.String" value="new ConstomButton()"/> + </AuxValues> + </Component> + <Component class="javax.swing.JButton" name="jButton8"> + <Properties> + <Property name="text" type="java.lang.String" value="craftbukkit官网"/> + </Properties> + <Events> + <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="jButton8ActionPerformed"/> + </Events> + <AuxValues> + <AuxValue name="JavaCodeGenerator_CreateCodeCustom" type="java.lang.String" value="new ConstomButton()"/> + </AuxValues> + </Component> + <Component class="javax.swing.JButton" name="jButton9"> + <Properties> + <Property name="text" type="java.lang.String" value="MCPC+下载"/> + </Properties> + <Events> + <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="jButton9ActionPerformed"/> + </Events> + <AuxValues> + <AuxValue name="JavaCodeGenerator_CreateCodeCustom" type="java.lang.String" value="new ConstomButton()"/> + </AuxValues> + </Component> + <Component class="javax.swing.JButton" name="jButton10"> + <Properties> + <Property name="text" type="java.lang.String" value="指令大全"/> + </Properties> + <Events> + <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="jButton10ActionPerformed"/> + </Events> + <AuxValues> + <AuxValue name="JavaCodeGenerator_CreateCodeCustom" type="java.lang.String" value="new ConstomButton()"/> + </AuxValues> + </Component> + </SubComponents> + </Container> + </SubComponents> + </Container> + </SubComponents> +</Form> diff --git a/HMCSM/src/main/java/org/jackhuang/hellominecraft/svrmgr/views/MainWindow.java b/HMCSM/src/main/java/org/jackhuang/hellominecraft/svrmgr/views/MainWindow.java new file mode 100644 index 000000000..44ad12c90 --- /dev/null +++ b/HMCSM/src/main/java/org/jackhuang/hellominecraft/svrmgr/views/MainWindow.java @@ -0,0 +1,4498 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package org.jackhuang.hellominecraft.svrmgr.views; + +import java.awt.Dimension; +import java.awt.Image; +import java.awt.Toolkit; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.ComponentAdapter; +import java.awt.event.ComponentEvent; +import java.awt.event.KeyEvent; +import java.io.File; +import java.io.IOException; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Date; +import java.util.List; +import java.util.Map; +import java.util.Timer; +import java.util.TimerTask; +import java.util.Vector; +import javax.swing.DefaultListModel; +import javax.swing.ImageIcon; +import javax.swing.JFileChooser; +import javax.swing.JLabel; +import javax.swing.JMenuItem; +import javax.swing.JOptionPane; +import javax.swing.JPopupMenu; +import javax.swing.filechooser.FileNameExtensionFilter; +import javax.swing.table.DefaultTableModel; +import org.jackhuang.hellominecraft.C; +import org.jackhuang.hellominecraft.utils.functions.DoneListener0; +import org.jackhuang.hellominecraft.DoneListener1; +import org.jackhuang.hellominecraft.HMCLog; +import org.jackhuang.hellominecraft.tasks.Task; +import org.jackhuang.hellominecraft.tasks.TaskWindow; +import org.jackhuang.hellominecraft.tasks.download.FileDownloadTask; +import org.jackhuang.hellominecraft.tasks.download.HTTPGetTask; +import org.jackhuang.hellominecraft.utils.FileUtils; +import org.jackhuang.hellominecraft.svrmgr.utils.IMonitorService; +import org.jackhuang.hellominecraft.utils.IOUtils; +import org.jackhuang.hellominecraft.utils.MessageBox; +import org.jackhuang.hellominecraft.svrmgr.utils.ModType; +import org.jackhuang.hellominecraft.svrmgr.utils.MonitorInfoBean; +import org.jackhuang.hellominecraft.svrmgr.utils.MonitorServiceImpl; +import org.jackhuang.hellominecraft.utils.Pair; +import org.jackhuang.hellominecraft.version.MinecraftRemoteVersions; +import org.jackhuang.hellominecraft.svrmgr.Main; +import org.jackhuang.hellominecraft.svrmgr.cbplugins.BukkitPlugin; +import org.jackhuang.hellominecraft.svrmgr.cbplugins.Category; +import org.jackhuang.hellominecraft.svrmgr.cbplugins.PluginInfo; +import org.jackhuang.hellominecraft.svrmgr.cbplugins.PluginInformation; +import org.jackhuang.hellominecraft.svrmgr.cbplugins.PluginManager; +import org.jackhuang.hellominecraft.svrmgr.installer.bukkit.BukkitFormatThread; +import org.jackhuang.hellominecraft.svrmgr.installer.bukkit.BukkitVersion; +import org.jackhuang.hellominecraft.svrmgr.installer.cauldron.ForgeFormatThread; +import org.jackhuang.hellominecraft.svrmgr.installer.cauldron.ForgeInstaller; +import org.jackhuang.hellominecraft.svrmgr.installer.cauldron.ForgeVersion; +import org.jackhuang.hellominecraft.svrmgr.server.ScheduleTranslator; +import org.jackhuang.hellominecraft.svrmgr.server.Server; +import org.jackhuang.hellominecraft.svrmgr.server.ServerChecker; +import org.jackhuang.hellominecraft.svrmgr.server.backups.BackupManager; +import org.jackhuang.hellominecraft.svrmgr.settings.BannedPlayers; +import org.jackhuang.hellominecraft.svrmgr.settings.Op; +import org.jackhuang.hellominecraft.svrmgr.settings.Schedule; +import org.jackhuang.hellominecraft.svrmgr.settings.ServerProperties; +import org.jackhuang.hellominecraft.svrmgr.settings.SettingsManager; +import org.jackhuang.hellominecraft.svrmgr.settings.WhiteList; +import org.jackhuang.hellominecraft.svrmgr.threads.MonitorThread; +import org.jackhuang.hellominecraft.svrmgr.utils.FolderOpener; +import org.jackhuang.hellominecraft.svrmgr.utils.IPGet; +import org.jackhuang.hellominecraft.svrmgr.utils.Utilities; +import org.jackhuang.hellominecraft.utils.SwingUtils; +import org.jackhuang.hellominecraft.version.MinecraftRemoteVersion; +import org.jackhuang.hellominecraft.lookandfeel.components.ConstomButton; + +/** + * + * @author hyh + */ +public final class MainWindow extends javax.swing.JFrame + implements MonitorThread.MonitorThreadListener, DoneListener1<Integer> { + + ImageIcon background = new ImageIcon(getClass().getResource("/background.jpg")); + JLabel backgroundLabel; + + ImageIcon getResizedImage() { + Image image = background.getImage(); + image = image.getScaledInstance(this.getWidth(), this.getHeight(), Image.SCALE_FAST); + background.setImage(image); + return new ImageIcon(image); + } + + void resizeBackgroundLabel() { + backgroundLabel.setIcon(getResizedImage()); + backgroundLabel.setBounds(0, 0, this.getWidth(), this.getHeight()); + } + + ArrayList<String> commandSet; + int commandIndex; + JPopupMenu ppmBasically; + Timer getPlayerNumberTimer; + Timer tmrSystem; + + private boolean outOfCommandSet() { + return outOfCommandSet(commandIndex); + } + + private boolean outOfCommandSet(int commandIndex) { + return (commandIndex < 0 || commandIndex >= commandSet.size()); + } + + /** + * Creates new form MainWindow + */ + public MainWindow() { + initComponents(); + + Dimension scrSize = Toolkit.getDefaultToolkit().getScreenSize(); + setLocation((scrSize.width - this.getWidth()) / 2, + (scrSize.height - this.getHeight()) / 2); + + this.setIconImage(new ImageIcon(getClass().getResource("/icon.png")).getImage()); + + if (!Utilities.isEmpty(SettingsManager.settings.bgPath)) { + txtBackgroundPath.setText(SettingsManager.settings.bgPath); + background = new ImageIcon(Toolkit.getDefaultToolkit().getImage(SettingsManager.settings.bgPath)); + } + backgroundLabel = new JLabel(getResizedImage()); + backgroundLabel.setBounds(0, 0, this.getWidth(), this.getHeight()); + this.getContentPane().add(backgroundLabel, -1); + + addComponentListener(new ComponentAdapter() { + @Override + public void componentResized(ComponentEvent e) { + resizeBackgroundLabel(); + } + }); + + setTitle(Main.makeTitle()); + String mainjar = SettingsManager.settings.mainjar; + if (!Utilities.isEmpty(mainjar)) { + ServerProperties.init(new File(mainjar).getParent()); + } + txtMainJar.setText(mainjar); + commandSet = new ArrayList<String>(); + btnStop.setEnabled(false); + btnShutdown.setEnabled(false); + btnCommand.setEnabled(false); + loadFromSettings(); + loadFromServerProperties(); + loadFromOPs(); + loadFromWhiteList(); + loadFromBannedPlayers(); + loadLocalMods(); + loadLocalCoreMods(); + loadLocalPlugins(); + loadWorlds(); + loadBackups(); + loadSchedules(); + refreshInfos(); + refreshReports(); + getIP(); + //lblMinecraftVersion.setText("鏈嶅姟绔増鏈:" + MCUtils.minecraftVersion(new File(SettingsManager.settings.mainjar)).version); + + tmrSystem = new Timer(); + pgsCPURatio.setMinimum(0); + pgsCPURatio.setMaximum(100); + pgsMemoryRatio.setMinimum(0); + pgsMemoryRatio.setMaximum(100); + tmrSystem.schedule(new TimerTask() { + + @Override + public void run() { + try { + IMonitorService service = new MonitorServiceImpl(); + MonitorInfoBean monitorInfo = service.getMonitorInfoBean(); + pgsCPURatio.setValue((int) Math.round(monitorInfo.getCpuRatio())); + lblTotalMemory.setText(monitorInfo.getTotalMemory() / 1024 + ""); + lblMaxMemory.setText(monitorInfo.getMaxMemory() / 1024 + ""); + lblOSName.setText(monitorInfo.getOsName()); + lblTotalMemorySize.setText(monitorInfo.getTotalMemorySize() / 1024 + "MB"); + lblFreeMemory.setText(monitorInfo.getFreeMemory() / 1024 + "MB"); + lblUsedMemory.setText(monitorInfo.getUsedMemory() / 1024 + "MB"); + lblTotalThread.setText(monitorInfo.getTotalThread() / 1024 + "MB"); + pgsMemoryRatio.setValue((int) (monitorInfo.getUsedMemory() * 100 / monitorInfo.getTotalMemorySize())); + } catch (Exception e) { + HMCLog.warn("Failed to get system information.", e); + } + } + + }, 0, 2000); + + //<editor-fold defaultstate="collapsed" desc="鍩烘湰淇℃伅鑿滃崟"> + JMenuItem itm; + ppmBasically = new JPopupMenu(); + itm = new JMenuItem("閲嶇疆鎻掍欢"); + itm.addActionListener(new ActionListener() { + + @Override + public void actionPerformed(ActionEvent e) { + Server.getInstance().sendCommand("reload"); + } + }); + ppmBasically = new JPopupMenu(); + itm = new JMenuItem("鍗堝"); + itm.addActionListener(new ActionListener() { + + @Override + public void actionPerformed(ActionEvent e) { + Server.getInstance().sendCommand("time set 18000"); + } + }); + ppmBasically.add(itm); + itm = new JMenuItem("鍑屾櫒"); + itm.addActionListener(new ActionListener() { + + @Override + public void actionPerformed(ActionEvent e) { + Server.getInstance().sendCommand("time set 0"); + } + }); + ppmBasically.add(itm); + itm = new JMenuItem("骞挎挱"); + itm.addActionListener(new ActionListener() { + + @Override + public void actionPerformed(ActionEvent e) { + String s = JOptionPane.showInputDialog("骞挎挱璁伅"); + Server.getInstance().sendCommand("say " + s); + } + }); + itm = new JMenuItem("绾㈠瓧骞挎挱"); + itm.addActionListener(new ActionListener() { + + @Override + public void actionPerformed(ActionEvent e) { + String s = JOptionPane.showInputDialog("骞挎挱璁伅"); + Server.getInstance().sendCommand("me " + s); + } + }); + itm = new JMenuItem("绉佽亰"); + itm.addActionListener(new ActionListener() { + + @Override + public void actionPerformed(ActionEvent e) { + InputDialog id = new InputDialog(MainWindow.this, true, new String[]{"鐜╁", "璁伅"}); + id.setVisible(true); + Server.getInstance().sendCommand("tell " + id.result[0] + " " + id.result[1]); + } + }); + ppmBasically.add(itm); + itm = new JMenuItem("缁欎簣OP"); + itm.addActionListener(new ActionListener() { + + @Override + public void actionPerformed(ActionEvent e) { + String s = JOptionPane.showInputDialog("鏂癘P鐨勬父鎴忓悕"); + Server.getInstance().sendCommand("op " + s); + } + }); + ppmBasically.add(itm); + itm = new JMenuItem("鍗搁櫎OP"); + itm.addActionListener(new ActionListener() { + + @Override + public void actionPerformed(ActionEvent e) { + String s = JOptionPane.showInputDialog("瑕佸嵏闄P鐨勬父鎴忓悕"); + Server.getInstance().sendCommand("deop " + s); + } + }); + ppmBasically.add(itm); + itm = new JMenuItem("缁欎簣鐜╁鐧藉悕鍗"); + itm.addActionListener(new ActionListener() { + + @Override + public void actionPerformed(ActionEvent e) { + String s = JOptionPane.showInputDialog("瑕佹坊鍏ョ櫧鍚嶅崟鐨勬父鎴忓悕"); + Server.getInstance().sendCommand("whitelist add " + s); + } + }); + ppmBasically.add(itm); + itm = new JMenuItem("瑙i櫎鐜╁鐧藉悕鍗"); + itm.addActionListener(new ActionListener() { + + @Override + public void actionPerformed(ActionEvent e) { + String s = JOptionPane.showInputDialog("瑕佽В闄ょ櫧鍚嶅崟鐨勬父鎴忓悕"); + Server.getInstance().sendCommand("whitelist remove " + s); + } + }); + ppmBasically.add(itm); + itm = new JMenuItem("鍚敤鐧藉悕鍗"); + itm.addActionListener(new ActionListener() { + + @Override + public void actionPerformed(ActionEvent e) { + Server.getInstance().sendCommand("whitelist on"); + } + }); + ppmBasically.add(itm); + itm = new JMenuItem("绂佺敤鐧藉悕鍗"); + itm.addActionListener(new ActionListener() { + + @Override + public void actionPerformed(ActionEvent e) { + Server.getInstance().sendCommand("whitelist off"); + } + }); + ppmBasically.add(itm); + itm = new JMenuItem("鍒楀嚭鐧藉悕鍗"); + itm.addActionListener(new ActionListener() { + + @Override + public void actionPerformed(ActionEvent e) { + Server.getInstance().sendCommand("whitelist list"); + } + }); + ppmBasically.add(itm); + itm = new JMenuItem("灏佺鐜╁"); + itm.addActionListener(new ActionListener() { + + @Override + public void actionPerformed(ActionEvent e) { + String s = JOptionPane.showInputDialog("瑕佸皝绂佺帺瀹剁殑娓告垙鍚"); + Server.getInstance().sendCommand("ban " + s); + } + }); + ppmBasically.add(itm); + itm = new JMenuItem("灏佺鐜╁IP"); + itm.addActionListener(new ActionListener() { + + @Override + public void actionPerformed(ActionEvent e) { + String s = JOptionPane.showInputDialog("瑕佸皝绂佺帺瀹禝P鐨勬父鎴忓悕"); + Server.getInstance().sendCommand("ban-ip " + s); + } + }); + itm = new JMenuItem("瑙e皝鐜╁"); + itm.addActionListener(new ActionListener() { + + @Override + public void actionPerformed(ActionEvent e) { + String s = JOptionPane.showInputDialog("瑕佽В灏佺帺瀹剁殑娓告垙鍚"); + Server.getInstance().sendCommand("pardon " + s); + } + }); + ppmBasically.add(itm); + itm = new JMenuItem("瑙e皝鐜╁IP"); + itm.addActionListener(new ActionListener() { + + @Override + public void actionPerformed(ActionEvent e) { + String s = JOptionPane.showInputDialog("瑕佽В灏佺帺瀹禝P鐨勬父鎴忓悕"); + Server.getInstance().sendCommand("pardon-ip " + s); + } + }); + itm = new JMenuItem("灏佺鐜╁"); + itm.addActionListener(new ActionListener() { + + @Override + public void actionPerformed(ActionEvent e) { + String s = JOptionPane.showInputDialog("瑕佸皝绂佺帺瀹剁殑娓告垙鍚"); + Server.getInstance().sendCommand("ban " + s); + } + }); + ppmBasically.add(itm); + itm = new JMenuItem("灏佺鐜╁IP"); + itm.addActionListener(new ActionListener() { + + @Override + public void actionPerformed(ActionEvent e) { + String s = JOptionPane.showInputDialog("瑕佸皝绂佺帺瀹禝P鐨勬父鎴忓悕"); + Server.getInstance().sendCommand("ban-ip " + s); + } + }); + itm = new JMenuItem("灏佺鐜╁鍒楄〃"); + itm.addActionListener(new ActionListener() { + + @Override + public void actionPerformed(ActionEvent e) { + Server.getInstance().sendCommand("banlist"); + } + }); + ppmBasically.add(itm); + itm = new JMenuItem("淇敼鏃堕棿"); + itm.addActionListener(new ActionListener() { + + @Override + public void actionPerformed(ActionEvent e) { + String s = JOptionPane.showInputDialog("瑕佽皟鏁寸殑鏃堕棿鍊"); + Server.getInstance().sendCommand("time set " + s); + } + }); + ppmBasically.add(itm); + itm = new JMenuItem("寰鍚庤皟鏁存椂闂"); + itm.addActionListener(new ActionListener() { + + @Override + public void actionPerformed(ActionEvent e) { + String s = JOptionPane.showInputDialog("瑕佸線鍚庤皟鏁寸殑鏃堕棿鍊"); + Server.getInstance().sendCommand("time add " + s); + } + }); + ppmBasically.add(itm); + itm = new JMenuItem("璋冩暣澶╂皵"); + itm.addActionListener(new ActionListener() { + + @Override + public void actionPerformed(ActionEvent e) { + String s = JOptionPane.showInputDialog("瑕佽皟鏁寸殑澶╂皵锛堝彧鑳藉~锛歝lear[鎰忔濇槸鍙栨秷鎵鏈夊ぉ姘擼鎴杛ain[鎰忔濇槸涓嬮洦]鎴杢hunder[鎰忔濇槸鎵撻浄]"); + Server.getInstance().sendCommand("weather " + s); + } + }); + ppmBasically.add(itm); + itm = new JMenuItem("璋冩暣涓瀹氭椂闂寸殑澶╂皵"); + itm.addActionListener(new ActionListener() { + + @Override + public void actionPerformed(ActionEvent e) { + InputDialog id = new InputDialog(MainWindow.this, true, new String[]{ + "瑕佽皟鏁寸殑澶╂皵锛堝彧鑳藉~锛歝lear[鎰忔濇槸鍙栨秷鎵鏈夊ぉ姘擼鎴杛ain[鎰忔濇槸涓嬮洦]鎴杢hunder[鎰忔濇槸鎵撻浄]", + "鏃堕棿" + }); + id.setVisible(true); + if (id.result != null) { + String s = JOptionPane.showInputDialog(""); + Server.getInstance().sendCommand("weather " + id.result[0] + " " + id.result[1]); + } + } + }); + ppmBasically.add(itm); + itm = new JMenuItem("娓呴櫎鑳屽寘"); + itm.addActionListener(new ActionListener() { + + @Override + public void actionPerformed(ActionEvent e) { + String s = JOptionPane.showInputDialog("瑕佽娓呴櫎鑳屽寘鐨勭帺瀹"); + Server.getInstance().sendCommand("clear " + s); + } + }); + ppmBasically.add(itm); + itm = new JMenuItem("韪㈠嚭鐜╁"); + itm.addActionListener(new ActionListener() { + + @Override + public void actionPerformed(ActionEvent e) { + String s = JOptionPane.showInputDialog("瑕佽韪㈠嚭鐨勭帺瀹"); + Server.getInstance().sendCommand("kick " + s); + } + }); + ppmBasically.add(itm); + itm = new JMenuItem("鍦ㄧ嚎鐜╁"); + itm.addActionListener(new ActionListener() { + + @Override + public void actionPerformed(ActionEvent e) { + Server.getInstance().sendCommand("list"); + } + }); + ppmBasically.add(itm); + itm = new JMenuItem("鎻掍欢鍒楄〃"); + itm.addActionListener(new ActionListener() { + + @Override + public void actionPerformed(ActionEvent e) { + Server.getInstance().sendCommand("plugins"); + } + }); + ppmBasically.add(itm); + itm = new JMenuItem("缁欎簣鐜╁鐗╁搧"); + itm.addActionListener(new ActionListener() { + + @Override + public void actionPerformed(ActionEvent e) { + InputDialog id = new InputDialog(MainWindow.this, true, new String[]{"鐜╁", "鐗╁搧ID", "鏁伴噺"}); + id.setVisible(true); + if (id.result != null) { + Server.getInstance().sendCommand("give " + id.result[0] + " " + id.result[1] + " " + id.result[2]); + } + } + }); + ppmBasically.add(itm); + itm = new JMenuItem("淇濆瓨鎵鏈"); + itm.addActionListener(new ActionListener() { + + @Override + public void actionPerformed(ActionEvent e) { + Server.getInstance().sendCommand("save-all"); + } + }); + ppmBasically.add(itm); + itm = new JMenuItem("寮鍚痓ukkit鑷姩淇濆瓨"); + itm.addActionListener(new ActionListener() { + + @Override + public void actionPerformed(ActionEvent e) { + Server.getInstance().sendCommand("save-on"); + } + }); + ppmBasically.add(itm); + itm = new JMenuItem("鍙栨秷bukkit鑷姩淇濆瓨"); + itm.addActionListener(new ActionListener() { + + @Override + public void actionPerformed(ActionEvent e) { + Server.getInstance().sendCommand("save-off"); + } + }); + ppmBasically.add(itm); + itm = new JMenuItem("闅惧害"); + itm.addActionListener(new ActionListener() { + + @Override + public void actionPerformed(ActionEvent e) { + String s = JOptionPane.showInputDialog("闅惧害"); + Server.getInstance().sendCommand("difficulty " + s); + } + }); + ppmBasically.add(itm); + itm = new JMenuItem("榛樿娓告垙妯″紡"); + itm.addActionListener(new ActionListener() { + + @Override + public void actionPerformed(ActionEvent e) { + String s = JOptionPane.showInputDialog("榛樿娓告垙妯″紡"); + Server.getInstance().sendCommand("defaultgamemode " + s); + } + }); + ppmBasically.add(itm); + itm = new JMenuItem("鍦板浘绉嶅瓙"); + itm.addActionListener(new ActionListener() { + + @Override + public void actionPerformed(ActionEvent e) { + Server.getInstance().sendCommand("seed"); + } + }); + ppmBasically.add(itm); + //</editor-fold> + } + + /** + * 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() { + + jTabbedPane1 = new javax.swing.JTabbedPane(); + jPanel1 = new javax.swing.JPanel(); + btnLaunch = new ConstomButton(); + jScrollPane4 = new javax.swing.JScrollPane(); + txtMain = new javax.swing.JTextArea(); + jLabel17 = new javax.swing.JLabel(); + txtMainJar = new javax.swing.JTextField(); + btnSetJar = new ConstomButton(); + txtCommand = new javax.swing.JTextField(); + btnSendCommand = new ConstomButton(); + jLabel1 = new javax.swing.JLabel(); + btnSave = new ConstomButton(); + jButton3 = new ConstomButton(); + btnRestart = new ConstomButton(); + btnShutdown = new ConstomButton(); + btnAutoSearch = new ConstomButton(); + lblIPAddress = new javax.swing.JLabel(); + btnStop = new ConstomButton(); + btnCommand = new ConstomButton(); + jPanel29 = new javax.swing.JPanel(); + jLabel29 = new javax.swing.JLabel(); + jLabel30 = new javax.swing.JLabel(); + jLabel32 = new javax.swing.JLabel(); + jLabel33 = new javax.swing.JLabel(); + jLabel34 = new javax.swing.JLabel(); + jLabel35 = new javax.swing.JLabel(); + jLabel36 = new javax.swing.JLabel(); + jLabel37 = new javax.swing.JLabel(); + pgsCPURatio = new javax.swing.JProgressBar(); + lblTotalMemory = new javax.swing.JLabel(); + lblMaxMemory = new javax.swing.JLabel(); + lblOSName = new javax.swing.JLabel(); + lblTotalMemorySize = new javax.swing.JLabel(); + lblFreeMemory = new javax.swing.JLabel(); + lblUsedMemory = new javax.swing.JLabel(); + lblTotalThread = new javax.swing.JLabel(); + pgsMemoryRatio = new javax.swing.JProgressBar(); + jLabel31 = new javax.swing.JLabel(); + jPanel2 = new javax.swing.JPanel(); + jTabbedPane2 = new javax.swing.JTabbedPane(); + jPanel24 = new javax.swing.JPanel(); + jTabbedPane6 = new javax.swing.JTabbedPane(); + jPanel3 = new javax.swing.JPanel(); + jLabel5 = new javax.swing.JLabel(); + txtServerPort = new javax.swing.JSpinner(); + jLabel6 = new javax.swing.JLabel(); + txtMaxPlayer = new javax.swing.JSpinner(); + txtViewDistance = new javax.swing.JSpinner(); + jLabel7 = new javax.swing.JLabel(); + jLabel8 = new javax.swing.JLabel(); + txtWorldName = new javax.swing.JTextField(); + jLabel9 = new javax.swing.JLabel(); + cboWorldType = new javax.swing.JComboBox(); + jLabel10 = new javax.swing.JLabel(); + txtServerMOTD = new javax.swing.JTextField(); + jLabel11 = new javax.swing.JLabel(); + cboDifficulty = new javax.swing.JComboBox(); + jLabel12 = new javax.swing.JLabel(); + cboGameMode = new javax.swing.JComboBox(); + chkEnalbleAnimals = new javax.swing.JCheckBox(); + chkEnableMonsters = new javax.swing.JCheckBox(); + chkEnableNPCs = new javax.swing.JCheckBox(); + chkAllowFlight = new javax.swing.JCheckBox(); + chkPVP = new javax.swing.JCheckBox(); + chkAllowNether = new javax.swing.JCheckBox(); + chkWhiteList = new javax.swing.JCheckBox(); + txtServerName = new javax.swing.JTextField(); + jLabel15 = new javax.swing.JLabel(); + jLabel16 = new javax.swing.JLabel(); + txtMaxBuildHeight = new javax.swing.JSpinner(); + jLabel18 = new javax.swing.JLabel(); + txtServerGeneratorSettings = new javax.swing.JTextField(); + txtWorldSeed = new javax.swing.JTextField(); + jLabel19 = new javax.swing.JLabel(); + chkGenerateStructures = new javax.swing.JCheckBox(); + chkOnlineMode = new javax.swing.JCheckBox(); + jPanel25 = new javax.swing.JPanel(); + jLabel14 = new javax.swing.JLabel(); + jLabel25 = new javax.swing.JLabel(); + txtJavaDir = new javax.swing.JTextField(); + txtJavaArgs = new javax.swing.JTextField(); + jLabel26 = new javax.swing.JLabel(); + txtMaxMemory = new javax.swing.JTextField(); + jPanel12 = new javax.swing.JPanel(); + jLabel20 = new javax.swing.JLabel(); + txtBackgroundPath = new javax.swing.JTextField(); + btnSetBackgroundPath = new ConstomButton(); + jPanel4 = new javax.swing.JPanel(); + jTabbedPane3 = new javax.swing.JTabbedPane(); + jPanel5 = new javax.swing.JPanel(); + jScrollPane1 = new javax.swing.JScrollPane(); + lstOP = new javax.swing.JList(); + btnAddOP = new ConstomButton(); + jLabel2 = new javax.swing.JLabel(); + txtOPName = new javax.swing.JTextField(); + btnDeleteOP = new ConstomButton(); + jLabel40 = new javax.swing.JLabel(); + jPanel6 = new javax.swing.JPanel(); + btnDeleteWhite = new ConstomButton(); + jScrollPane3 = new javax.swing.JScrollPane(); + lstWhiteList = new javax.swing.JList(); + jLabel4 = new javax.swing.JLabel(); + txtWhiteName = new javax.swing.JTextField(); + btnAddWhite = new ConstomButton(); + jLabel41 = new javax.swing.JLabel(); + jPanel7 = new javax.swing.JPanel(); + btnUnban = new ConstomButton(); + jScrollPane2 = new javax.swing.JScrollPane(); + lstBanned = new javax.swing.JList(); + jLabel3 = new javax.swing.JLabel(); + txtBanName = new javax.swing.JTextField(); + btnAddBan = new ConstomButton(); + jLabel42 = new javax.swing.JLabel(); + jPanel8 = new javax.swing.JPanel(); + jTabbedPane4 = new javax.swing.JTabbedPane(); + jPanel9 = new javax.swing.JPanel(); + jScrollPane5 = new javax.swing.JScrollPane(); + lstExternalMods = new javax.swing.JTable(); + btnManageExtMods = new ConstomButton(); + btnAddExternelMod = new ConstomButton(); + btnDeleteExternelMod = new ConstomButton(); + btnSaveExtMod = new ConstomButton(); + jPanel10 = new javax.swing.JPanel(); + jScrollPane6 = new javax.swing.JScrollPane(); + lstCoreMods = new javax.swing.JTable(); + btnManageCoreMods = new ConstomButton(); + btnAddExternelCoreMod = new ConstomButton(); + btnDeleteExternelCoreMod = new ConstomButton(); + btnSaveCoreMod = new ConstomButton(); + jPanel11 = new javax.swing.JPanel(); + jScrollPane7 = new javax.swing.JScrollPane(); + lstPlugins = new javax.swing.JTable(); + btnManagePlugins = new ConstomButton(); + btnAddPlugins = new ConstomButton(); + btnDeletePlugins = new ConstomButton(); + btnSavePlugins = new ConstomButton(); + jPanel13 = new javax.swing.JPanel(); + jPanel14 = new javax.swing.JPanel(); + jLabel21 = new javax.swing.JLabel(); + cboTimerTask = new javax.swing.JComboBox(); + txtTimerTaskPeriod = new javax.swing.JTextField(); + jLabel22 = new javax.swing.JLabel(); + btnNewTask = new ConstomButton(); + jLabel13 = new javax.swing.JLabel(); + txtTimerTaskContent = new javax.swing.JTextField(); + jLabel28 = new javax.swing.JLabel(); + cboTimeType = new javax.swing.JComboBox(); + btnDelSelectedSchedule = new ConstomButton(); + jScrollPane9 = new javax.swing.JScrollPane(); + lstSchedules = new javax.swing.JTable(); + jPanel15 = new javax.swing.JPanel(); + jPanel16 = new javax.swing.JPanel(); + jPanel17 = new javax.swing.JPanel(); + jLabel23 = new javax.swing.JLabel(); + cboBackupTypes = new javax.swing.JComboBox(); + btnBackup = new ConstomButton(); + jButton1 = new ConstomButton(); + btnDeleteBackup = new ConstomButton(); + btnRestoreBackup = new ConstomButton(); + jScrollPane11 = new javax.swing.JScrollPane(); + lstBackups = new javax.swing.JTable(); + jPanel18 = new javax.swing.JPanel(); + jScrollPane10 = new javax.swing.JScrollPane(); + lstWorlds = new javax.swing.JTable(); + btnRefreshWorlds = new ConstomButton(); + btnSaveWorld = new ConstomButton(); + jPanel19 = new javax.swing.JPanel(); + jTabbedPane5 = new javax.swing.JTabbedPane(); + jPanel20 = new javax.swing.JPanel(); + jScrollPane18 = new javax.swing.JScrollPane(); + lstCraftbukkit = new javax.swing.JTable(); + btnDownloadCraftbukkit = new ConstomButton(); + lstRefreshCraftbukkit = new ConstomButton(); + cboBukkitType = new javax.swing.JComboBox(); + jLabel39 = new javax.swing.JLabel(); + jPanel30 = new javax.swing.JPanel(); + jScrollPane19 = new javax.swing.JScrollPane(); + lstMCPC = new javax.swing.JTable(); + btnDownloadMCPC = new ConstomButton(); + lstRefreshMCPC = new ConstomButton(); + jLabel38 = new javax.swing.JLabel(); + cboCauldronMinecraft = new javax.swing.JComboBox(); + btnInstallMCPC = new ConstomButton(); + jPanel21 = new javax.swing.JPanel(); + btnRefreshDownloads = new ConstomButton(); + jScrollPane12 = new javax.swing.JScrollPane(); + lstDownloads = new javax.swing.JTable(); + btnMinecraftServerDownload = new ConstomButton(); + jPanel23 = new javax.swing.JPanel(); + jScrollPane15 = new javax.swing.JScrollPane(); + lstBukkitPlugins = new javax.swing.JTable(); + cboCategory = new javax.swing.JComboBox(); + jLabel24 = new javax.swing.JLabel(); + btnShowPluginInfo = new ConstomButton(); + jButton11 = new javax.swing.JButton(); + jPanel22 = new javax.swing.JPanel(); + jScrollPane13 = new javax.swing.JScrollPane(); + lstInfos = new javax.swing.JTable(); + btnRefreshInfos = new ConstomButton(); + jScrollPane14 = new javax.swing.JScrollPane(); + txtInfo = new javax.swing.JTextArea(); + btnShowInfo = new ConstomButton(); + jPanel26 = new javax.swing.JPanel(); + btnRefreshReports = new ConstomButton(); + jScrollPane17 = new javax.swing.JScrollPane(); + txtCrashReport = new javax.swing.JTextArea(); + btnShowReport = new ConstomButton(); + jScrollPane8 = new javax.swing.JScrollPane(); + lstReports = new javax.swing.JList(); + jPanel27 = new javax.swing.JPanel(); + lblPlayers = new javax.swing.JLabel(); + btnRefreshPlayers = new ConstomButton(); + jScrollPane16 = new javax.swing.JScrollPane(); + lstPlayers = new javax.swing.JList(); + jLabel27 = new javax.swing.JLabel(); + jPanel28 = new javax.swing.JPanel(); + jButton2 = new ConstomButton(); + jButton4 = new ConstomButton(); + jButton5 = new ConstomButton(); + jButton6 = new ConstomButton(); + jButton7 = new ConstomButton(); + jButton8 = new ConstomButton(); + jButton9 = new ConstomButton(); + jButton10 = new ConstomButton(); + + setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE); + setTitle("Hello Minecraft! Server Manager 0.1"); + addWindowListener(new java.awt.event.WindowAdapter() { + public void windowClosed(java.awt.event.WindowEvent evt) { + formWindowClosed(evt); + } + public void windowClosing(java.awt.event.WindowEvent evt) { + formWindowClosing(evt); + } + }); + + jTabbedPane1.setTabPlacement(javax.swing.JTabbedPane.LEFT); + + btnLaunch.setText("鍚姩"); + btnLaunch.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + btnLaunchActionPerformed(evt); + } + }); + + txtMain.setEditable(false); + txtMain.setColumns(20); + txtMain.setRows(5); + jScrollPane4.setViewportView(txtMain); + + jLabel17.setText("鍚姩jar"); + + txtMainJar.addFocusListener(new java.awt.event.FocusAdapter() { + public void focusLost(java.awt.event.FocusEvent evt) { + txtMainJarFocusLost(evt); + } + }); + + btnSetJar.setText("鎵嬪姩璁剧疆"); + btnSetJar.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + btnSetJarActionPerformed(evt); + } + }); + + txtCommand.addKeyListener(new java.awt.event.KeyAdapter() { + public void keyPressed(java.awt.event.KeyEvent evt) { + txtCommandKeyPressed(evt); + } + }); + + btnSendCommand.setText("鍙戦佸懡浠"); + btnSendCommand.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + btnSendCommandActionPerformed(evt); + } + }); + + jLabel1.setText("鎸囦护"); + + btnSave.setText("淇濆瓨"); + btnSave.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + btnSaveActionPerformed(evt); + } + }); + + jButton3.setText("娓呴櫎璁板綍"); + jButton3.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + jButton3ActionPerformed(evt); + } + }); + + btnRestart.setText("閲嶅惎"); + btnRestart.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + btnRestartActionPerformed(evt); + } + }); + + btnShutdown.setText("寮哄埗鍏抽棴"); + btnShutdown.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + btnShutdownActionPerformed(evt); + } + }); + + btnAutoSearch.setText("鑷姩鎼滃"); + btnAutoSearch.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + btnAutoSearchActionPerformed(evt); + } + }); + + lblIPAddress.setText("鑾峰彇IP鍦板潃..."); + lblIPAddress.setToolTipText(""); + + btnStop.setText("鍋滄"); + btnStop.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + btnStopActionPerformed(evt); + } + }); + + btnCommand.setText("鍩烘湰鍛戒护"); + btnCommand.addMouseListener(new java.awt.event.MouseAdapter() { + public void mouseClicked(java.awt.event.MouseEvent evt) { + btnCommandMouseClicked(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() + .addContainerGap() + .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING) + .addGroup(jPanel1Layout.createSequentialGroup() + .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING) + .addGroup(jPanel1Layout.createSequentialGroup() + .addComponent(jLabel17) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(txtMainJar)) + .addGroup(jPanel1Layout.createSequentialGroup() + .addComponent(lblIPAddress) + .addGap(0, 265, Short.MAX_VALUE))) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(btnSetJar) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(btnAutoSearch)) + .addGroup(jPanel1Layout.createSequentialGroup() + .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jPanel1Layout.createSequentialGroup() + .addComponent(jLabel1) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(txtCommand)) + .addComponent(jScrollPane4)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false) + .addComponent(btnLaunch, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(btnRestart, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(btnSave, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(btnShutdown, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(btnCommand, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(jButton3, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(btnStop, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(btnSendCommand, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)))) + .addContainerGap()) + ); + jPanel1Layout.setVerticalGroup( + jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jPanel1Layout.createSequentialGroup() + .addContainerGap() + .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(txtMainJar, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(btnSetJar) + .addComponent(jLabel17) + .addComponent(btnAutoSearch)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(lblIPAddress) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jPanel1Layout.createSequentialGroup() + .addComponent(jButton3) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(btnCommand) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 147, Short.MAX_VALUE) + .addComponent(btnShutdown) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(btnSave) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(btnRestart) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(btnStop) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(btnLaunch)) + .addComponent(jScrollPane4)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(txtCommand, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(btnSendCommand) + .addComponent(jLabel1)) + .addContainerGap()) + ); + + jTabbedPane1.addTab("涓婚〉", jPanel1); + + jLabel29.setText("cpu鍗犳湁鐜"); + + jLabel30.setText("鍙娇鐢ㄥ唴瀛"); + + jLabel32.setText("鏈澶у彲浣跨敤鍐呭瓨"); + + jLabel33.setText("鎿嶄綔绯荤粺"); + + jLabel34.setText("鎬荤殑鐗╃悊鍐呭瓨"); + + jLabel35.setText("鍓╀綑鐨勭墿鐞嗗唴瀛"); + + jLabel36.setText("宸蹭娇鐢ㄧ殑鐗╃悊鍐呭瓨"); + + jLabel37.setText("绾跨▼鎬绘暟"); + + lblTotalMemory.setText("jLabel38"); + + lblMaxMemory.setText("jLabel40"); + + lblOSName.setText("jLabel41"); + + lblTotalMemorySize.setText("jLabel42"); + + lblFreeMemory.setText("jLabel43"); + + lblUsedMemory.setText("jLabel44"); + + lblTotalThread.setText("jLabel45"); + + jLabel31.setText("鍐呭瓨鍗犳湁鐜"); + + javax.swing.GroupLayout jPanel29Layout = new javax.swing.GroupLayout(jPanel29); + jPanel29.setLayout(jPanel29Layout); + jPanel29Layout.setHorizontalGroup( + jPanel29Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jPanel29Layout.createSequentialGroup() + .addContainerGap() + .addGroup(jPanel29Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(jLabel29) + .addComponent(jLabel30) + .addComponent(jLabel32) + .addComponent(jLabel33) + .addComponent(jLabel34) + .addComponent(jLabel35) + .addComponent(jLabel36) + .addComponent(jLabel37) + .addComponent(jLabel31)) + .addGap(34, 34, 34) + .addGroup(jPanel29Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(pgsMemoryRatio, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(lblTotalThread) + .addComponent(lblUsedMemory) + .addComponent(lblFreeMemory) + .addComponent(lblTotalMemorySize) + .addComponent(lblOSName) + .addComponent(lblMaxMemory) + .addComponent(lblTotalMemory) + .addComponent(pgsCPURatio, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addContainerGap(247, Short.MAX_VALUE)) + ); + jPanel29Layout.setVerticalGroup( + jPanel29Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jPanel29Layout.createSequentialGroup() + .addContainerGap() + .addGroup(jPanel29Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(jLabel29) + .addComponent(pgsCPURatio, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(jPanel29Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(jLabel30) + .addComponent(lblTotalMemory)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(jPanel29Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(jLabel32) + .addComponent(lblMaxMemory)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(jPanel29Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(jLabel33) + .addComponent(lblOSName)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(jPanel29Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(jLabel34) + .addComponent(lblTotalMemorySize)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(jPanel29Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(jLabel35) + .addComponent(lblFreeMemory)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(jPanel29Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(jLabel36) + .addComponent(lblUsedMemory)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(jPanel29Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING) + .addComponent(jLabel31) + .addComponent(pgsMemoryRatio, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(jPanel29Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(jLabel37) + .addComponent(lblTotalThread)) + .addContainerGap(267, Short.MAX_VALUE)) + ); + + jTabbedPane1.addTab("鐘舵", jPanel29); + + jLabel5.setText("鏈嶅姟鍣ㄧ鍙"); + + txtServerPort.addFocusListener(new java.awt.event.FocusAdapter() { + public void focusLost(java.awt.event.FocusEvent evt) { + txtServerPortFocusLost(evt); + } + }); + + jLabel6.setText("鏈澶т汉鏁"); + + txtMaxPlayer.addFocusListener(new java.awt.event.FocusAdapter() { + public void focusLost(java.awt.event.FocusEvent evt) { + txtMaxPlayerFocusLost(evt); + } + }); + + txtViewDistance.addFocusListener(new java.awt.event.FocusAdapter() { + public void focusLost(java.awt.event.FocusEvent evt) { + txtViewDistanceFocusLost(evt); + } + }); + + jLabel7.setText("瑙嗙嚎璺濈"); + + jLabel8.setText("鍦板浘鍚嶇О"); + + txtWorldName.addFocusListener(new java.awt.event.FocusAdapter() { + public void focusLost(java.awt.event.FocusEvent evt) { + txtWorldNameFocusLost(evt); + } + }); + + jLabel9.setText("鍦板浘绫诲瀷"); + + cboWorldType.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "榛樿", "瓒呭钩鍧", "宸ㄥ瀷鐢熺墿缇ょ郴" })); + cboWorldType.addItemListener(new java.awt.event.ItemListener() { + public void itemStateChanged(java.awt.event.ItemEvent evt) { + cboWorldTypeItemStateChanged(evt); + } + }); + + jLabel10.setText("鏈嶅姟鍣ㄤ粙缁"); + + txtServerMOTD.addFocusListener(new java.awt.event.FocusAdapter() { + public void focusLost(java.awt.event.FocusEvent evt) { + txtServerMOTDFocusLost(evt); + } + }); + + jLabel11.setText("娓告垙妯″紡"); + + cboDifficulty.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "鍜屽钩", "绠鍗", "鏅", "鍥伴毦" })); + cboDifficulty.addItemListener(new java.awt.event.ItemListener() { + public void itemStateChanged(java.awt.event.ItemEvent evt) { + cboDifficultyItemStateChanged(evt); + } + }); + + jLabel12.setText("闅惧害"); + + cboGameMode.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "鐢熷瓨", "鍒涢", "鏋侀檺" })); + cboGameMode.addItemListener(new java.awt.event.ItemListener() { + public void itemStateChanged(java.awt.event.ItemEvent evt) { + cboGameModeItemStateChanged(evt); + } + }); + + chkEnalbleAnimals.setText("鐢熸垚鍔ㄧ墿"); + chkEnalbleAnimals.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + chkEnalbleAnimalsActionPerformed(evt); + } + }); + + chkEnableMonsters.setText("鐢熸垚鎬墿"); + chkEnableMonsters.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + chkEnableMonstersActionPerformed(evt); + } + }); + + chkEnableNPCs.setText("鐢熸垚鏉戞皯"); + chkEnableNPCs.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + chkEnableNPCsActionPerformed(evt); + } + }); + + chkAllowFlight.setText("鍏佽椋炶"); + chkAllowFlight.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + chkAllowFlightActionPerformed(evt); + } + }); + + chkPVP.setText("鍏佽pvp"); + chkPVP.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + chkPVPActionPerformed(evt); + } + }); + + chkAllowNether.setText("寮鏀惧湴鐙"); + chkAllowNether.setToolTipText(""); + chkAllowNether.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + chkAllowNetherActionPerformed(evt); + } + }); + + chkWhiteList.setText("寮鍚櫧鍚嶅崟"); + chkWhiteList.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + chkWhiteListActionPerformed(evt); + } + }); + + txtServerName.addFocusListener(new java.awt.event.FocusAdapter() { + public void focusLost(java.awt.event.FocusEvent evt) { + txtServerNameFocusLost(evt); + } + }); + + jLabel15.setText("鏈嶅姟鍣ㄥ悕绉"); + + jLabel16.setText("鏈澶у缓绛戦珮搴"); + + txtMaxBuildHeight.addFocusListener(new java.awt.event.FocusAdapter() { + public void focusLost(java.awt.event.FocusEvent evt) { + txtMaxBuildHeightFocusLost(evt); + } + }); + + jLabel18.setText("鍦板浘鐢熸垚鍣ㄨ缃"); + + txtServerGeneratorSettings.addFocusListener(new java.awt.event.FocusAdapter() { + public void focusLost(java.awt.event.FocusEvent evt) { + txtServerGeneratorSettingsFocusLost(evt); + } + }); + + txtWorldSeed.addFocusListener(new java.awt.event.FocusAdapter() { + public void focusLost(java.awt.event.FocusEvent evt) { + txtWorldSeedFocusLost(evt); + } + }); + + jLabel19.setText("鍦板浘绉嶅瓙"); + + chkGenerateStructures.setText("鐢熸垚寤虹瓚"); + chkGenerateStructures.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + chkGenerateStructuresActionPerformed(evt); + } + }); + + chkOnlineMode.setText("寮鍚鐗"); + chkOnlineMode.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + chkOnlineModeActionPerformed(evt); + } + }); + + javax.swing.GroupLayout jPanel3Layout = new javax.swing.GroupLayout(jPanel3); + jPanel3.setLayout(jPanel3Layout); + jPanel3Layout.setHorizontalGroup( + jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jPanel3Layout.createSequentialGroup() + .addContainerGap() + .addGroup(jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jPanel3Layout.createSequentialGroup() + .addGroup(jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(jLabel5) + .addComponent(jLabel6) + .addComponent(jLabel7) + .addComponent(jLabel16) + .addComponent(jLabel8) + .addComponent(jLabel18)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(txtServerGeneratorSettings) + .addComponent(txtWorldName) + .addComponent(txtMaxBuildHeight) + .addComponent(txtViewDistance) + .addComponent(txtMaxPlayer) + .addComponent(txtServerPort))) + .addGroup(jPanel3Layout.createSequentialGroup() + .addGroup(jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(jLabel15) + .addComponent(jLabel10) + .addComponent(jLabel11) + .addComponent(jLabel9) + .addComponent(jLabel12) + .addComponent(jLabel19)) + .addGroup(jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jPanel3Layout.createSequentialGroup() + .addGap(26, 26, 26) + .addGroup(jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(cboDifficulty, 0, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(cboGameMode, javax.swing.GroupLayout.Alignment.TRAILING, 0, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(txtServerMOTD, javax.swing.GroupLayout.Alignment.TRAILING))) + .addGroup(jPanel3Layout.createSequentialGroup() + .addGap(28, 28, 28) + .addGroup(jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(txtServerName, javax.swing.GroupLayout.Alignment.TRAILING) + .addComponent(cboWorldType, javax.swing.GroupLayout.Alignment.TRAILING, 0, 418, Short.MAX_VALUE) + .addComponent(txtWorldSeed))))) + .addGroup(jPanel3Layout.createSequentialGroup() + .addGroup(jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jPanel3Layout.createSequentialGroup() + .addComponent(chkEnalbleAnimals) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) + .addComponent(chkEnableMonsters)) + .addGroup(jPanel3Layout.createSequentialGroup() + .addComponent(chkAllowFlight) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) + .addComponent(chkPVP))) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) + .addGroup(jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jPanel3Layout.createSequentialGroup() + .addComponent(chkEnableNPCs) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) + .addComponent(chkGenerateStructures) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(chkOnlineMode)) + .addGroup(jPanel3Layout.createSequentialGroup() + .addComponent(chkAllowNether) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) + .addComponent(chkWhiteList))))) + .addContainerGap()) + ); + jPanel3Layout.setVerticalGroup( + jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jPanel3Layout.createSequentialGroup() + .addContainerGap() + .addGroup(jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(jLabel5) + .addComponent(txtServerPort, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(jLabel6) + .addComponent(txtMaxPlayer, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(jLabel7) + .addComponent(txtViewDistance, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(jLabel16) + .addComponent(txtMaxBuildHeight, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(jLabel8) + .addComponent(txtWorldName, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(jLabel18) + .addComponent(txtServerGeneratorSettings, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(jLabel19) + .addComponent(txtWorldSeed, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(jLabel9) + .addComponent(cboWorldType, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(jLabel15) + .addComponent(txtServerName, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(jLabel10) + .addComponent(txtServerMOTD, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(jLabel11) + .addComponent(cboGameMode, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(jLabel12) + .addComponent(cboDifficulty, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) + .addGroup(jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(chkEnalbleAnimals) + .addComponent(chkEnableMonsters) + .addComponent(chkEnableNPCs) + .addComponent(chkGenerateStructures) + .addComponent(chkOnlineMode)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) + .addGroup(jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(chkAllowFlight) + .addComponent(chkPVP) + .addComponent(chkAllowNether) + .addComponent(chkWhiteList)) + .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) + ); + + jTabbedPane6.addTab("娓告垙璁剧疆", jPanel3); + + jLabel14.setText("鍐呭瓨澶у皬"); + + jLabel25.setText("Java璺緞"); + + jLabel26.setText("Java鍙傛暟"); + + txtMaxMemory.setText("jTextField1"); + txtMaxMemory.addFocusListener(new java.awt.event.FocusAdapter() { + public void focusLost(java.awt.event.FocusEvent evt) { + txtMaxMemoryFocusLost(evt); + } + }); + + javax.swing.GroupLayout jPanel25Layout = new javax.swing.GroupLayout(jPanel25); + jPanel25.setLayout(jPanel25Layout); + jPanel25Layout.setHorizontalGroup( + jPanel25Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jPanel25Layout.createSequentialGroup() + .addContainerGap() + .addGroup(jPanel25Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jPanel25Layout.createSequentialGroup() + .addComponent(jLabel14) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(txtMaxMemory)) + .addGroup(jPanel25Layout.createSequentialGroup() + .addComponent(jLabel25) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(txtJavaDir, javax.swing.GroupLayout.DEFAULT_SIZE, 468, Short.MAX_VALUE)) + .addGroup(jPanel25Layout.createSequentialGroup() + .addComponent(jLabel26) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(txtJavaArgs, javax.swing.GroupLayout.DEFAULT_SIZE, 446, Short.MAX_VALUE))) + .addContainerGap()) + ); + jPanel25Layout.setVerticalGroup( + jPanel25Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jPanel25Layout.createSequentialGroup() + .addContainerGap() + .addGroup(jPanel25Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(jLabel14) + .addComponent(txtMaxMemory, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(jPanel25Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(jLabel25) + .addComponent(txtJavaDir, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(jPanel25Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(jLabel26) + .addComponent(txtJavaArgs, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addContainerGap(342, Short.MAX_VALUE)) + ); + + jTabbedPane6.addTab("Java璁剧疆", jPanel25); + + javax.swing.GroupLayout jPanel24Layout = new javax.swing.GroupLayout(jPanel24); + jPanel24.setLayout(jPanel24Layout); + jPanel24Layout.setHorizontalGroup( + jPanel24Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(jTabbedPane6) + ); + jPanel24Layout.setVerticalGroup( + jPanel24Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(jTabbedPane6) + ); + + jTabbedPane6.getAccessibleContext().setAccessibleName(""); + + jTabbedPane2.addTab("鏈嶅姟鍣ㄨ缃", jPanel24); + + jLabel20.setText("鑳屾櫙"); + + txtBackgroundPath.addFocusListener(new java.awt.event.FocusAdapter() { + public void focusLost(java.awt.event.FocusEvent evt) { + txtBackgroundPathFocusLost(evt); + } + }); + + btnSetBackgroundPath.setText("娴忚"); + btnSetBackgroundPath.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + btnSetBackgroundPathActionPerformed(evt); + } + }); + + javax.swing.GroupLayout jPanel12Layout = new javax.swing.GroupLayout(jPanel12); + jPanel12.setLayout(jPanel12Layout); + jPanel12Layout.setHorizontalGroup( + jPanel12Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jPanel12Layout.createSequentialGroup() + .addContainerGap() + .addComponent(jLabel20) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(txtBackgroundPath, javax.swing.GroupLayout.DEFAULT_SIZE, 412, Short.MAX_VALUE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(btnSetBackgroundPath) + .addContainerGap()) + ); + jPanel12Layout.setVerticalGroup( + jPanel12Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jPanel12Layout.createSequentialGroup() + .addContainerGap() + .addGroup(jPanel12Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(jLabel20) + .addComponent(txtBackgroundPath, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(btnSetBackgroundPath)) + .addContainerGap(419, Short.MAX_VALUE)) + ); + + jTabbedPane2.addTab("寮鏈嶅櫒璁剧疆", jPanel12); + + jScrollPane1.setViewportView(lstOP); + + btnAddOP.setText("娣诲姞"); + btnAddOP.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + btnAddOPActionPerformed(evt); + } + }); + + jLabel2.setText("鐜╁鍚"); + + btnDeleteOP.setText("鍒犻櫎閫変腑"); + btnDeleteOP.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + btnDeleteOPActionPerformed(evt); + } + }); + + jLabel40.setText("<html>\n鍦ㄦ病鏈夊紑鏈嶇殑<br/>\n鎯呭喌涓嬩娇鐢ㄦ湰<br/>\n鍔熻兘浼氱洿鎺ヨ<br/>\n鐩杍son鏂囦欢锛<br/>\n杩欎細瀵艰嚧鍦<br/>\n1.7.10鏈嶅姟绔腑<br/>\n鐨勮缃鎶归櫎<br/>\n锛岃屼笖涓嶆敮鎸<br/>\n姝g増楠岃瘉锛岄潪<br/>\n1.7.10鎴栨洿楂<br/>\n鐗堟湰鏈嶅姟绔棤<br/>\n姝ら棶棰樸俓n</html>"); + + javax.swing.GroupLayout jPanel5Layout = new javax.swing.GroupLayout(jPanel5); + jPanel5.setLayout(jPanel5Layout); + jPanel5Layout.setHorizontalGroup( + jPanel5Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jPanel5Layout.createSequentialGroup() + .addContainerGap() + .addComponent(jScrollPane1) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(jPanel5Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jPanel5Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false) + .addComponent(jLabel2) + .addComponent(btnAddOP, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(txtOPName) + .addComponent(btnDeleteOP, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) + .addComponent(jLabel40, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addContainerGap()) + ); + jPanel5Layout.setVerticalGroup( + jPanel5Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel5Layout.createSequentialGroup() + .addContainerGap() + .addGroup(jPanel5Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING) + .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 405, Short.MAX_VALUE) + .addGroup(jPanel5Layout.createSequentialGroup() + .addComponent(jLabel2) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(txtOPName, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(btnAddOP) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(jLabel40, 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) + .addComponent(btnDeleteOP))) + .addContainerGap()) + ); + + jTabbedPane3.addTab("绠$悊鍛", jPanel5); + + btnDeleteWhite.setText("鍒犻櫎閫変腑"); + btnDeleteWhite.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + btnDeleteWhiteActionPerformed(evt); + } + }); + + jScrollPane3.setViewportView(lstWhiteList); + + jLabel4.setText("鐜╁鍚"); + + btnAddWhite.setText("娣诲姞"); + btnAddWhite.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + btnAddWhiteActionPerformed(evt); + } + }); + + jLabel41.setText("<html>\n鍦ㄦ病鏈夊紑鏈嶇殑<br/>\n鎯呭喌涓嬩娇鐢ㄦ湰<br/>\n鍔熻兘浼氱洿鎺ヨ<br/>\n鐩杍son鏂囦欢锛<br/>\n杩欎細瀵艰嚧鍦<br/>\n1.7.10鏈嶅姟绔腑<br/>\n鐨勮缃鎶归櫎<br/>\n锛岃屼笖涓嶆敮鎸<br/>\n姝g増楠岃瘉锛岄潪<br/>\n1.7.10鎴栨洿楂<br/>\n鐗堟湰鏈嶅姟绔棤<br/>\n姝ら棶棰樸俓n</html>"); + + javax.swing.GroupLayout jPanel6Layout = new javax.swing.GroupLayout(jPanel6); + jPanel6.setLayout(jPanel6Layout); + jPanel6Layout.setHorizontalGroup( + jPanel6Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jPanel6Layout.createSequentialGroup() + .addContainerGap() + .addComponent(jScrollPane3, javax.swing.GroupLayout.DEFAULT_SIZE, 413, Short.MAX_VALUE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(jPanel6Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jPanel6Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false) + .addComponent(jLabel4) + .addComponent(btnDeleteWhite, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(btnAddWhite, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(txtWhiteName)) + .addComponent(jLabel41, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addContainerGap()) + ); + jPanel6Layout.setVerticalGroup( + jPanel6Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel6Layout.createSequentialGroup() + .addContainerGap() + .addGroup(jPanel6Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING) + .addComponent(jScrollPane3, javax.swing.GroupLayout.DEFAULT_SIZE, 405, Short.MAX_VALUE) + .addGroup(jPanel6Layout.createSequentialGroup() + .addComponent(jLabel4) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(txtWhiteName, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(btnAddWhite) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(jLabel41, 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) + .addComponent(btnDeleteWhite))) + .addContainerGap()) + ); + + jTabbedPane3.addTab("鐧藉悕鍗", jPanel6); + + btnUnban.setText("鍒犻櫎閫変腑"); + btnUnban.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + btnUnbanActionPerformed(evt); + } + }); + + jScrollPane2.setViewportView(lstBanned); + + jLabel3.setText("鐜╁鍚"); + + btnAddBan.setText("娣诲姞"); + btnAddBan.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + btnAddBanActionPerformed(evt); + } + }); + + jLabel42.setText("<html>\n鍦ㄦ病鏈夊紑鏈嶇殑<br/>\n鎯呭喌涓嬩娇鐢ㄦ湰<br/>\n鍔熻兘浼氱洿鎺ヨ<br/>\n鐩杍son鏂囦欢锛<br/>\n杩欎細瀵艰嚧鍦<br/>\n1.7.10鏈嶅姟绔腑<br/>\n鐨勮缃鎶归櫎<br/>\n锛岃屼笖涓嶆敮鎸<br/>\n姝g増楠岃瘉锛岄潪<br/>\n1.7.10鎴栨洿楂<br/>\n鐗堟湰鏈嶅姟绔棤<br/>\n姝ら棶棰樸俓n</html>"); + + javax.swing.GroupLayout jPanel7Layout = new javax.swing.GroupLayout(jPanel7); + jPanel7.setLayout(jPanel7Layout); + jPanel7Layout.setHorizontalGroup( + jPanel7Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jPanel7Layout.createSequentialGroup() + .addContainerGap() + .addComponent(jScrollPane2, javax.swing.GroupLayout.DEFAULT_SIZE, 413, Short.MAX_VALUE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(jPanel7Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jPanel7Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false) + .addComponent(jLabel3) + .addComponent(btnUnban, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(btnAddBan, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(txtBanName)) + .addComponent(jLabel42, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addContainerGap()) + ); + jPanel7Layout.setVerticalGroup( + jPanel7Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel7Layout.createSequentialGroup() + .addContainerGap() + .addGroup(jPanel7Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING) + .addComponent(jScrollPane2, javax.swing.GroupLayout.DEFAULT_SIZE, 405, Short.MAX_VALUE) + .addGroup(jPanel7Layout.createSequentialGroup() + .addComponent(jLabel3) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(txtBanName, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(btnAddBan) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(jLabel42, 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) + .addComponent(btnUnban))) + .addContainerGap()) + ); + + jTabbedPane3.addTab("榛戝悕鍗", jPanel7); + + javax.swing.GroupLayout jPanel4Layout = new javax.swing.GroupLayout(jPanel4); + jPanel4.setLayout(jPanel4Layout); + jPanel4Layout.setHorizontalGroup( + jPanel4Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(jTabbedPane3) + ); + jPanel4Layout.setVerticalGroup( + jPanel4Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(jTabbedPane3, javax.swing.GroupLayout.Alignment.TRAILING) + ); + + jTabbedPane2.addTab("鐜╁绠$悊", jPanel4); + + javax.swing.GroupLayout jPanel2Layout = new javax.swing.GroupLayout(jPanel2); + jPanel2.setLayout(jPanel2Layout); + jPanel2Layout.setHorizontalGroup( + jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(jTabbedPane2) + ); + jPanel2Layout.setVerticalGroup( + jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(jTabbedPane2) + ); + + jTabbedPane1.addTab("璁剧疆", jPanel2); + + lstExternalMods.setModel(new javax.swing.table.DefaultTableModel( + new Object [][] { + + }, + new String [] { + "娲诲姩", "璺緞", "绫诲瀷" + } + ) { + Class[] types = new Class [] { + java.lang.Boolean.class, java.lang.String.class, java.lang.String.class + }; + + public Class getColumnClass(int columnIndex) { + return types [columnIndex]; + } + }); + jScrollPane5.setViewportView(lstExternalMods); + + btnManageExtMods.setText("绠$悊"); + btnManageExtMods.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + btnManageExtModsActionPerformed(evt); + } + }); + + java.util.ResourceBundle bundle = java.util.ResourceBundle.getBundle("org/jackhuang/hellominecraftlauncher/VersionSettingsWindow"); // NOI18N + btnAddExternelMod.setText(bundle.getString("澧炲姞")); // NOI18N + btnAddExternelMod.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + btnAddExternelModActionPerformed(evt); + } + }); + + btnDeleteExternelMod.setText(bundle.getString("鍒犻櫎")); // NOI18N + btnDeleteExternelMod.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + btnDeleteExternelModActionPerformed(evt); + } + }); + + btnSaveExtMod.setText("淇濆瓨"); + btnSaveExtMod.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + btnSaveExtModActionPerformed(evt); + } + }); + + javax.swing.GroupLayout jPanel9Layout = new javax.swing.GroupLayout(jPanel9); + jPanel9.setLayout(jPanel9Layout); + jPanel9Layout.setHorizontalGroup( + jPanel9Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jPanel9Layout.createSequentialGroup() + .addContainerGap() + .addComponent(jScrollPane5, javax.swing.GroupLayout.DEFAULT_SIZE, 450, Short.MAX_VALUE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(jPanel9Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jPanel9Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(btnAddExternelMod, javax.swing.GroupLayout.Alignment.TRAILING) + .addComponent(btnDeleteExternelMod, javax.swing.GroupLayout.Alignment.TRAILING)) + .addComponent(btnManageExtMods) + .addComponent(btnSaveExtMod, javax.swing.GroupLayout.Alignment.TRAILING)) + .addContainerGap()) + ); + jPanel9Layout.setVerticalGroup( + jPanel9Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jPanel9Layout.createSequentialGroup() + .addContainerGap() + .addGroup(jPanel9Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jPanel9Layout.createSequentialGroup() + .addComponent(jScrollPane5, javax.swing.GroupLayout.PREFERRED_SIZE, 0, Short.MAX_VALUE) + .addContainerGap()) + .addGroup(jPanel9Layout.createSequentialGroup() + .addComponent(btnManageExtMods) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(btnAddExternelMod) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(btnDeleteExternelMod) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(btnSaveExtMod) + .addGap(0, 317, Short.MAX_VALUE)))) + ); + + jTabbedPane4.addTab("Mod绠$悊", jPanel9); + + lstCoreMods.setModel(new javax.swing.table.DefaultTableModel( + new Object [][] { + + }, + new String [] { + "娲诲姩", "璺緞", "绫诲瀷" + } + ) { + Class[] types = new Class [] { + java.lang.Boolean.class, java.lang.String.class, java.lang.String.class + }; + + public Class getColumnClass(int columnIndex) { + return types [columnIndex]; + } + }); + jScrollPane6.setViewportView(lstCoreMods); + + btnManageCoreMods.setText("绠$悊"); + btnManageCoreMods.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + btnManageCoreModsActionPerformed(evt); + } + }); + + btnAddExternelCoreMod.setText(bundle.getString("澧炲姞")); // NOI18N + btnAddExternelCoreMod.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + btnAddExternelCoreModActionPerformed(evt); + } + }); + + btnDeleteExternelCoreMod.setText(bundle.getString("鍒犻櫎")); // NOI18N + btnDeleteExternelCoreMod.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + btnDeleteExternelCoreModActionPerformed(evt); + } + }); + + btnSaveCoreMod.setText("淇濆瓨"); + btnSaveCoreMod.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + btnSaveCoreModActionPerformed(evt); + } + }); + + javax.swing.GroupLayout jPanel10Layout = new javax.swing.GroupLayout(jPanel10); + jPanel10.setLayout(jPanel10Layout); + jPanel10Layout.setHorizontalGroup( + jPanel10Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jPanel10Layout.createSequentialGroup() + .addContainerGap() + .addComponent(jScrollPane6, javax.swing.GroupLayout.DEFAULT_SIZE, 450, Short.MAX_VALUE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(jPanel10Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(btnSaveCoreMod) + .addGroup(jPanel10Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(btnManageCoreMods) + .addComponent(btnAddExternelCoreMod, javax.swing.GroupLayout.Alignment.TRAILING)) + .addComponent(btnDeleteExternelCoreMod)) + .addContainerGap()) + ); + jPanel10Layout.setVerticalGroup( + jPanel10Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jPanel10Layout.createSequentialGroup() + .addContainerGap() + .addGroup(jPanel10Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(jScrollPane6, javax.swing.GroupLayout.DEFAULT_SIZE, 435, Short.MAX_VALUE) + .addGroup(jPanel10Layout.createSequentialGroup() + .addComponent(btnManageCoreMods) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(btnAddExternelCoreMod) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(btnDeleteExternelCoreMod) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(btnSaveCoreMod) + .addGap(0, 0, Short.MAX_VALUE))) + .addContainerGap()) + ); + + jTabbedPane4.addTab("鏍稿績Mod绠$悊", jPanel10); + + lstPlugins.setModel(new javax.swing.table.DefaultTableModel( + new Object [][] { + + }, + new String [] { + "娲诲姩", "璺緞", "鍚嶇О", "鐗堟湰", "浣滆", "鎻忚堪" + } + ) { + Class[] types = new Class [] { + java.lang.Boolean.class, java.lang.String.class, java.lang.String.class, java.lang.String.class, java.lang.String.class, java.lang.String.class + }; + + public Class getColumnClass(int columnIndex) { + return types [columnIndex]; + } + }); + jScrollPane7.setViewportView(lstPlugins); + + btnManagePlugins.setText("绠$悊"); + btnManagePlugins.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + btnManagePluginsActionPerformed(evt); + } + }); + + btnAddPlugins.setText(bundle.getString("澧炲姞")); // NOI18N + btnAddPlugins.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + btnAddPluginsActionPerformed(evt); + } + }); + + btnDeletePlugins.setText(bundle.getString("鍒犻櫎")); // NOI18N + btnDeletePlugins.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + btnDeletePluginsActionPerformed(evt); + } + }); + + btnSavePlugins.setText("淇濆瓨"); + btnSavePlugins.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + btnSavePluginsActionPerformed(evt); + } + }); + + javax.swing.GroupLayout jPanel11Layout = new javax.swing.GroupLayout(jPanel11); + jPanel11.setLayout(jPanel11Layout); + jPanel11Layout.setHorizontalGroup( + jPanel11Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jPanel11Layout.createSequentialGroup() + .addContainerGap() + .addComponent(jScrollPane7, javax.swing.GroupLayout.DEFAULT_SIZE, 450, Short.MAX_VALUE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(jPanel11Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jPanel11Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(btnAddPlugins, javax.swing.GroupLayout.Alignment.TRAILING) + .addComponent(btnDeletePlugins, javax.swing.GroupLayout.Alignment.TRAILING)) + .addComponent(btnSavePlugins) + .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel11Layout.createSequentialGroup() + .addComponent(btnManagePlugins) + .addContainerGap()))) + ); + jPanel11Layout.setVerticalGroup( + jPanel11Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jPanel11Layout.createSequentialGroup() + .addContainerGap() + .addGroup(jPanel11Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jPanel11Layout.createSequentialGroup() + .addComponent(btnManagePlugins) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(btnAddPlugins) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(btnDeletePlugins) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(btnSavePlugins) + .addGap(0, 0, Short.MAX_VALUE)) + .addComponent(jScrollPane7, javax.swing.GroupLayout.DEFAULT_SIZE, 435, Short.MAX_VALUE)) + .addContainerGap()) + ); + + jTabbedPane4.addTab("鎻掍欢绠$悊", jPanel11); + + javax.swing.GroupLayout jPanel8Layout = new javax.swing.GroupLayout(jPanel8); + jPanel8.setLayout(jPanel8Layout); + jPanel8Layout.setHorizontalGroup( + jPanel8Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(jTabbedPane4) + ); + jPanel8Layout.setVerticalGroup( + jPanel8Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(jTabbedPane4) + ); + + jTabbedPane1.addTab("妯$粍绠$悊", jPanel8); + + jLabel21.setText("鏂板缓璁″垝浠诲姟"); + + cboTimerTask.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "鑷姩淇濆瓨", "鑷姩閲嶅惎", "鑷姩澶囦唤", "鑷姩骞挎挱", "鑷姩鍙戦佸懡浠" })); + + jLabel22.setText("闂撮殧鏃堕棿锛堝垎閽燂級"); + + btnNewTask.setText("鏂板缓璁″垝浠诲姟"); + btnNewTask.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + btnNewTaskActionPerformed(evt); + } + }); + + jLabel13.setText("鍐呭"); + + jLabel28.setText("鏃堕棿绫诲瀷"); + + cboTimeType.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "姣弜鍒嗛挓", "鏁寸偣杩囧幓x鍒嗛挓", "鏈嶅姟鍣ㄥ惎鍔", "鏈嶅姟鍣ㄥ叧闂", "鏈嶅姟鍣ㄥ穿婧" })); + + btnDelSelectedSchedule.setText("鍒犻櫎閫変腑"); + btnDelSelectedSchedule.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + btnDelSelectedScheduleActionPerformed(evt); + } + }); + + javax.swing.GroupLayout jPanel14Layout = new javax.swing.GroupLayout(jPanel14); + jPanel14.setLayout(jPanel14Layout); + jPanel14Layout.setHorizontalGroup( + jPanel14Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jPanel14Layout.createSequentialGroup() + .addContainerGap() + .addGroup(jPanel14Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jPanel14Layout.createSequentialGroup() + .addGroup(jPanel14Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(cboTimerTask, javax.swing.GroupLayout.PREFERRED_SIZE, 95, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(jLabel21)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(jPanel14Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(jLabel28) + .addComponent(cboTimeType, 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(jPanel14Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(txtTimerTaskPeriod, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.PREFERRED_SIZE, 96, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(jLabel22, javax.swing.GroupLayout.Alignment.TRAILING))) + .addComponent(jLabel13) + .addComponent(txtTimerTaskContent, javax.swing.GroupLayout.PREFERRED_SIZE, 197, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addGroup(jPanel14Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jPanel14Layout.createSequentialGroup() + .addGap(73, 73, 73) + .addComponent(btnNewTask)) + .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel14Layout.createSequentialGroup() + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(btnDelSelectedSchedule))) + .addContainerGap()) + ); + jPanel14Layout.setVerticalGroup( + jPanel14Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jPanel14Layout.createSequentialGroup() + .addContainerGap() + .addGroup(jPanel14Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jPanel14Layout.createSequentialGroup() + .addGroup(jPanel14Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(jLabel21) + .addComponent(jLabel22) + .addComponent(jLabel28)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(jPanel14Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(cboTimerTask, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(txtTimerTaskPeriod, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(cboTimeType, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(jLabel13) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(txtTimerTaskContent, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addGroup(jPanel14Layout.createSequentialGroup() + .addComponent(btnNewTask) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(btnDelSelectedSchedule))) + .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) + ); + + lstSchedules.setModel(new javax.swing.table.DefaultTableModel( + new Object [][] { + + }, + new String [] { + "绫诲瀷", "鏃堕棿绫诲瀷", "闂撮殧鏃堕棿锛堝垎閽燂級", "鍐呭" + } + ) { + Class[] types = new Class [] { + java.lang.String.class, java.lang.String.class, java.lang.Double.class, java.lang.String.class + }; + boolean[] canEdit = new boolean [] { + true, false, false, true + }; + + public Class getColumnClass(int columnIndex) { + return types [columnIndex]; + } + + public boolean isCellEditable(int rowIndex, int columnIndex) { + return canEdit [columnIndex]; + } + }); + jScrollPane9.setViewportView(lstSchedules); + + javax.swing.GroupLayout jPanel13Layout = new javax.swing.GroupLayout(jPanel13); + jPanel13.setLayout(jPanel13Layout); + jPanel13Layout.setHorizontalGroup( + jPanel13Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(jPanel14, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(jScrollPane9) + ); + jPanel13Layout.setVerticalGroup( + jPanel13Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel13Layout.createSequentialGroup() + .addComponent(jScrollPane9, javax.swing.GroupLayout.DEFAULT_SIZE, 356, Short.MAX_VALUE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(jPanel14, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) + ); + + jTabbedPane1.addTab("璁″垝浠诲姟", jPanel13); + + jLabel23.setText("鏂板缓澶囦唤"); + + cboBackupTypes.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "鍦板浘澶囦唤", "鎻掍欢澶囦唤" })); + + btnBackup.setText("澶囦唤"); + btnBackup.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + btnBackupActionPerformed(evt); + } + }); + + javax.swing.GroupLayout jPanel17Layout = new javax.swing.GroupLayout(jPanel17); + jPanel17.setLayout(jPanel17Layout); + jPanel17Layout.setHorizontalGroup( + jPanel17Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jPanel17Layout.createSequentialGroup() + .addContainerGap() + .addGroup(jPanel17Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jPanel17Layout.createSequentialGroup() + .addComponent(jLabel23) + .addGap(0, 0, Short.MAX_VALUE)) + .addComponent(cboBackupTypes, 0, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel17Layout.createSequentialGroup() + .addGap(0, 0, Short.MAX_VALUE) + .addComponent(btnBackup))) + .addContainerGap()) + ); + jPanel17Layout.setVerticalGroup( + jPanel17Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jPanel17Layout.createSequentialGroup() + .addContainerGap() + .addComponent(jLabel23) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(cboBackupTypes, 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) + .addComponent(btnBackup) + .addContainerGap()) + ); + + jButton1.setText("鍒锋柊澶囦唤鍒楄〃"); + jButton1.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + jButton1ActionPerformed(evt); + } + }); + + btnDeleteBackup.setText("鍒犻櫎閫変腑澶囦唤"); + btnDeleteBackup.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + btnDeleteBackupActionPerformed(evt); + } + }); + + btnRestoreBackup.setText("鎭㈠閫変腑澶囦唤"); + btnRestoreBackup.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + btnRestoreBackupActionPerformed(evt); + } + }); + + javax.swing.GroupLayout jPanel16Layout = new javax.swing.GroupLayout(jPanel16); + jPanel16.setLayout(jPanel16Layout); + jPanel16Layout.setHorizontalGroup( + jPanel16Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(jPanel17, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addGroup(jPanel16Layout.createSequentialGroup() + .addContainerGap() + .addGroup(jPanel16Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(jButton1) + .addComponent(btnDeleteBackup) + .addComponent(btnRestoreBackup)) + .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) + ); + jPanel16Layout.setVerticalGroup( + jPanel16Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jPanel16Layout.createSequentialGroup() + .addComponent(jPanel17, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 272, Short.MAX_VALUE) + .addComponent(btnRestoreBackup) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(btnDeleteBackup) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(jButton1) + .addContainerGap()) + ); + + lstBackups.setModel(new javax.swing.table.DefaultTableModel( + new Object [][] { + + }, + new String [] { + "绫诲瀷", "鏃堕棿", "鍚嶇О" + } + ) { + Class[] types = new Class [] { + java.lang.String.class, java.lang.String.class, java.lang.String.class + }; + + public Class getColumnClass(int columnIndex) { + return types [columnIndex]; + } + }); + jScrollPane11.setViewportView(lstBackups); + + javax.swing.GroupLayout jPanel15Layout = new javax.swing.GroupLayout(jPanel15); + jPanel15.setLayout(jPanel15Layout); + jPanel15Layout.setHorizontalGroup( + jPanel15Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jPanel15Layout.createSequentialGroup() + .addComponent(jPanel16, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(jScrollPane11, javax.swing.GroupLayout.DEFAULT_SIZE, 391, Short.MAX_VALUE) + .addContainerGap()) + ); + jPanel15Layout.setVerticalGroup( + jPanel15Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(jPanel16, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel15Layout.createSequentialGroup() + .addContainerGap() + .addComponent(jScrollPane11, javax.swing.GroupLayout.PREFERRED_SIZE, 0, Short.MAX_VALUE) + .addContainerGap()) + ); + + jTabbedPane1.addTab("澶囦唤", jPanel15); + + lstWorlds.setModel(new javax.swing.table.DefaultTableModel( + new Object [][] { + + }, + new String [] { + "鍦板浘鍚", "璺緞", "鏄惁鍏佽澶囦唤" + } + ) { + Class[] types = new Class [] { + java.lang.String.class, java.lang.String.class, java.lang.Boolean.class + }; + + public Class getColumnClass(int columnIndex) { + return types [columnIndex]; + } + }); + jScrollPane10.setViewportView(lstWorlds); + + btnRefreshWorlds.setText("鍒锋柊"); + btnRefreshWorlds.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + btnRefreshWorldsActionPerformed(evt); + } + }); + + btnSaveWorld.setText("淇濆瓨淇敼"); + btnSaveWorld.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + btnSaveWorldActionPerformed(evt); + } + }); + + javax.swing.GroupLayout jPanel18Layout = new javax.swing.GroupLayout(jPanel18); + jPanel18.setLayout(jPanel18Layout); + jPanel18Layout.setHorizontalGroup( + jPanel18Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jPanel18Layout.createSequentialGroup() + .addContainerGap() + .addGroup(jPanel18Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(jScrollPane10, javax.swing.GroupLayout.DEFAULT_SIZE, 521, Short.MAX_VALUE) + .addGroup(jPanel18Layout.createSequentialGroup() + .addComponent(btnRefreshWorlds) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(btnSaveWorld))) + .addContainerGap()) + ); + jPanel18Layout.setVerticalGroup( + jPanel18Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jPanel18Layout.createSequentialGroup() + .addContainerGap() + .addComponent(jScrollPane10, javax.swing.GroupLayout.DEFAULT_SIZE, 431, Short.MAX_VALUE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(jPanel18Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(btnRefreshWorlds) + .addComponent(btnSaveWorld)) + .addContainerGap()) + ); + + jTabbedPane1.addTab("鍦板浘绠$悊", jPanel18); + + lstCraftbukkit.setModel(new javax.swing.table.DefaultTableModel( + new Object [][] { + + }, + new String [] { + "缂栬瘧鍙", "鐗堟湰" + } + ) { + Class[] types = new Class [] { + java.lang.String.class, java.lang.String.class + }; + + public Class getColumnClass(int columnIndex) { + return types [columnIndex]; + } + }); + lstCraftbukkit.setSelectionMode(javax.swing.ListSelectionModel.SINGLE_SELECTION); + jScrollPane18.setViewportView(lstCraftbukkit); + + btnDownloadCraftbukkit.setText("涓嬭浇"); + btnDownloadCraftbukkit.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + btnDownloadCraftbukkitActionPerformed(evt); + } + }); + + lstRefreshCraftbukkit.setText("鍒锋柊"); + lstRefreshCraftbukkit.setToolTipText(""); + lstRefreshCraftbukkit.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + lstRefreshCraftbukkitActionPerformed(evt); + } + }); + + cboBukkitType.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "绋冲畾鐗", "娴嬭瘯鐗", "鏈鏂板紑鍙戠増" })); + cboBukkitType.addItemListener(new java.awt.event.ItemListener() { + public void itemStateChanged(java.awt.event.ItemEvent evt) { + cboBukkitTypeItemStateChanged(evt); + } + }); + + jLabel39.setText("Bukkit绫诲瀷"); + + javax.swing.GroupLayout jPanel20Layout = new javax.swing.GroupLayout(jPanel20); + jPanel20.setLayout(jPanel20Layout); + jPanel20Layout.setHorizontalGroup( + jPanel20Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jPanel20Layout.createSequentialGroup() + .addContainerGap() + .addGroup(jPanel20Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jPanel20Layout.createSequentialGroup() + .addComponent(jLabel39) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(cboBukkitType, 0, 442, Short.MAX_VALUE)) + .addGroup(jPanel20Layout.createSequentialGroup() + .addComponent(jScrollPane18, javax.swing.GroupLayout.DEFAULT_SIZE, 450, Short.MAX_VALUE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(jPanel20Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(btnDownloadCraftbukkit, javax.swing.GroupLayout.Alignment.TRAILING) + .addComponent(lstRefreshCraftbukkit, javax.swing.GroupLayout.Alignment.TRAILING)))) + .addContainerGap()) + ); + jPanel20Layout.setVerticalGroup( + jPanel20Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jPanel20Layout.createSequentialGroup() + .addContainerGap() + .addGroup(jPanel20Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(jLabel39) + .addComponent(cboBukkitType, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(jPanel20Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jPanel20Layout.createSequentialGroup() + .addComponent(btnDownloadCraftbukkit) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(lstRefreshCraftbukkit) + .addGap(0, 0, Short.MAX_VALUE)) + .addComponent(jScrollPane18, javax.swing.GroupLayout.DEFAULT_SIZE, 402, Short.MAX_VALUE)) + .addContainerGap()) + ); + + jTabbedPane5.addTab("CraftBukkit", jPanel20); + + lstMCPC.setModel(new javax.swing.table.DefaultTableModel( + new Object [][] { + + }, + new String [] { + "MC鐗堟湰", "Cauldron鐗堟湰", "閲婃斁鏃堕棿" + } + ) { + Class[] types = new Class [] { + java.lang.String.class, java.lang.String.class, java.lang.String.class + }; + boolean[] canEdit = new boolean [] { + false, false, false + }; + + public Class getColumnClass(int columnIndex) { + return types [columnIndex]; + } + + public boolean isCellEditable(int rowIndex, int columnIndex) { + return canEdit [columnIndex]; + } + }); + lstMCPC.setSelectionMode(javax.swing.ListSelectionModel.SINGLE_SELECTION); + jScrollPane19.setViewportView(lstMCPC); + + btnDownloadMCPC.setLabel("涓嬭浇"); + btnDownloadMCPC.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + btnDownloadMCPCActionPerformed(evt); + } + }); + + lstRefreshMCPC.setToolTipText(""); + lstRefreshMCPC.setLabel("鍒锋柊"); + lstRefreshMCPC.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + lstRefreshMCPCActionPerformed(evt); + } + }); + + jLabel38.setText("Minecraft鐗堟湰"); + + cboCauldronMinecraft.addItemListener(new java.awt.event.ItemListener() { + public void itemStateChanged(java.awt.event.ItemEvent evt) { + cboCauldronMinecraftItemStateChanged(evt); + } + }); + + btnInstallMCPC.setText("閲嶈瘯"); + btnInstallMCPC.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + btnInstallMCPCActionPerformed(evt); + } + }); + + javax.swing.GroupLayout jPanel30Layout = new javax.swing.GroupLayout(jPanel30); + jPanel30.setLayout(jPanel30Layout); + jPanel30Layout.setHorizontalGroup( + jPanel30Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jPanel30Layout.createSequentialGroup() + .addContainerGap() + .addGroup(jPanel30Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jPanel30Layout.createSequentialGroup() + .addComponent(jScrollPane19, javax.swing.GroupLayout.DEFAULT_SIZE, 450, Short.MAX_VALUE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(jPanel30Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jPanel30Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(lstRefreshMCPC) + .addComponent(btnInstallMCPC, javax.swing.GroupLayout.Alignment.TRAILING)) + .addComponent(btnDownloadMCPC, javax.swing.GroupLayout.Alignment.TRAILING))) + .addGroup(jPanel30Layout.createSequentialGroup() + .addComponent(jLabel38) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(cboCauldronMinecraft, 0, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))) + .addContainerGap()) + ); + jPanel30Layout.setVerticalGroup( + jPanel30Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel30Layout.createSequentialGroup() + .addContainerGap() + .addGroup(jPanel30Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(jLabel38) + .addComponent(cboCauldronMinecraft, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(jPanel30Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(jScrollPane19, javax.swing.GroupLayout.DEFAULT_SIZE, 402, Short.MAX_VALUE) + .addGroup(jPanel30Layout.createSequentialGroup() + .addComponent(lstRefreshMCPC) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(btnDownloadMCPC) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(btnInstallMCPC) + .addGap(0, 0, Short.MAX_VALUE))) + .addContainerGap()) + ); + + jTabbedPane5.addTab("Cauldron", jPanel30); + + java.util.ResourceBundle bundle1 = java.util.ResourceBundle.getBundle("org/jackhuang/hellominecraftlauncher/I18N"); // NOI18N + btnRefreshDownloads.setText(bundle1.getString("鍒锋柊")); // NOI18N + btnRefreshDownloads.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + btnRefreshDownloadsActionPerformed(evt); + } + }); + + lstDownloads.setModel(new javax.swing.table.DefaultTableModel( + new Object [][] { + + }, + new String [] { + "鐗堟湰", "鍙戝竷鏃堕棿", "閲婃斁鏃堕棿", "绫诲瀷" + } + ) { + Class[] types = new Class [] { + java.lang.String.class, java.lang.String.class, java.lang.String.class, java.lang.String.class + }; + boolean[] canEdit = new boolean [] { + false, false, false, false + }; + + public Class getColumnClass(int columnIndex) { + return types [columnIndex]; + } + + public boolean isCellEditable(int rowIndex, int columnIndex) { + return canEdit [columnIndex]; + } + }); + lstDownloads.setToolTipText(""); + jScrollPane12.setViewportView(lstDownloads); + + btnMinecraftServerDownload.setText(bundle1.getString("涓嬭浇")); // NOI18N + btnMinecraftServerDownload.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + btnMinecraftServerDownloadActionPerformed(evt); + } + }); + + javax.swing.GroupLayout jPanel21Layout = new javax.swing.GroupLayout(jPanel21); + jPanel21.setLayout(jPanel21Layout); + jPanel21Layout.setHorizontalGroup( + jPanel21Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jPanel21Layout.createSequentialGroup() + .addContainerGap() + .addComponent(jScrollPane12, javax.swing.GroupLayout.DEFAULT_SIZE, 450, Short.MAX_VALUE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(jPanel21Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false) + .addComponent(btnRefreshDownloads, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(btnMinecraftServerDownload, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) + .addContainerGap()) + ); + jPanel21Layout.setVerticalGroup( + jPanel21Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jPanel21Layout.createSequentialGroup() + .addContainerGap() + .addGroup(jPanel21Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(jScrollPane12, javax.swing.GroupLayout.DEFAULT_SIZE, 435, Short.MAX_VALUE) + .addGroup(jPanel21Layout.createSequentialGroup() + .addComponent(btnRefreshDownloads) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(btnMinecraftServerDownload) + .addGap(0, 0, Short.MAX_VALUE))) + .addContainerGap()) + ); + + jTabbedPane5.addTab("瀹樻柟鏈嶅姟鍣", jPanel21); + + lstBukkitPlugins.setModel(new javax.swing.table.DefaultTableModel( + new Object [][] { + + }, + new String [] { + "鍚嶅瓧", "鎻忚堪", "鐗堟湰", "Bukkit鐗堟湰" + } + ) { + Class[] types = new Class [] { + java.lang.String.class, java.lang.String.class, java.lang.String.class, java.lang.String.class + }; + boolean[] canEdit = new boolean [] { + false, false, false, false + }; + + public Class getColumnClass(int columnIndex) { + return types [columnIndex]; + } + + public boolean isCellEditable(int rowIndex, int columnIndex) { + return canEdit [columnIndex]; + } + }); + jScrollPane15.setViewportView(lstBukkitPlugins); + + cboCategory.addItemListener(new java.awt.event.ItemListener() { + public void itemStateChanged(java.awt.event.ItemEvent evt) { + cboCategoryItemStateChanged(evt); + } + }); + + jLabel24.setText("鍒嗙被"); + + btnShowPluginInfo.setText("閫変腑鎻掍欢淇℃伅"); + btnShowPluginInfo.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + btnShowPluginInfoActionPerformed(evt); + } + }); + + jButton11.setText("鍒锋柊"); + jButton11.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + jButton11ActionPerformed(evt); + } + }); + + javax.swing.GroupLayout jPanel23Layout = new javax.swing.GroupLayout(jPanel23); + jPanel23.setLayout(jPanel23Layout); + jPanel23Layout.setHorizontalGroup( + jPanel23Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jPanel23Layout.createSequentialGroup() + .addContainerGap() + .addGroup(jPanel23Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(jScrollPane15, javax.swing.GroupLayout.DEFAULT_SIZE, 516, Short.MAX_VALUE) + .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel23Layout.createSequentialGroup() + .addComponent(btnShowPluginInfo) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(jButton11) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(jLabel24) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(cboCategory, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))) + .addContainerGap()) + ); + jPanel23Layout.setVerticalGroup( + jPanel23Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel23Layout.createSequentialGroup() + .addContainerGap() + .addGroup(jPanel23Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(cboCategory, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(jLabel24) + .addComponent(btnShowPluginInfo) + .addComponent(jButton11)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(jScrollPane15, javax.swing.GroupLayout.DEFAULT_SIZE, 401, Short.MAX_VALUE) + .addContainerGap()) + ); + + jTabbedPane5.addTab("鏈嶅姟鍣ㄦ彃浠", jPanel23); + + javax.swing.GroupLayout jPanel19Layout = new javax.swing.GroupLayout(jPanel19); + jPanel19.setLayout(jPanel19Layout); + jPanel19Layout.setHorizontalGroup( + jPanel19Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(jTabbedPane5, javax.swing.GroupLayout.Alignment.TRAILING) + ); + jPanel19Layout.setVerticalGroup( + jPanel19Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(jTabbedPane5) + ); + + jTabbedPane5.getAccessibleContext().setAccessibleName("CraftBukkit"); + + jTabbedPane1.addTab("涓嬭浇涓績", jPanel19); + + lstInfos.setModel(new javax.swing.table.DefaultTableModel( + new Object [][] { + + }, + new String [] { + "鍚嶅瓧", "鏃堕棿" + } + ) { + Class[] types = new Class [] { + java.lang.String.class, java.lang.String.class + }; + boolean[] canEdit = new boolean [] { + false, false + }; + + public Class getColumnClass(int columnIndex) { + return types [columnIndex]; + } + + public boolean isCellEditable(int rowIndex, int columnIndex) { + return canEdit [columnIndex]; + } + }); + jScrollPane13.setViewportView(lstInfos); + + btnRefreshInfos.setText("鍒锋柊"); + btnRefreshInfos.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + btnRefreshInfosActionPerformed(evt); + } + }); + + txtInfo.setEditable(false); + txtInfo.setColumns(20); + txtInfo.setRows(5); + jScrollPane14.setViewportView(txtInfo); + + btnShowInfo.setText("鏄剧ず"); + btnShowInfo.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + btnShowInfoActionPerformed(evt); + } + }); + + javax.swing.GroupLayout jPanel22Layout = new javax.swing.GroupLayout(jPanel22); + jPanel22.setLayout(jPanel22Layout); + jPanel22Layout.setHorizontalGroup( + jPanel22Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jPanel22Layout.createSequentialGroup() + .addContainerGap() + .addGroup(jPanel22Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false) + .addGroup(jPanel22Layout.createSequentialGroup() + .addComponent(btnRefreshInfos) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(btnShowInfo)) + .addComponent(jScrollPane13, javax.swing.GroupLayout.PREFERRED_SIZE, 141, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(jScrollPane14, javax.swing.GroupLayout.DEFAULT_SIZE, 374, Short.MAX_VALUE) + .addContainerGap()) + ); + jPanel22Layout.setVerticalGroup( + jPanel22Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jPanel22Layout.createSequentialGroup() + .addContainerGap() + .addGroup(jPanel22Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(jScrollPane14, javax.swing.GroupLayout.DEFAULT_SIZE, 465, Short.MAX_VALUE) + .addGroup(jPanel22Layout.createSequentialGroup() + .addComponent(jScrollPane13, javax.swing.GroupLayout.PREFERRED_SIZE, 0, Short.MAX_VALUE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(jPanel22Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(btnRefreshInfos) + .addComponent(btnShowInfo)))) + .addContainerGap()) + ); + + jTabbedPane1.addTab("淇℃伅璁板綍", jPanel22); + + btnRefreshReports.setText("鍒锋柊"); + btnRefreshReports.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + btnRefreshReportsActionPerformed(evt); + } + }); + + txtCrashReport.setEditable(false); + txtCrashReport.setColumns(20); + txtCrashReport.setRows(5); + jScrollPane17.setViewportView(txtCrashReport); + + btnShowReport.setText("鏄剧ず"); + btnShowReport.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + btnShowReportActionPerformed(evt); + } + }); + + jScrollPane8.setViewportView(lstReports); + + javax.swing.GroupLayout jPanel26Layout = new javax.swing.GroupLayout(jPanel26); + jPanel26.setLayout(jPanel26Layout); + jPanel26Layout.setHorizontalGroup( + jPanel26Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jPanel26Layout.createSequentialGroup() + .addContainerGap() + .addGroup(jPanel26Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false) + .addGroup(jPanel26Layout.createSequentialGroup() + .addComponent(btnRefreshReports) + .addGap(27, 27, 27) + .addComponent(btnShowReport)) + .addComponent(jScrollPane8, javax.swing.GroupLayout.PREFERRED_SIZE, 0, Short.MAX_VALUE)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(jScrollPane17, javax.swing.GroupLayout.DEFAULT_SIZE, 368, Short.MAX_VALUE) + .addContainerGap()) + ); + jPanel26Layout.setVerticalGroup( + jPanel26Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jPanel26Layout.createSequentialGroup() + .addContainerGap() + .addGroup(jPanel26Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(jScrollPane17, javax.swing.GroupLayout.DEFAULT_SIZE, 465, Short.MAX_VALUE) + .addGroup(jPanel26Layout.createSequentialGroup() + .addComponent(jScrollPane8) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(jPanel26Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(btnRefreshReports) + .addComponent(btnShowReport)))) + .addContainerGap()) + ); + + jTabbedPane1.addTab("宕╂簝璁板綍", jPanel26); + + lblPlayers.setText("鍦ㄧ嚎浜烘暟"); + + btnRefreshPlayers.setText("鍒锋柊鍦ㄧ嚎浜烘暟"); + btnRefreshPlayers.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + btnRefreshPlayersActionPerformed(evt); + } + }); + + jScrollPane16.setViewportView(lstPlayers); + + jLabel27.setText("姝ゅ垪琛ㄦ瘡涓鍒嗛挓鍒锋柊涓娆"); + + javax.swing.GroupLayout jPanel27Layout = new javax.swing.GroupLayout(jPanel27); + jPanel27.setLayout(jPanel27Layout); + jPanel27Layout.setHorizontalGroup( + jPanel27Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jPanel27Layout.createSequentialGroup() + .addContainerGap() + .addGroup(jPanel27Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(jScrollPane16, javax.swing.GroupLayout.DEFAULT_SIZE, 521, Short.MAX_VALUE) + .addGroup(jPanel27Layout.createSequentialGroup() + .addComponent(lblPlayers) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(btnRefreshPlayers)) + .addGroup(jPanel27Layout.createSequentialGroup() + .addComponent(jLabel27) + .addGap(0, 0, Short.MAX_VALUE))) + .addContainerGap()) + ); + jPanel27Layout.setVerticalGroup( + jPanel27Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jPanel27Layout.createSequentialGroup() + .addContainerGap() + .addGroup(jPanel27Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(lblPlayers) + .addComponent(btnRefreshPlayers)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(jScrollPane16, javax.swing.GroupLayout.DEFAULT_SIZE, 407, Short.MAX_VALUE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(jLabel27) + .addContainerGap()) + ); + + jTabbedPane1.addTab("鍦ㄧ嚎鐜╁", jPanel27); + + jButton2.setText("鑺辩敓澹6.5宸ョ▼鐗(鏃犻渶鍏綉IP锛屾棤闇璺敱绔彛鏄犲皠)"); + jButton2.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + jButton2ActionPerformed(evt); + } + }); + + jButton4.setText("mcbbs"); + jButton4.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + jButton4ActionPerformed(evt); + } + }); + + jButton5.setText("minecraft璐村惂"); + jButton5.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + jButton5ActionPerformed(evt); + } + }); + + jButton6.setText("mcbbs鍙戝竷甯"); + jButton6.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + jButton6ActionPerformed(evt); + } + }); + + jButton7.setText("minecraft瀹樼綉"); + jButton7.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + jButton7ActionPerformed(evt); + } + }); + + jButton8.setText("craftbukkit瀹樼綉"); + jButton8.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + jButton8ActionPerformed(evt); + } + }); + + jButton9.setText("MCPC+涓嬭浇"); + jButton9.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + jButton9ActionPerformed(evt); + } + }); + + jButton10.setText("鎸囦护澶у叏"); + jButton10.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + jButton10ActionPerformed(evt); + } + }); + + javax.swing.GroupLayout jPanel28Layout = new javax.swing.GroupLayout(jPanel28); + jPanel28.setLayout(jPanel28Layout); + jPanel28Layout.setHorizontalGroup( + jPanel28Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jPanel28Layout.createSequentialGroup() + .addContainerGap() + .addGroup(jPanel28Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(jButton2) + .addGroup(jPanel28Layout.createSequentialGroup() + .addComponent(jButton4) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(jButton5) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(jButton6) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(jButton7)) + .addGroup(jPanel28Layout.createSequentialGroup() + .addComponent(jButton8) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(jButton9)) + .addComponent(jButton10)) + .addContainerGap(100, Short.MAX_VALUE)) + ); + jPanel28Layout.setVerticalGroup( + jPanel28Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jPanel28Layout.createSequentialGroup() + .addContainerGap() + .addComponent(jButton2) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(jButton10) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 341, Short.MAX_VALUE) + .addGroup(jPanel28Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(jButton8) + .addComponent(jButton9)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(jPanel28Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(jButton4) + .addComponent(jButton5) + .addComponent(jButton6) + .addComponent(jButton7)) + .addContainerGap()) + ); + + jTabbedPane1.addTab("搴旂敤涓績", jPanel28); + + javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane()); + getContentPane().setLayout(layout); + layout.setHorizontalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(jTabbedPane1) + ); + layout.setVerticalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(jTabbedPane1) + ); + + pack(); + }// </editor-fold>//GEN-END:initComponents + + void loadFromSettings() { + txtJavaArgs.setText(SettingsManager.settings.javaArgs); + txtJavaDir.setText(SettingsManager.settings.javaDir); + txtMaxMemory.setText(SettingsManager.settings.maxMemory); + } + + void loadFromServerProperties() { + ServerProperties sp = ServerProperties.getInstance(); + if (sp == null) { + return; + } + txtServerPort.setValue(sp.getPropertyInt("server-port", 25565)); + txtServerName.setText(sp.getProperty("server-name")); + cboGameMode.setSelectedIndex(sp.getPropertyInt("gamemode", 0)); + cboDifficulty.setSelectedIndex(sp.getPropertyInt("difficulty", 1)); + String wt = sp.getProperty("level-type"); + if (wt.equals("LARGEBIOMES")) { + cboWorldType.setSelectedIndex(2); + } else if (wt.equals("FLAT")) { + cboWorldType.setSelectedIndex(1); + } else if (wt.equals("DEFAULT")) { + cboWorldType.setSelectedIndex(0); + } else { + cboWorldType.setSelectedIndex(0); + } + txtMaxPlayer.setValue(sp.getPropertyInt("max-players", 20)); + chkAllowFlight.setSelected(sp.getPropertyBoolean("allow-flight", false)); + chkAllowNether.setSelected(sp.getPropertyBoolean("allow-nether", true)); + chkEnableMonsters.setSelected(sp.getPropertyBoolean("spawn-monsters", true)); + chkEnableNPCs.setSelected(sp.getPropertyBoolean("spawn-npcs", true)); + chkEnalbleAnimals.setSelected(sp.getPropertyBoolean("spawn-animals", true)); + chkPVP.setSelected(sp.getPropertyBoolean("pvp", true)); + chkWhiteList.setSelected(sp.getPropertyBoolean("white-list", false)); + chkGenerateStructures.setSelected(sp.getPropertyBoolean("generate-structures", true)); + chkOnlineMode.setSelected(sp.getPropertyBoolean("online-mode", false)); + txtViewDistance.setValue(sp.getPropertyInt("view-distance", 10)); + txtMaxBuildHeight.setValue(sp.getPropertyInt("max-build-height", 256)); + txtServerGeneratorSettings.setText(sp.getProperty("generator-settings")); + txtWorldSeed.setText(sp.getProperty("level-seed")); + txtWorldName.setText(sp.getProperty("level-name")); + } + + void loadFromOPs() { + File mainjar = new File(SettingsManager.settings.mainjar); + if (!mainjar.exists()) { + return; + } + File folder = mainjar.getParentFile(); + op = new Op(); + op.initByBoth(new File(folder, "ops.txt"), new File(folder, "ops.json")); + for (Op.Operator ss : op.op) { + lstOPModel.addElement(ss.name); + } + lstOP.setModel(lstOPModel); + } + + void loadFromWhiteList() { + File mainjar = new File(SettingsManager.settings.mainjar); + if (!mainjar.exists()) { + return; + } + File folder = mainjar.getParentFile(); + whitelist = new WhiteList(); + whitelist.initByBoth(new File(folder, "white-list.txt"), new File(folder, "white-list.json")); + for (WhiteList.WhiteListPlayer ss : whitelist.op) { + lstWhiteListModel.addElement(ss.name); + } + lstWhiteList.setModel(lstWhiteListModel); + } + + void loadFromBannedPlayers() { + File mainjar = new File(SettingsManager.settings.mainjar); + if (!mainjar.exists()) { + return; + } + File folder = mainjar.getParentFile(); + banned = new BannedPlayers(); + banned.initByBoth(new File(folder, "banned-players.txt"), new File(folder, "banned-players.json")); + for (BannedPlayers.BannedPlayer ss : banned.op) { + lstBannedModel.addElement(ss.name); + } + lstBanned.setModel(lstBannedModel); + } + + void loadLocalMods() { + String path = Utilities.getPath("mods"); + if (path == null) { + return; + } + ArrayList<String> sl = Utilities.findAllFile(new File(path)); + DefaultTableModel model = (DefaultTableModel) lstExternalMods.getModel(); + while (model.getRowCount() > 0) { + model.removeRow(0); + } + for (String s : sl) { + model.addRow(new Object[]{!SettingsManager.settings.inactiveExtMods.contains(s), s, ModType.getModTypeShowName(ModType.getModType(Utilities.addSeparator(path) + s))}); + } + + lstExternalMods.updateUI(); + } + + void loadLocalPlugins() { + String path = Utilities.getPath("plugins"); + if (path == null) { + return; + } + ArrayList<String> sl = Utilities.findAllFile(new File(path)); + DefaultTableModel model = (DefaultTableModel) lstPlugins.getModel(); + while (model.getRowCount() > 0) { + model.removeRow(0); + } + for (String s : sl) { + PluginInformation p = PluginManager.getPluginYML(new File(Utilities.getGameDir() + "plugins" + File.separator + s)); + if (p == null) { + model.addRow(new Object[]{!SettingsManager.settings.inactivePlugins.contains(s), s, + "", "", "", ""}); + } else { + model.addRow(new Object[]{!SettingsManager.settings.inactivePlugins.contains(s), s, + p.name, p.version, p.author, p.description}); + } + } + + lstPlugins.updateUI(); + } + + void loadLocalCoreMods() { + String path = Utilities.getPath("coremods"); + if (path == null) { + return; + } + ArrayList<String> sl = Utilities.findAllFile(new File(path)); + DefaultTableModel model = (DefaultTableModel) lstCoreMods.getModel(); + while (model.getRowCount() > 0) { + model.removeRow(0); + } + for (String s : sl) { + model.addRow(new Object[]{!SettingsManager.settings.inactiveCoreMods.contains(s), s, ModType.getModTypeShowName(ModType.getModType(Utilities.addSeparator(path) + s))}); + } + + lstCoreMods.updateUI(); + } + + void loadWorlds() { + ArrayList<String> s = BackupManager.findAllWorlds(); + DefaultTableModel model = (DefaultTableModel) lstWorlds.getModel(); + if (SettingsManager.settings.inactiveWorlds == null) { + SettingsManager.settings.inactiveWorlds = new ArrayList<String>(); + } + for (String world : s) { + model.addRow(new Object[]{ + world, Utilities.getGameDir() + world, !SettingsManager.settings.inactiveWorlds.contains(world) + }); + } + lstWorlds.updateUI(); + } + + void loadBackups() { + ArrayList<String> al = BackupManager.getBackupList(); + DefaultTableModel model = (DefaultTableModel) lstBackups.getModel(); + for (String backup : al) { + String[] names = Utilities.trimExtension(backup).split("\\+"); + model.addRow(new Object[]{ + names[0], names[1], names[2] + }); + } + lstBackups.updateUI(); + } + + void loadSchedules() { + if (SettingsManager.settings.schedules == null) { + SettingsManager.settings.schedules = new ArrayList<Schedule>(); + } + DefaultTableModel model = (DefaultTableModel) lstSchedules.getModel(); + for (Schedule s : SettingsManager.settings.schedules) { + model.addRow(ScheduleTranslator.getRow(s)); + } + lstSchedules.updateUI(); + } + + void clearListDownloads() { + SwingUtils.clearDefaultTable(lstDownloads); + } + + void loadBukkits() { + int idx = cboBukkitType.getSelectedIndex(); + if (idx == -1) { + return; + } + String url = null; + if (idx == 1) { + BukkitFormatThread thread = new BukkitFormatThread( + "http://dl.bukkit.org/downloads/craftbukkit/list/beta/", + new DoneListener1<List<BukkitVersion>>() { + @Override + public void onDone(List<BukkitVersion> value) { + craftBukkitBeta = value; + reloadBukkitList(); + } + }); + thread.start(); + } else if (idx == 0) { + BukkitFormatThread thread = new BukkitFormatThread( + "http://dl.bukkit.org/downloads/craftbukkit/list/rb/", + new DoneListener1<List<BukkitVersion>>() { + @Override + public void onDone(List<BukkitVersion> value) { + craftBukkitRecommended = value; + reloadBukkitList(); + } + }); + thread.start(); + } else if (idx == 2) { + BukkitFormatThread thread = new BukkitFormatThread( + "http://dl.bukkit.org/downloads/craftbukkit/list/dev/", + new DoneListener1<List<BukkitVersion>>() { + @Override + public void onDone(List<BukkitVersion> value) { + craftBukkitDev = value; + reloadBukkitList(); + } + }); + thread.start(); + } + } + + void loadMCPCs() { + ForgeFormatThread thread = new ForgeFormatThread( + new DoneListener1<Map<String, List<ForgeVersion>>>() { + @Override + public void onDone(Map<String, List<ForgeVersion>> value) { + mcpcPackages = value; + reloadMCPCList(); + } + }); + thread.start(); + } + + public void reloadMCPCList() { + if (mcpcPackages == null) { + return; + } + int cnt = cboCauldronMinecraft.getItemCount(); + cboCauldronMinecraft.removeAllItems(); + for (String s : mcpcPackages.keySet()) { + cboCauldronMinecraft.addItem(s); + } + + String mcver = (String) cboCauldronMinecraft.getSelectedItem(); + useMCPCVersions(mcver); + } + + public void useMCPCVersions(String ver) { + DefaultTableModel model = (DefaultTableModel) lstMCPC.getModel(); + while (model.getRowCount() > 0) { + model.removeRow(0); + } + for (ForgeVersion v : mcpcPackages.get(ver)) { + Object[] row = new Object[]{ + v.mcver, v.ver, v.releasetime + }; + model.addRow(row); + } + lstMCPC.updateUI(); + } + + public void reloadBukkitList() { + int idx = cboBukkitType.getSelectedIndex(); + if (idx == -1) { + return; + } + if (idx == 1) { + useBukkitVersions(craftBukkitBeta); + } else if (idx == 0) { + useBukkitVersions(craftBukkitRecommended); + } else if (idx == 2) { + useBukkitVersions(craftBukkitDev); + } + } + + public void useBukkitVersions(List<BukkitVersion> list) { + if (list == null) { + return; + } + DefaultTableModel model = (DefaultTableModel) lstCraftbukkit.getModel(); + while (model.getRowCount() > 0) { + model.removeRow(0); + } + for (BukkitVersion v : list) { + Object[] row = new Object[]{ + v.buildNumber, v.version + }; + model.addRow(row); + } + lstCraftbukkit.updateUI(); + } + + class RefreshDownloadsDone extends Task { + + HTTPGetTask task; + + RefreshDownloadsDone() { + task = new HTTPGetTask("https://s3.amazonaws.com/Minecraft.Download/versions/versions.json"); + } + + @Override + public Collection<Task> getDependTasks() { + return Arrays.<Task>asList(task); + } + + @Override + public boolean executeTask() { + javax.swing.JTable table = MainWindow.this.lstDownloads; + DefaultTableModel model = (DefaultTableModel) table.getModel(); + + MinecraftRemoteVersions v = MinecraftRemoteVersions.fromJson(task.getResult()); + for (MinecraftRemoteVersion ver : v.versions) { + String[] line = new String[4]; + line[0] = ver.id; + line[1] = ver.releaseTime; + line[2] = ver.time; + line[3] = ver.type; + model.addRow(line); + } + return true; + } + + @Override + public String getInfo() { + return "Get Version List"; + } + + } + + void refreshDownloads() { + clearListDownloads(); + TaskWindow.getInstance().addTask(new RefreshDownloadsDone()).start(); + } + + void refreshInfos() { + ArrayList<String> al = Utilities.findAllFile(new File(Utilities.getGameDir() + "infos-HMCSM")); + DefaultTableModel model = (DefaultTableModel) lstInfos.getModel(); + for (String s : al) { + model.addRow(new Object[]{s, Utilities.trimExtension(s)}); + } + lstInfos.updateUI(); + } + + void refreshReports() { + ArrayList<String> al = Utilities.findAllFile(new File(Utilities.getGameDir() + "crash-reports")); + for (String s : al) { + lstCrashReportsModel.addElement(s); + } + lstReports.setModel(lstCrashReportsModel); + } + + void getIP() { + IPGet get = new IPGet(); + get.dl = new DoneListener1<String>() { + + @Override + public void onDone(String value) { + lblIPAddress.setText("IP: " + value); + } + }; + get.start(); + } + + void loadBukkitPlugins() { + final DefaultTableModel model = (DefaultTableModel) lstBukkitPlugins.getModel(); + while (model.getRowCount() > 0) { + model.removeRow(0); + } + lstBukkitPlugins.updateUI(); + Thread t = new Thread() { + @Override + public void run() { + try { + List<BukkitPlugin> l; + if (cboCategory.getSelectedIndex() == 0) { + l = PluginManager.getPlugins(); + } else { + l = PluginManager.getPluginsByCategory(cboCategory.getSelectedItem().toString()); + } + plugins = l; + for (BukkitPlugin p : l) { + model.addRow(new Object[]{ + p.plugin_name, p.description, p.getLatestVersion(), p.getLatestBukkit() + }); + } + lstBukkitPlugins.updateUI(); + } catch (Exception ex) { + HMCLog.warn("Failed to get plugins", ex); + } + } + }; + t.start(); + } + + void loadBukkitCategory() { + Thread t = new Thread() { + @Override + public void run() { + try { + List<Category> l = PluginManager.getCategories(); + cboCategory.removeAllItems(); + cboCategory.addItem("鎵鏈"); + for (Category c : l) { + cboCategory.addItem(c.name); + } + } catch (Exception ex) { + HMCLog.warn("Failed to load bukkit categories."); + } + } + }; + t.start(); + } + + class MyTask extends TimerTask { + + @Override + public void run() { + Server s = Server.getInstance(); + if (s != null && !s.isRunning) { + System.out.println("AutoSave world"); + s.sendCommand("save-all"); + } + } + + } + + void loadPlayers() { + Server s = Server.getInstance(); + if (s != null && s.isRunning) { + s.getPlayerNumber(new DoneListener1<Pair<String, String[]>>() { + @Override + public void onDone(Pair<String, String[]> t) { + lblPlayers.setText("鍦ㄧ嚎浜烘暟" + t.key); + lstPlayersModel.clear(); + for (String s : t.value) { + lstPlayersModel.addElement(s); + } + lstPlayers.setModel(lstPlayersModel); + } + }); + } else { + MessageBox.Show("鏈嶅姟鍣ㄦ湭寮鍚紒"); + } + } + + class ServerBeginListener implements DoneListener0 { + + @Override + public void onDone() { + commandSet = new ArrayList<String>(); + txtMain.setText(""); + btnLaunch.setEnabled(false); + btnStop.setEnabled(true); + btnShutdown.setEnabled(true); + btnCommand.setEnabled(true); + } + + } + + class ServerDoneListener implements DoneListener0 { + + @Override + public void onDone() { + getPlayerNumberTimer = new Timer(); + getPlayerNumberTimer.schedule(new TimerTask() { + + @Override + public void run() { + loadPlayers(); + } + }, 1000 * 60 * 10, 1000 * 60 * 10); + } + + } + + private void btnLaunchActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnLaunchActionPerformed + File eula = new File(new File(SettingsManager.settings.mainjar).getParentFile(), "eula.txt"); + if (!eula.exists()) { + int option = JOptionPane.showConfirmDialog(null, "鎮ㄦ槸鍚︾‘璁ゆ柊鐨凟ULA(https://account.mojang.com/documents/minecraft_eula)锛熷鏋滄嫆缁濅細瀵艰嚧鏃犳硶鍚姩Minecraft 1.7.10鎴栨洿楂樼増鏈殑鏈嶅姟绔"); + try { + if (option == JOptionPane.YES_OPTION) { + FileUtils.write(eula, "eula=true"); + } else if (option == JOptionPane.NO_OPTION) { + FileUtils.write(eula, "eula=false"); + } + } catch (IOException e) { + MessageBox.Show("纭rula澶辫触"); + } + } + File serverproperties = new File(new File(SettingsManager.settings.mainjar).getParentFile(), "server.properties"); + + if (!serverproperties.exists()) { + try { + FileUtils.write(serverproperties, ServerProperties.getDefault()); + } catch (IOException ex) { + HMCLog.warn("Failed to save server.properties", ex); + } + } + + Server.init(SettingsManager.settings.mainjar, String.valueOf(SettingsManager.settings.maxMemory)); + Server.getInstance() + .addListener((MonitorThread.MonitorThreadListener) this); + Server.getInstance() + .addListener((DoneListener1<Integer>) this); + Server.getInstance() + .clearSchedule(); + for (Schedule s : SettingsManager.settings.schedules) { + Server.getInstance().addSchedule(s); + } + + Server.getInstance() + .addServerStartedListener(new ServerBeginListener()); + Server.getInstance() + .addServerDoneListener(new ServerDoneListener()); + try { + Server.getInstance().run(); + } catch (IOException ex) { + MessageBox.Show("鍚姩鏈嶅姟绔け璐ワ紒"); + HMCLog.err("Failed to launch!", ex); + } + }//GEN-LAST:event_btnLaunchActionPerformed + + private void txtMainJarFocusLost(java.awt.event.FocusEvent evt) {//GEN-FIRST:event_txtMainJarFocusLost + SettingsManager.settings.mainjar = txtMainJar.getText(); + SettingsManager.save(); + }//GEN-LAST:event_txtMainJarFocusLost + + public void stopServer() { + Server.getInstance().stop(); + btnStop.setEnabled(false); + btnCommand.setEnabled(false); + } + + private void txtCommandKeyPressed(java.awt.event.KeyEvent evt) {//GEN-FIRST:event_txtCommandKeyPressed + int newCommandIndex = commandIndex; + int type = 0; + if (evt.getKeyCode() == KeyEvent.VK_UP) { + newCommandIndex--; + type = 1; + } else if (evt.getKeyCode() == KeyEvent.VK_DOWN) { + newCommandIndex++; + type = 1; + } else if (evt.getKeyCode() == KeyEvent.VK_ENTER) { + type = 2; + } + if (type == 1) { + if (outOfCommandSet(newCommandIndex)) { + return; + } + commandIndex = newCommandIndex; + txtCommand.setText(commandSet.get(commandIndex)); + } else if (type == 2) { + sendCommand(); + } + }//GEN-LAST:event_txtCommandKeyPressed + + private void btnSendCommandActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnSendCommandActionPerformed + sendCommand(); + }//GEN-LAST:event_btnSendCommandActionPerformed + + private void btnSetJarActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnSetJarActionPerformed + JFileChooser fc = new JFileChooser(); + fc.setFileFilter(new FileNameExtensionFilter("Jar file", "jar")); + if (fc.showOpenDialog(this) == JFileChooser.APPROVE_OPTION) { + File f = fc.getSelectedFile(); + if (f != null) { + txtMainJar.setText(f.getAbsolutePath()); + SettingsManager.settings.mainjar = f.getAbsolutePath(); + SettingsManager.save(); + loadFromServerProperties(); + loadFromOPs(); + } + } + }//GEN-LAST:event_btnSetJarActionPerformed + + private void cboDifficultyItemStateChanged(java.awt.event.ItemEvent evt) {//GEN-FIRST:event_cboDifficultyItemStateChanged + ServerProperties.getInstance().setDifficulty(cboDifficulty.getSelectedIndex()); + }//GEN-LAST:event_cboDifficultyItemStateChanged + + private void txtMaxBuildHeightFocusLost(java.awt.event.FocusEvent evt) {//GEN-FIRST:event_txtMaxBuildHeightFocusLost + ServerProperties.getInstance().setMaxBuildHeight(Integer.parseInt(txtMaxBuildHeight.getValue().toString())); + }//GEN-LAST:event_txtMaxBuildHeightFocusLost + + private void txtServerNameFocusLost(java.awt.event.FocusEvent evt) {//GEN-FIRST:event_txtServerNameFocusLost + ServerProperties.getInstance().setServerName(txtServerName.getText()); + }//GEN-LAST:event_txtServerNameFocusLost + + private void txtServerMOTDFocusLost(java.awt.event.FocusEvent evt) {//GEN-FIRST:event_txtServerMOTDFocusLost + ServerProperties.getInstance().setMotd(txtServerMOTD.getText()); + }//GEN-LAST:event_txtServerMOTDFocusLost + + private void cboGameModeItemStateChanged(java.awt.event.ItemEvent evt) {//GEN-FIRST:event_cboGameModeItemStateChanged + ServerProperties.getInstance().setGameMode(cboGameMode.getSelectedIndex()); + }//GEN-LAST:event_cboGameModeItemStateChanged + + private void chkEnalbleAnimalsActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_chkEnalbleAnimalsActionPerformed + ServerProperties.getInstance().setSpawnAnimals(chkEnalbleAnimals.isSelected()); + }//GEN-LAST:event_chkEnalbleAnimalsActionPerformed + + private void chkEnableMonstersActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_chkEnableMonstersActionPerformed + ServerProperties.getInstance().setSpawnMonsters(chkEnableMonsters.isSelected()); + }//GEN-LAST:event_chkEnableMonstersActionPerformed + + private void chkEnableNPCsActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_chkEnableNPCsActionPerformed + ServerProperties.getInstance().setSpawnNPCs(chkEnableNPCs.isSelected()); + }//GEN-LAST:event_chkEnableNPCsActionPerformed + + private void chkAllowFlightActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_chkAllowFlightActionPerformed + ServerProperties.getInstance().setAllowFlight(chkAllowFlight.isSelected()); + }//GEN-LAST:event_chkAllowFlightActionPerformed + + private void chkPVPActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_chkPVPActionPerformed + ServerProperties.getInstance().setPVP(chkPVP.isSelected()); + }//GEN-LAST:event_chkPVPActionPerformed + + private void chkAllowNetherActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_chkAllowNetherActionPerformed + ServerProperties.getInstance().setAllowNether(chkAllowNether.isSelected()); + }//GEN-LAST:event_chkAllowNetherActionPerformed + + private void chkWhiteListActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_chkWhiteListActionPerformed + ServerProperties.getInstance().setWhiteList(chkWhiteList.isSelected()); + }//GEN-LAST:event_chkWhiteListActionPerformed + + private void txtServerPortFocusLost(java.awt.event.FocusEvent evt) {//GEN-FIRST:event_txtServerPortFocusLost + ServerProperties.getInstance().setServerPort(Integer.parseInt(txtServerPort.getValue().toString())); + }//GEN-LAST:event_txtServerPortFocusLost + + private void txtMaxPlayerFocusLost(java.awt.event.FocusEvent evt) {//GEN-FIRST:event_txtMaxPlayerFocusLost + ServerProperties.getInstance().setMaxPlayers(Integer.parseInt(txtMaxPlayer.getValue().toString())); + }//GEN-LAST:event_txtMaxPlayerFocusLost + + private void txtViewDistanceFocusLost(java.awt.event.FocusEvent evt) {//GEN-FIRST:event_txtViewDistanceFocusLost + ServerProperties.getInstance().setViewDistence(Integer.parseInt(txtViewDistance.getValue().toString())); + }//GEN-LAST:event_txtViewDistanceFocusLost + + private void cboWorldTypeItemStateChanged(java.awt.event.ItemEvent evt) {//GEN-FIRST:event_cboWorldTypeItemStateChanged + int OAO = cboWorldType.getSelectedIndex(); + String type = "DEFAULT"; + if (OAO == 0) { + type = "DEFAULT"; + } else if (OAO == 1) { + type = "FLAT"; + } else if (OAO == 2) { + type = "LARGEBIMOES"; + } + ServerProperties.getInstance().setLevelType(type); + }//GEN-LAST:event_cboWorldTypeItemStateChanged + + private void txtWorldSeedFocusLost(java.awt.event.FocusEvent evt) {//GEN-FIRST:event_txtWorldSeedFocusLost + ServerProperties.getInstance().setLevelSeed(txtWorldSeed.getText()); + }//GEN-LAST:event_txtWorldSeedFocusLost + + private void txtServerGeneratorSettingsFocusLost(java.awt.event.FocusEvent evt) {//GEN-FIRST:event_txtServerGeneratorSettingsFocusLost + ServerProperties.getInstance().setGeneratorSettings(txtServerGeneratorSettings.getText()); + }//GEN-LAST:event_txtServerGeneratorSettingsFocusLost + + private void txtWorldNameFocusLost(java.awt.event.FocusEvent evt) {//GEN-FIRST:event_txtWorldNameFocusLost + ServerProperties.getInstance().setLevelName(txtWorldName.getText()); + }//GEN-LAST:event_txtWorldNameFocusLost + + private void chkGenerateStructuresActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_chkGenerateStructuresActionPerformed + ServerProperties.getInstance().setGenerateStructures(chkGenerateStructures.isSelected()); + }//GEN-LAST:event_chkGenerateStructuresActionPerformed + + private void btnAddOPActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnAddOPActionPerformed + lstOPModel.addElement(txtOPName.getText()); + lstOP.updateUI(); + + if (Server.isInstanceRunning()) { + Server.getInstance().sendCommand("op " + txtOPName.getText()); + } else { + Op.Operator operator = new Op.Operator(txtOPName.getText()); + op.op.add(operator); + File dir = new File(SettingsManager.settings.mainjar).getParentFile(); + try { + op.saveAsBoth(new File(dir, "ops.txt"), new File(dir, "ops.json")); + } catch (IOException ex) { + HMCLog.warn("Failed to save ops", ex); + MessageBox.Show("娣诲姞澶辫触銆傘傘"); + } + } + }//GEN-LAST:event_btnAddOPActionPerformed + + private void btnDeleteOPActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnDeleteOPActionPerformed + String s = lstOP.getSelectedValue().toString(); + lstOPModel.removeElement(lstOP.getSelectedIndex()); + lstOP.updateUI(); + + if (Server.isInstanceRunning()) { + Server.getInstance().sendCommand("deop " + txtOPName.getText()); + } else { + Op.Operator operator = new Op.Operator(s); + op.op.remove(operator); + File dir = new File(SettingsManager.settings.mainjar).getParentFile(); + try { + op.saveAsBoth(new File(dir, "ops.txt"), new File(dir, "ops.json")); + } catch (IOException ex) { + HMCLog.warn("Failed to save ops", ex); + MessageBox.Show("鍒犻櫎澶辫触銆傘傘"); + } + } + }//GEN-LAST:event_btnDeleteOPActionPerformed + + private void btnAddWhiteActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnAddWhiteActionPerformed + lstWhiteListModel.addElement(txtWhiteName.getText()); + lstWhiteList.updateUI(); + + if (Server.isInstanceRunning()) { + Server.getInstance().sendCommand("whitelist add " + txtWhiteName.getText()); + } else { + WhiteList.WhiteListPlayer player = new WhiteList.WhiteListPlayer(txtWhiteName.getText()); + whitelist.op.add(player); + File dir = new File(SettingsManager.settings.mainjar).getParentFile(); + try { + whitelist.saveAsBoth(new File(dir, "white-list.txt"), new File(dir, "white-list.json")); + } catch (IOException ex) { + HMCLog.warn("Failed to save white-list", ex); + MessageBox.Show("娣诲姞澶辫触銆傘傘"); + } + } + }//GEN-LAST:event_btnAddWhiteActionPerformed + + private void btnDeleteWhiteActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnDeleteWhiteActionPerformed + String name = lstWhiteList.getSelectedValue().toString(); + lstWhiteListModel.removeElement(lstWhiteList.getSelectedIndex()); + lstWhiteList.updateUI(); + + if (Server.isInstanceRunning()) { + Server.getInstance().sendCommand("whitelist remove " + txtWhiteName.getText()); + } else { + WhiteList.WhiteListPlayer player = new WhiteList.WhiteListPlayer(name); + whitelist.op.remove(player); + File dir = new File(SettingsManager.settings.mainjar).getParentFile(); + try { + whitelist.saveAsBoth(new File(dir, "white-list.txt"), new File(dir, "white-list.json")); + } catch (IOException ex) { + HMCLog.warn("Failed to save white-list", ex); + MessageBox.Show("鍒犻櫎澶辫触銆傘傘"); + } + } + }//GEN-LAST:event_btnDeleteWhiteActionPerformed + + private void btnManageExtModsActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnManageExtModsActionPerformed + FolderOpener.openMods(); + }//GEN-LAST:event_btnManageExtModsActionPerformed + + private void btnAddExternelModActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnAddExternelModActionPerformed + java.util.ResourceBundle bundle = java.util.ResourceBundle.getBundle("org/jackhuang/hellominecraftlauncher/VersionSettingsWindow"); + JFileChooser fc = new JFileChooser(); + fc.setFileSelectionMode(JFileChooser.FILES_ONLY); + fc.setDialogTitle(bundle.getString("閫夋嫨妯$粍")); + fc.setMultiSelectionEnabled(false); + fc.showOpenDialog(this); + try { + String path = fc.getSelectedFile().getCanonicalPath(); + String path2 = Utilities.try2GetPath("mods"); + File newf = new File(path2); + newf.mkdirs(); + newf = new File(path2 + File.separator + fc.getSelectedFile().getName()); + FileUtils.copyFile(new File(path), newf); + + DefaultTableModel model = (DefaultTableModel) lstExternalMods.getModel(); + model.addRow(new Object[]{fc.getSelectedFile().getName(), ModType.getModTypeShowName(ModType.getModType(newf))}); + lstExternalMods.updateUI(); + } catch (IOException e) { + MessageBox.Show(bundle.getString("娣诲姞澶辫触")); + HMCLog.warn("Failed to add ext mods", e); + } + }//GEN-LAST:event_btnAddExternelModActionPerformed + + private void btnDeleteExternelModActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnDeleteExternelModActionPerformed + DefaultTableModel model = (DefaultTableModel) lstExternalMods.getModel(); + int idx = lstExternalMods.getSelectedRow(); + String selectedName = (String) model.getValueAt(idx, 0); + model.removeRow(idx); + String path = Utilities.getPath("mods"); + if (path == null) { + MessageBox.Show(java.util.ResourceBundle.getBundle("org/jackhuang/hellominecraftlauncher/VersionSettingsWindow").getString("鍒犻櫎澶辫触")); + return; + } + File newf = new File(path + File.separator + selectedName); + newf.delete(); + }//GEN-LAST:event_btnDeleteExternelModActionPerformed + + private void btnManageCoreModsActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnManageCoreModsActionPerformed + FolderOpener.openCoreMods(); + }//GEN-LAST:event_btnManageCoreModsActionPerformed + + private void btnAddExternelCoreModActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnAddExternelCoreModActionPerformed + JFileChooser fc = new JFileChooser(); + fc.setFileSelectionMode(JFileChooser.FILES_ONLY); + fc.setDialogTitle(java.util.ResourceBundle.getBundle("org/jackhuang/hellominecraftlauncher/VersionSettingsWindow").getString("閫夋嫨妯$粍")); + fc.setMultiSelectionEnabled(false); + fc.showOpenDialog(this); + try { + String path = fc.getSelectedFile().getCanonicalPath(); + String path2 = Utilities.try2GetPath("coremods"); + File newf = new File(path2); + newf.mkdirs(); + newf = new File(path2 + File.separator + fc.getSelectedFile().getName()); + + DefaultTableModel model = (DefaultTableModel) lstCoreMods.getModel(); + lstCoreMods.updateUI(); + model.addRow(new Object[]{fc.getSelectedFile().getName(), ModType.getModTypeShowName(ModType.getModType(newf))}); + FileUtils.copyFile(new File(path), newf); + } catch (IOException e) { + MessageBox.Show(java.util.ResourceBundle.getBundle("org/jackhuang/hellominecraftlauncher/VersionSettingsWindow").getString("娣诲姞澶辫触")); + HMCLog.warn("Failed to add ext core mod.", e); + } + }//GEN-LAST:event_btnAddExternelCoreModActionPerformed + + private void btnDeleteExternelCoreModActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnDeleteExternelCoreModActionPerformed + DefaultTableModel model = (DefaultTableModel) lstCoreMods.getModel(); + int idx = lstCoreMods.getSelectedRow(); + String selectedName = (String) model.getValueAt(idx, 0); + model.removeRow(idx); + lstCoreMods.updateUI(); + String path = Utilities.getPath("coremods"); + if (path == null) { + MessageBox.Show(java.util.ResourceBundle.getBundle("org/jackhuang/hellominecraftlauncher/VersionSettingsWindow").getString("鍒犻櫎澶辫触")); + return; + } + File newf = new File(path + File.separator + selectedName); + newf.delete(); + }//GEN-LAST:event_btnDeleteExternelCoreModActionPerformed + + private void btnManagePluginsActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnManagePluginsActionPerformed + FolderOpener.openPlugins(); + }//GEN-LAST:event_btnManagePluginsActionPerformed + + private void btnAddPluginsActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnAddPluginsActionPerformed + JFileChooser fc = new JFileChooser(); + fc.setFileSelectionMode(JFileChooser.FILES_ONLY); + fc.setDialogTitle(java.util.ResourceBundle.getBundle("org/jackhuang/hellominecraftlauncher/VersionSettingsWindow").getString("閫夋嫨妯$粍")); + fc.setMultiSelectionEnabled(false); + fc.showOpenDialog(this); + try { + String path = fc.getSelectedFile().getCanonicalPath(); + String path2 = Utilities.try2GetPath("plugins"); + File newf = new File(path2); + newf.mkdirs(); + newf = new File(path2 + File.separator + fc.getSelectedFile().getName()); + + DefaultTableModel model = (DefaultTableModel) lstPlugins.getModel(); + lstPlugins.updateUI(); + model.addRow(new Object[]{fc.getSelectedFile().getName(), ModType.getModTypeShowName(ModType.getModType(newf))}); + FileUtils.copyFile(new File(path), newf); + } catch (IOException e) { + MessageBox.Show(java.util.ResourceBundle.getBundle("org/jackhuang/hellominecraftlauncher/VersionSettingsWindow").getString("娣诲姞澶辫触")); + HMCLog.warn("Failed to add plugin", e); + } + }//GEN-LAST:event_btnAddPluginsActionPerformed + + private void btnDeletePluginsActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnDeletePluginsActionPerformed + DefaultTableModel model = (DefaultTableModel) lstPlugins.getModel(); + int idx = lstPlugins.getSelectedRow(); + String selectedName = (String) model.getValueAt(idx, 0); + model.removeRow(idx); + lstPlugins.updateUI(); + String path = Utilities.getPath("plugins"); + if (path == null) { + MessageBox.Show(java.util.ResourceBundle.getBundle("org/jackhuang/hellominecraftlauncher/VersionSettingsWindow").getString("鍒犻櫎澶辫触")); + return; + } + File newf = new File(path + File.separator + selectedName); + newf.delete(); + }//GEN-LAST:event_btnDeletePluginsActionPerformed + + private void btnShutdownActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnShutdownActionPerformed + Server.getInstance().shutdown(); + }//GEN-LAST:event_btnShutdownActionPerformed + + private void btnSaveActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnSaveActionPerformed + Server.getInstance().sendCommand("save-all"); + }//GEN-LAST:event_btnSaveActionPerformed + + private void btnSaveExtModActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnSaveExtModActionPerformed + ArrayList<String> arrayList = new ArrayList<String>(); + Vector strings = ((DefaultTableModel) lstExternalMods.getModel()).getDataVector(); + for (Object s : strings) { + Vector v = (Vector) s; + if (!(Boolean) v.elementAt(0)) { + arrayList.add((String) v.elementAt(1)); + } + } + SettingsManager.settings.inactiveExtMods = arrayList; + SettingsManager.save(); + }//GEN-LAST:event_btnSaveExtModActionPerformed + + private void btnSavePluginsActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnSavePluginsActionPerformed + ArrayList<String> arrayList = new ArrayList<String>(); + Vector strings = ((DefaultTableModel) lstCoreMods.getModel()).getDataVector(); + for (Object s : strings) { + Vector v = (Vector) s; + if (!(Boolean) v.elementAt(0)) { + arrayList.add((String) v.elementAt(1)); + } + } + SettingsManager.settings.inactiveCoreMods = arrayList; + SettingsManager.save(); + }//GEN-LAST:event_btnSavePluginsActionPerformed + + private void btnAddBanActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnAddBanActionPerformed + lstBannedModel.addElement(txtBanName.getText()); + lstBanned.updateUI(); + + if (Server.isInstanceRunning()) { + Server.getInstance().sendCommand("ban " + txtBanName.getText()); + } else { + BannedPlayers.BannedPlayer player = new BannedPlayers.BannedPlayer(txtBanName.getText()); + banned.op.add(player); + File dir = new File(SettingsManager.settings.mainjar).getParentFile(); + try { + whitelist.saveAsBoth(new File(dir, "banned-players.txt"), new File(dir, "banned-players.json")); + } catch (IOException ex) { + HMCLog.warn("Failed to save banned-players", ex); + MessageBox.Show("娣诲姞澶辫触銆傘傘"); + } + } + }//GEN-LAST:event_btnAddBanActionPerformed + + private void btnUnbanActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnUnbanActionPerformed + String s = lstBanned.getSelectedValue().toString(); + lstBannedModel.removeElement(lstBanned.getSelectedIndex()); + lstBanned.updateUI(); + + if (Server.isInstanceRunning()) { + Server.getInstance().sendCommand("pardon " + txtBanName.getText()); + } else { + BannedPlayers.BannedPlayer player = new BannedPlayers.BannedPlayer(s); + banned.op.remove(player); + File dir = new File(SettingsManager.settings.mainjar).getParentFile(); + try { + whitelist.saveAsBoth(new File(dir, "banned-players.txt"), new File(dir, "banned-players.json")); + } catch (IOException ex) { + HMCLog.warn("Failed to save white-list", ex); + MessageBox.Show("鍒犻櫎澶辫触銆傘傘"); + } + } + }//GEN-LAST:event_btnUnbanActionPerformed + + private void btnSetBackgroundPathActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnSetBackgroundPathActionPerformed + JFileChooser fc = new JFileChooser(); + fc.setFileSelectionMode(JFileChooser.FILES_ONLY); + fc.setDialogTitle(java.util.ResourceBundle.getBundle("org/jackhuang/hellominecraftlauncher/I18N").getString("閫夋嫨鑳屾櫙璺緞")); + fc.setMultiSelectionEnabled(false); + fc.showOpenDialog(this); + try { + String path = fc.getSelectedFile().getCanonicalPath(); + path = Utilities.removeLastSeparator(path); + txtBackgroundPath.setText(path); + SettingsManager.settings.bgPath = path; + SettingsManager.save(); + background = new ImageIcon(Toolkit.getDefaultToolkit().getImage(path)); + resizeBackgroundLabel(); + } catch (IOException e) { + HMCLog.warn("Failed to set background path", e); + MessageBox.Show(java.util.ResourceBundle.getBundle("org/jackhuang/hellominecraftlauncher/I18N").getString("璁剧疆澶辫触锛") + e.getMessage()); + } + }//GEN-LAST:event_btnSetBackgroundPathActionPerformed + + private void txtBackgroundPathFocusLost(java.awt.event.FocusEvent evt) {//GEN-FIRST:event_txtBackgroundPathFocusLost + String path = txtBackgroundPath.getText(); + SettingsManager.settings.bgPath = path; + SettingsManager.save(); + background = new ImageIcon(Toolkit.getDefaultToolkit().getImage(path)); + resizeBackgroundLabel(); + }//GEN-LAST:event_txtBackgroundPathFocusLost + + private void btnNewTaskActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnNewTaskActionPerformed + Schedule s = new Schedule(); + s.type = cboTimerTask.getSelectedIndex(); + s.type2 = 0; + s.timeType = cboTimeType.getSelectedIndex(); + s.content = txtTimerTaskContent.getText(); + try { + s.per = Double.parseDouble(txtTimerTaskPeriod.getText()); + } catch (NumberFormatException e) { + HMCLog.warn("Failed to parse double: " + txtTimerTaskPeriod.getText(), e); + MessageBox.Show("閿欒鐨勯棿闅旀椂闂"); + return; + } + SettingsManager.settings.schedules.add(s); + SettingsManager.save(); + DefaultTableModel model = (DefaultTableModel) lstSchedules.getModel(); + model.addRow(ScheduleTranslator.getRow(s)); + lstSchedules.updateUI(); + }//GEN-LAST:event_btnNewTaskActionPerformed + + private void jButton3ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton3ActionPerformed + txtMain.setText(""); + }//GEN-LAST:event_jButton3ActionPerformed + + private void btnDelSelectedScheduleActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnDelSelectedScheduleActionPerformed + int index = lstSchedules.getSelectedRow(); + SettingsManager.settings.schedules.remove(index); + SettingsManager.save(); + DefaultTableModel model = (DefaultTableModel) lstSchedules.getModel(); + model.removeRow(index); + lstSchedules.updateUI(); + }//GEN-LAST:event_btnDelSelectedScheduleActionPerformed + + private void btnRestartActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnRestartActionPerformed + Server.getInstance().restart(); + }//GEN-LAST:event_btnRestartActionPerformed + + private void btnRefreshWorldsActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnRefreshWorldsActionPerformed + loadWorlds(); + }//GEN-LAST:event_btnRefreshWorldsActionPerformed + + private void btnSaveWorldActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnSaveWorldActionPerformed + + DefaultTableModel model = (DefaultTableModel) lstWorlds.getModel(); + SettingsManager.settings.inactiveWorlds = new ArrayList<String>(); + for (int i = 0; i < model.getRowCount(); i++) { + if ((Boolean) model.getValueAt(i, 2) == false) { + SettingsManager.settings.inactiveWorlds.add((String) model.getValueAt(i, 0)); + } + } + SettingsManager.save(); + }//GEN-LAST:event_btnSaveWorldActionPerformed + + private void btnBackupActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnBackupActionPerformed + switch (cboBackupTypes.getSelectedIndex()) { + case 0: + BackupManager.backupAllWorlds(); + break; + case 1: + BackupManager.backupAllPlugins(); + break; + } + }//GEN-LAST:event_btnBackupActionPerformed + + private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton1ActionPerformed + loadBackups(); + }//GEN-LAST:event_jButton1ActionPerformed + + private void btnDeleteBackupActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnDeleteBackupActionPerformed + int index = lstBackups.getSelectedRow(); + if (index == -1) { + return; + } + DefaultTableModel model = (DefaultTableModel) lstBackups.getModel(); + Utilities.deleteAll(new File(BackupManager.backupDir() + + model.getValueAt(index, 0) + "+" + + model.getValueAt(index, 1) + "+" + + model.getValueAt(index, 2) + ".zip")); + model.removeRow(index); + }//GEN-LAST:event_btnDeleteBackupActionPerformed + + private void btnRestoreBackupActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnRestoreBackupActionPerformed + int index = lstBackups.getSelectedRow(); + if (index == -1) { + return; + } + DefaultTableModel model = (DefaultTableModel) lstBackups.getModel(); + BackupManager.restoreBackup(BackupManager.backupDir() + + model.getValueAt(index, 0) + "+" + + model.getValueAt(index, 1) + "+" + + model.getValueAt(index, 2) + ".zip"); + }//GEN-LAST:event_btnRestoreBackupActionPerformed + + private void btnRefreshDownloadsActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnRefreshDownloadsActionPerformed + refreshDownloads(); + }//GEN-LAST:event_btnRefreshDownloadsActionPerformed + + private void btnMinecraftServerDownloadActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnMinecraftServerDownloadActionPerformed + String id = (String) lstDownloads.getModel().getValueAt(lstDownloads.getSelectedRow(), 0); + final String MC_DOWNLOAD_URL = "https://s3.amazonaws.com/Minecraft.Download/versions/"; + String url = MC_DOWNLOAD_URL + id + "/"; + File serverjar = new File(IOUtils.currentDir(), "minecraft_server." + id + ".jar"); + serverjar.delete(); + + String downloadURL = url + "minecraft_server." + id + ".jar"; + TaskWindow.getInstance().addTask(new FileDownloadTask(downloadURL, serverjar).setTag(id)).start(); + }//GEN-LAST:event_btnMinecraftServerDownloadActionPerformed + + private void btnRefreshInfosActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnRefreshInfosActionPerformed + refreshInfos(); + }//GEN-LAST:event_btnRefreshInfosActionPerformed + + private void btnShowInfoActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnShowInfoActionPerformed + try { + DefaultTableModel model = (DefaultTableModel) lstInfos.getModel(); + int index = lstInfos.getSelectedRow(); + if (index == -1) { + return; + } + String path = Utilities.getGameDir() + "infos-HMCSM" + File.separator + model.getValueAt(index, 0); + String content = FileUtils.readFileToString(new File(path)); + txtInfo.setText(content); + } catch (IOException ex) { + HMCLog.warn("Failed to read info.", ex); + } + }//GEN-LAST:event_btnShowInfoActionPerformed + + private void btnAutoSearchActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnAutoSearchActionPerformed + ArrayList<String> al = Utilities.findAllFile(IOUtils.currentDir()); + for (String s : al) { + if (ServerChecker.isServerJar(new File(s))) { + String path = IOUtils.tryGetCanonicalFilePath(new File(IOUtils.currentDir(), s)); + txtMainJar.setText(path); + SettingsManager.settings.mainjar = path; + SettingsManager.save(); + } + } + }//GEN-LAST:event_btnAutoSearchActionPerformed + + private void cboCategoryItemStateChanged(java.awt.event.ItemEvent evt) {//GEN-FIRST:event_cboCategoryItemStateChanged + loadBukkitPlugins(); + }//GEN-LAST:event_cboCategoryItemStateChanged + + private void btnShowPluginInfoActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnShowPluginInfoActionPerformed + try { + int index = lstBukkitPlugins.getSelectedRow(); + if (index == -1) { + return; + } + PluginInfo pi = PluginManager.getPluginInfo(plugins.get(index).slug); + PluginInfoDialog w = new PluginInfoDialog(this, true, pi); + w.setVisible(true); + } catch (Exception ex) { + HMCLog.warn("Failed to get plugin info", ex); + } + }//GEN-LAST:event_btnShowPluginInfoActionPerformed + + private void btnRefreshReportsActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnRefreshReportsActionPerformed + refreshReports(); + }//GEN-LAST:event_btnRefreshReportsActionPerformed + + private void btnShowReportActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnShowReportActionPerformed + try { + int index = lstReports.getSelectedIndex(); + if (index == -1) { + return; + } + String path = Utilities.getGameDir() + "crash-reports" + File.separator + lstCrashReportsModel.get(index); + String content = FileUtils.readFileToString(new File(path)); + txtCrashReport.setText(content); + } catch (IOException ex) { + HMCLog.warn("Failed to get crash-report.", ex); + MessageBox.Show("鏃犳硶鑾峰彇宕╂簝鎶ュ憡"); + } + }//GEN-LAST:event_btnShowReportActionPerformed + + private void btnRefreshPlayersActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnRefreshPlayersActionPerformed + loadPlayers(); + }//GEN-LAST:event_btnRefreshPlayersActionPerformed + + private void chkOnlineModeActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_chkOnlineModeActionPerformed + ServerProperties.getInstance().setOnlineMode(chkOnlineMode.isSelected()); + }//GEN-LAST:event_chkOnlineModeActionPerformed + + private void jButton4ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton4ActionPerformed + Utilities.openLink("http://www.mcbbs.net/"); + }//GEN-LAST:event_jButton4ActionPerformed + + private void jButton5ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton5ActionPerformed + Utilities.openLink("http://tieba.baidu.com/minecraft"); + }//GEN-LAST:event_jButton5ActionPerformed + + private void jButton6ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton6ActionPerformed + Utilities.openLink("http://www.mcbbs.net/thread-171239-1-1.html"); + }//GEN-LAST:event_jButton6ActionPerformed + + private void jButton7ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton7ActionPerformed + Utilities.openLink("http://www.minecraft.net/"); + }//GEN-LAST:event_jButton7ActionPerformed + + private void jButton2ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton2ActionPerformed + Utilities.openLink("http://www.oray.com/peanuthull/download_ddns_6.5.php"); + }//GEN-LAST:event_jButton2ActionPerformed + + private void jButton8ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton8ActionPerformed + Utilities.openLink("http://www.bukkit.org/"); + }//GEN-LAST:event_jButton8ActionPerformed + + private void jButton9ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton9ActionPerformed + Utilities.openLink("http://ci.md-5.net/job/MCPC-Plus/"); + }//GEN-LAST:event_jButton9ActionPerformed + + private void jButton10ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton10ActionPerformed + new CommandsWindow(this, true).setVisible(true); + }//GEN-LAST:event_jButton10ActionPerformed + + private void lstRefreshCraftbukkitActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_lstRefreshCraftbukkitActionPerformed + loadBukkits(); + }//GEN-LAST:event_lstRefreshCraftbukkitActionPerformed + + private void btnDownloadCraftbukkitActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnDownloadCraftbukkitActionPerformed + int idx = lstCraftbukkit.getSelectedRow(); + if (idx == -1) { + return; + } + String ext = ""; + List<BukkitVersion> cb = null; + int idx2 = cboBukkitType.getSelectedIndex(); + if (idx2 == -1) { + return; + } + switch (idx2) { + case 0: + ext = "rb"; + cb = craftBukkitRecommended; + break; + case 1: + ext = "beta"; + cb = craftBukkitBeta; + break; + } + BukkitVersion v = cb.get(idx); + File file = new File(IOUtils.currentDir(), "craftbukkit-" + ext + "-" + v.version + ".jar"); + TaskWindow.getInstance().addTask(new FileDownloadTask(v.downloadLink, IOUtils.tryGetCanonicalFile(file)).setTag("bukkit-" + ext + "-" + v.version)) + .start(); + }//GEN-LAST:event_btnDownloadCraftbukkitActionPerformed + + private void btnDownloadMCPCActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnDownloadMCPCActionPerformed + int idx = lstMCPC.getSelectedRow(); + if (idx == -1) { + return; + } + ForgeVersion v = mcpcPackages.get(cboCauldronMinecraft.getSelectedItem().toString()).get(idx); + String url; + File filepath = new File(IOUtils.currentDir(), "forge-installer.jar"); + url = v.installer[1]; + if (!TaskWindow.getInstance().addTask(new FileDownloadTask(url, filepath).setTag("cauldron-" + v.ver)).start()) { + MessageBox.Show(C.I18N.getString("install.failed_download_forge")); + } else { + installMCPC(filepath); + } + }//GEN-LAST:event_btnDownloadMCPCActionPerformed + + private void installMCPC(final File filepath) { + try { + ForgeInstaller installer = new ForgeInstaller(IOUtils.currentDir(), filepath); + installer.install(); + MessageBox.Show(C.I18N.getString("install.success")); + } catch (Exception e) { + HMCLog.warn("Failed to install liteloader", e); + MessageBox.Show(C.I18N.getString("install.failed_forge")); + } + } + + private void lstRefreshMCPCActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_lstRefreshMCPCActionPerformed + loadMCPCs(); + }//GEN-LAST:event_lstRefreshMCPCActionPerformed + + private void btnSaveCoreModActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnSaveCoreModActionPerformed + ArrayList<String> arrayList = new ArrayList<String>(); + Vector strings = ((DefaultTableModel) lstPlugins.getModel()).getDataVector(); + for (Object s : strings) { + Vector v = (Vector) s; + if (!(Boolean) v.elementAt(0)) { + arrayList.add((String) v.elementAt(1)); + } + } + SettingsManager.settings.inactivePlugins = arrayList; + SettingsManager.save(); + }//GEN-LAST:event_btnSaveCoreModActionPerformed + + private void cboCauldronMinecraftItemStateChanged(java.awt.event.ItemEvent evt) {//GEN-FIRST:event_cboCauldronMinecraftItemStateChanged + if (cboCauldronMinecraft.getItemCount() > 0 && mcpcPackages != null && mcpcPackages.containsKey(cboCauldronMinecraft.getSelectedItem().toString())) { + useMCPCVersions(cboCauldronMinecraft.getSelectedItem().toString()); + } + }//GEN-LAST:event_cboCauldronMinecraftItemStateChanged + + private void btnInstallMCPCActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnInstallMCPCActionPerformed + File filepath = new File(IOUtils.currentDir(), "forge-installer.jar"); + if (!filepath.exists()) { + MessageBox.Show("鎮ㄨ繕鏈笅杞紺auldron锛佽鐐瑰嚮涓嬭浇鎸夐挳涓嬭浇骞惰嚜鍔ㄥ畨瑁咃紒"); + return; + } + installMCPC(filepath); + }//GEN-LAST:event_btnInstallMCPCActionPerformed + + private void cboBukkitTypeItemStateChanged(java.awt.event.ItemEvent evt) {//GEN-FIRST:event_cboBukkitTypeItemStateChanged + reloadBukkitList(); + }//GEN-LAST:event_cboBukkitTypeItemStateChanged + + private void jButton11ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton11ActionPerformed + loadBukkitPlugins(); + loadBukkitCategory(); + }//GEN-LAST:event_jButton11ActionPerformed + + private void btnCommandMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_btnCommandMouseClicked + if (Server.getInstance() == null || !Server.getInstance().isRunning || !btnCommand.isEnabled()) { + return; + } + ppmBasically.show(evt.getComponent(), evt.getPoint().x, evt.getPoint().y); + }//GEN-LAST:event_btnCommandMouseClicked + + private void btnStopActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnStopActionPerformed + Server.getInstance().stop(); + }//GEN-LAST:event_btnStopActionPerformed + + private void formWindowClosed(java.awt.event.WindowEvent evt) {//GEN-FIRST:event_formWindowClosed + + }//GEN-LAST:event_formWindowClosed + + private void formWindowClosing(java.awt.event.WindowEvent evt) {//GEN-FIRST:event_formWindowClosing + if (Server.getInstance() != null && Server.getInstance().isRunning) { + Server.getInstance().stop(); + } + }//GEN-LAST:event_formWindowClosing + + private void txtMaxMemoryFocusLost(java.awt.event.FocusEvent evt) {//GEN-FIRST:event_txtMaxMemoryFocusLost + SettingsManager.settings.maxMemory = txtMaxMemory.getText(); + SettingsManager.save(); + }//GEN-LAST:event_txtMaxMemoryFocusLost + + @Override + public void onStatus(String status) { + String text = txtMain.getText(); + text += status + System.getProperty("line.separator"); + int position = text.length(); + txtMain.setText(text); + txtMain.setCaretPosition(position); + } + + @Override + public void onDone(Integer t) { + btnLaunch.setEnabled(true); + btnStop.setEnabled(false); + btnShutdown.setEnabled(false); + btnCommand.setEnabled(false); + SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH-mm-ss"); + try { + FileUtils.write(new File(Utilities.getGameDir() + "infos-HMCSM" + + File.separator + format.format(new Date()) + ".txt"), + txtMain.getText()); + } catch (IOException ex) { + HMCLog.warn("Failed to save info", ex); + } + if (getPlayerNumberTimer != null) { + getPlayerNumberTimer.cancel(); + getPlayerNumberTimer = null; + } + } + + private void sendCommand() { + String command = txtCommand.getText(); + boolean append = false; + if (outOfCommandSet()) { + append = true; + } else if (!command.equals(commandSet.get(commandIndex))) { + append = true; + } + if (Server.getInstance() != null) { + Server.getInstance().sendCommand(command); + } else { + System.err.println("Server is null."); + } + System.out.println("Send command: " + command); + onStatus(">" + command); + txtCommand.setText(""); + if (append) { + commandSet.add(command); + commandIndex = commandSet.size(); + } else { + commandIndex++; + } + } + + MonitorThread mainThread; + DefaultListModel lstOPModel = new DefaultListModel(), + lstWhiteListModel = new DefaultListModel(), + lstBannedModel = new DefaultListModel(), + lstCrashReportsModel = new DefaultListModel(), + lstPlayersModel = new DefaultListModel(); + List<BukkitPlugin> plugins; + Map<String, List<ForgeVersion>> mcpcPackages; + List<BukkitVersion> craftBukkitRecommended, craftBukkitBeta, craftBukkitDev; + WhiteList whitelist; + Op op; + BannedPlayers banned; + + // Variables declaration - do not modify//GEN-BEGIN:variables + private javax.swing.JButton btnAddBan; + private javax.swing.JButton btnAddExternelCoreMod; + private javax.swing.JButton btnAddExternelMod; + private javax.swing.JButton btnAddOP; + private javax.swing.JButton btnAddPlugins; + private javax.swing.JButton btnAddWhite; + private javax.swing.JButton btnAutoSearch; + private javax.swing.JButton btnBackup; + private javax.swing.JButton btnCommand; + private javax.swing.JButton btnDelSelectedSchedule; + private javax.swing.JButton btnDeleteBackup; + private javax.swing.JButton btnDeleteExternelCoreMod; + private javax.swing.JButton btnDeleteExternelMod; + private javax.swing.JButton btnDeleteOP; + private javax.swing.JButton btnDeletePlugins; + private javax.swing.JButton btnDeleteWhite; + private javax.swing.JButton btnDownloadCraftbukkit; + private javax.swing.JButton btnDownloadMCPC; + private javax.swing.JButton btnInstallMCPC; + private javax.swing.JButton btnLaunch; + private javax.swing.JButton btnManageCoreMods; + private javax.swing.JButton btnManageExtMods; + private javax.swing.JButton btnManagePlugins; + private javax.swing.JButton btnMinecraftServerDownload; + private javax.swing.JButton btnNewTask; + private javax.swing.JButton btnRefreshDownloads; + private javax.swing.JButton btnRefreshInfos; + private javax.swing.JButton btnRefreshPlayers; + private javax.swing.JButton btnRefreshReports; + private javax.swing.JButton btnRefreshWorlds; + private javax.swing.JButton btnRestart; + private javax.swing.JButton btnRestoreBackup; + private javax.swing.JButton btnSave; + private javax.swing.JButton btnSaveCoreMod; + private javax.swing.JButton btnSaveExtMod; + private javax.swing.JButton btnSavePlugins; + private javax.swing.JButton btnSaveWorld; + private javax.swing.JButton btnSendCommand; + private javax.swing.JButton btnSetBackgroundPath; + private javax.swing.JButton btnSetJar; + private javax.swing.JButton btnShowInfo; + private javax.swing.JButton btnShowPluginInfo; + private javax.swing.JButton btnShowReport; + private javax.swing.JButton btnShutdown; + private javax.swing.JButton btnStop; + private javax.swing.JButton btnUnban; + private javax.swing.JComboBox cboBackupTypes; + private javax.swing.JComboBox cboBukkitType; + private javax.swing.JComboBox cboCategory; + private javax.swing.JComboBox cboCauldronMinecraft; + private javax.swing.JComboBox cboDifficulty; + private javax.swing.JComboBox cboGameMode; + private javax.swing.JComboBox cboTimeType; + private javax.swing.JComboBox cboTimerTask; + private javax.swing.JComboBox cboWorldType; + private javax.swing.JCheckBox chkAllowFlight; + private javax.swing.JCheckBox chkAllowNether; + private javax.swing.JCheckBox chkEnableMonsters; + private javax.swing.JCheckBox chkEnableNPCs; + private javax.swing.JCheckBox chkEnalbleAnimals; + private javax.swing.JCheckBox chkGenerateStructures; + private javax.swing.JCheckBox chkOnlineMode; + private javax.swing.JCheckBox chkPVP; + private javax.swing.JCheckBox chkWhiteList; + private javax.swing.JButton jButton1; + private javax.swing.JButton jButton10; + private javax.swing.JButton jButton11; + private javax.swing.JButton jButton2; + private javax.swing.JButton jButton3; + private javax.swing.JButton jButton4; + private javax.swing.JButton jButton5; + private javax.swing.JButton jButton6; + private javax.swing.JButton jButton7; + private javax.swing.JButton jButton8; + private javax.swing.JButton jButton9; + private javax.swing.JLabel jLabel1; + private javax.swing.JLabel jLabel10; + private javax.swing.JLabel jLabel11; + private javax.swing.JLabel jLabel12; + private javax.swing.JLabel jLabel13; + private javax.swing.JLabel jLabel14; + private javax.swing.JLabel jLabel15; + private javax.swing.JLabel jLabel16; + private javax.swing.JLabel jLabel17; + private javax.swing.JLabel jLabel18; + private javax.swing.JLabel jLabel19; + private javax.swing.JLabel jLabel2; + private javax.swing.JLabel jLabel20; + private javax.swing.JLabel jLabel21; + private javax.swing.JLabel jLabel22; + private javax.swing.JLabel jLabel23; + private javax.swing.JLabel jLabel24; + private javax.swing.JLabel jLabel25; + private javax.swing.JLabel jLabel26; + private javax.swing.JLabel jLabel27; + private javax.swing.JLabel jLabel28; + private javax.swing.JLabel jLabel29; + private javax.swing.JLabel jLabel3; + private javax.swing.JLabel jLabel30; + private javax.swing.JLabel jLabel31; + private javax.swing.JLabel jLabel32; + private javax.swing.JLabel jLabel33; + private javax.swing.JLabel jLabel34; + private javax.swing.JLabel jLabel35; + private javax.swing.JLabel jLabel36; + private javax.swing.JLabel jLabel37; + private javax.swing.JLabel jLabel38; + private javax.swing.JLabel jLabel39; + private javax.swing.JLabel jLabel4; + private javax.swing.JLabel jLabel40; + private javax.swing.JLabel jLabel41; + private javax.swing.JLabel jLabel42; + private javax.swing.JLabel jLabel5; + private javax.swing.JLabel jLabel6; + private javax.swing.JLabel jLabel7; + private javax.swing.JLabel jLabel8; + private javax.swing.JLabel jLabel9; + private javax.swing.JPanel jPanel1; + private javax.swing.JPanel jPanel10; + private javax.swing.JPanel jPanel11; + private javax.swing.JPanel jPanel12; + private javax.swing.JPanel jPanel13; + private javax.swing.JPanel jPanel14; + private javax.swing.JPanel jPanel15; + private javax.swing.JPanel jPanel16; + private javax.swing.JPanel jPanel17; + private javax.swing.JPanel jPanel18; + private javax.swing.JPanel jPanel19; + private javax.swing.JPanel jPanel2; + private javax.swing.JPanel jPanel20; + private javax.swing.JPanel jPanel21; + private javax.swing.JPanel jPanel22; + private javax.swing.JPanel jPanel23; + private javax.swing.JPanel jPanel24; + private javax.swing.JPanel jPanel25; + private javax.swing.JPanel jPanel26; + private javax.swing.JPanel jPanel27; + private javax.swing.JPanel jPanel28; + private javax.swing.JPanel jPanel29; + private javax.swing.JPanel jPanel3; + private javax.swing.JPanel jPanel30; + private javax.swing.JPanel jPanel4; + private javax.swing.JPanel jPanel5; + private javax.swing.JPanel jPanel6; + private javax.swing.JPanel jPanel7; + private javax.swing.JPanel jPanel8; + private javax.swing.JPanel jPanel9; + private javax.swing.JScrollPane jScrollPane1; + private javax.swing.JScrollPane jScrollPane10; + private javax.swing.JScrollPane jScrollPane11; + private javax.swing.JScrollPane jScrollPane12; + private javax.swing.JScrollPane jScrollPane13; + private javax.swing.JScrollPane jScrollPane14; + private javax.swing.JScrollPane jScrollPane15; + private javax.swing.JScrollPane jScrollPane16; + private javax.swing.JScrollPane jScrollPane17; + private javax.swing.JScrollPane jScrollPane18; + private javax.swing.JScrollPane jScrollPane19; + private javax.swing.JScrollPane jScrollPane2; + private javax.swing.JScrollPane jScrollPane3; + private javax.swing.JScrollPane jScrollPane4; + private javax.swing.JScrollPane jScrollPane5; + private javax.swing.JScrollPane jScrollPane6; + private javax.swing.JScrollPane jScrollPane7; + private javax.swing.JScrollPane jScrollPane8; + private javax.swing.JScrollPane jScrollPane9; + private javax.swing.JTabbedPane jTabbedPane1; + private javax.swing.JTabbedPane jTabbedPane2; + private javax.swing.JTabbedPane jTabbedPane3; + private javax.swing.JTabbedPane jTabbedPane4; + private javax.swing.JTabbedPane jTabbedPane5; + private javax.swing.JTabbedPane jTabbedPane6; + private javax.swing.JLabel lblFreeMemory; + private javax.swing.JLabel lblIPAddress; + private javax.swing.JLabel lblMaxMemory; + private javax.swing.JLabel lblOSName; + private javax.swing.JLabel lblPlayers; + private javax.swing.JLabel lblTotalMemory; + private javax.swing.JLabel lblTotalMemorySize; + private javax.swing.JLabel lblTotalThread; + private javax.swing.JLabel lblUsedMemory; + private javax.swing.JTable lstBackups; + private javax.swing.JList lstBanned; + private javax.swing.JTable lstBukkitPlugins; + private javax.swing.JTable lstCoreMods; + private javax.swing.JTable lstCraftbukkit; + private javax.swing.JTable lstDownloads; + private javax.swing.JTable lstExternalMods; + private javax.swing.JTable lstInfos; + private javax.swing.JTable lstMCPC; + private javax.swing.JList lstOP; + private javax.swing.JList lstPlayers; + private javax.swing.JTable lstPlugins; + private javax.swing.JButton lstRefreshCraftbukkit; + private javax.swing.JButton lstRefreshMCPC; + private javax.swing.JList lstReports; + private javax.swing.JTable lstSchedules; + private javax.swing.JList lstWhiteList; + private javax.swing.JTable lstWorlds; + private javax.swing.JProgressBar pgsCPURatio; + private javax.swing.JProgressBar pgsMemoryRatio; + private javax.swing.JTextField txtBackgroundPath; + private javax.swing.JTextField txtBanName; + private javax.swing.JTextField txtCommand; + private javax.swing.JTextArea txtCrashReport; + private javax.swing.JTextArea txtInfo; + private javax.swing.JTextField txtJavaArgs; + private javax.swing.JTextField txtJavaDir; + private javax.swing.JTextArea txtMain; + private javax.swing.JTextField txtMainJar; + private javax.swing.JSpinner txtMaxBuildHeight; + private javax.swing.JTextField txtMaxMemory; + private javax.swing.JSpinner txtMaxPlayer; + private javax.swing.JTextField txtOPName; + private javax.swing.JTextField txtServerGeneratorSettings; + private javax.swing.JTextField txtServerMOTD; + private javax.swing.JTextField txtServerName; + private javax.swing.JSpinner txtServerPort; + private javax.swing.JTextField txtTimerTaskContent; + private javax.swing.JTextField txtTimerTaskPeriod; + private javax.swing.JSpinner txtViewDistance; + private javax.swing.JTextField txtWhiteName; + private javax.swing.JTextField txtWorldName; + private javax.swing.JTextField txtWorldSeed; + // End of variables declaration//GEN-END:variables + +} diff --git a/HMCSM/src/main/java/org/jackhuang/hellominecraft/svrmgr/views/PluginInfoDialog.form b/HMCSM/src/main/java/org/jackhuang/hellominecraft/svrmgr/views/PluginInfoDialog.form new file mode 100644 index 000000000..125fa86c0 --- /dev/null +++ b/HMCSM/src/main/java/org/jackhuang/hellominecraft/svrmgr/views/PluginInfoDialog.form @@ -0,0 +1,226 @@ +<?xml version="1.0" encoding="UTF-8" ?> + +<Form version="1.5" maxVersion="1.8" type="org.netbeans.modules.form.forminfo.JDialogFormInfo"> + <Properties> + <Property name="defaultCloseOperation" type="int" value="2"/> + </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" alignment="0" attributes="0"> + <EmptySpace max="-2" attributes="0"/> + <Group type="103" groupAlignment="0" attributes="0"> + <Component id="jScrollPane1" alignment="0" pref="368" max="32767" attributes="0"/> + <Group type="102" alignment="0" 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="lblName" min="-2" max="-2" attributes="0"/> + </Group> + <Group type="102" alignment="0" attributes="0"> + <Component id="jLabel3" min="-2" max="-2" attributes="0"/> + <EmptySpace max="-2" attributes="0"/> + <Component id="lblDescription" min="-2" max="-2" attributes="0"/> + </Group> + <Group type="102" alignment="0" attributes="0"> + <Component id="jLabel5" min="-2" max="-2" attributes="0"/> + <EmptySpace max="-2" attributes="0"/> + <Component id="lblAuthors" min="-2" max="-2" attributes="0"/> + </Group> + <Group type="102" alignment="0" attributes="0"> + <Component id="jLabel6" min="-2" max="-2" attributes="0"/> + <EmptySpace max="-2" attributes="0"/> + <Component id="lblCategories" min="-2" max="-2" attributes="0"/> + </Group> + <Group type="102" alignment="0" attributes="0"> + <Component id="jLabel9" min="-2" max="-2" attributes="0"/> + <EmptySpace max="-2" attributes="0"/> + <Component id="lblStatus" min="-2" max="-2" attributes="0"/> + </Group> + <Group type="102" alignment="0" attributes="0"> + <Component id="jLabel11" min="-2" max="-2" attributes="0"/> + <EmptySpace max="-2" attributes="0"/> + <Component id="lblWebsite" min="-2" max="-2" attributes="0"/> + </Group> + </Group> + <EmptySpace max="32767" attributes="0"/> + <Group type="103" groupAlignment="0" max="-2" attributes="0"> + <Component id="jButton1" alignment="1" max="32767" attributes="0"/> + <Component id="jButton2" 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="0" attributes="0"> + <Group type="102" attributes="0"> + <Group type="103" groupAlignment="3" attributes="0"> + <Component id="jLabel1" alignment="3" min="-2" max="-2" attributes="0"/> + <Component id="lblName" alignment="3" min="-2" max="-2" attributes="0"/> + </Group> + <EmptySpace max="-2" attributes="0"/> + <Group type="103" groupAlignment="3" attributes="0"> + <Component id="jLabel3" alignment="3" min="-2" max="-2" attributes="0"/> + <Component id="lblDescription" alignment="3" min="-2" max="-2" attributes="0"/> + </Group> + <EmptySpace max="-2" attributes="0"/> + <Group type="103" groupAlignment="3" attributes="0"> + <Component id="jLabel5" alignment="3" min="-2" max="-2" attributes="0"/> + <Component id="lblAuthors" alignment="3" min="-2" max="-2" attributes="0"/> + </Group> + <EmptySpace max="-2" attributes="0"/> + <Group type="103" groupAlignment="3" attributes="0"> + <Component id="jLabel6" alignment="3" min="-2" pref="11" max="-2" attributes="0"/> + <Component id="lblCategories" alignment="3" min="-2" max="-2" attributes="0"/> + </Group> + <EmptySpace max="-2" attributes="0"/> + <Group type="103" groupAlignment="3" attributes="0"> + <Component id="jLabel9" alignment="3" min="-2" max="-2" attributes="0"/> + <Component id="lblStatus" alignment="3" min="-2" max="-2" attributes="0"/> + </Group> + <EmptySpace max="-2" attributes="0"/> + <Group type="103" groupAlignment="3" attributes="0"> + <Component id="jLabel11" alignment="3" min="-2" max="-2" attributes="0"/> + <Component id="lblWebsite" alignment="3" min="-2" max="-2" attributes="0"/> + </Group> + </Group> + <Group type="102" attributes="0"> + <Component id="jButton1" min="-2" max="-2" attributes="0"/> + <EmptySpace max="-2" attributes="0"/> + <Component id="jButton2" min="-2" max="-2" attributes="0"/> + </Group> + </Group> + <EmptySpace max="-2" attributes="0"/> + <Component id="jScrollPane1" pref="159" max="32767" attributes="0"/> + <EmptySpace max="-2" attributes="0"/> + </Group> + </Group> + </DimensionLayout> + </Layout> + <SubComponents> + <Component class="javax.swing.JLabel" name="lblAuthors"> + <Properties> + <Property name="text" type="java.lang.String" value="jLabel7"/> + </Properties> + </Component> + <Component class="javax.swing.JLabel" name="jLabel3"> + <Properties> + <Property name="text" type="java.lang.String" value="描述"/> + </Properties> + </Component> + <Component class="javax.swing.JLabel" name="jLabel6"> + <Properties> + <Property name="text" type="java.lang.String" value="分类"/> + </Properties> + </Component> + <Component class="javax.swing.JLabel" name="jLabel9"> + <Properties> + <Property name="text" type="java.lang.String" value="状态"/> + </Properties> + </Component> + <Component class="javax.swing.JLabel" name="lblCategories"> + <Properties> + <Property name="text" type="java.lang.String" value="jLabel8"/> + </Properties> + </Component> + <Component class="javax.swing.JLabel" name="jLabel11"> + <Properties> + <Property name="text" type="java.lang.String" value="网址"/> + </Properties> + </Component> + <Component class="javax.swing.JLabel" name="lblStatus"> + <Properties> + <Property name="text" type="java.lang.String" value="jLabel10"/> + </Properties> + </Component> + <Container class="javax.swing.JScrollPane" name="jScrollPane1"> + <AuxValues> + <AuxValue name="autoScrollPane" type="java.lang.Boolean" value="true"/> + </AuxValues> + + <Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/> + <SubComponents> + <Component class="javax.swing.JTable" name="lstPluginInfo"> + <Properties> + <Property name="model" type="javax.swing.table.TableModel" editor="org.netbeans.modules.form.editors2.TableModelEditor"> + <Table columnCount="5" rowCount="0"> + <Column editable="true" title="日期" type="java.lang.String"/> + <Column editable="true" title="版本" type="java.lang.String"/> + <Column editable="true" title="文件" type="java.lang.String"/> + <Column editable="true" title="Bukkit版本" type="java.lang.String"/> + <Column editable="true" title="类型" type="java.lang.String"/> + </Table> + </Property> + <Property name="tableHeader" type="javax.swing.table.JTableHeader" editor="org.netbeans.modules.form.editors2.JTableHeaderEditor"> + <TableHeader reorderingAllowed="true" resizingAllowed="true"/> + </Property> + </Properties> + </Component> + </SubComponents> + </Container> + <Component class="javax.swing.JLabel" name="lblWebsite"> + <Properties> + <Property name="text" type="java.lang.String" value="jLabel12"/> + </Properties> + </Component> + <Component class="javax.swing.JButton" name="jButton1"> + <Properties> + <Property name="text" type="java.lang.String" value="安装选中"/> + </Properties> + <Events> + <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="jButton1ActionPerformed"/> + </Events> + </Component> + <Component class="javax.swing.JButton" name="jButton2"> + <Properties> + <Property name="text" type="java.lang.String" value="关闭窗口"/> + </Properties> + <Events> + <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="jButton2ActionPerformed"/> + </Events> + </Component> + <Component class="javax.swing.JLabel" name="lblDescription"> + <Properties> + <Property name="text" type="java.lang.String" value="jLabel4"/> + </Properties> + </Component> + <Component class="javax.swing.JLabel" name="jLabel1"> + <Properties> + <Property name="text" type="java.lang.String" value="名字"/> + </Properties> + </Component> + <Component class="javax.swing.JLabel" name="jLabel5"> + <Properties> + <Property name="text" type="java.lang.String" value="作者"/> + </Properties> + </Component> + <Component class="javax.swing.JLabel" name="lblName"> + <Properties> + <Property name="text" type="java.lang.String" value="jLabel2"/> + </Properties> + </Component> + </SubComponents> +</Form> diff --git a/HMCSM/src/main/java/org/jackhuang/hellominecraft/svrmgr/views/PluginInfoDialog.java b/HMCSM/src/main/java/org/jackhuang/hellominecraft/svrmgr/views/PluginInfoDialog.java new file mode 100644 index 000000000..dba992ef8 --- /dev/null +++ b/HMCSM/src/main/java/org/jackhuang/hellominecraft/svrmgr/views/PluginInfoDialog.java @@ -0,0 +1,247 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package org.jackhuang.hellominecraft.svrmgr.views; + +import java.io.File; +import javax.swing.table.DefaultTableModel; +import org.jackhuang.hellominecraft.tasks.TaskWindow; +import org.jackhuang.hellominecraft.tasks.download.FileDownloadTask; +import org.jackhuang.hellominecraft.utils.StrUtils; +import org.jackhuang.hellominecraft.svrmgr.cbplugins.PluginInfo; +import org.jackhuang.hellominecraft.svrmgr.cbplugins.PluginVersion; +import org.jackhuang.hellominecraft.svrmgr.utils.Utilities; + +/** + * + * @author hyh + */ +public class PluginInfoDialog extends javax.swing.JDialog { + + PluginInfo pi; + + /** + * Creates new form PluginInfoDialog + */ + public PluginInfoDialog(java.awt.Frame parent, boolean modal, PluginInfo pi) { + super(parent, modal); + initComponents(); + this.pi = pi; + lblName.setText(pi.plugin_name); + lblDescription.setText(pi.description); + lblStatus.setText(pi.stage); + lblAuthors.setText(StrUtils.parseParams("", pi.authors.toArray(), ", ")); + lblCategories.setText(StrUtils.parseParams("", pi.categories.toArray(), ", ")); + lblWebsite.setText(pi.link); + //SimpleDateFormat f = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); + DefaultTableModel model = (DefaultTableModel) lstPluginInfo.getModel(); + for (PluginVersion v : pi.versions) { + model.addRow(new Object[]{ + v.date, v.version, v.filename, StrUtils.parseParams("", v.game_versions.toArray(), ", "), + v.type + }); + } + lstPluginInfo.updateUI(); + } + + /** + * 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() { + + lblAuthors = new javax.swing.JLabel(); + jLabel3 = new javax.swing.JLabel(); + jLabel6 = new javax.swing.JLabel(); + jLabel9 = new javax.swing.JLabel(); + lblCategories = new javax.swing.JLabel(); + jLabel11 = new javax.swing.JLabel(); + lblStatus = new javax.swing.JLabel(); + jScrollPane1 = new javax.swing.JScrollPane(); + lstPluginInfo = new javax.swing.JTable(); + lblWebsite = new javax.swing.JLabel(); + jButton1 = new javax.swing.JButton(); + jButton2 = new javax.swing.JButton(); + lblDescription = new javax.swing.JLabel(); + jLabel1 = new javax.swing.JLabel(); + jLabel5 = new javax.swing.JLabel(); + lblName = new javax.swing.JLabel(); + + setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE); + + lblAuthors.setText("jLabel7"); + + jLabel3.setText("鎻忚堪"); + + jLabel6.setText("鍒嗙被"); + + jLabel9.setText("鐘舵"); + + lblCategories.setText("jLabel8"); + + jLabel11.setText("缃戝潃"); + + lblStatus.setText("jLabel10"); + + lstPluginInfo.setModel(new javax.swing.table.DefaultTableModel( + new Object [][] { + + }, + new String [] { + "鏃ユ湡", "鐗堟湰", "鏂囦欢", "Bukkit鐗堟湰", "绫诲瀷" + } + ) { + Class[] types = new Class [] { + java.lang.String.class, java.lang.String.class, java.lang.String.class, java.lang.String.class, java.lang.String.class + }; + + public Class getColumnClass(int columnIndex) { + return types [columnIndex]; + } + }); + jScrollPane1.setViewportView(lstPluginInfo); + + lblWebsite.setText("jLabel12"); + + jButton1.setText("瀹夎閫変腑"); + jButton1.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + jButton1ActionPerformed(evt); + } + }); + + jButton2.setText("鍏抽棴绐楀彛"); + jButton2.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + jButton2ActionPerformed(evt); + } + }); + + lblDescription.setText("jLabel4"); + + jLabel1.setText("鍚嶅瓧"); + + jLabel5.setText("浣滆"); + + lblName.setText("jLabel2"); + + 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) + .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 368, Short.MAX_VALUE) + .addGroup(layout.createSequentialGroup() + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(layout.createSequentialGroup() + .addComponent(jLabel1) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(lblName)) + .addGroup(layout.createSequentialGroup() + .addComponent(jLabel3) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(lblDescription)) + .addGroup(layout.createSequentialGroup() + .addComponent(jLabel5) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(lblAuthors)) + .addGroup(layout.createSequentialGroup() + .addComponent(jLabel6) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(lblCategories)) + .addGroup(layout.createSequentialGroup() + .addComponent(jLabel9) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(lblStatus)) + .addGroup(layout.createSequentialGroup() + .addComponent(jLabel11) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(lblWebsite))) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false) + .addComponent(jButton1, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(jButton2, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, 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.LEADING) + .addGroup(layout.createSequentialGroup() + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(jLabel1) + .addComponent(lblName)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(jLabel3) + .addComponent(lblDescription)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(jLabel5) + .addComponent(lblAuthors)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(jLabel6, javax.swing.GroupLayout.PREFERRED_SIZE, 11, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(lblCategories)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(jLabel9) + .addComponent(lblStatus)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(jLabel11) + .addComponent(lblWebsite))) + .addGroup(layout.createSequentialGroup() + .addComponent(jButton1) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(jButton2))) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 159, Short.MAX_VALUE) + .addContainerGap()) + ); + + pack(); + }// </editor-fold>//GEN-END:initComponents + + private void jButton2ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton2ActionPerformed + this.dispose(); + }//GEN-LAST:event_jButton2ActionPerformed + + private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton1ActionPerformed + int index = lstPluginInfo.getSelectedRow(); + if (index == -1) { + return; + } + String url = pi.versions.get(index).download; + TaskWindow.getInstance() + .addTask(new FileDownloadTask(url, new File(Utilities.getGameDir() + "plugins" + + File.separator + pi.versions.get(index).filename))) + .start(); + }//GEN-LAST:event_jButton1ActionPerformed + + // Variables declaration - do not modify//GEN-BEGIN:variables + private javax.swing.JButton jButton1; + private javax.swing.JButton jButton2; + private javax.swing.JLabel jLabel1; + private javax.swing.JLabel jLabel11; + private javax.swing.JLabel jLabel3; + private javax.swing.JLabel jLabel5; + private javax.swing.JLabel jLabel6; + private javax.swing.JLabel jLabel9; + private javax.swing.JScrollPane jScrollPane1; + private javax.swing.JLabel lblAuthors; + private javax.swing.JLabel lblCategories; + private javax.swing.JLabel lblDescription; + private javax.swing.JLabel lblName; + private javax.swing.JLabel lblStatus; + private javax.swing.JLabel lblWebsite; + private javax.swing.JTable lstPluginInfo; + // End of variables declaration//GEN-END:variables +} diff --git a/HMCSM/src/main/resources/background.jpg b/HMCSM/src/main/resources/background.jpg new file mode 100644 index 000000000..1e8d78385 Binary files /dev/null and b/HMCSM/src/main/resources/background.jpg differ diff --git a/HMCSM/src/main/resources/icon.icns b/HMCSM/src/main/resources/icon.icns new file mode 100644 index 000000000..dc329d24b Binary files /dev/null and b/HMCSM/src/main/resources/icon.icns differ diff --git a/HMCSM/src/main/resources/icon.png b/HMCSM/src/main/resources/icon.png new file mode 100644 index 000000000..25f3cf6c8 Binary files /dev/null and b/HMCSM/src/main/resources/icon.png differ diff --git a/HMCSM/src/main/resources/index.html b/HMCSM/src/main/resources/index.html new file mode 100644 index 000000000..835f442b8 --- /dev/null +++ b/HMCSM/src/main/resources/index.html @@ -0,0 +1,16 @@ +<!DOCTYPE html> +<!-- +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. +--> +<html> + <head> + <title>Hello Minecraft! 寮鏈嶅櫒 + + + + + + + diff --git a/HMCSM/src/main/resources/log4j2.xml b/HMCSM/src/main/resources/log4j2.xml new file mode 100644 index 000000000..a2f8833ab --- /dev/null +++ b/HMCSM/src/main/resources/log4j2.xml @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/HMCSM/src/main/resources/org/jackhuang/hellominecraftlauncher/VersionSettingsWindow.properties b/HMCSM/src/main/resources/org/jackhuang/hellominecraftlauncher/VersionSettingsWindow.properties new file mode 100644 index 000000000..80b3539a9 --- /dev/null +++ b/HMCSM/src/main/resources/org/jackhuang/hellominecraftlauncher/VersionSettingsWindow.properties @@ -0,0 +1,48 @@ +\u540d\u79f0=\u540d\u79f0 +\u4fdd\u5b58\u5931\u8d25=\u4fdd\u5b58\u5931\u8d25 +\u4fdd\u5b58\u538b\u7f29\u5305\u5230=\u4fdd\u5b58\u538b\u7f29\u5305\u5230 +\u9009\u62e9\u6750\u8d28\u5305=\u9009\u62e9\u6750\u8d28\u5305 +\u9009\u62e9\u8d44\u6e90\u5305=\u9009\u62e9\u8d44\u6e90\u5305 +\u9009\u62e9\u5e93/\u6a21\u7ec4=\u9009\u62e9\u5e93/\u6a21\u7ec4 +\u6ca1\u6709\u9009\u4e2d\u4efb\u4f55\u4e00\u4e2a\u5e93/\u6a21\u7ec4\u3002=\u6ca1\u6709\u9009\u4e2d\u4efb\u4f55\u4e00\u4e2a\u5e93/\u6a21\u7ec4\u3002 +\u5220\u9664\u5931\u8d25=\u5220\u9664\u5931\u8d25 +\u6dfb\u52a0\u5931\u8d25=\u6dfb\u52a0\u5931\u8d25 +\u9009\u62e9\u6a21\u7ec4=\u9009\u62e9\u6a21\u7ec4 +\u7248\u672c\u540d\u79f0\u4e0d\u80fd\u4e3a\u7a7a=\u7248\u672c\u540d\u79f0\u4e0d\u80fd\u4e3a\u7a7a +\u5907\u4efd\u5230=\u5907\u4efd\u5230 +\u662fCOREODS\u6587\u4ef6\u5939\u5185\u7684\u6240\u6709\u6838\u5fc3\u6a21\u7ec4=\u662fCoremods\u6587\u4ef6\u5939\u5185\u7684\u6240\u6709\u6838\u5fc3\u6a21\u7ec4 +\u662fMODS\u6587\u4ef6\u5939\u5185\u7684\u6240\u6709\u6a21\u7ec4=\u662fMods\u6587\u4ef6\u5939\u5185\u7684\u6240\u6709\u6a21\u7ec4 +\u901a\u5e38\u662f\u6a21\u7ec4=\u901a\u5e38\u662f\u6a21\u7ec4 +\u4e0b\u79fb=\u4e0b\u79fb +\u4e0a\u79fb=\u4e0a\u79fb +\u5220\u9664=\u5220\u9664 +\u589e\u52a0=\u589e\u52a0 +\u901a\u5e38\u662fFORGE,MODLOADER\u4ee5\u53caMINECRAFT\u6240\u4f9d\u8d56\u7684\u5e93=\u901a\u5e38\u662fForge,Modloader\u4ee5\u53caMinecraft\u6240\u4f9d\u8d56\u7684\u5e93 +\u9644\u52a0\u542f\u52a8\u53c2\u6570=\u9644\u52a0\u542f\u52a8\u53c2\u6570 +\u81ea\u5b9a\u4e49\u5e93\u6587\u4ef6\u5939(LIBRARIES\u6587\u4ef6\u5939)=\u81ea\u5b9a\u4e49\u5e93\u6587\u4ef6\u5939(libraries\u6587\u4ef6\u5939) +\u4e3b\u7c7b=\u4e3b\u7c7b +\u81ea\u5b9a\u4e49\u8d44\u6e90\u6587\u4ef6\u5939(ASSETS\u6587\u4ef6\u5939)=\u81ea\u5b9a\u4e49\u8d44\u6e90\u6587\u4ef6\u5939(assets\u6587\u4ef6\u5939) +\u624b\u52a8\u8bbe\u7f6e=\u624b\u52a8\u8bbe\u7f6e +\u4e0d\u5f3a\u5236=\u4e0d\u5f3a\u5236 +32\u4f4d=32\u4f4d +64\u4f4d=64\u4f4d +\u542f\u52a8\u6a21\u5f0f=\u542f\u52a8\u6a21\u5f0f +\u73a9\u5bb6\u540d=\u73a9\u5bb6\u540d +1.6\u53ca\u4ee5\u4e0a\u7248\u672c\u4ee5\u53ca\u5bfc\u5165\u7684\u65e7\u7248\u672c=1.6\u53ca\u4ee5\u4e0a\u7248\u672c\u4ee5\u53ca\u5bfc\u5165\u7684\u65e7\u7248\u672c +\u6700\u5927\u5185\u5b58=\u6700\u5927\u5185\u5b58 +JAVA\u865a\u62df\u673a\u53c2\u6570=Java\u865a\u62df\u673a\u53c2\u6570 +JAVA\u8def\u5f84=Java\u8def\u5f84 +\u5168\u5c4f=\u5168\u5c4f +\u5206\u8fa8\u7387=\u5206\u8fa8\u7387 +\u6e38\u620f\u8def\u5f84=\u6e38\u620f\u8def\u5f84 +\u4ee5\u4e0b\u8bbe\u7f6e\u5b57\u6bb5\u4e3a\u7a7a\u4ee3\u8868\u7740\u4f7f\u7528\u9ed8\u8ba4\u8bbe\u7f6e=\u9664\u540d\u79f0\u4ee5\u4e0b\u5b57\u6bb5\u53ef\u4ee5\u4e0d\u586b +\u53d6\u6d88=\u53d6\u6d88 +\u786e\u5b9a=\u786e\u5b9a +game_download=\u6e38\u620f\u4e0b\u8f7d +public_settings=\u5168\u5c40\u8bbe\u7f6e +invalid=\u65e0\u6548\u7684 +invalid_jar=\u65e0\u6548\u7684jar\u5305 +not_a_file=\u4e0d\u662f\u6587\u4ef6 +not_found=\u627e\u4e0d\u5230minecraft.jar +not_readable=minecraft.jar\u4e0d\u53ef\u8bfb +modified=(\u4fee\u6539\u7684!) \ No newline at end of file diff --git a/HMCSM/src/main/resources/org/jackhuang/hellominecraftlauncher/VersionSettingsWindow_en_US.properties b/HMCSM/src/main/resources/org/jackhuang/hellominecraftlauncher/VersionSettingsWindow_en_US.properties new file mode 100644 index 000000000..9710f3630 --- /dev/null +++ b/HMCSM/src/main/resources/org/jackhuang/hellominecraftlauncher/VersionSettingsWindow_en_US.properties @@ -0,0 +1,46 @@ +\u540d\u79f0=Name +\u4fdd\u5b58\u5931\u8d25=Failed to save +\u4fdd\u5b58\u538b\u7f29\u5305\u5230=Save zip file to +\u9009\u62e9\u6750\u8d28\u5305=Choose texture pack +\u9009\u62e9\u8d44\u6e90\u5305=Choose resource pack +\u9009\u62e9\u5e93/\u6a21\u7ec4=Choose library/mod +\u6ca1\u6709\u9009\u4e2d\u4efb\u4f55\u4e00\u4e2a\u5e93/\u6a21\u7ec4\u3002=Not selected any library/mod. +\u5220\u9664\u5931\u8d25=Failed to delete +\u6dfb\u52a0\u5931\u8d25=Failed to add +\u9009\u62e9\u6a21\u7ec4=Choose mod +\u7248\u672c\u540d\u79f0\u4e0d\u80fd\u4e3a\u7a7a=Version name cannot be empty. +\u5907\u4efd\u5230=Backup to +\u662fCOREODS\u6587\u4ef6\u5939\u5185\u7684\u6240\u6709\u6838\u5fc3\u6a21\u7ec4=They're all the core mods in coremods folder. +\u662fMODS\u6587\u4ef6\u5939\u5185\u7684\u6240\u6709\u6a21\u7ec4=They're all the mods in mods folder. +\u901a\u5e38\u662f\u6a21\u7ec4=Usually mods. +\u4e0b\u79fb=Down +\u4e0a\u79fb=Up +\u5220\u9664=Delete +\u589e\u52a0=Add +\u901a\u5e38\u662fFORGE,MODLOADER\u4ee5\u53caMINECRAFT\u6240\u4f9d\u8d56\u7684\u5e93=They're usually Forge, Modloader and libraries. +\u9644\u52a0\u542f\u52a8\u53c2\u6570=Addition launch arguments +\u81ea\u5b9a\u4e49\u5e93\u6587\u4ef6\u5939(LIBRARIES\u6587\u4ef6\u5939)=Custom libraries folder +\u4e3b\u7c7b=Main class +\u81ea\u5b9a\u4e49\u8d44\u6e90\u6587\u4ef6\u5939(ASSETS\u6587\u4ef6\u5939)=Custom assets folder +\u624b\u52a8\u8bbe\u7f6e=manually set +\u4e0d\u5f3a\u5236=Default +32\u4f4d=32\u4f4d +64\u4f4d=64\u4f4d +\u542f\u52a8\u6a21\u5f0f=Launch mode +\u73a9\u5bb6\u540d=Player name +1.6\u53ca\u4ee5\u4e0a\u7248\u672c\u4ee5\u53ca\u5bfc\u5165\u7684\u65e7\u7248\u672c=Version 1.6 and above, and imported the old version +\u6700\u5927\u5185\u5b58=Max memory +JAVA\u865a\u62df\u673a\u53c2\u6570=JVM arguments +JAVA\u8def\u5f84=Java path +\u5168\u5c4f=Fullscreen +\u5206\u8fa8\u7387=Resolution +\u6e38\u620f\u8def\u5f84=Game dir +\u4ee5\u4e0b\u8bbe\u7f6e\u5b57\u6bb5\u4e3a\u7a7a\u4ee3\u8868\u7740\u4f7f\u7528\u9ed8\u8ba4\u8bbe\u7f6e=These field could not fill except the name field. +\u53d6\u6d88=Cancel +\u786e\u5b9a=Ok +invalid=invalid +invalid_jar=invalid jar +not_a_file=not a file +not_found=not found +not_readable=not readable +modified=(modified!) \ No newline at end of file diff --git a/HMCSM/src/main/resources/org/jackhuang/hellominecraftlauncher/VersionSettingsWindow_zh_CN.properties b/HMCSM/src/main/resources/org/jackhuang/hellominecraftlauncher/VersionSettingsWindow_zh_CN.properties new file mode 100644 index 000000000..80b3539a9 --- /dev/null +++ b/HMCSM/src/main/resources/org/jackhuang/hellominecraftlauncher/VersionSettingsWindow_zh_CN.properties @@ -0,0 +1,48 @@ +\u540d\u79f0=\u540d\u79f0 +\u4fdd\u5b58\u5931\u8d25=\u4fdd\u5b58\u5931\u8d25 +\u4fdd\u5b58\u538b\u7f29\u5305\u5230=\u4fdd\u5b58\u538b\u7f29\u5305\u5230 +\u9009\u62e9\u6750\u8d28\u5305=\u9009\u62e9\u6750\u8d28\u5305 +\u9009\u62e9\u8d44\u6e90\u5305=\u9009\u62e9\u8d44\u6e90\u5305 +\u9009\u62e9\u5e93/\u6a21\u7ec4=\u9009\u62e9\u5e93/\u6a21\u7ec4 +\u6ca1\u6709\u9009\u4e2d\u4efb\u4f55\u4e00\u4e2a\u5e93/\u6a21\u7ec4\u3002=\u6ca1\u6709\u9009\u4e2d\u4efb\u4f55\u4e00\u4e2a\u5e93/\u6a21\u7ec4\u3002 +\u5220\u9664\u5931\u8d25=\u5220\u9664\u5931\u8d25 +\u6dfb\u52a0\u5931\u8d25=\u6dfb\u52a0\u5931\u8d25 +\u9009\u62e9\u6a21\u7ec4=\u9009\u62e9\u6a21\u7ec4 +\u7248\u672c\u540d\u79f0\u4e0d\u80fd\u4e3a\u7a7a=\u7248\u672c\u540d\u79f0\u4e0d\u80fd\u4e3a\u7a7a +\u5907\u4efd\u5230=\u5907\u4efd\u5230 +\u662fCOREODS\u6587\u4ef6\u5939\u5185\u7684\u6240\u6709\u6838\u5fc3\u6a21\u7ec4=\u662fCoremods\u6587\u4ef6\u5939\u5185\u7684\u6240\u6709\u6838\u5fc3\u6a21\u7ec4 +\u662fMODS\u6587\u4ef6\u5939\u5185\u7684\u6240\u6709\u6a21\u7ec4=\u662fMods\u6587\u4ef6\u5939\u5185\u7684\u6240\u6709\u6a21\u7ec4 +\u901a\u5e38\u662f\u6a21\u7ec4=\u901a\u5e38\u662f\u6a21\u7ec4 +\u4e0b\u79fb=\u4e0b\u79fb +\u4e0a\u79fb=\u4e0a\u79fb +\u5220\u9664=\u5220\u9664 +\u589e\u52a0=\u589e\u52a0 +\u901a\u5e38\u662fFORGE,MODLOADER\u4ee5\u53caMINECRAFT\u6240\u4f9d\u8d56\u7684\u5e93=\u901a\u5e38\u662fForge,Modloader\u4ee5\u53caMinecraft\u6240\u4f9d\u8d56\u7684\u5e93 +\u9644\u52a0\u542f\u52a8\u53c2\u6570=\u9644\u52a0\u542f\u52a8\u53c2\u6570 +\u81ea\u5b9a\u4e49\u5e93\u6587\u4ef6\u5939(LIBRARIES\u6587\u4ef6\u5939)=\u81ea\u5b9a\u4e49\u5e93\u6587\u4ef6\u5939(libraries\u6587\u4ef6\u5939) +\u4e3b\u7c7b=\u4e3b\u7c7b +\u81ea\u5b9a\u4e49\u8d44\u6e90\u6587\u4ef6\u5939(ASSETS\u6587\u4ef6\u5939)=\u81ea\u5b9a\u4e49\u8d44\u6e90\u6587\u4ef6\u5939(assets\u6587\u4ef6\u5939) +\u624b\u52a8\u8bbe\u7f6e=\u624b\u52a8\u8bbe\u7f6e +\u4e0d\u5f3a\u5236=\u4e0d\u5f3a\u5236 +32\u4f4d=32\u4f4d +64\u4f4d=64\u4f4d +\u542f\u52a8\u6a21\u5f0f=\u542f\u52a8\u6a21\u5f0f +\u73a9\u5bb6\u540d=\u73a9\u5bb6\u540d +1.6\u53ca\u4ee5\u4e0a\u7248\u672c\u4ee5\u53ca\u5bfc\u5165\u7684\u65e7\u7248\u672c=1.6\u53ca\u4ee5\u4e0a\u7248\u672c\u4ee5\u53ca\u5bfc\u5165\u7684\u65e7\u7248\u672c +\u6700\u5927\u5185\u5b58=\u6700\u5927\u5185\u5b58 +JAVA\u865a\u62df\u673a\u53c2\u6570=Java\u865a\u62df\u673a\u53c2\u6570 +JAVA\u8def\u5f84=Java\u8def\u5f84 +\u5168\u5c4f=\u5168\u5c4f +\u5206\u8fa8\u7387=\u5206\u8fa8\u7387 +\u6e38\u620f\u8def\u5f84=\u6e38\u620f\u8def\u5f84 +\u4ee5\u4e0b\u8bbe\u7f6e\u5b57\u6bb5\u4e3a\u7a7a\u4ee3\u8868\u7740\u4f7f\u7528\u9ed8\u8ba4\u8bbe\u7f6e=\u9664\u540d\u79f0\u4ee5\u4e0b\u5b57\u6bb5\u53ef\u4ee5\u4e0d\u586b +\u53d6\u6d88=\u53d6\u6d88 +\u786e\u5b9a=\u786e\u5b9a +game_download=\u6e38\u620f\u4e0b\u8f7d +public_settings=\u5168\u5c40\u8bbe\u7f6e +invalid=\u65e0\u6548\u7684 +invalid_jar=\u65e0\u6548\u7684jar\u5305 +not_a_file=\u4e0d\u662f\u6587\u4ef6 +not_found=\u627e\u4e0d\u5230minecraft.jar +not_readable=minecraft.jar\u4e0d\u53ef\u8bfb +modified=(\u4fee\u6539\u7684!) \ No newline at end of file diff --git a/HMCSM/src/main/resources/org/jackhuang/hellominecraftlauncher/VersionSettingsWindow_zh_TW.properties b/HMCSM/src/main/resources/org/jackhuang/hellominecraftlauncher/VersionSettingsWindow_zh_TW.properties new file mode 100644 index 000000000..51fe9b2dc --- /dev/null +++ b/HMCSM/src/main/resources/org/jackhuang/hellominecraftlauncher/VersionSettingsWindow_zh_TW.properties @@ -0,0 +1,48 @@ +\u540d\u79f0=\u540d\u7a31 +\u4fdd\u5b58\u5931\u8d25=\u4fdd\u5b58\u5931\u6557 +\u4fdd\u5b58\u538b\u7f29\u5305\u5230=\u4fdd\u5b58\u58d3\u7e2e\u5305\u5230 +\u9009\u62e9\u6750\u8d28\u5305=\u9078\u64c7\u6750\u8cea\u5305 +\u9009\u62e9\u8d44\u6e90\u5305=\u9078\u64c7\u8cc7\u6e90\u5305 +\u9009\u62e9\u5e93/\u6a21\u7ec4=\u9078\u64c7\u5eab/\u6a21\u7d44 +\u6ca1\u6709\u9009\u4e2d\u4efb\u4f55\u4e00\u4e2a\u5e93/\u6a21\u7ec4\u3002=\u6c92\u6709\u9078\u4e2d\u4efb\u4f55\u4e00\u500b\u5eab/\u6a21\u7d44\u3002 +\u5220\u9664\u5931\u8d25=\u522a\u9664\u5931\u6557 +\u6dfb\u52a0\u5931\u8d25=\u6dfb\u52a0\u5931\u6557 +\u9009\u62e9\u6a21\u7ec4=\u9078\u64c7\u6a21\u7d44 +\u7248\u672c\u540d\u79f0\u4e0d\u80fd\u4e3a\u7a7a=\u7248\u672c\u540d\u7a31\u4e0d\u80fd\u70ba\u7a7a +\u5907\u4efd\u5230=\u5099\u4efd\u5230 +\u662fCOREODS\u6587\u4ef6\u5939\u5185\u7684\u6240\u6709\u6838\u5fc3\u6a21\u7ec4=\u662fCoremods\u6587\u4ef6\u593e\u5167\u7684\u6240\u6709\u6838\u5fc3\u6a21\u7d44 +\u662fMODS\u6587\u4ef6\u5939\u5185\u7684\u6240\u6709\u6a21\u7ec4=\u662fMods\u6587\u4ef6\u593e\u5167\u7684\u6240\u6709\u6a21\u7d44 +\u901a\u5e38\u662f\u6a21\u7ec4=\u901a\u5e38\u662f\u6a21\u7d44 +\u4e0b\u79fb=\u4e0b\u79fb +\u4e0a\u79fb=\u4e0a\u79fb +\u5220\u9664=\u522a\u9664 +\u589e\u52a0=\u589e\u52a0 +\u901a\u5e38\u662fFORGE,MODLOADER\u4ee5\u53caMINECRAFT\u6240\u4f9d\u8d56\u7684\u5e93=\u901a\u5e38\u662fForge,Modloader\u4ee5\u53caMinecraft\u6240\u4f9d\u8cf4\u7684\u5eab +\u9644\u52a0\u542f\u52a8\u53c2\u6570=\u9644\u52a0\u555f\u52d5\u53c3\u6578 +\u81ea\u5b9a\u4e49\u5e93\u6587\u4ef6\u5939(LIBRARIES\u6587\u4ef6\u5939)=\u81ea\u5b9a\u7fa9\u5eab\u8cc7\u6599\u593e(libraries\u8cc7\u6599\u593e) +\u4e3b\u7c7b=\u4e3b\u7c7b +\u81ea\u5b9a\u4e49\u8d44\u6e90\u6587\u4ef6\u5939(ASSETS\u6587\u4ef6\u5939)=\u81ea\u5b9a\u7fa9\u8cc7\u6e90\u8cc7\u6599\u593e(assets\u8cc7\u6599\u593e) +\u624b\u52a8\u8bbe\u7f6e=\u624b\u52d5\u8a2d\u5b9a +\u4e0d\u5f3a\u5236=\u4e0d\u5f37\u5236 +32\u4f4d=32\u4f4d +64\u4f4d=64\u4f4d +\u542f\u52a8\u6a21\u5f0f=\u555f\u52d5\u6a21\u5f0f +\u73a9\u5bb6\u540d=\u73a9\u5bb6\u540d +1.6\u53ca\u4ee5\u4e0a\u7248\u672c\u4ee5\u53ca\u5bfc\u5165\u7684\u65e7\u7248\u672c=1.6\u53ca\u4ee5\u4e0a\u7248\u672c\u4ee5\u53ca\u5c0e\u5165\u7684\u820a\u7248\u672c +\u6700\u5927\u5185\u5b58=\u6700\u5927\u5167\u5b58 +JAVA\u865a\u62df\u673a\u53c2\u6570=Java\u865b\u64ec\u6a5f\u53c3\u6578 +JAVA\u8def\u5f84=Java\u8def\u5f91 +\u5168\u5c4f=\u5168\u5c4f +\u5206\u8fa8\u7387=\u5206\u8fa8\u7387 +\u6e38\u620f\u8def\u5f84=\u904a\u6232\u8def\u5f91 +\u4ee5\u4e0b\u8bbe\u7f6e\u5b57\u6bb5\u4e3a\u7a7a\u4ee3\u8868\u7740\u4f7f\u7528\u9ed8\u8ba4\u8bbe\u7f6e=\u9664\u540d\u7a31\u4ee5\u4e0b\u5b57\u6bb5\u53ef\u4ee5\u4e0d\u586b +\u53d6\u6d88=\u53d6\u6d88 +\u786e\u5b9a=\u78ba\u5b9a +game_download=\u904a\u6232\u4e0b\u8f09 +public_settings=\u5168\u5c40\u8a2d\u5b9a +invalid=\u7121\u6548\u7684 +invalid_jar=\u7121\u6548\u7684jar\u5305 +not_a_file=\u4e0d\u662f\u6587\u4ef6 +not_found=\u627e\u4e0d\u5230minecraft.jar +not_readable=minecraft.jar\u4e0d\u53ef\u8b80 +modified=(\u4fee\u6539\u7684!) \ No newline at end of file diff --git a/MetroLookAndFeel/build.gradle b/MetroLookAndFeel/build.gradle new file mode 100644 index 000000000..4b8a15165 --- /dev/null +++ b/MetroLookAndFeel/build.gradle @@ -0,0 +1,19 @@ +apply plugin: 'me.tatarka.retrolambda' + +if (!hasProperty('mainClass')) { + ext.mainClass = '' +} + +buildscript { + repositories { + mavenCentral(); + + dependencies { + classpath 'me.tatarka:gradle-retrolambda:3.1.0' + } + } +} + +retrolambda { + javaVersion = JavaVersion.VERSION_1_7 +} diff --git a/MetroLookAndFeel/src/main/java/org/jackhuang/hellominecraft/lookandfeel/GraphicsUtils.java b/MetroLookAndFeel/src/main/java/org/jackhuang/hellominecraft/lookandfeel/GraphicsUtils.java new file mode 100644 index 000000000..a413163b1 --- /dev/null +++ b/MetroLookAndFeel/src/main/java/org/jackhuang/hellominecraft/lookandfeel/GraphicsUtils.java @@ -0,0 +1,203 @@ +package org.jackhuang.hellominecraft.lookandfeel; + +import java.awt.Color; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.RenderingHints; +import java.awt.Toolkit; +import java.awt.image.BufferedImage; +import java.util.Map; +import javax.imageio.ImageIO; +import javax.swing.plaf.synth.SynthContext; +import javax.swing.plaf.synth.SynthGraphicsUtils; + +/** + * NimbusGraphicsUtils - extends SynthGraphicsUtils to force all Synth painted + * text to be antialiased and provides some static helper methods. + * + * @author Created by Jasper Potts (Jan 4, 2007) + * @version 1.0 + */ +public class GraphicsUtils extends SynthGraphicsUtils { + + private Map desktopHints; + + /** + * Get rendering hints from a Graphics instance. "hintsToSave" is a Map of + * RenderingHint key-values. For each hint key present in that map, the + * value of that hint is obtained from the Graphics and stored as the value + * for the key in savedHints. + * + * @param g2d the graphics surface + * @param hintsToSave the list of rendering hints to set on the graphics + * @param savedHints a set where to save the previous rendering hints, might + * be null + * @return the previous set of rendering hints + */ + public static RenderingHints getRenderingHints(Graphics2D g2d, + Map hintsToSave, + RenderingHints savedHints) { + if (savedHints == null) { + savedHints = new RenderingHints(null); + } else { + savedHints.clear(); + } + if (hintsToSave.isEmpty()) { + return savedHints; + } + /* RenderingHints.keySet() returns Set */ + for (Object o : hintsToSave.keySet()) { + RenderingHints.Key key = (RenderingHints.Key) o; + Object value = g2d.getRenderingHint(key); + savedHints.put(key, value); + } + return savedHints; + } + + /** + * Overrides paintText in SynthGraphicsUtils to force all Synth painted text + * to be antialiased + */ + @Override + public void paintText(SynthContext ss, Graphics g, String text, int x, int y, int mnemonicIndex) { + Graphics2D g2 = (Graphics2D) g; + + // XXX: In Java SE 6, Synth already uses the desktop hints, this code should just check whether java.version < 1.6 + if (desktopHints == null) { + Toolkit toolkit = Toolkit.getDefaultToolkit(); + desktopHints = (Map) (toolkit.getDesktopProperty("awt.font.desktophints")); + } + + Object oldAA = null; + RenderingHints oldHints = null; + + if (desktopHints != null) { + oldHints = getRenderingHints(g2, desktopHints, null); + g2.addRenderingHints(desktopHints); + } else { + oldAA = g2.getRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING); + g2.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, + RenderingHints.VALUE_TEXT_ANTIALIAS_ON); + } + + super.paintText(ss, g, text, x, y, mnemonicIndex); + + if (oldHints != null) { + g2.addRenderingHints(oldHints); + } else if (oldAA != null) { + g2.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, + oldAA); + } + } + + /** + * Load an image using ImageIO from resource in + * org.jdesktop.swingx.plaf.nimbus.images. Catches and prints all Exceptions + * so that it can safely be used in a static context. + * + * @param imgName The name of the image to load, eg. "border.png" + * @return The loaded image + */ + public static BufferedImage loadImage(String imgName) { + try { + return ImageIO.read(GraphicsUtils.class.getClassLoader().getResource("org/jackhuang/hellominecraft/lookandfeel/images/" + imgName)); + } catch (Exception e) { + System.err.println("Error loading image \"org/jackhuang/hellominecraft/lookandfeel/images/" + imgName + "\""); + e.printStackTrace(); + } + return null; + } + + /** + * Get a Color object from a web color string of the form "FF00AB" or + * "#FF00AB". + * + * @param c The color string + * @return The Color described + */ + public static Color getWebColor(String c) { + if (c.startsWith("#")) { + c = c.substring(1); + } + return new Color( + Integer.parseInt(c.substring(0, 2), 16), + Integer.parseInt(c.substring(2, 4), 16), + Integer.parseInt(c.substring(4, 6), 16) + ); + } + + /** + * Get a Color object from a web color string of the form "FF00AB" or + * "#FF00AB". + * + * @param c The color string + * @return The Color described + */ + public static Color getWebColorWithAlpha(String c) { + if (c.startsWith("#")) { + c = c.substring(1); + } + return new Color( + Integer.parseInt(c.substring(0, 2), 16), + Integer.parseInt(c.substring(2, 4), 16), + Integer.parseInt(c.substring(4, 6), 16), + Integer.parseInt(c.substring(6, 8), 16) + ); + } + + /** + * Get a Color that is 50% inbetween the two web colors given. The Web + * colors are of the form "FF00AB" or "#FF00AB". + * + * @param c1 The first color string + * @param c2 The second color string + * @return The Color middle color + */ + public static Color getMidWebColor(String c1, String c2) { + return getMidWebColor(c1, c2, 50); + } + + /** + * Get a Color that is 50% inbetween the two web colors given. The Web + * colors are of the form "FF00AB" or "#FF00AB". + * + * @param c1 The first color string + * @param c2 The second color string + * @return The Color middle color + */ + public static Color getMidWebColor(String c1, String c2, int percent) { + if (c1.startsWith("#")) { + c1 = c1.substring(1); + } + if (c2.startsWith("#")) { + c2 = c2.substring(1); + } + int rTop = Integer.parseInt(c1.substring(0, 2), 16); + int gTop = Integer.parseInt(c1.substring(2, 4), 16); + int bTop = Integer.parseInt(c1.substring(4, 6), 16); + int rBot = Integer.parseInt(c2.substring(0, 2), 16); + int gBot = Integer.parseInt(c2.substring(2, 4), 16); + int bBot = Integer.parseInt(c2.substring(4, 6), 16); + int rMid = rTop + ((rBot - rTop) * percent / 100); + int gMid = gTop + ((gBot - gTop) * percent / 100); + int bMid = bTop + ((bBot - bTop) * percent / 100); + return new Color(rMid, gMid, bMid); + } + + public static Color getMidWebColor(Color c1, Color c2, int percent) { + int rTop = c1.getRed(); + int gTop = c1.getGreen(); + int bTop = c1.getBlue(); + int aTop = c1.getAlpha(); + int rBot = c2.getRed(); + int gBot = c2.getGreen(); + int bBot = c2.getBlue(); + int aBot = c2.getAlpha(); + int rMid = rTop + ((rBot - rTop) * percent / 100); + int gMid = gTop + ((gBot - gTop) * percent / 100); + int bMid = bTop + ((bBot - bTop) * percent / 100); + int aMid = aTop + ((aBot - aTop) * percent / 100); + return new Color(rMid, gMid, bMid, aMid); + } + +} diff --git a/MetroLookAndFeel/src/main/java/org/jackhuang/hellominecraft/lookandfeel/HelloMinecraftLookAndFeel.java b/MetroLookAndFeel/src/main/java/org/jackhuang/hellominecraft/lookandfeel/HelloMinecraftLookAndFeel.java new file mode 100644 index 000000000..a8dcd0987 --- /dev/null +++ b/MetroLookAndFeel/src/main/java/org/jackhuang/hellominecraft/lookandfeel/HelloMinecraftLookAndFeel.java @@ -0,0 +1,51 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package org.jackhuang.hellominecraft.lookandfeel; + +import java.text.ParseException; +import javax.swing.plaf.synth.SynthLookAndFeel; + +/** + * + * @author hyh + */ +public class HelloMinecraftLookAndFeel extends SynthLookAndFeel { + + /** + * Creates a new instance of NimbusLookAndFeel + */ + public HelloMinecraftLookAndFeel() throws ParseException { + load(HelloMinecraftLookAndFeel.class.getResourceAsStream("/org/jackhuang/hellominecraft/lookandfeel/synth.xml"), HelloMinecraftLookAndFeel.class); + } + + /** + * Return a short string that identifies this look and feel. + * + * @return a short string identifying this look and feel. + */ + @Override + public String getName() { + return "HelloMinecraftLookAndFeel"; + } + + /** + * Return a string that identifies this look and feel. + * + * @return a short string identifying this look and feel. + */ + @Override + public String getID() { + return "HelloMinecraftLookAndFeel"; + } + + /** + * Returns a textual description of this look and feel. + * + * @return textual description of this look and feel. + */ + public String getDescription() { + return "HelloMinecraftLookAndFeel"; + } +} diff --git a/MetroLookAndFeel/src/main/java/org/jackhuang/hellominecraft/lookandfeel/components/ConstomButton.java b/MetroLookAndFeel/src/main/java/org/jackhuang/hellominecraft/lookandfeel/components/ConstomButton.java new file mode 100644 index 000000000..f415f0233 --- /dev/null +++ b/MetroLookAndFeel/src/main/java/org/jackhuang/hellominecraft/lookandfeel/components/ConstomButton.java @@ -0,0 +1,24 @@ +/* + * 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.lookandfeel.components; + +import java.awt.Color; +import org.jackhuang.hellominecraft.lookandfeel.GraphicsUtils; + +/** + * + * @author hyh + */ +public class ConstomButton extends javax.swing.JButton { + public Color normalFg = GraphicsUtils.getWebColorWithAlpha("DDDDDD3F"), normalBg = GraphicsUtils.getWebColorWithAlpha("DDDDDD3F"), + prelightFg = GraphicsUtils.getWebColorWithAlpha("FFFFFF7F"), prelightBg = GraphicsUtils.getWebColorWithAlpha("FFFFFF7F"), + activeFg = GraphicsUtils.getWebColorWithAlpha("EAEDF83F"), activeBg = GraphicsUtils.getWebColorWithAlpha("EAEDF83F"); + public int drawPercent = 0; + public long lastDrawTime = 0; + public int radix = 0; + public boolean notDraw = false; +} diff --git a/MetroLookAndFeel/src/main/java/org/jackhuang/hellominecraft/lookandfeel/components/IConstomable.java b/MetroLookAndFeel/src/main/java/org/jackhuang/hellominecraft/lookandfeel/components/IConstomable.java new file mode 100644 index 000000000..a4feae77b --- /dev/null +++ b/MetroLookAndFeel/src/main/java/org/jackhuang/hellominecraft/lookandfeel/components/IConstomable.java @@ -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.lookandfeel.components; + +/** + * + * @author hyh + */ +public interface IConstomable { + boolean constomBackground(); + boolean constomForeground(); +} diff --git a/MetroLookAndFeel/src/main/java/org/jackhuang/hellominecraft/lookandfeel/painters/ButtonPainter.java b/MetroLookAndFeel/src/main/java/org/jackhuang/hellominecraft/lookandfeel/painters/ButtonPainter.java new file mode 100644 index 000000000..8220096f2 --- /dev/null +++ b/MetroLookAndFeel/src/main/java/org/jackhuang/hellominecraft/lookandfeel/painters/ButtonPainter.java @@ -0,0 +1,277 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package org.jackhuang.hellominecraft.lookandfeel.painters; + +/** + * + * @author hyh + */ +/* + * $Id: MetroGraphicsUtils.java,v 1.9 2005/12/05 15:00:55 kizune Exp $ + * + * Copyright 2004 Sun Microsystems, Inc., 4150 Network Circle, + * Santa Clara, California 95054, U.S.A. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ +import java.awt.Color; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.RenderingHints; +import java.awt.geom.Rectangle2D; +import java.awt.geom.RoundRectangle2D; +import javax.swing.SwingUtilities; +import javax.swing.plaf.synth.SynthConstants; +import javax.swing.plaf.synth.SynthContext; +import javax.swing.plaf.synth.SynthPainter; +import org.jackhuang.hellominecraft.lookandfeel.GraphicsUtils; +import org.jackhuang.hellominecraft.lookandfeel.components.ConstomButton; + +/** + * ButtonPainter - handles painting Nimbus style buttons with Java2D + * + * @author Created by Jasper Potts (Jan 4, 2007) + * @version 1.0 + */ +public class ButtonPainter extends SynthPainter { + + private static final String DEFAULT_NORMAL = "D5D5D5"; + private static final Color[] DEFAULT_NORMAL_FG = new Color[]{ + GraphicsUtils.getWebColor(DEFAULT_NORMAL), + GraphicsUtils.getWebColor(DEFAULT_NORMAL) + }; + private static final String DEFAULT_PRELIGHT = "A9A9A9"; + private static final Color[] DEFAULT_PRELIGHT_FG = new Color[]{ + GraphicsUtils.getWebColor(DEFAULT_PRELIGHT), + GraphicsUtils.getWebColor(DEFAULT_PRELIGHT) + }; + private static final String DEFAULT_ACTIVE = "222222"; + private static final Color[] DEFAULT_ACTIVE_FG = new Color[]{ + GraphicsUtils.getWebColor(DEFAULT_ACTIVE), + GraphicsUtils.getWebColor(DEFAULT_ACTIVE) + }; + + private static final Color[] DISABLED_BG = new Color[]{ + GraphicsUtils.getWebColor("E3EFE9"), + GraphicsUtils.getMidWebColor("E3EFE9", "DFE2E6"), + GraphicsUtils.getWebColor("DFE2E6"), + GraphicsUtils.getMidWebColor("DFE2E6", "D6D9DF"), + GraphicsUtils.getWebColor("D6D9DF"), + GraphicsUtils.getWebColor("D6D9DF"), + GraphicsUtils.getMidWebColor("D6D9DF", "D8DBE1"), + GraphicsUtils.getWebColor("D8DBE1"), + GraphicsUtils.getWebColor("DADDE3") + }; + private static final Color[] DISABLED_FG = new Color[]{ + GraphicsUtils.getWebColor("C9CCD2"), + GraphicsUtils.getWebColor("C9CCD2"), + GraphicsUtils.getWebColor("BCBFC5"), + GraphicsUtils.getWebColor("BCBFC5") + }; + + private static boolean processCustomButton(final ConstomButton c, int add) { + if (System.currentTimeMillis() > c.lastDrawTime) { + c.lastDrawTime = System.currentTimeMillis(); + c.drawPercent += add; + if (c.drawPercent > 100 && add > 0) { + c.drawPercent = 100; + } else if (c.drawPercent < 0 && add < 0) { + c.drawPercent = 0; + } else { + SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { + c.updateUI(); + } + }); + } + } + return true; + } + + /** + * {@inheritDoc} + */ + @Override + public void paintButtonBackground(SynthContext context, Graphics g, int x, int y, int w, int h) { + Graphics2D g2 = (Graphics2D) g.create(); + g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); + Color[] fg, bg; + if ((context.getComponentState() & SynthConstants.DEFAULT) != 0) { + if ((context.getComponentState() & SynthConstants.PRESSED) != 0) { + if (context.getComponent() instanceof ConstomButton) { + ConstomButton c = (ConstomButton) context.getComponent(); + fg = new Color[]{c.activeFg, c.activeFg}; + bg = new Color[]{c.activeFg, c.activeFg}; + } else { + fg = DEFAULT_ACTIVE_FG; + bg = DEFAULT_ACTIVE_FG; + } + } else if ((context.getComponentState() & SynthConstants.DISABLED) != 0) { + return; + //fg = DISABLED_FG; + //bg = DISABLED_BG; + } else if ((context.getComponentState() & SynthConstants.MOUSE_OVER) != 0) { + if (context.getComponent() instanceof ConstomButton) { + final ConstomButton c = (ConstomButton) context.getComponent(); + if (!processCustomButton(c, 1)) { + return; + } + Color fgs = GraphicsUtils.getMidWebColor(c.normalFg, c.prelightFg, c.drawPercent); + Color bgs = GraphicsUtils.getMidWebColor(c.normalBg, c.prelightBg, c.drawPercent); + fg = new Color[]{fgs, fgs}; + bg = new Color[]{bgs, bgs}; + } else { + fg = DEFAULT_PRELIGHT_FG; + bg = DEFAULT_PRELIGHT_FG; + } + } else { + if (context.getComponent() instanceof ConstomButton) { + final ConstomButton c = (ConstomButton) context.getComponent(); + if (!processCustomButton(c, -1)) { + return; + } + Color fgs = GraphicsUtils.getMidWebColor(c.normalFg, c.prelightFg, c.drawPercent); + Color bgs = GraphicsUtils.getMidWebColor(c.normalBg, c.prelightBg, c.drawPercent); + fg = new Color[]{fgs, fgs}; + bg = new Color[]{bgs, bgs}; + } else { + fg = DEFAULT_NORMAL_FG; + bg = DEFAULT_NORMAL_FG; + } + } + } else { + if ((context.getComponentState() & SynthConstants.PRESSED) != 0) { + if (context.getComponent() instanceof ConstomButton) { + ConstomButton c = (ConstomButton) context.getComponent(); + fg = new Color[]{c.activeFg, c.activeFg}; + bg = new Color[]{c.activeFg, c.activeFg}; + } else { + fg = DEFAULT_ACTIVE_FG; + bg = DEFAULT_ACTIVE_FG; + } + } else if ((context.getComponentState() & SynthConstants.DISABLED) != 0) { + return; + //fg = DISABLED_FG; + //bg = DISABLED_BG; + } else if ((context.getComponentState() & SynthConstants.MOUSE_OVER) != 0) { + if (context.getComponent() instanceof ConstomButton) { + final ConstomButton c = (ConstomButton) context.getComponent(); + if (!processCustomButton(c, 1)) { + return; + } + Color fgs = GraphicsUtils.getMidWebColor(c.normalFg, c.prelightFg, c.drawPercent); + Color bgs = GraphicsUtils.getMidWebColor(c.normalBg, c.prelightBg, c.drawPercent); + fg = new Color[]{fgs, fgs}; + bg = new Color[]{bgs, bgs}; + } else { + if (context.getComponent() instanceof ConstomButton) { + ConstomButton c = (ConstomButton) context.getComponent(); + fg = new Color[]{c.prelightFg, c.prelightFg}; + bg = new Color[]{c.prelightBg, c.prelightBg}; + } else { + fg = DEFAULT_PRELIGHT_FG; + bg = DEFAULT_PRELIGHT_FG; + } + } + } else { + if (context.getComponent() instanceof ConstomButton) { + final ConstomButton c = (ConstomButton) context.getComponent(); + if (!processCustomButton(c, -1)) { + return; + } + Color fgs = GraphicsUtils.getMidWebColor(c.normalFg, c.prelightFg, c.drawPercent); + Color bgs = GraphicsUtils.getMidWebColor(c.normalBg, c.prelightBg, c.drawPercent); + fg = new Color[]{fgs, fgs}; + bg = new Color[]{bgs, bgs}; + } else { + fg = DEFAULT_NORMAL_FG; + bg = DEFAULT_NORMAL_FG; + } + } + } + /*w = w - 2; + h = h - 2; + + g2.setPaint(new LinearGradientPaint(x, y, x, y + h, + new float[]{0, 1}, bg)); + g2.fillRect(x, y, w, h); + + g2.setPaint(new LinearGradientPaint(x, y, x, y + h, + new float[]{0, 1}, fg)); + g2.drawRect(x, y, w, h);*/ + + int radix = (context.getComponent() instanceof ConstomButton) ? ((ConstomButton) context.getComponent()).radix : 0; + + g2.setColor(fg[0]); + RoundRectangle2D fgshape = new RoundRectangle2D.Float(x, y, w, h, radix, radix); + g2.draw(fgshape); + g2.setColor(bg[0]); + RoundRectangle2D bgshape = new RoundRectangle2D.Float(x, y, w, h, radix, radix); + g2.fill(bgshape); + } + + @Override + public void paintToggleButtonBackground(SynthContext context, Graphics g, int x, int y, int w, int h) { + Graphics2D g2 = (Graphics2D) g.create(); + g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); + Color[] fg, bg; + if ((context.getComponentState() & SynthConstants.DEFAULT) != 0) { + if ((context.getComponentState() & SynthConstants.PRESSED) != 0 || (context.getComponentState() & SynthConstants.SELECTED) != 0) { + fg = DEFAULT_ACTIVE_FG; + bg = DEFAULT_ACTIVE_FG; + } else if ((context.getComponentState() & SynthConstants.DISABLED) != 0) { + fg = DISABLED_FG; + bg = DISABLED_BG; + } else if ((context.getComponentState() & SynthConstants.MOUSE_OVER) != 0) { + fg = DEFAULT_PRELIGHT_FG; + bg = DEFAULT_PRELIGHT_FG; + } else { + fg = DEFAULT_NORMAL_FG; + bg = DEFAULT_NORMAL_FG; + } + } else { + if ((context.getComponentState() & SynthConstants.PRESSED) != 0 || (context.getComponentState() & SynthConstants.SELECTED) != 0) { + fg = DEFAULT_ACTIVE_FG; + bg = DEFAULT_ACTIVE_FG; + } else if ((context.getComponentState() & SynthConstants.DISABLED) != 0) { + fg = DISABLED_FG; + bg = DISABLED_BG; + } else if ((context.getComponentState() & SynthConstants.MOUSE_OVER) != 0) { + fg = DEFAULT_PRELIGHT_FG; + bg = DEFAULT_PRELIGHT_FG; + } else { + fg = DEFAULT_NORMAL_FG; + bg = DEFAULT_NORMAL_FG; + } + } + g2.setColor(fg[0]); + Rectangle2D fgshape = new Rectangle2D.Float(x, y, w, h); + g2.draw(fgshape); + g2.setColor(bg[0]); + Rectangle2D bgshape = new Rectangle2D.Float(x, y, w, h); + g2.fill(bgshape); + + /*g2.setPaint(new LinearGradientPaint(x, y, x, y + h, + new float[]{0, 1}, bg)); + g2.fillRect(x, y, w, h); + + g2.setPaint(new LinearGradientPaint(x, y, x, y + h, + new float[]{0, 1}, fg)); + g2.drawRect(x, y, w, h);*/ + } +} diff --git a/MetroLookAndFeel/src/main/java/org/jackhuang/hellominecraft/lookandfeel/painters/ProgressPainter.java b/MetroLookAndFeel/src/main/java/org/jackhuang/hellominecraft/lookandfeel/painters/ProgressPainter.java new file mode 100644 index 000000000..be0db277e --- /dev/null +++ b/MetroLookAndFeel/src/main/java/org/jackhuang/hellominecraft/lookandfeel/painters/ProgressPainter.java @@ -0,0 +1,103 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package org.jackhuang.hellominecraft.lookandfeel.painters; + +/* + * $Id: MetroGraphicsUtils.java,v 1.9 2005/12/05 15:00:55 kizune Exp $ + * + * Copyright 2004 Sun Microsystems, Inc., 4150 Network Circle, + * Santa Clara, California 95054, U.S.A. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ +import org.jackhuang.hellominecraft.lookandfeel.GraphicsUtils; + +import javax.swing.plaf.synth.SynthContext; +import javax.swing.plaf.synth.SynthPainter; +import java.awt.Color; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.LinearGradientPaint; + +/** + * ProgressPainter - Synth painter for Nimbus progressbars + * + * @author Created by Jasper Potts (Jan 3, 2007) + * @version 1.0 + */ +public class ProgressPainter extends SynthPainter { + + private static final float[] NORMAL_BG_PTS = new float[]{0, 1}; + private static final Color[] NORMAL_BG = new Color[]{ + GraphicsUtils.getWebColor("c6c6c6"), + GraphicsUtils.getWebColor("c6c6c6") + }; + private static final float[] NORMAL_FG_PTS = new float[]{0, 1}; + private static final Color[] NORMAL_FG = new Color[]{ + GraphicsUtils.getWebColor("c6c6c6"), + GraphicsUtils.getWebColor("c6c6c6") + }; + private static final float[] BAR_BG_PTS = new float[]{0, 1}; + private static final Color[] BAR_BG = new Color[]{ + GraphicsUtils.getWebColor("41B1E1"), + GraphicsUtils.getWebColor("41B1E1") + }; + private static final float[] BAR_FG_PTS = new float[]{0, 1}; + private static final Color[] BAR_FG = new Color[]{ + GraphicsUtils.getWebColor("41B1E1"), + GraphicsUtils.getWebColor("41B1E1") + }; + + /** + * {@inheritDoc} + */ + public void paintProgressBarBackground(SynthContext context, Graphics g, int x, int y, int w, int h, + int orientation) { + Graphics2D g2 = (Graphics2D) g.create(); + g2.setPaint(new LinearGradientPaint(x, y + 3, x, y + h - 4, NORMAL_BG_PTS, NORMAL_BG)); + if (x + 2 < w - 5 && y + 2 < h - 5) { + g2.fillRect(x + 2, y + 2, w - 5, h - 5); + } + g2.setPaint(new LinearGradientPaint(x, y + 2, x, y + h - 5, NORMAL_FG_PTS, NORMAL_FG)); + if (x + 2 < w - 5 && y + 2 < h - 5) { + g2.drawRect(x + 2, y + 2, w - 5, h - 5); + } + } + + /** + * {@inheritDoc} + */ + public void paintProgressBarForeground(SynthContext context, Graphics g, int x, int y, int w, int h, + int orientation) { + Graphics2D g2 = (Graphics2D) g.create(); + g2.setPaint(new LinearGradientPaint(x, y + 3, x, y + h - 4, BAR_BG_PTS, BAR_BG)); + if (x + 2 < w - 5 && y + 2 < h - 5) { + g2.fillRect(x + 2, y + 2, w - 5, h - 5); + } + g2.setPaint(new LinearGradientPaint(x, y + 2, x, y + h - 2, BAR_FG_PTS, BAR_FG)); + if (x + 2 < w - 5 && y + 2 < h - 5) { + g2.drawRect(x + 2, y + 2, w - 5, h - 5); + } + + } + + /** + * {@inheritDoc} + */ + public void paintProgressBarBorder(SynthContext context, Graphics g, int x, int y, int w, int h, int orientation) { + } +} diff --git a/MetroLookAndFeel/src/main/java/org/jackhuang/hellominecraft/lookandfeel/painters/TextFieldPainter.java b/MetroLookAndFeel/src/main/java/org/jackhuang/hellominecraft/lookandfeel/painters/TextFieldPainter.java new file mode 100644 index 000000000..6330ebb3b --- /dev/null +++ b/MetroLookAndFeel/src/main/java/org/jackhuang/hellominecraft/lookandfeel/painters/TextFieldPainter.java @@ -0,0 +1,104 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package org.jackhuang.hellominecraft.lookandfeel.painters; + +/* +* $Id: NimbusGraphicsUtils.java,v 1.9 2005/12/05 15:00:55 kizune Exp $ +* +* Copyright 2004 Sun Microsystems, Inc., 4150 Network Circle, +* Santa Clara, California 95054, U.S.A. All rights reserved. +* +* This library is free software; you can redistribute it and/or +* modify it under the terms of the GNU Lesser General Public +* License as published by the Free Software Foundation; either +* version 2.1 of the License, or (at your option) any later version. +* +* This library is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +* Lesser General Public License for more details. +* +* You should have received a copy of the GNU Lesser General Public +* License along with this library; if not, write to the Free Software +* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +import javax.swing.plaf.synth.SynthContext; +import javax.swing.plaf.synth.SynthPainter; +import java.awt.Color; +import java.awt.Graphics; +import javax.swing.plaf.synth.SynthConstants; +import org.jackhuang.hellominecraft.lookandfeel.GraphicsUtils; + +/** + * TextFieldPainter + * + * @author Created by Jasper Potts (Jan 4, 2007) + * @version 1.0 + */ +public class TextFieldPainter extends SynthPainter { + + private boolean fill = true; + + private static final Color disabled = GraphicsUtils.getWebColor("F3F3F3"), + normal = GraphicsUtils.getWebColor("CCCCCC"), + focused = GraphicsUtils.getWebColor("000000"), + over = GraphicsUtils.getWebColor("7F7F7F"); + + public TextFieldPainter() {} + + public TextFieldPainter(boolean fill) { + this.fill = fill; + } + + private void paintFieldBackground(SynthContext context, Graphics g, int x, int y, int w, int h) { + w--; + h--; + if (fill) { + g.setColor(Color.WHITE); + g.fillRect(x, y, w, h); + } + Color color = null; + if((context.getComponentState() & SynthConstants.MOUSE_OVER) != 0) { + color = over; + } else if((context.getComponentState() & SynthConstants.DISABLED) != 0) { + color = disabled; + } else if((context.getComponentState() & SynthConstants.FOCUSED) != 0) { + color = focused; + } else { + color = normal; + } + g.setColor(color); + g.drawLine(x, y, x + w, y); + g.drawLine(x, y, x, y + w); + g.drawLine(x + w, y, x + w, y + h); + g.drawLine(x, y + h, x + w, y + h); + } + + @Override + public void paintPasswordFieldBackground(SynthContext context, Graphics g, int x, int y, int w, int h) { + paintFieldBackground(context, g, x, y, w, h); + } + + @Override + public void paintTextAreaBackground(SynthContext context, Graphics g, int x, int y, int w, int h) { + paintFieldBackground(context, g, x, y, w, h); + } + + @Override + public void paintTextFieldBackground(SynthContext context, Graphics g, int x, int y, int w, int h) { + paintFieldBackground(context, g, x, y, w, h); + } + + @Override + public void paintTextPaneBackground(SynthContext context, Graphics g, int x, int y, int w, int h) { + paintFieldBackground(context, g, x, y, w, h); + } + + @Override + public void paintScrollPaneBackground(SynthContext context, Graphics g, int x, int y, int w, int h) { + paintFieldBackground(context, g, x, y, w, h); + } +} diff --git a/MetroLookAndFeel/src/main/java/org/jackhuang/hellominecraft/lookandfeel/ui/ComboBoxUI.java b/MetroLookAndFeel/src/main/java/org/jackhuang/hellominecraft/lookandfeel/ui/ComboBoxUI.java new file mode 100644 index 000000000..7d567d42e --- /dev/null +++ b/MetroLookAndFeel/src/main/java/org/jackhuang/hellominecraft/lookandfeel/ui/ComboBoxUI.java @@ -0,0 +1,277 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package org.jackhuang.hellominecraft.lookandfeel.ui; + +import static org.jackhuang.hellominecraft.lookandfeel.GraphicsUtils.loadImage; + +import javax.swing.plaf.ComponentUI; +import javax.swing.plaf.basic.BasicComboBoxUI; +import javax.swing.JComponent; +import javax.swing.JButton; +import javax.swing.JComboBox; +import javax.swing.ListCellRenderer; +import java.awt.Graphics; +import java.awt.Rectangle; +import java.awt.Insets; +import java.awt.LayoutManager; +import java.awt.Component; +import java.awt.Dimension; +import java.awt.Container; +import java.awt.image.BufferedImage; +import java.awt.event.MouseListener; +import java.awt.event.MouseEvent; + +/** + * NimbusComboBoxUI + * + * @author Created by Jasper Potts (Feb 1, 2007) + * @version 1.0 + */ +public class ComboBoxUI extends BasicComboBoxUI implements MouseListener { + + private static final BufferedImage combo_normal = loadImage("combo_normal.png"); + private static final BufferedImage combo_over = loadImage("combo_over.png"); + private static final BufferedImage combo_pressed = loadImage("combo_pressed.png"); + private static final BufferedImage combo_disabled = loadImage("combo_disabled.png"); + private static final Dimension BTN_SIZE = new Dimension(17, 20); + private final Dimension btnSize = new Dimension(BTN_SIZE); + + /** + * Creates a new UI deligate for the given component. It is a standard + * method that all UI deligates must have. + * + * @param c The component that the UI is for + * @return a new instance of NimbusComboBoxUI + */ + public static ComponentUI createUI(JComponent c) { + return new ComboBoxUI(); + } + + @Override + public void installUI(JComponent c) { + super.installUI(c); + c.setOpaque(false); + } + + @Override + protected void installListeners() { + super.installListeners(); + comboBox.addMouseListener(this); + } + + @Override + protected void uninstallListeners() { + super.uninstallListeners(); + comboBox.removeMouseListener(this); + } + + /** + * The minumum size is the size of the display area plus insets plus the + * button. + */ + public Dimension getMinimumSize(JComponent c) { + if (!isMinimumSizeDirty) { + return new Dimension(cachedMinimumSize); + } + Dimension size = getDisplaySize(); + Insets insets = getInsets(); + btnSize.height = size.height = Math.max(size.height, BTN_SIZE.height); + btnSize.width = (int) ((double) (BTN_SIZE.width / (double) BTN_SIZE.height) * btnSize.height); + size.height += insets.top + insets.bottom; + size.width += insets.left + insets.right + btnSize.width; + + cachedMinimumSize.setSize(size.width, size.height); + isMinimumSizeDirty = false; + + return new Dimension(size); + } + + protected JButton createArrowButton() { + JButton button = new JButton() { + @Override + protected void paintComponent(Graphics g) { + if (comboBox.isEditable()) { + BufferedImage img = combo_normal; + if (mouseDown) { + img = combo_pressed; + } else if (!comboBox.isEnabled()) { + img = combo_normal; + } else if (mouseInside) { + img = combo_over; + } + g.drawImage(img, + 0, 0, getWidth(), getHeight(), + 0, 0, img.getWidth(), img.getHeight(), comboBox); + } + } + }; + button.addMouseListener(this); + button.setMinimumSize(BTN_SIZE); + button.setPreferredSize(BTN_SIZE); + button.setMargin(new Insets(0, 0, 0, 0)); + return button; + } + + public void paint(Graphics g, JComponent c) { + hasFocus = comboBox.hasFocus(); + ListCellRenderer renderer = comboBox.getRenderer(); + Rectangle r = new Rectangle(0, 0, comboBox.getWidth(), comboBox.getHeight()); + paintCurrentValueBackground(g, r, hasFocus); + if (!comboBox.isEditable()) { + if (renderer instanceof JComponent) { + ((JComponent) renderer).setOpaque(false); + ((JComponent) renderer).setForeground(comboBox.getForeground()); + } + paintCurrentValue(g, rectangleForCurrentValue(), false); + if (renderer instanceof JComponent) { + ((JComponent) renderer).setOpaque(true); + } + } + } + + @Override + public void paintCurrentValueBackground(Graphics g, Rectangle bounds, boolean hasFocus) { + if (!comboBox.isEditable()) { + BufferedImage img = combo_normal; + if (!comboBox.isEnabled()) { + img = combo_disabled; + } else if (mouseDown) { + img = combo_pressed; + } else if (mouseInside) { + img = combo_over; + } + g.drawImage(img, + bounds.x, bounds.y, bounds.x + 4, bounds.y + bounds.height, + 0, 0, 1, 26, comboBox); + g.drawImage(img, + bounds.x + 1, bounds.y, bounds.x + bounds.width - 25, bounds.y + bounds.height, + 1, 0, 3, 26, comboBox); + g.drawImage(img, + bounds.x + bounds.width - 25, bounds.y, bounds.x + bounds.width, bounds.y + bounds.height, + 4, 0, 29, 26, comboBox); + } else { + /*g.setColor(Color.WHITE); + g.fillRect(bounds.x, bounds.y, bounds.width - btnSize.width, bounds.height - 1); + int x = bounds.x, y = bounds.y, w = bounds.width - btnSize.width, h = bounds.height - 1; + Insets insets = getInsets(); + g.setColor(new Color(141, 142, 143)); + g.drawLine(x, y, x + insets.left, y); + g.setColor(new Color(203, 203, 204)); + g.drawLine(x + 1, y + 1, x + insets.left, y + 1); + g.setColor(new Color(152, 152, 153)); + g.drawLine(x, y + 1, x, y + 1); + g.setColor(new Color(242, 242, 242)); + g.drawLine(x + 1, y + 2, x + insets.left, y + 2); + g.setColor(new Color(176, 176, 177)); + g.drawLine(x, y + 2, x, y + 2); + g.setColor(new Color(192, 192, 193)); + g.drawLine(x, y + h, x + insets.left, y + h); + g.setColor(new Color(184, 184, 185)); + g.drawLine(x, y + 3, x, y + h);*/ + } + } + + protected LayoutManager createLayoutManager() { + return new ComboLayout(); + } + + @Override + protected Insets getInsets() { + return new Insets(0, 5, 0, 0); + } + // ================================================================================================================= + // MouseListener Methods + private boolean mouseInside = false; + private boolean mouseDown = false; + + public void mouseClicked(MouseEvent e) { + } + + public void mouseEntered(MouseEvent e) { + if (comboBox.isEditable()) { + if (e.getComponent() == arrowButton) { + mouseInside = true; + } + } else { + mouseInside = true; + comboBox.repaint(); + } + } + + public void mouseExited(MouseEvent e) { + if (comboBox.isEditable()) { + if (e.getComponent() == arrowButton) { + mouseInside = false; + } + } else { + mouseInside = false; + comboBox.repaint(); + } + } + + public void mousePressed(MouseEvent e) { + if (comboBox.isEditable()) { + if (e.getComponent() == arrowButton) { + mouseDown = true; + } + } else { + mouseDown = true; + comboBox.repaint(); + } + } + + public void mouseReleased(MouseEvent e) { + if (comboBox.isEditable()) { + if (e.getComponent() == arrowButton) { + mouseDown = false; + } + } else { + mouseDown = false; + comboBox.repaint(); + } + } + + // ================================================================================================================= + // LayoutManager + private class ComboLayout implements LayoutManager { + + public void addLayoutComponent(String name, Component comp) { + } + + public void removeLayoutComponent(Component comp) { + } + + public Dimension preferredLayoutSize(Container parent) { + return parent.getPreferredSize(); + } + + public Dimension minimumLayoutSize(Container parent) { + return parent.getMinimumSize(); + } + + public void layoutContainer(Container parent) { + JComboBox cb = (JComboBox) parent; + int width = cb.getWidth(); + + Insets insets = getInsets(); + Rectangle cvb; + + if (arrowButton != null) { + if (cb.getComponentOrientation().isLeftToRight()) { + arrowButton.setBounds(width - (insets.right + btnSize.width), + insets.top, + btnSize.width, btnSize.height); + } else { + arrowButton.setBounds(insets.left, insets.top, + btnSize.width, btnSize.height); + } + } + if (editor != null) { + cvb = rectangleForCurrentValue(); + editor.setBounds(cvb.x, cvb.y, cvb.width, cvb.height); + } + } + } +} diff --git a/MetroLookAndFeel/src/main/java/org/jackhuang/hellominecraft/lookandfeel/ui/ListCellRender.java b/MetroLookAndFeel/src/main/java/org/jackhuang/hellominecraft/lookandfeel/ui/ListCellRender.java new file mode 100644 index 000000000..ae32d2d94 --- /dev/null +++ b/MetroLookAndFeel/src/main/java/org/jackhuang/hellominecraft/lookandfeel/ui/ListCellRender.java @@ -0,0 +1,47 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package org.jackhuang.hellominecraft.lookandfeel.ui; + +/* +* $Id: NimbusGraphicsUtils.java,v 1.9 2005/12/05 15:00:55 kizune Exp $ +* +* Copyright 2004 Sun Microsystems, Inc., 4150 Network Circle, +* Santa Clara, California 95054, U.S.A. All rights reserved. +* +* This library is free software; you can redistribute it and/or +* modify it under the terms of the GNU Lesser General Public +* License as published by the Free Software Foundation; either +* version 2.1 of the License, or (at your option) any later version. +* +* This library is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +* Lesser General Public License for more details. +* +* You should have received a copy of the GNU Lesser General Public +* License along with this library; if not, write to the Free Software +* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +import javax.swing.DefaultListCellRenderer; +import javax.swing.JList; +import java.awt.Color; +import java.awt.Component; + +/** + * NimbusListCellRender + * + * @author Created by Jasper Potts (Jan 19, 2007) + * @version 1.0 + */ +public class ListCellRender extends DefaultListCellRenderer { + + @Override public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, + boolean cellHasFocus) { + setOpaque(true); + setBackground(Color.magenta); + return super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus); + } +} diff --git a/MetroLookAndFeel/src/main/java/org/jackhuang/hellominecraft/lookandfeel/ui/ScrollBarUI.java b/MetroLookAndFeel/src/main/java/org/jackhuang/hellominecraft/lookandfeel/ui/ScrollBarUI.java new file mode 100644 index 000000000..147364f05 --- /dev/null +++ b/MetroLookAndFeel/src/main/java/org/jackhuang/hellominecraft/lookandfeel/ui/ScrollBarUI.java @@ -0,0 +1,179 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package org.jackhuang.hellominecraft.lookandfeel.ui; + +import static org.jackhuang.hellominecraft.lookandfeel.GraphicsUtils.loadImage; + +import javax.swing.JButton; +import javax.swing.JComponent; +import javax.swing.JScrollBar; +import javax.swing.plaf.ComponentUI; +import javax.swing.plaf.metal.MetalScrollBarUI; +import java.awt.Dimension; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.Rectangle; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.awt.geom.AffineTransform; +import java.awt.image.BufferedImage; + +/** + * NimbusScrollBarUI - A custom scrollbar ui for nimbus. It is special as it handles all the painting for the buttons as + * well so that it can cope with the buttons being non-recangular. + * + * @author Created by Jasper Potts (Jan 17, 2007) + * @version 1.0 + */ +public class ScrollBarUI extends MetalScrollBarUI { + + private static final BufferedImage BACKGROUND_ENABLED = loadImage("scroll_enabled.png"); + private static final BufferedImage BACKGROUND_DISABLED = loadImage("scroll_disabled.png"); + private static final BufferedImage SCROLL_DEC_NORMAL = loadImage("scroll_dec_normal.png"); + private static final BufferedImage SCROLL_DEC_OVER = loadImage("scroll_dec_over.png"); + private static final BufferedImage SCROLL_DEC_PRESSED = loadImage("scroll_dec_pressed.png"); + private static final BufferedImage SCROLL_INC_NORMAL = loadImage("scroll_inc_normal.png"); + private static final BufferedImage SCROLL_INC_OVER = loadImage("scroll_inc_over.png"); + private static final BufferedImage SCROLL_INC_PRESSED = loadImage("scroll_inc_pressed.png"); + private static final BufferedImage SCROLL_THUMB_NORMAL = loadImage("scroll_thumb_normal.png"); + private static final BufferedImage SCROLL_THUMB_OVER = loadImage("scroll_thumb_over.png"); + private static final BufferedImage SCROLL_THUMB_PRESSED = loadImage("scroll_thumb_pressed.png"); + + private boolean incBtnMouseOver, incBtnMousePressed; + private boolean decBtnMouseOver, decBtnMousePressed; + private boolean thumbMousePressed; + + /** + * Creates a new UI deligate for the given component. It is a standard method that all UI deligates must have. + * + * @param c The component that the UI is for + * @return a new instance of NimbusScrollBarUI + */ + public static ComponentUI createUI(JComponent c) { + return new ScrollBarUI(); + } + + /** {@inheritDoc} */ + @Override public void installUI(JComponent c) { + super.installUI(c); + c.setOpaque(true); + c.addMouseListener(new MouseAdapter() { + @Override public void mousePressed(MouseEvent e) { + if (isThumbRollover()) { + thumbMousePressed = true; + scrollbar.repaint(); + } + } + + @Override public void mouseReleased(MouseEvent e) { + thumbMousePressed = false; + } + }); + } + + /** {@inheritDoc} */ + @Override protected Dimension getMinimumThumbSize() { + return new Dimension(15, 15); + } + + /** {@inheritDoc} */ + @Override protected JButton createDecreaseButton(int orientation) { + decreaseButton = new ScrollButton(orientation, scrollBarWidth, isFreeStanding); + decreaseButton.addMouseListener(new MouseAdapter() { + @Override public void mouseEntered(MouseEvent e) { + decBtnMouseOver = true; + } + + @Override public void mouseExited(MouseEvent e) { + decBtnMouseOver = false; + } + + @Override public void mousePressed(MouseEvent e) { + decBtnMousePressed = true; + } + + @Override public void mouseReleased(MouseEvent e) { + decBtnMousePressed = false; + } + }); + return decreaseButton; + } + + /** {@inheritDoc} */ + @Override protected JButton createIncreaseButton(int orientation) { + increaseButton = new ScrollButton(orientation, scrollBarWidth, isFreeStanding); + increaseButton.addMouseListener(new MouseAdapter() { + @Override public void mouseEntered(MouseEvent e) { + incBtnMouseOver = true; + } + + @Override public void mouseExited(MouseEvent e) { + incBtnMouseOver = false; + } + + @Override public void mousePressed(MouseEvent e) { + incBtnMousePressed = true; + } + + @Override public void mouseReleased(MouseEvent e) { + incBtnMousePressed = false; + } + }); + return increaseButton; + } + + /** {@inheritDoc} */ + @Override protected void paintTrack(Graphics g, JComponent c, Rectangle trackBounds) { + BufferedImage decImg = + decBtnMousePressed ? SCROLL_DEC_PRESSED : decBtnMouseOver ? SCROLL_DEC_OVER : SCROLL_DEC_NORMAL; + BufferedImage incImg = + incBtnMousePressed ? SCROLL_INC_PRESSED : incBtnMouseOver ? SCROLL_INC_OVER : SCROLL_INC_NORMAL; + Graphics2D g2 = (Graphics2D) g; + AffineTransform origTransform = g2.getTransform(); + int scrollWidth = scrollbar.getWidth(); + if (scrollbar.getOrientation() == JScrollBar.VERTICAL) { + scrollWidth = scrollbar.getHeight(); + g2.scale(1, -1); + g2.rotate(-Math.PI / 2, 0, 0); + } + // draw track & bottons + if (scrollbar.isEnabled()) { + g.drawImage(decImg, 0, 0, scrollbar); + //g.drawImage(BACKGROUND_ENABLED, 15, 0, scrollWidth - 15, 15, 0, 0, 1, 15, scrollbar); + g.drawImage(incImg, scrollWidth - 15, 0, scrollbar); + } else { + //g.drawImage(BACKGROUND_DISABLED, 0, 0, scrollWidth, 15, 0, 0, 1, 15, scrollbar); + } + // undo any transform + g2.setTransform(origTransform); + } + + /** {@inheritDoc} */ + @Override protected void paintThumb(Graphics g, JComponent c, Rectangle thumbBounds) { + if (scrollbar.isEnabled()) { + BufferedImage thumbImg = thumbMousePressed ? SCROLL_THUMB_PRESSED : + isThumbRollover() ? SCROLL_THUMB_OVER : SCROLL_THUMB_NORMAL; + Graphics2D g2 = (Graphics2D) g; + AffineTransform origTransform = g2.getTransform(); + Rectangle b = thumbBounds; + if (scrollbar.getOrientation() == JScrollBar.VERTICAL) { + b = new Rectangle(thumbBounds.y, thumbBounds.x, thumbBounds.height, thumbBounds.width); + g2.scale(1, -1); + g2.rotate(-Math.PI / 2, 0, 0); + } + g.drawImage(thumbImg, + b.x, b.y, b.x + 14, b.y + 15, + 0, 0, 14, 15, scrollbar); + g.drawImage(thumbImg, + b.x + 14, b.y, b.x + b.width - 14, b.y + 15, + 16, 0, 17, 15, scrollbar); + g.drawImage(thumbImg, + b.x + b.width - 14, b.y, b.x + b.width, b.y + 15, + 24, 0, 38, 15, scrollbar); + // undo any transform + g2.setTransform(origTransform); + } + } +} diff --git a/MetroLookAndFeel/src/main/java/org/jackhuang/hellominecraft/lookandfeel/ui/ScrollButton.java b/MetroLookAndFeel/src/main/java/org/jackhuang/hellominecraft/lookandfeel/ui/ScrollButton.java new file mode 100644 index 000000000..594ad22fe --- /dev/null +++ b/MetroLookAndFeel/src/main/java/org/jackhuang/hellominecraft/lookandfeel/ui/ScrollButton.java @@ -0,0 +1,82 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package org.jackhuang.hellominecraft.lookandfeel.ui; + +/* +* $Id: NimbusGraphicsUtils.java,v 1.9 2005/12/05 15:00:55 kizune Exp $ +* +* Copyright 2004 Sun Microsystems, Inc., 4150 Network Circle, +* Santa Clara, California 95054, U.S.A. All rights reserved. +* +* This library is free software; you can redistribute it and/or +* modify it under the terms of the GNU Lesser General Public +* License as published by the Free Software Foundation; either +* version 2.1 of the License, or (at your option) any later version. +* +* This library is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +* Lesser General Public License for more details. +* +* You should have received a copy of the GNU Lesser General Public +* License along with this library; if not, write to the Free Software +* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +import static javax.swing.SwingConstants.NORTH; +import static javax.swing.SwingConstants.SOUTH; + +import javax.swing.SwingConstants; +import javax.swing.plaf.metal.MetalScrollButton; +import java.awt.Dimension; +import java.awt.Graphics; + +/** + * NimbusScrollButton - a fixed size 15x17 vertical 17x15 horizontal transparent button. + * + * @author Created by Jasper Potts (Jan 17, 2007) + * @version 1.0 + */ +public class ScrollButton extends MetalScrollButton implements SwingConstants { + + private final int btnWidth, btnHeight; + + ScrollButton(int direction, int width, boolean freeStanding) { + super(direction, width, freeStanding); + setOpaque(false); + if (direction == NORTH || direction == SOUTH) { + btnWidth = 15; + btnHeight = 17; + } else { + btnWidth = 17; + btnHeight = 15; + } + } + + @Override public Dimension getMaximumSize() { + return this.getPreferredSize(); + } + + @Override public Dimension getMinimumSize() { + return this.getPreferredSize(); + } + + @Override public Dimension getPreferredSize() { + return new Dimension(btnWidth, btnHeight); + } + + @Override public void repaint(long tm, int x, int y, int width, int height) { + if (getParent() != null) getParent().repaint(); + } + + /** + * Don't paint anything as all painting is done by the scrollbar + * + * @param g {@inheritDoc} + */ + @Override public void paint(Graphics g) { + } +} + diff --git a/MetroLookAndFeel/src/main/resources/org/jackhuang/hellominecraft/lookandfeel/images/checkbox_off.png b/MetroLookAndFeel/src/main/resources/org/jackhuang/hellominecraft/lookandfeel/images/checkbox_off.png new file mode 100644 index 000000000..a0afbaed2 Binary files /dev/null and b/MetroLookAndFeel/src/main/resources/org/jackhuang/hellominecraft/lookandfeel/images/checkbox_off.png differ diff --git a/MetroLookAndFeel/src/main/resources/org/jackhuang/hellominecraft/lookandfeel/images/checkbox_off_disabled.png b/MetroLookAndFeel/src/main/resources/org/jackhuang/hellominecraft/lookandfeel/images/checkbox_off_disabled.png new file mode 100644 index 000000000..bb507cdb0 Binary files /dev/null and b/MetroLookAndFeel/src/main/resources/org/jackhuang/hellominecraft/lookandfeel/images/checkbox_off_disabled.png differ diff --git a/MetroLookAndFeel/src/main/resources/org/jackhuang/hellominecraft/lookandfeel/images/checkbox_off_over.png b/MetroLookAndFeel/src/main/resources/org/jackhuang/hellominecraft/lookandfeel/images/checkbox_off_over.png new file mode 100644 index 000000000..738e2030d Binary files /dev/null and b/MetroLookAndFeel/src/main/resources/org/jackhuang/hellominecraft/lookandfeel/images/checkbox_off_over.png differ diff --git a/MetroLookAndFeel/src/main/resources/org/jackhuang/hellominecraft/lookandfeel/images/checkbox_off_pressed.png b/MetroLookAndFeel/src/main/resources/org/jackhuang/hellominecraft/lookandfeel/images/checkbox_off_pressed.png new file mode 100644 index 000000000..974d1d65a Binary files /dev/null and b/MetroLookAndFeel/src/main/resources/org/jackhuang/hellominecraft/lookandfeel/images/checkbox_off_pressed.png differ diff --git a/MetroLookAndFeel/src/main/resources/org/jackhuang/hellominecraft/lookandfeel/images/checkbox_on.png b/MetroLookAndFeel/src/main/resources/org/jackhuang/hellominecraft/lookandfeel/images/checkbox_on.png new file mode 100644 index 000000000..5a2cda110 Binary files /dev/null and b/MetroLookAndFeel/src/main/resources/org/jackhuang/hellominecraft/lookandfeel/images/checkbox_on.png differ diff --git a/MetroLookAndFeel/src/main/resources/org/jackhuang/hellominecraft/lookandfeel/images/checkbox_on_disabled.png b/MetroLookAndFeel/src/main/resources/org/jackhuang/hellominecraft/lookandfeel/images/checkbox_on_disabled.png new file mode 100644 index 000000000..453ca15d0 Binary files /dev/null and b/MetroLookAndFeel/src/main/resources/org/jackhuang/hellominecraft/lookandfeel/images/checkbox_on_disabled.png differ diff --git a/MetroLookAndFeel/src/main/resources/org/jackhuang/hellominecraft/lookandfeel/images/checkbox_on_over.png b/MetroLookAndFeel/src/main/resources/org/jackhuang/hellominecraft/lookandfeel/images/checkbox_on_over.png new file mode 100644 index 000000000..0842c1139 Binary files /dev/null and b/MetroLookAndFeel/src/main/resources/org/jackhuang/hellominecraft/lookandfeel/images/checkbox_on_over.png differ diff --git a/MetroLookAndFeel/src/main/resources/org/jackhuang/hellominecraft/lookandfeel/images/checkbox_on_pressed.png b/MetroLookAndFeel/src/main/resources/org/jackhuang/hellominecraft/lookandfeel/images/checkbox_on_pressed.png new file mode 100644 index 000000000..7baafae75 Binary files /dev/null and b/MetroLookAndFeel/src/main/resources/org/jackhuang/hellominecraft/lookandfeel/images/checkbox_on_pressed.png differ diff --git a/MetroLookAndFeel/src/main/resources/org/jackhuang/hellominecraft/lookandfeel/images/combo_disabled.png b/MetroLookAndFeel/src/main/resources/org/jackhuang/hellominecraft/lookandfeel/images/combo_disabled.png new file mode 100644 index 000000000..538f02b64 Binary files /dev/null and b/MetroLookAndFeel/src/main/resources/org/jackhuang/hellominecraft/lookandfeel/images/combo_disabled.png differ diff --git a/MetroLookAndFeel/src/main/resources/org/jackhuang/hellominecraft/lookandfeel/images/combo_normal.png b/MetroLookAndFeel/src/main/resources/org/jackhuang/hellominecraft/lookandfeel/images/combo_normal.png new file mode 100644 index 000000000..eb8b16585 Binary files /dev/null and b/MetroLookAndFeel/src/main/resources/org/jackhuang/hellominecraft/lookandfeel/images/combo_normal.png differ diff --git a/MetroLookAndFeel/src/main/resources/org/jackhuang/hellominecraft/lookandfeel/images/combo_over.png b/MetroLookAndFeel/src/main/resources/org/jackhuang/hellominecraft/lookandfeel/images/combo_over.png new file mode 100644 index 000000000..ba4df60d6 Binary files /dev/null and b/MetroLookAndFeel/src/main/resources/org/jackhuang/hellominecraft/lookandfeel/images/combo_over.png differ diff --git a/MetroLookAndFeel/src/main/resources/org/jackhuang/hellominecraft/lookandfeel/images/combo_pressed.png b/MetroLookAndFeel/src/main/resources/org/jackhuang/hellominecraft/lookandfeel/images/combo_pressed.png new file mode 100644 index 000000000..a8d2c44bc Binary files /dev/null and b/MetroLookAndFeel/src/main/resources/org/jackhuang/hellominecraft/lookandfeel/images/combo_pressed.png differ diff --git a/MetroLookAndFeel/src/main/resources/org/jackhuang/hellominecraft/lookandfeel/images/option_pane_error.png b/MetroLookAndFeel/src/main/resources/org/jackhuang/hellominecraft/lookandfeel/images/option_pane_error.png new file mode 100644 index 000000000..6baa7d9a5 Binary files /dev/null and b/MetroLookAndFeel/src/main/resources/org/jackhuang/hellominecraft/lookandfeel/images/option_pane_error.png differ diff --git a/MetroLookAndFeel/src/main/resources/org/jackhuang/hellominecraft/lookandfeel/images/option_pane_info.png b/MetroLookAndFeel/src/main/resources/org/jackhuang/hellominecraft/lookandfeel/images/option_pane_info.png new file mode 100644 index 000000000..00552523f Binary files /dev/null and b/MetroLookAndFeel/src/main/resources/org/jackhuang/hellominecraft/lookandfeel/images/option_pane_info.png differ diff --git a/MetroLookAndFeel/src/main/resources/org/jackhuang/hellominecraft/lookandfeel/images/option_pane_question.png b/MetroLookAndFeel/src/main/resources/org/jackhuang/hellominecraft/lookandfeel/images/option_pane_question.png new file mode 100644 index 000000000..208fef537 Binary files /dev/null and b/MetroLookAndFeel/src/main/resources/org/jackhuang/hellominecraft/lookandfeel/images/option_pane_question.png differ diff --git a/MetroLookAndFeel/src/main/resources/org/jackhuang/hellominecraft/lookandfeel/images/option_pane_warning.png b/MetroLookAndFeel/src/main/resources/org/jackhuang/hellominecraft/lookandfeel/images/option_pane_warning.png new file mode 100644 index 000000000..2b42e6c84 Binary files /dev/null and b/MetroLookAndFeel/src/main/resources/org/jackhuang/hellominecraft/lookandfeel/images/option_pane_warning.png differ diff --git a/MetroLookAndFeel/src/main/resources/org/jackhuang/hellominecraft/lookandfeel/images/radio_btn.png b/MetroLookAndFeel/src/main/resources/org/jackhuang/hellominecraft/lookandfeel/images/radio_btn.png new file mode 100644 index 000000000..b87150ff1 Binary files /dev/null and b/MetroLookAndFeel/src/main/resources/org/jackhuang/hellominecraft/lookandfeel/images/radio_btn.png differ diff --git a/MetroLookAndFeel/src/main/resources/org/jackhuang/hellominecraft/lookandfeel/images/radio_btn_disabled_normal.png b/MetroLookAndFeel/src/main/resources/org/jackhuang/hellominecraft/lookandfeel/images/radio_btn_disabled_normal.png new file mode 100644 index 000000000..a081781ea Binary files /dev/null and b/MetroLookAndFeel/src/main/resources/org/jackhuang/hellominecraft/lookandfeel/images/radio_btn_disabled_normal.png differ diff --git a/MetroLookAndFeel/src/main/resources/org/jackhuang/hellominecraft/lookandfeel/images/radio_btn_disabled_selected.png b/MetroLookAndFeel/src/main/resources/org/jackhuang/hellominecraft/lookandfeel/images/radio_btn_disabled_selected.png new file mode 100644 index 000000000..932ec20c1 Binary files /dev/null and b/MetroLookAndFeel/src/main/resources/org/jackhuang/hellominecraft/lookandfeel/images/radio_btn_disabled_selected.png differ diff --git a/MetroLookAndFeel/src/main/resources/org/jackhuang/hellominecraft/lookandfeel/images/radio_btn_over.png b/MetroLookAndFeel/src/main/resources/org/jackhuang/hellominecraft/lookandfeel/images/radio_btn_over.png new file mode 100644 index 000000000..d6a3a608f Binary files /dev/null and b/MetroLookAndFeel/src/main/resources/org/jackhuang/hellominecraft/lookandfeel/images/radio_btn_over.png differ diff --git a/MetroLookAndFeel/src/main/resources/org/jackhuang/hellominecraft/lookandfeel/images/radio_btn_pressed.png b/MetroLookAndFeel/src/main/resources/org/jackhuang/hellominecraft/lookandfeel/images/radio_btn_pressed.png new file mode 100644 index 000000000..d4519c5a8 Binary files /dev/null and b/MetroLookAndFeel/src/main/resources/org/jackhuang/hellominecraft/lookandfeel/images/radio_btn_pressed.png differ diff --git a/MetroLookAndFeel/src/main/resources/org/jackhuang/hellominecraft/lookandfeel/images/radio_btn_selected.png b/MetroLookAndFeel/src/main/resources/org/jackhuang/hellominecraft/lookandfeel/images/radio_btn_selected.png new file mode 100644 index 000000000..d4b998c2e Binary files /dev/null and b/MetroLookAndFeel/src/main/resources/org/jackhuang/hellominecraft/lookandfeel/images/radio_btn_selected.png differ diff --git a/MetroLookAndFeel/src/main/resources/org/jackhuang/hellominecraft/lookandfeel/images/radio_btn_selected_over.png b/MetroLookAndFeel/src/main/resources/org/jackhuang/hellominecraft/lookandfeel/images/radio_btn_selected_over.png new file mode 100644 index 000000000..a51c6c3a7 Binary files /dev/null and b/MetroLookAndFeel/src/main/resources/org/jackhuang/hellominecraft/lookandfeel/images/radio_btn_selected_over.png differ diff --git a/MetroLookAndFeel/src/main/resources/org/jackhuang/hellominecraft/lookandfeel/images/radio_btn_selected_pressed.png b/MetroLookAndFeel/src/main/resources/org/jackhuang/hellominecraft/lookandfeel/images/radio_btn_selected_pressed.png new file mode 100644 index 000000000..6a5fed0c9 Binary files /dev/null and b/MetroLookAndFeel/src/main/resources/org/jackhuang/hellominecraft/lookandfeel/images/radio_btn_selected_pressed.png differ diff --git a/MetroLookAndFeel/src/main/resources/org/jackhuang/hellominecraft/lookandfeel/images/scroll_dec_normal.png b/MetroLookAndFeel/src/main/resources/org/jackhuang/hellominecraft/lookandfeel/images/scroll_dec_normal.png new file mode 100644 index 000000000..afccc9998 Binary files /dev/null and b/MetroLookAndFeel/src/main/resources/org/jackhuang/hellominecraft/lookandfeel/images/scroll_dec_normal.png differ diff --git a/MetroLookAndFeel/src/main/resources/org/jackhuang/hellominecraft/lookandfeel/images/scroll_dec_over.png b/MetroLookAndFeel/src/main/resources/org/jackhuang/hellominecraft/lookandfeel/images/scroll_dec_over.png new file mode 100644 index 000000000..fa21afbe5 Binary files /dev/null and b/MetroLookAndFeel/src/main/resources/org/jackhuang/hellominecraft/lookandfeel/images/scroll_dec_over.png differ diff --git a/MetroLookAndFeel/src/main/resources/org/jackhuang/hellominecraft/lookandfeel/images/scroll_dec_pressed.png b/MetroLookAndFeel/src/main/resources/org/jackhuang/hellominecraft/lookandfeel/images/scroll_dec_pressed.png new file mode 100644 index 000000000..afccc9998 Binary files /dev/null and b/MetroLookAndFeel/src/main/resources/org/jackhuang/hellominecraft/lookandfeel/images/scroll_dec_pressed.png differ diff --git a/MetroLookAndFeel/src/main/resources/org/jackhuang/hellominecraft/lookandfeel/images/scroll_disabled.png b/MetroLookAndFeel/src/main/resources/org/jackhuang/hellominecraft/lookandfeel/images/scroll_disabled.png new file mode 100644 index 000000000..fe990d02f Binary files /dev/null and b/MetroLookAndFeel/src/main/resources/org/jackhuang/hellominecraft/lookandfeel/images/scroll_disabled.png differ diff --git a/MetroLookAndFeel/src/main/resources/org/jackhuang/hellominecraft/lookandfeel/images/scroll_enabled.png b/MetroLookAndFeel/src/main/resources/org/jackhuang/hellominecraft/lookandfeel/images/scroll_enabled.png new file mode 100644 index 000000000..29055171e Binary files /dev/null and b/MetroLookAndFeel/src/main/resources/org/jackhuang/hellominecraft/lookandfeel/images/scroll_enabled.png differ diff --git a/MetroLookAndFeel/src/main/resources/org/jackhuang/hellominecraft/lookandfeel/images/scroll_inc_normal.png b/MetroLookAndFeel/src/main/resources/org/jackhuang/hellominecraft/lookandfeel/images/scroll_inc_normal.png new file mode 100644 index 000000000..74fe160ea Binary files /dev/null and b/MetroLookAndFeel/src/main/resources/org/jackhuang/hellominecraft/lookandfeel/images/scroll_inc_normal.png differ diff --git a/MetroLookAndFeel/src/main/resources/org/jackhuang/hellominecraft/lookandfeel/images/scroll_inc_over.png b/MetroLookAndFeel/src/main/resources/org/jackhuang/hellominecraft/lookandfeel/images/scroll_inc_over.png new file mode 100644 index 000000000..1c4f3f5e4 Binary files /dev/null and b/MetroLookAndFeel/src/main/resources/org/jackhuang/hellominecraft/lookandfeel/images/scroll_inc_over.png differ diff --git a/MetroLookAndFeel/src/main/resources/org/jackhuang/hellominecraft/lookandfeel/images/scroll_inc_pressed.png b/MetroLookAndFeel/src/main/resources/org/jackhuang/hellominecraft/lookandfeel/images/scroll_inc_pressed.png new file mode 100644 index 000000000..74fe160ea Binary files /dev/null and b/MetroLookAndFeel/src/main/resources/org/jackhuang/hellominecraft/lookandfeel/images/scroll_inc_pressed.png differ diff --git a/MetroLookAndFeel/src/main/resources/org/jackhuang/hellominecraft/lookandfeel/images/scroll_thumb_normal.png b/MetroLookAndFeel/src/main/resources/org/jackhuang/hellominecraft/lookandfeel/images/scroll_thumb_normal.png new file mode 100644 index 000000000..7f80ad314 Binary files /dev/null and b/MetroLookAndFeel/src/main/resources/org/jackhuang/hellominecraft/lookandfeel/images/scroll_thumb_normal.png differ diff --git a/MetroLookAndFeel/src/main/resources/org/jackhuang/hellominecraft/lookandfeel/images/scroll_thumb_over.png b/MetroLookAndFeel/src/main/resources/org/jackhuang/hellominecraft/lookandfeel/images/scroll_thumb_over.png new file mode 100644 index 000000000..4bfc80afd Binary files /dev/null and b/MetroLookAndFeel/src/main/resources/org/jackhuang/hellominecraft/lookandfeel/images/scroll_thumb_over.png differ diff --git a/MetroLookAndFeel/src/main/resources/org/jackhuang/hellominecraft/lookandfeel/images/scroll_thumb_pressed.png b/MetroLookAndFeel/src/main/resources/org/jackhuang/hellominecraft/lookandfeel/images/scroll_thumb_pressed.png new file mode 100644 index 000000000..4bfc80afd Binary files /dev/null and b/MetroLookAndFeel/src/main/resources/org/jackhuang/hellominecraft/lookandfeel/images/scroll_thumb_pressed.png differ diff --git a/MetroLookAndFeel/src/main/resources/org/jackhuang/hellominecraft/lookandfeel/synth.xml b/MetroLookAndFeel/src/main/resources/org/jackhuang/hellominecraft/lookandfeel/synth.xml new file mode 100644 index 000000000..576064ab4 --- /dev/null +++ b/MetroLookAndFeel/src/main/resources/org/jackhuang/hellominecraft/lookandfeel/synth.xml @@ -0,0 +1,424 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 237 + 239 + 242 + + + + 0 + 0 + 0 + + + + 160 + 216 + 240 + + + + 35 + 35 + 36 + + + + + + + + + + + + + + + + + + + + + + 237 + 239 + 242 + + + + 255 + 255 + 255 + + + + 0 + 0 + 255 + + + + 35 + 35 + 36 + + + + + + + + + + + + + + + + + diff --git a/build.gradle b/build.gradle new file mode 100644 index 000000000..bdff2c0c5 --- /dev/null +++ b/build.gradle @@ -0,0 +1,24 @@ +import org.gradle.api.artifacts.* + +apply plugin: 'base' // To add "clean" task to the root project. + +subprojects { + apply from: rootProject.file('common.gradle') +} + +task mergedJavadoc(type: Javadoc, description: 'Creates Javadoc from all the projects.') { + title = 'All modules' + destinationDir = new File(project.buildDir, 'merged-javadoc') + + // Note: The closures below are executed lazily. + source { + subprojects*.sourceSets*.main*.allSource + } + classpath.from { + subprojects*.configurations*.compile*.copyRecursive({ !(it instanceof ProjectDependency); })*.resolve() + } +} + +task wrapper(type: Wrapper, description: 'Creates and deploys the Gradle wrapper to the current directory.') { + gradleVersion = '1.11' +} \ No newline at end of file diff --git a/common.gradle b/common.gradle new file mode 100644 index 000000000..61b1fc551 --- /dev/null +++ b/common.gradle @@ -0,0 +1,44 @@ +// +// This file is to be applied to every subproject. +// + +apply plugin: 'java' +apply plugin: 'maven' + +//sourceCompatibility = '1.7' +[compileJava, compileTestJava]*.options*.encoding = 'UTF-8' + +repositories { + mavenCentral(); +} + +buildscript { + repositories { + mavenCentral(); + } +} + +dependencies { + // Adding dependencies here will add the dependencies to each subproject. + + compile 'com.google.code.gson:gson:2.2.4' // Apache License 2.0 +} + +task sourcesJar(type: Jar, dependsOn: classes, description: 'Creates a jar from the source files.') { + classifier = 'sources' + from sourceSets.main.allSource +} + +artifacts { + archives jar + archives sourcesJar +} + +task createFolders(description: 'Creates the source folders if they do not exist.') doLast { + sourceSets*.allSource*.srcDirs*.each { File srcDir -> + if (!srcDir.isDirectory()) { + println "Creating source folder: ${srcDir}" + srcDir.mkdirs() + } + } +} \ No newline at end of file diff --git a/settings.gradle b/settings.gradle new file mode 100644 index 000000000..c0fd4b414 --- /dev/null +++ b/settings.gradle @@ -0,0 +1,20 @@ +rootProject.name = 'HMCL' + +// Find the directories containing a "build.gradle" file in the root directory +// of the project. That is, every directory containing a "build.gradle" will +// be automatically the subproject of this project. +def subDirs = rootDir.listFiles(new FileFilter() { + public boolean accept(File file) { + if (!file.isDirectory()) { + return false + } + if (file.name == 'buildSrc') { + return false + } + return new File(file, 'build.gradle').isFile() + } +}); + +subDirs.each { File dir -> + include dir.name +}