Compare commits

...
60 Commits
32 ... 64
Author SHA1 Message Date
南宫临风 fd5b5ebd8d Try test travis 2016-07-11 15:23:10 +08:00
南宫临风 2f42873793 Fix gradle build file 2016-07-11 11:54:22 +08:00
南宫临风 3b4b63e57b Modify publish link 2016-07-11 11:47:12 +08:00
南宫临风 c33a99d9ed show update log 2016-07-09 22:04:43 +08:00
南宫临风 b6be41e5c5 update git ignore file 2016-07-09 21:02:57 +08:00
南宫临风 bd4c07a013 read buildNumber from travis 2016-07-09 21:01:37 +08:00
南宫临风 ba763b2d2a Synchronize version.properties 2016-07-08 20:40:55 +08:00
南宫临风 c15ec71be9 update travis 2016-07-08 20:31:25 +08:00
南宫临风 93273d555d update README.md 2016-07-08 19:54:48 +08:00
南宫临风 793f81e287 update travis 2016-07-08 19:49:06 +08:00
南宫临风 d87b768fc0 修正模组信息解析问题 2016-07-07 18:01:58 +08:00
南宫临风 c07d2dc6d3 update link 2016-07-07 16:53:46 +08:00
南宫临风 95af0222f3 update dynamic provider 2016-07-07 14:32:35 +08:00
南宫临风 3f15eddb0c 修正使用java 8 API导致启动失败 2016-07-06 16:24:33 +08:00
南宫临风 c39f1ad75f 使用gradle管理buildNumber 2016-07-05 12:03:34 +08:00
南宫临风 f27b60e031 udpate version 2016-07-05 11:25:36 +08:00
南宫临风 5f1d0a5936 强制更新的时候不刷新标题栏 2016-07-04 18:22:01 +08:00
南宫临风 4fdadd5474 统计版本号 2016-07-04 18:16:34 +08:00
南宫临风 b2ea6d449e 忽略版本更新功能 2016-07-04 17:29:22 +08:00
南宫临风 3afff687b2 修改版本升级地址 2016-07-04 14:34:04 +08:00
evilwk 37ddecf629 加入强制升级和升级提示 2016-07-03 18:33:53 +08:00
南宫临风 27e58edb1f MainPagePanel content 2016-06-30 20:05:12 +08:00
南宫临风 3dd421a2bf fix library url parse 2016-06-29 16:54:29 +08:00
南宫临风 4537f9e48f 修正library补全Bug 2016-06-29 15:47:40 +08:00
南宫临风 94b6cda86e 添加可以在线控制的下载源 2016-06-28 20:48:27 +08:00
南宫临风 9ae010a391 改进自动下载数据排序
自动下载表格加入表头排序
2016-06-27 17:43:34 +08:00
南宫临风 13c105472e Update README.md 2016-06-27 10:23:39 +08:00
huanghongxun 88194e479e Update README.md 2016-06-07 23:00:07 +08:00
huangyuhui b36c194f67 Merge branch 'master' of https://github.com/huanghongxun/HMCL 2016-05-28 23:19:21 +08:00
huangyuhui 7c7b6e0fd9 Fixed #73 2016-05-28 23:17:49 +08:00
huanghongxun 01b77f1f5f Merge pull request #71 from Cat7373/master
Windows 启动脚本中允许跨分区 cd
2016-05-23 19:28:18 +08:00
Cat73 840a0ad840 Windows 启动脚本中允许跨分区 cd
修复跨分区的情况下一些文件如 logs 仍然生成在脚本所在目录,而不是 .minecraft 目录
2016-05-23 13:25:58 +08:00
huangyuhui ab1ca18488 Fixed NullPointerException when minecraftArguments=null 2016-05-23 13:09:30 +08:00
huangyuhui 75e0fa2def Fixed mainClass of macAppBundle 2016-05-16 18:10:30 +08:00
huangyuhui ca3ed47d21 Applied macosapp. Closes #63 2016-05-16 12:55:35 +08:00
huangyuhui 61a8ab5199 Supplements: 'SerializedName' 2016-05-14 20:24:42 +08:00
huangyuhui ce721c2e09 Reconstruct codes 2016-05-13 18:25:55 +08:00
huangyuhui 2862e3a6ee TWords in title bar can be dragged now 2016-05-11 13:42:46 +08:00
huangyuhui 75c4a24cbd Fixed #68 2016-05-10 13:24:06 +08:00
huanghongxun 1cf7d791cc Changes logo. Closes #67 2016-05-08 22:46:11 +08:00
huangyuhui 62fecc08ac Fixed #65 2016-05-08 10:04:23 +08:00
huangyuhui 491ca63342 Merge branch 'master' of https://github.com/huanghongxun/HMCL 2016-05-08 09:42:00 +08:00
huangyuhui b232a255e7 Fixed #66 2016-05-08 09:41:27 +08:00
huanghongxun 0870f42557 Merge pull request #64 from Cat7373/master
在 Windows 的启动脚本里增加一行 cd %appdata%
2016-05-03 19:12:59 +08:00
Cat73 85237eac7e 在 Windows 的启动脚本里增加一行 cd %appdata%
这样可以避免一些文件如 logs 生成在脚本所在目录,而不是 .minecraft 目录
2016-05-03 09:41:55 +08:00
huangyuhui 8d5088d2e4 Removed findbugs 2016-04-25 23:28:29 +08:00
huangyuhui 47f5bf1ea5 Added an options to disable online game complete check 2016-04-25 23:09:56 +08:00
huangyuhui deebadef3a Fixed #61 2016-04-11 13:40:06 +08:00
huangyuhui ce24ae4fae Fixed #60 2016-04-06 19:41:33 +08:00
huangyuhui 16152de39d Fixed ClassCastException 2016-04-05 22:16:29 +08:00
huangyuhui 4a2ac63d25 Added removal of installers for Issue #55 2016-03-28 20:57:01 +08:00
huangyuhui 5437968c83 Fixed #56 2016-03-28 20:45:06 +08:00
huangyuhui 8022252452 Fixed task system 2016-03-27 14:13:59 +08:00
huangyuhui ea6571fdb6 Fix #53 2016-03-26 13:02:47 +08:00
huanghongxun 2f7f692b84 Merge pull request #51 from tsl0922/master
Fix cpu ratio for mac
2016-03-25 19:19:46 +08:00
Shuanglei Tao 721df1d17c Fix cpu ratio for mac 2016-03-24 21:29:48 +08:00
huangyuhui 7a2e43f949 Fixed #50 2016-03-19 19:55:42 +08:00
huangyuhui 4e5cc3dadb sponsor 2016-03-17 18:38:17 +08:00
huangyuhui f6d5dd5a82 Fixed NullPointerException when a version not exists. 2016-03-15 18:49:31 +08:00
huangyuhui cafcf458b8 Fixed auto-loading when deleting a profile 2016-03-12 11:57:30 +08:00
339 changed files with 2904 additions and 12758 deletions

No files matched your search

Executable → Regular
+4
View File
@@ -25,3 +25,7 @@ HMCL/build/
HMCLServer/ HMCLServer/
HMCSM/build/ HMCSM/build/
MetroLookAndFeel/build/ MetroLookAndFeel/build/
/HMCUtils/build/
/HMCLaF/build/
HMCL/version.properties
.idea/
+10 -1
View File
@@ -14,6 +14,15 @@
<task-args/> <task-args/>
<task-jvm-args/> <task-jvm-args/>
</task> </task>
<task>
<display-name>createApp</display-name>
<non-blocking>no</non-blocking>
<task-names>
<name must-exist="yes">createApp</name>
</task-names>
<task-args/>
<task-jvm-args/>
</task>
</common-tasks> </common-tasks>
<script-platform> <script-platform>
<spec-name>j2se</spec-name> <spec-name>j2se</spec-name>
@@ -22,6 +31,6 @@
<license-header> <license-header>
<name>GNU General Public License</name> <name>GNU General Public License</name>
<template>license-header.txt</template> <template>license-header.txt</template>
<property name="organization">huangyuhui</property> <property name="organization">HMCLSoft</property>
</license-header> </license-header>
</gradle-project-properties> </gradle-project-properties>
+4 -4
View File
@@ -11,15 +11,15 @@ before_deploy:
- git push -q ${REPO} --tags - git push -q ${REPO} --tags
deploy: deploy:
provider: releases provider: releases
api_key: api_key: ${DEPLOY_REPO}
secure: lfFEwKtij/s9Ao/SKL7oVdsWcfASshZuwT27gllMrTx1ZQqLCG2I5mGJOp5ukx7lb3y4Tu316nFasLjy9NI3eLXSx9f0w4q+wMf0K5Yj9iOwu/TIn7JkLyHDMQ20qRwGxZplS2WUb669gIRg+l6jUHeTBW+dlTxr0mMa6WHIl8UDpHwfFrGC3i6dL4y6WlDwGl2rYktvOoA/iqvtglBcHuXaL2sDfhp5MXRcYULTIw+b9zmiQXP665DQN+Su5I3gwB4y5X8RH72GAacZn13fEIo5i8UUoHM7UQxM8y8DKSO3avyFCfpUle9+9sErQVW7b6JV1c+AoLWuAhNJLMlUTKarZE7UMqfjvoQHxX5hp2B2WHLEON/UJiGf25HJWx6VhJitE0/odujqnG/umesqki2jMTs6gPcxbc9iBjzUg+ZmFztdtC+Emnni7lpqVVl+Y5hsJRn3Z6rIiNgwmaE0r2OQgAm1vRYFc7jvOdRfyFG+uCRZF6nS56BzJ7dLc0WW8dTgSft6YFll4ZYL6hiI9qiIaBAK948y5HV+6VBWuO3xf/G2CUFbE1Y9qUCjToh3ahxNDzZvXB+rXqvlvNQOi5l8n594oQ61n45qIHSKlMBn9Bxhw29oWT5mo1aYIaNXbpzKam2w4mK0T3VrgTszu/3282wRbNr+VAwdGMfwW1s=
file: file:
- HMCL/build/libs/HMCL-${HMCL_VERSION_ROOT}.${TRAVIS_BUILD_NUMBER}.jar - HMCL/build/libs/HMCL-${HMCL_VERSION_ROOT}.${TRAVIS_BUILD_NUMBER}.jar
- HMCL/build/libs/HMCL-${HMCL_VERSION_ROOT}.${TRAVIS_BUILD_NUMBER}.exe - HMCL/build/libs/HMCL-${HMCL_VERSION_ROOT}.${TRAVIS_BUILD_NUMBER}.exe
- HMCL/build/libs/HMCL-${HMCL_VERSION_ROOT}.${TRAVIS_BUILD_NUMBER}-MacOSApp.zip
- HMCSM/build/libs/HMCSM-${HMCSM_VERSION_ROOT}.${TRAVIS_BUILD_NUMBER}.jar - HMCSM/build/libs/HMCSM-${HMCSM_VERSION_ROOT}.${TRAVIS_BUILD_NUMBER}.jar
- HMCSM/build/libs/HMCSM-${HMCSM_VERSION_ROOT}.${TRAVIS_BUILD_NUMBER}.exe - HMCSM/build/libs/HMCSM-${HMCSM_VERSION_ROOT}.${TRAVIS_BUILD_NUMBER}.exe
- HMCSM/build/libs/HMCSM-${HMCSM_VERSION_ROOT}.${TRAVIS_BUILD_NUMBER}-MacOSApp.zip
on: on:
repo: huanghongxun/HMCL
tags: false tags: false
skip_cleanup: true skip_cleanup: true
install: echo "skip 'gradle assemble' step" install: echo "skip 'gradle assemble' step"
@@ -29,4 +29,4 @@ before_cache:
cache: cache:
directories: directories:
- "$HOME/.gradle/caches/" - "$HOME/.gradle/caches/"
- "$HOME/.gradle/wrapper/" - "$HOME/.gradle/wrapper/"
+128 -47
View File
@@ -15,46 +15,6 @@
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see {http://www.gnu.org/licenses/}. * along with this program. If not, see {http://www.gnu.org/licenses/}.
*/ */
import java.util.jar.JarOutputStream
import java.util.zip.ZipEntry
import java.util.zip.ZipFile
apply plugin: 'launch4j'
apply plugin: 'me.tatarka.retrolambda'
if (!hasProperty('mainClass')) {
ext.mainClass = 'org.jackhuang.hellominecraft.launcher.Main'
}
def buildnumber = System.getenv("TRAVIS_BUILD_NUMBER")
if (buildnumber == null)
buildnumber = System.getenv("BUILD_NUMBER")
if (buildnumber == null)
buildnumber = "233"
def versionroot = System.getenv("VERSION_ROOT")
if (versionroot == null)
versionroot = "2.4.1"
String mavenGroupId = 'HMCL'
String mavenVersion = versionroot + '.' + buildnumber
String bundleName = "Hello Minecraft! Launcher"
group = mavenGroupId
version = mavenVersion
String mavenArtifactId = name
task generateSources(type: Copy) {
from 'src/main/java'
into "$buildDir/generated-src"
filter(org.apache.tools.ant.filters.ReplaceTokens, tokens: [
'HELLO_MINECRAFT_LAUNCHER_VERSION_FOR_GRADLE_REPLACING': mavenVersion
])
}
compileJava.setSource "$buildDir/generated-src"
compileJava.dependsOn generateSources
buildscript { buildscript {
repositories { repositories {
mavenCentral(); mavenCentral();
@@ -67,10 +27,131 @@ buildscript {
classpath 'net.sf.proguard:proguard-gradle:4.10' classpath 'net.sf.proguard:proguard-gradle:4.10'
classpath 'edu.sc.seis.gradle:launch4j:1.0.6' classpath 'edu.sc.seis.gradle:launch4j:1.0.6'
classpath 'me.tatarka:gradle-retrolambda:3.1.0' classpath 'me.tatarka:gradle-retrolambda:3.1.0'
classpath 'com.google.code.gson:gson:2.2.4'
} }
} }
} }
plugins {
id "edu.sc.seis.macAppBundle" version "2.1.6"
}
import java.util.jar.JarOutputStream
import java.util.zip.ZipEntry
import java.util.zip.ZipFile
import com.google.gson.JsonParser
apply plugin: 'launch4j'
apply plugin: 'me.tatarka.retrolambda'
if (!hasProperty('mainClass')) {
ext.mainClass = 'org.jackhuang.hellominecraft.launcher.Main'
}
def readBuildNumber() {
def versionPropsFile = file('version.properties')
def Properties versionProps = new Properties()
if (versionPropsFile.canRead()) {
versionProps.load(new FileInputStream(versionPropsFile))
def code = versionProps['VERSION_CODE'].toInteger() + 1
return code.toString()
} else {
versionPropsFile.createNewFile()
String url = 'https://api.travis-ci.org/repos/mclauncher/HMCL/branches'
def json = new JsonParser().parse(url.toURL().text);
if (json.has('branches') && json.get('branches').isJsonArray()) {
def branches = json.getAsJsonArray('branches')
if (branches != null && branches.size() > 0) {
def info = branches.get(0).getAsJsonObject()
def code = info.get('number').getAsInt()
versionProps['VERSION_CODE'] = code.toString()
versionProps.store(versionPropsFile.newWriter(), null)
return (code + 1).toString()
}
}
}
return '233'
}
task cleanVersionFile << {
file("version.properties").delete()
}
def buildnumber = System.getenv("TRAVIS_BUILD_NUMBER")
if (buildnumber == null)
buildnumber = System.getenv("BUILD_NUMBER")
if (buildnumber == null)
buildnumber = readBuildNumber()
def versionroot = System.getenv("VERSION_ROOT")
if (versionroot == null)
versionroot = "2.5.0"
String mavenGroupId = 'HMCL'
String mavenVersion = versionroot + '.' + buildnumber
String bundleName = "Hello Minecraft! Launcher"
group = mavenGroupId
version = mavenVersion
String mavenArtifactId = name
task generateSources(type: Copy) {
from 'src/main/java'
from 'src/core/java'
into "$buildDir/generated-src"
filter(org.apache.tools.ant.filters.ReplaceTokens, tokens: [
'HELLO_MINECRAFT_LAUNCHER_VERSION_FOR_GRADLE_REPLACING': mavenVersion
])
}
compileJava.setSource "$buildDir/generated-src"
compileJava.dependsOn generateSources
task macAppCompressed(type: Zip, dependsOn: createApp) {
archiveName "HMCL-$mavenVersion-MacOSApp.zip"
include '**'
destinationDir file("$buildDir/libs/")
from "$buildDir/macApp"
}
macAppBundle {
mainClassName = mainClass
icon = "src/main/icon.icns"
javaProperties.put("apple.laf.useScreenMenuBar", "true")
}
sourceSets {
main {
java {
srcDirs = [
'src/core/java/',
'src/main/java/'
]
}
resources {
srcDirs = ['src/main/resources/']
}
}
core {
java {
compileClasspath += main.compileClasspath
runtimeClasspath += main.runtimeClasspath
srcDirs 'src/core/java/'
}
resources {
srcDirs 'src/main/resources/'
}
}
}
configurations {
coreCompile.extendsFrom compile
coreRuntime.extendsFrom runtime
}
configure(install.repositories.mavenInstaller) { configure(install.repositories.mavenInstaller) {
pom.project { pom.project {
groupId = mavenGroupId groupId = mavenGroupId
@@ -80,8 +161,8 @@ configure(install.repositories.mavenInstaller) {
} }
dependencies { dependencies {
compile project(":MetroLookAndFeel") compile project(":HMCLaF")
compile project(":HMCLAPI") compile project(":HMCUtils")
compile group: "org.commonjava.googlecode.markdown4j", name: "markdown4j", version: "2.2-cj-1.0" compile group: "org.commonjava.googlecode.markdown4j", name: "markdown4j", version: "2.2-cj-1.0"
} }
@@ -93,22 +174,20 @@ jar {
from { configurations.compile.collect { it.isDirectory() ? it : zipTree(it) } } from { configurations.compile.collect { it.isDirectory() ? it : zipTree(it) } }
manifest { manifest {
attributes 'Created-By' : 'Copyright(c) 2013-2016 huangyuhui.', attributes 'Created-By' : 'Copyright(c) 2013-2016 HMCLSoft.',
'Main-Class' : mainClass 'Main-Class' : mainClass
} }
} }
launch4j { launch4j {
launch4jCmd = 'D:\\Develop\\Java\\Launch4j\\launch4j.exe' supportUrl = 'http://www.hmclsoft.com'
//launch4jCmd = '/home/huangyuhui/softwares/launch4j/launch4j'
supportUrl = 'http://www.mcbbs.net/thread-142335-1-1.html'
jreMinVersion = '1.6.0' jreMinVersion = '1.6.0'
mainClassName = mainClass mainClassName = mainClass
icon = new File(project.buildDir, '../icon.ico').absolutePath icon = new File(project.buildDir, '../icon.ico').absolutePath
version = mavenVersion version = mavenVersion
downloadUrl = 'http://java.com/download' downloadUrl = 'http://java.com/download'
copyright = "Copyright(c) 2013-2015 huangyuhui." copyright = "Copyright(c) 2013-2015 HMCLSoft."
jar = new File(project.buildDir, 'libs/' + mavenGroupId + '-' + mavenVersion + '.jar').absolutePath jar = new File(project.buildDir, 'libs/' + mavenGroupId + '-' + mavenVersion + '.jar').absolutePath
outfile = mavenGroupId + '-' + mavenVersion + '.exe' outfile = mavenGroupId + '-' + mavenVersion + '.exe'
@@ -121,5 +200,7 @@ processResources {
} }
} }
build.dependsOn cleanVersionFile
build.dependsOn makeExecutable build.dependsOn makeExecutable
build.dependsOn makePackGZ build.dependsOn makePackGZ
build.dependsOn macAppCompressed
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
@@ -19,7 +19,6 @@ package org.jackhuang.hellominecraft.launcher.api;
import org.jackhuang.hellominecraft.launcher.core.GameException; import org.jackhuang.hellominecraft.launcher.core.GameException;
import org.jackhuang.hellominecraft.launcher.core.service.IMinecraftService; import org.jackhuang.hellominecraft.launcher.core.service.IMinecraftService;
import org.jackhuang.hellominecraft.launcher.setting.Profile;
import org.jackhuang.hellominecraft.launcher.core.auth.AuthenticationException; import org.jackhuang.hellominecraft.launcher.core.auth.AuthenticationException;
import org.jackhuang.hellominecraft.launcher.core.auth.IAuthenticator; import org.jackhuang.hellominecraft.launcher.core.auth.IAuthenticator;
import org.jackhuang.hellominecraft.launcher.core.auth.UserProfileProvider; import org.jackhuang.hellominecraft.launcher.core.auth.UserProfileProvider;
@@ -35,12 +34,12 @@ public interface IPlugin {
/** /**
* You can modify the application actions by this method. * You can modify the application actions by this method.
* *
* @param profile info to the Minecraft Loader * @param obj minecraft service wanted
* *
* @return For example, you can implement IMinecraftProvider to support * @return For example, you can implement IMinecraftProvider to support
* MultiMC * MultiMC
*/ */
IMinecraftService provideMinecraftService(Profile profile); IMinecraftService provideMinecraftService(Object obj);
/** /**
* Register authenticators by calling IAuthenticator.LOGINS.add. * Register authenticators by calling IAuthenticator.LOGINS.add.
@@ -18,7 +18,6 @@
package org.jackhuang.hellominecraft.launcher.api; package org.jackhuang.hellominecraft.launcher.api;
import org.jackhuang.hellominecraft.util.logging.HMCLog; import org.jackhuang.hellominecraft.util.logging.HMCLog;
import org.jackhuang.hellominecraft.launcher.util.DefaultPlugin;
/** /**
* *
@@ -26,17 +25,21 @@ import org.jackhuang.hellominecraft.launcher.util.DefaultPlugin;
*/ */
public class PluginManager { public class PluginManager {
private static IPlugin NOW_PLUGIN = new DefaultPlugin(); private static IPlugin NOW_PLUGIN;
public static void getServerPlugin() { public static void getServerPlugin() {
try { try {
ClassLoader cl = Thread.currentThread().getContextClassLoader(); getPlugin(Thread.currentThread().getContextClassLoader().loadClass("org.jackhuang.hellominecraft.launcher.server.ServerPlugin"));
Class c = cl.loadClass("org.jackhuang.hellominecraft.launcher.server.ServerPlugin");
IPlugin p = (IPlugin) c.newInstance();
NOW_PLUGIN = p;
} catch (ClassNotFoundException ignore) { } catch (ClassNotFoundException ignore) {
}
}
public static void getPlugin(Class<?> cls) {
try {
IPlugin p = (IPlugin) cls.newInstance();
NOW_PLUGIN = p;
} catch (Exception e) { } catch (Exception e) {
HMCLog.err("Failed to new instance"); HMCLog.err("Failed to new instance");
} }
} }
@@ -20,7 +20,6 @@ package org.jackhuang.hellominecraft.launcher.core;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import org.jackhuang.hellominecraft.util.system.FileUtils; import org.jackhuang.hellominecraft.util.system.FileUtils;
import org.jackhuang.hellominecraft.util.system.IOUtils;
import org.jackhuang.hellominecraft.util.system.OS; import org.jackhuang.hellominecraft.util.system.OS;
/** /**
@@ -63,14 +62,11 @@ public final class MCUtils {
} }
public static File getInitGameDir() { public static File getInitGameDir() {
File gameDir = IOUtils.currentDir(); File gameDir = new File(MCUtils.minecraft());
if (gameDir.exists()) { if (!gameDir.exists()) {
gameDir = new File(gameDir, MCUtils.minecraft()); File newFile = MCUtils.getLocation();
if (!gameDir.exists()) { if (newFile.exists())
File newFile = MCUtils.getLocation(); gameDir = newFile;
if (newFile.exists())
gameDir = newFile;
}
} }
return gameDir; return gameDir;
} }
@@ -80,6 +76,6 @@ public final class MCUtils {
public static void tryWriteProfile(File gameDir) throws IOException { public static void tryWriteProfile(File gameDir) throws IOException {
File file = new File(gameDir, "launcher_profiles.json"); File file = new File(gameDir, "launcher_profiles.json");
if (!file.exists()) if (!file.exists())
FileUtils.writeStringToFile(file, PROFILE); FileUtils.write(file, PROFILE);
} }
} }
@@ -17,6 +17,7 @@
*/ */
package org.jackhuang.hellominecraft.launcher.core.asset; package org.jackhuang.hellominecraft.launcher.core.asset;
import com.google.gson.annotations.SerializedName;
import java.util.HashSet; import java.util.HashSet;
import java.util.LinkedHashMap; import java.util.LinkedHashMap;
import java.util.Map; import java.util.Map;
@@ -29,7 +30,11 @@ import java.util.Set;
public class AssetsIndex { public class AssetsIndex {
public static final String DEFAULT_ASSET_NAME = "legacy"; public static final String DEFAULT_ASSET_NAME = "legacy";
@SerializedName("objects")
public Map<String, AssetsObject> objects; public Map<String, AssetsObject> objects;
@SerializedName("virtual")
public boolean virtual; public boolean virtual;
public AssetsIndex() { public AssetsIndex() {
@@ -66,7 +66,7 @@ public class AssetsMojangLoader extends IAssetsHandler {
public void executeTask() throws Throwable { public void executeTask() throws Throwable {
if (!areDependTasksSucceeded) if (!areDependTasksSucceeded)
throw new IllegalStateException("Failed to get asset index"); throw new IllegalStateException("Failed to get asset index");
String result = FileUtils.readFileToString(f); String result = FileUtils.read(f);
if (StrUtils.isBlank(result)) if (StrUtils.isBlank(result))
throw new IllegalStateException("Index json is empty, please redownload it!"); throw new IllegalStateException("Index json is empty, please redownload it!");
AssetsIndex o = C.GSON.fromJson(result, AssetsIndex.class); AssetsIndex o = C.GSON.fromJson(result, AssetsIndex.class);
@@ -98,7 +98,7 @@ public class AssetsMojangLoader extends IAssetsHandler {
@Override @Override
public Task getDownloadTask(IDownloadProvider sourceType) { public Task getDownloadTask(IDownloadProvider sourceType) {
return new AssetsTask(sourceType.getAssetsDownloadURL()); return new AssetsTask(sourceType.getAssetsDownloadURL(), sourceType.getRetryAssetsDownloadURL());
} }
@Override @Override
@@ -34,6 +34,8 @@ import org.jackhuang.hellominecraft.util.code.DigestUtils;
import org.jackhuang.hellominecraft.util.system.IOUtils; import org.jackhuang.hellominecraft.util.system.IOUtils;
import org.jackhuang.hellominecraft.util.NetUtils; import org.jackhuang.hellominecraft.util.NetUtils;
import org.jackhuang.hellominecraft.util.OverridableSwingWorker; import org.jackhuang.hellominecraft.util.OverridableSwingWorker;
import org.jackhuang.hellominecraft.util.StrUtils;
import org.jackhuang.hellominecraft.util.func.Function;
import org.jackhuang.hellominecraft.util.tasks.TaskInfo; import org.jackhuang.hellominecraft.util.tasks.TaskInfo;
/** /**
@@ -89,30 +91,37 @@ public abstract class IAssetsHandler {
protected class AssetsTask extends TaskInfo { protected class AssetsTask extends TaskInfo {
ArrayList<Task> al; ArrayList<Task> tasks;
String u; String baseUrl;
String retryBaseUrl;
public AssetsTask(String url) { public AssetsTask(String url, String retryUrl) {
super(C.i18n("assets.download")); super(C.i18n("assets.download"));
this.u = url; this.baseUrl = url;
this.retryBaseUrl = retryUrl;
} }
@Override @Override
public void executeTask() { public void executeTask() {
if (assetsDownloadURLs == null || assetsLocalNames == null || contents == null) if (assetsDownloadURLs == null || assetsLocalNames == null || contents == null)
throw new IllegalStateException(C.i18n("assets.not_refreshed")); throw new IllegalStateException(C.i18n("assets.not_refreshed"));
tasks = new ArrayList<>();
int max = assetsDownloadURLs.size(); int max = assetsDownloadURLs.size();
al = new ArrayList<>();
int hasDownloaded = 0; int hasDownloaded = 0;
for (int i = 0; i < max; i++) { for (int i = 0; i < max; i++) {
String mark = assetsDownloadURLs.get(i); String mark = assetsDownloadURLs.get(i);
String url = u + mark; String downloadUrl = baseUrl + mark;
String downloadRetryUrl = StrUtils.isNotBlank(retryBaseUrl) ? retryBaseUrl + mark : "";
File location = assetsLocalNames.get(i); File location = assetsLocalNames.get(i);
if (!location.getParentFile().exists() && !location.getParentFile().mkdirs()) if (!location.getParentFile().exists() && !location.getParentFile().mkdirs())
HMCLog.warn("Failed to make directories: " + location.getParent()); HMCLog.warn("Failed to make directories: " + location.getParent());
if (location.isDirectory()) if (location.isDirectory())
continue; continue;
boolean need = true;
boolean needDownload = true;
try { try {
if (location.exists()) { if (location.exists()) {
FileInputStream fis = new FileInputStream(location); FileInputStream fis = new FileInputStream(location);
@@ -121,23 +130,39 @@ public abstract class IAssetsHandler {
if (contents.get(i).geteTag().equals(sha)) { if (contents.get(i).geteTag().equals(sha)) {
++hasDownloaded; ++hasDownloaded;
HMCLog.log("File " + assetsLocalNames.get(i) + " has been downloaded successfully, skipped downloading."); HMCLog.log("File " + assetsLocalNames.get(i) + " has been downloaded successfully, skipped downloading.");
if (ppl != null) if (ppl != null) {
ppl.setProgress(this, hasDownloaded, max); ppl.setProgress(this, hasDownloaded, max);
}
continue; continue;
} }
} }
} catch (IOException e) { } catch (IOException e) {
HMCLog.warn("Failed to get hash: " + location, e); HMCLog.warn("Failed to get hash: " + location, e);
need = !location.exists(); needDownload = !location.exists();
} }
if (need)
al.add(new FileDownloadTask(url, location).setTag(mark)); if (needDownload) {
FileDownloadTask fileDownloadTask = new FileDownloadTask(downloadUrl, location);
fileDownloadTask.setTag(mark);
// retry
if (StrUtils.isNotBlank(downloadRetryUrl)) {
fileDownloadTask.setFailedCallbackReturnsNewURL(new Function<Integer, String>() {
@Override
public String apply(Integer t) {
return downloadRetryUrl;
}
});
}
tasks.add(fileDownloadTask);
}
} }
} }
@Override @Override
public Collection<Task> getAfterTasks() { public Collection<Task> getAfterTasks() {
return al; return tasks;
} }
} }
} }
@@ -22,7 +22,6 @@ import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collection; import java.util.Collection;
import java.util.HashSet;
import java.util.Map; import java.util.Map;
import org.jackhuang.hellominecraft.util.C; import org.jackhuang.hellominecraft.util.C;
import org.jackhuang.hellominecraft.launcher.core.service.IMinecraftAssetService; import org.jackhuang.hellominecraft.launcher.core.service.IMinecraftAssetService;
@@ -30,8 +29,7 @@ import org.jackhuang.hellominecraft.launcher.core.service.IMinecraftService;
import org.jackhuang.hellominecraft.launcher.core.version.AssetIndexDownloadInfo; import org.jackhuang.hellominecraft.launcher.core.version.AssetIndexDownloadInfo;
import org.jackhuang.hellominecraft.launcher.core.version.MinecraftVersion; import org.jackhuang.hellominecraft.launcher.core.version.MinecraftVersion;
import org.jackhuang.hellominecraft.util.MessageBox; import org.jackhuang.hellominecraft.util.MessageBox;
import org.jackhuang.hellominecraft.util.Utils; import org.jackhuang.hellominecraft.util.func.BiFunction;
import org.jackhuang.hellominecraft.util.func.Function;
import org.jackhuang.hellominecraft.util.logging.HMCLog; import org.jackhuang.hellominecraft.util.logging.HMCLog;
import org.jackhuang.hellominecraft.util.tasks.Task; import org.jackhuang.hellominecraft.util.tasks.Task;
import org.jackhuang.hellominecraft.util.tasks.TaskWindow; import org.jackhuang.hellominecraft.util.tasks.TaskWindow;
@@ -56,24 +54,10 @@ public class MinecraftAssetService extends IMinecraftAssetService {
} }
public Task downloadAssets(final MinecraftVersion mv) { public Task downloadAssets(final MinecraftVersion mv) {
Utils.requireNonNull(mv); if (mv == null)
return new TaskInfo("Download Assets") { return null;
Collection<Task> afters = new HashSet<>(); return IAssetsHandler.ASSETS_HANDLER.getList(mv, service.asset())
.after(IAssetsHandler.ASSETS_HANDLER.getDownloadTask(service.getDownloadType().getProvider()));
@Override
public Collection<Task> getDependTasks() {
return Arrays.asList(IAssetsHandler.ASSETS_HANDLER.getList(mv, service.asset()));
}
@Override
public void executeTask() {
}
@Override
public Collection<Task> getAfterTasks() {
return Arrays.asList(IAssetsHandler.ASSETS_HANDLER.getDownloadTask(service.getDownloadType().getProvider()));
}
};
} }
@Override @Override
@@ -150,7 +134,7 @@ public class MinecraftAssetService extends IMinecraftAssetService {
File objectsDir = new File(assetsDir, "objects"); File objectsDir = new File(assetsDir, "objects");
File indexFile = new File(indexDir, assetVersion + ".json"); File indexFile = new File(indexDir, assetVersion + ".json");
try { try {
AssetsIndex index = (AssetsIndex) C.GSON.fromJson(FileUtils.readFileToString(indexFile, "UTF-8"), AssetsIndex.class); AssetsIndex index = (AssetsIndex) C.GSON.fromJson(FileUtils.read(indexFile, "UTF-8"), AssetsIndex.class);
String hash = ((AssetsObject) index.getFileMap().get(name)).getHash(); String hash = ((AssetsObject) index.getFileMap().get(name)).getHash();
return new File(objectsDir, hash.substring(0, 2) + "/" + hash); return new File(objectsDir, hash.substring(0, 2) + "/" + hash);
@@ -169,7 +153,7 @@ public class MinecraftAssetService extends IMinecraftAssetService {
return false; return false;
try { try {
String assetIndexContent = FileUtils.readFileToString(indexFile, "UTF-8"); String assetIndexContent = FileUtils.read(indexFile, "UTF-8");
AssetsIndex index = (AssetsIndex) C.GSON.fromJson(assetIndexContent, AssetsIndex.class); AssetsIndex index = (AssetsIndex) C.GSON.fromJson(assetIndexContent, AssetsIndex.class);
if (index == null) if (index == null)
@@ -197,7 +181,7 @@ public class MinecraftAssetService extends IMinecraftAssetService {
} }
try { try {
String assetIndexContent = FileUtils.readFileToString(indexFile, "UTF-8"); String assetIndexContent = FileUtils.read(indexFile, "UTF-8");
AssetsIndex index = (AssetsIndex) C.GSON.fromJson(assetIndexContent, AssetsIndex.class); AssetsIndex index = (AssetsIndex) C.GSON.fromJson(assetIndexContent, AssetsIndex.class);
if (index == null) if (index == null)
@@ -212,7 +196,7 @@ public class MinecraftAssetService extends IMinecraftAssetService {
if (original.exists()) { if (original.exists()) {
cnt++; cnt++;
if (!target.isFile()) if (!target.isFile())
FileUtils.copyFile(original, target, false); FileUtils.copyFile(original, target);
} }
} }
// If the scale new format existent file is lower then 0.1, use the old format. // If the scale new format existent file is lower then 0.1, use the old format.
@@ -226,8 +210,8 @@ public class MinecraftAssetService extends IMinecraftAssetService {
return virtualRoot; return virtualRoot;
} }
public final Function<MinecraftVersion, String> ASSET_PROVIDER_IMPL = t -> { public final BiFunction<MinecraftVersion, Boolean, String> ASSET_PROVIDER_IMPL = (t, allow) -> {
if (!checkAssetsExistance(t.getAssetsIndex())) if (allow && !checkAssetsExistance(t.getAssetsIndex()))
if (MessageBox.Show(C.i18n("assets.no_assets"), MessageBox.YES_NO_OPTION) == MessageBox.YES_OPTION) if (MessageBox.Show(C.i18n("assets.no_assets"), MessageBox.YES_NO_OPTION) == MessageBox.YES_OPTION)
TaskWindow.execute(downloadAssets(t)); TaskWindow.execute(downloadAssets(t));
return reconstructAssets(t.getAssetsIndex()).getAbsolutePath(); return reconstructAssets(t.getAssetsIndex()).getAbsolutePath();
@@ -96,7 +96,8 @@ public abstract class IAuthenticator {
public void onLoadSettings(Map m) { public void onLoadSettings(Map m) {
if (m == null) if (m == null)
return; return;
username = (String) m.get("IAuthenticator_UserName"); Object o = m.get("IAuthenticator_UserName");
username = o instanceof String ? (String) o : "";
} }
public String getUserName() { public String getUserName() {
@@ -17,14 +17,24 @@
*/ */
package org.jackhuang.hellominecraft.launcher.core.auth.yggdrasil; package org.jackhuang.hellominecraft.launcher.core.auth.yggdrasil;
import com.google.gson.annotations.SerializedName;
public class Response { public class Response {
public String accessToken, clientToken; @SerializedName("accessToken")
public String accessToken;
@SerializedName("clientToken")
public String clientToken;
@SerializedName("selectedProfile")
public GameProfile selectedProfile; public GameProfile selectedProfile;
@SerializedName("availableProfiles")
public GameProfile[] availableProfiles; public GameProfile[] availableProfiles;
@SerializedName("user")
public User user; public User user;
@SerializedName("error")
public String error; public String error;
@SerializedName("errorMessage")
public String errorMessage; public String errorMessage;
@SerializedName("cause")
public String cause; public String cause;
} }
@@ -148,7 +148,7 @@ public class YggdrasilAuthentication {
if (StrUtils.isNotBlank(response.error)) { if (StrUtils.isNotBlank(response.error)) {
HMCLog.err("Failed to log in, the auth server returned an error: " + response.error + ", message: " + response.errorMessage + ", cause: " + response.cause); HMCLog.err("Failed to log in, the auth server returned an error: " + response.error + ", message: " + response.errorMessage + ", cause: " + response.cause);
if (response.errorMessage.contains("Invalid token")) if (response.errorMessage != null && response.errorMessage.contains("Invalid token"))
response.errorMessage = C.i18n("login.invalid_token"); response.errorMessage = C.i18n("login.invalid_token");
throw new AuthenticationException("Request error: " + response.errorMessage); throw new AuthenticationException("Request error: " + response.errorMessage);
} }
@@ -25,7 +25,7 @@ public class CurseDownloadProvider extends MojangDownloadProvider {
@Override @Override
public String getParsedDownloadURL(String str) { public String getParsedDownloadURL(String str) {
return str == null ? null : str.replace("http://files.minecraftforge.net/maven", "http://ftb.cursecdn.com/FTB2/maven/"); return str == null ? null : str.replace("http://files.minecraftforge.net/maven", "http://ftb.cursecdn.com/FTB2/maven");
} }
} }
@@ -29,10 +29,12 @@ public class DownloadLibraryJob {
public IMinecraftLibrary lib; public IMinecraftLibrary lib;
public String url; public String url;
public String retryUrl;
public File path; public File path;
public DownloadLibraryJob(IMinecraftLibrary n, String u, File p) { public DownloadLibraryJob(IMinecraftLibrary n, String u, String retry, File p) {
url = u; url = u;
retryUrl = retry;
lib = n; lib = n;
path = IOUtils.tryGetCanonicalFile(p); path = IOUtils.tryGetCanonicalFile(p);
} }
@@ -29,7 +29,8 @@ public enum DownloadType {
Mojang("download.mojang", new MojangDownloadProvider()), Mojang("download.mojang", new MojangDownloadProvider()),
BMCL("download.BMCL", new BMCLAPIDownloadProvider()), BMCL("download.BMCL", new BMCLAPIDownloadProvider()),
//RapidData("download.rapid_data", new RapidDataDownloadProvider()), //RapidData("download.rapid_data", new RapidDataDownloadProvider()),
Curse("Curse CDN", new CurseDownloadProvider()); Curse("Curse CDN", new CurseDownloadProvider()),
Dynamic("HMCLSoft", DynamicDownloadProvider.getInstance());
private final String name; private final String name;
private final IDownloadProvider provider; private final IDownloadProvider provider;
@@ -47,7 +48,7 @@ public enum DownloadType {
return C.i18n(name); return C.i18n(name);
} }
private static DownloadType suggestedDownloadType = Mojang; private static DownloadType suggestedDownloadType = Dynamic;
public static DownloadType getSuggestedDownloadType() { public static DownloadType getSuggestedDownloadType() {
return suggestedDownloadType; return suggestedDownloadType;
@@ -0,0 +1,160 @@
/*
* Hello Minecraft! Launcher.
* Copyright (C) 2013 huangyuhui <huanghongxun2008@126.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see {http://www.gnu.org/licenses/}.
*/
package org.jackhuang.hellominecraft.launcher.core.download;
import com.google.gson.reflect.TypeToken;
import java.io.IOException;
import java.util.Map;
import org.jackhuang.hellominecraft.util.C;
import org.jackhuang.hellominecraft.util.NetUtils;
import org.jackhuang.hellominecraft.util.StrUtils;
/**
*
* @author evilwk <evilwk@gmail.com>
*/
public class DynamicDownloadProvider extends MojangDownloadProvider {
private static final String PROVIDER_ADDR = "http://client.api.mcgogogo.com:81/provider.php";
private volatile static DynamicDownloadProvider instance;
private String versionManifestAddr = null;
private String launcherMetaAddr = null;
private String launcherAddr = null;
private String librariesAddr = null;
private String assetsAddr = null;
public void setVersionManifestAddr(String versionManifestAddr) {
this.versionManifestAddr = versionManifestAddr;
}
public void setLauncherMetaAddr(String launcherMetaAddr) {
this.launcherMetaAddr = launcherMetaAddr;
}
public void setLauncherAddr(String launcherAddr) {
this.launcherAddr = launcherAddr;
}
public void setLibrariesAddr(String librariesAddr) {
this.librariesAddr = librariesAddr;
}
public void setAssetsAddr(String assetsAddr) {
this.assetsAddr = assetsAddr;
}
private DynamicDownloadProvider() {
}
public static DynamicDownloadProvider getInstance() {
if (instance == null) {
synchronized (DynamicDownloadProvider.class) {
if (instance == null) {
instance = new DynamicDownloadProvider();
}
}
}
return instance;
}
@Override
public String getRetryAssetsDownloadURL() {
return super.getAssetsDownloadURL();
}
@Override
public String getRetryLibraryDownloadURL() {
return super.getLibraryDownloadURL();
}
@Override
public String getAssetsDownloadURL() {
if (StrUtils.isNotBlank(assetsAddr)) {
return assetsAddr;
}
return super.getAssetsDownloadURL();
}
@Override
public String getLibraryDownloadURL() {
if (StrUtils.isNotBlank(librariesAddr)) {
return librariesAddr;
}
return super.getLibraryDownloadURL();
}
@Override
public String getVersionsListDownloadURL() {
if (StrUtils.isNotBlank(versionManifestAddr)) {
return versionManifestAddr;
}
return super.getVersionsListDownloadURL();
}
@Override
public String getParsedDownloadURL(String str) {
if (StrUtils.isNotBlank(librariesAddr)) {
str = str.replace("https://libraries.minecraft.net", librariesAddr);
}
if (StrUtils.isNotBlank(launcherMetaAddr)) {
str = str.replace("https://launchermeta.mojang.com", launcherMetaAddr);
}
if (StrUtils.isNotBlank(launcherMetaAddr)) {
str = str.replace("https://launcher.mojang.com", launcherAddr);
}
return super.getParsedDownloadURL(str);
}
public void init() {
new Thread() {
private String getValue(Map<String, String> addrInfo, String key) {
String value = null;
do {
if (!addrInfo.containsKey(key))
continue;
value = addrInfo.get(key);
} while(false);
return value;
}
@Override
public void run() {
try {
String providerInfo = NetUtils.get(PROVIDER_ADDR);
Map<String, String> addrInfo = null;
addrInfo = C.GSON.fromJson(providerInfo, new TypeToken<Map<String, String>>() {
}.getType());
if (addrInfo != null) {
setLibrariesAddr(getValue(addrInfo, "libraries"));
setAssetsAddr(getValue(addrInfo, "assets"));
setLauncherMetaAddr(getValue(addrInfo, "launcherMeta"));
setLauncherAddr(getValue(addrInfo, "launcher"));
setVersionManifestAddr(getValue(addrInfo, "versionManifest"));
}
} catch (IOException ex) {
}
}
}.start();
}
}
@@ -38,7 +38,7 @@ public abstract class IDownloadProvider {
return null; return null;
} }
} }
public abstract InstallerVersionList getForgeInstaller(); public abstract InstallerVersionList getForgeInstaller();
public abstract InstallerVersionList getLiteLoaderInstaller(); public abstract InstallerVersionList getLiteLoaderInstaller();
@@ -46,6 +46,10 @@ public abstract class IDownloadProvider {
public abstract InstallerVersionList getOptiFineInstaller(); public abstract InstallerVersionList getOptiFineInstaller();
public abstract String getLibraryDownloadURL(); public abstract String getLibraryDownloadURL();
public String getRetryLibraryDownloadURL() {
return "";
}
public abstract String getVersionsDownloadURL(); public abstract String getVersionsDownloadURL();
@@ -55,6 +59,10 @@ public abstract class IDownloadProvider {
public abstract String getAssetsDownloadURL(); public abstract String getAssetsDownloadURL();
public String getRetryAssetsDownloadURL() {
return "";
}
/** /**
* For example, minecraft.json/assetIndex/url or * For example, minecraft.json/assetIndex/url or
* minecraft.json/downloads/client/url * minecraft.json/downloads/client/url
@@ -31,6 +31,7 @@ import org.jackhuang.hellominecraft.launcher.core.GameException;
import org.jackhuang.hellominecraft.launcher.core.service.IMinecraftService; import org.jackhuang.hellominecraft.launcher.core.service.IMinecraftService;
import org.jackhuang.hellominecraft.launcher.core.version.GameDownloadInfo; import org.jackhuang.hellominecraft.launcher.core.version.GameDownloadInfo;
import org.jackhuang.hellominecraft.launcher.core.version.IMinecraftLibrary; import org.jackhuang.hellominecraft.launcher.core.version.IMinecraftLibrary;
import org.jackhuang.hellominecraft.launcher.core.version.LibraryDownloadInfo;
import org.jackhuang.hellominecraft.launcher.core.version.MinecraftVersion; import org.jackhuang.hellominecraft.launcher.core.version.MinecraftVersion;
import org.jackhuang.hellominecraft.util.tasks.download.FileDownloadTask; import org.jackhuang.hellominecraft.util.tasks.download.FileDownloadTask;
import org.jackhuang.hellominecraft.util.func.Function; import org.jackhuang.hellominecraft.util.func.Function;
@@ -53,14 +54,17 @@ public class MinecraftDownloadService extends IMinecraftDownloadService {
ArrayList<DownloadLibraryJob> downloadLibraries = new ArrayList<>(); ArrayList<DownloadLibraryJob> downloadLibraries = new ArrayList<>();
if (mv == null) if (mv == null)
return downloadLibraries; return downloadLibraries;
MinecraftVersion v = mv.resolve(service.version()); MinecraftVersion v = mv.resolve(service.version());
for (IMinecraftLibrary l : v.getLibraries()) for (IMinecraftLibrary libraryInfo : v.getLibraries())
if (l != null && l.allow()) { if (libraryInfo != null && libraryInfo.allow() && libraryInfo.getDownloadInfo() != null) {
File ff = l.getFilePath(service.baseDirectory()); File ff = libraryInfo.getFilePath(service.baseDirectory());
if (!ff.exists()) { if (!ff.exists()) {
String libURL = l.getDownloadInfo().getUrl(service.getDownloadType()); LibraryDownloadInfo downloadInfo = libraryInfo.getDownloadInfo();
if (libURL != null) String downloadUrl = downloadInfo.getUrl(service.getDownloadType());
downloadLibraries.add(new DownloadLibraryJob(l, libURL, ff)); String retryDownloadUrl = downloadInfo.getRetryUrl(service.getDownloadType());
if (downloadUrl != null)
downloadLibraries.add(new DownloadLibraryJob(libraryInfo, downloadUrl, retryDownloadUrl, ff));
} }
} }
return downloadLibraries; return downloadLibraries;
@@ -85,7 +89,7 @@ public class MinecraftDownloadService extends IMinecraftDownloadService {
if (mvj.exists() && !mvj.delete()) if (mvj.exists() && !mvj.delete())
HMCLog.warn("Failed to delete " + mvj); HMCLog.warn("Failed to delete " + mvj);
try { try {
MinecraftVersion mv = C.GSON.fromJson(FileUtils.readFileToStringQuietly(new File(vpath, id + ".json")), MinecraftVersion.class); MinecraftVersion mv = C.GSON.fromJson(FileUtils.readQuietly(new File(vpath, id + ".json")), MinecraftVersion.class);
if (mv == null) if (mv == null)
throw new JsonSyntaxException("incorrect version"); throw new JsonSyntaxException("incorrect version");
@@ -114,10 +118,13 @@ public class MinecraftDownloadService extends IMinecraftDownloadService {
} }
@Override @Override
public String apply(Integer t) { public String apply(Integer repeat) {
return DownloadType.values()[t / 2].getProvider().getVersionsDownloadURL() + suffix; int index = repeat / 2;
if (index > DownloadType.values().length) {
index = 0;
}
return DownloadType.values()[index].getProvider().getVersionsDownloadURL() + suffix;
} }
} }
@Override @Override
@@ -29,6 +29,6 @@ public class MinecraftRemoteVersion {
public String getUrl(DownloadType type) { public String getUrl(DownloadType type) {
if (url == null) if (url == null)
return type.getProvider().getVersionsDownloadURL() + id + "/" + id + ".json"; return type.getProvider().getVersionsDownloadURL() + id + "/" + id + ".json";
return url; return type.getProvider().getParsedDownloadURL(url);
} }
} }
@@ -17,6 +17,7 @@
*/ */
package org.jackhuang.hellominecraft.launcher.core.download; package org.jackhuang.hellominecraft.launcher.core.download;
import com.google.gson.annotations.SerializedName;
import java.util.ArrayList; import java.util.ArrayList;
import org.jackhuang.hellominecraft.util.C; import org.jackhuang.hellominecraft.util.C;
import org.jackhuang.hellominecraft.util.NetUtils; import org.jackhuang.hellominecraft.util.NetUtils;
@@ -28,7 +29,9 @@ import org.jackhuang.hellominecraft.util.OverridableSwingWorker;
*/ */
public class MinecraftRemoteVersions { public class MinecraftRemoteVersions {
@SerializedName("versions")
public ArrayList<MinecraftRemoteVersion> versions; public ArrayList<MinecraftRemoteVersion> versions;
@SerializedName("latest")
public MinecraftRemoteLatestVersion latest; public MinecraftRemoteLatestVersion latest;
private static volatile MinecraftRemoteVersions INSTANCE = null; private static volatile MinecraftRemoteVersions INSTANCE = null;
@@ -41,30 +41,35 @@ public class MojangDownloadProvider extends IDownloadProvider {
public InstallerVersionList getOptiFineInstaller() { public InstallerVersionList getOptiFineInstaller() {
return org.jackhuang.hellominecraft.launcher.core.install.optifine.vanilla.OptiFineVersionList.getInstance(); return org.jackhuang.hellominecraft.launcher.core.install.optifine.vanilla.OptiFineVersionList.getInstance();
} }
// jars
@Override @Override
public String getLibraryDownloadURL() { public String getLibraryDownloadURL() {
return "https://libraries.minecraft.net"; return "https://libraries.minecraft.net";
} }
// jars
@Override @Override
public String getVersionsDownloadURL() { public String getVersionsDownloadURL() {
return "http://s3.amazonaws.com/Minecraft.Download/versions/"; return "http://s3.amazonaws.com/Minecraft.Download/versions/";
} }
// resource
@Override @Override
public String getIndexesDownloadURL() { public String getIndexesDownloadURL() {
return "http://s3.amazonaws.com/Minecraft.Download/indexes/"; return "http://s3.amazonaws.com/Minecraft.Download/indexes/";
} }
// game versions json
@Override @Override
public String getVersionsListDownloadURL() { public String getVersionsListDownloadURL() {
return "https://launchermeta.mojang.com/mc/game/version_manifest.json"; return "https://launchermeta.mojang.com/mc/game/version_manifest.json";
} }
// resource
@Override @Override
public String getAssetsDownloadURL() { public String getAssetsDownloadURL() {
return "http://resources.download.minecraft.net/"; return "https://resources.download.minecraft.net/";
} }
@Override @Override
@@ -0,0 +1,139 @@
/*
* Hello Minecraft! Launcher.
* Copyright (C) 2013 huangyuhui <huanghongxun2008@126.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see {http://www.gnu.org/licenses/}.
*/
package org.jackhuang.hellominecraft.launcher.core.install;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Objects;
import org.jackhuang.hellominecraft.util.tasks.Task;
/**
*
* @author huangyuhui
*/
public abstract class InstallerVersionList {
/**
* Refresh installer versions list from the downloaded content.
*
* @param versions Minecraft versions you need to refresh
*
* @throws java.lang.Exception including network exceptions, IO exceptions.
*/
public abstract Task refresh(String[] versions);
/**
* Installer name.
*
* @return installer name.
*/
public abstract String getName();
/**
* Get installers you want.
*
* @param mcVersion the installers to this Minecraft version.
*
* @return cached result.
*/
protected abstract List<InstallerVersion> getVersionsImpl(String mcVersion);
/**
* Get installers you want, please cache this method's result to save time.
*
* @param mcVersion the installers to this Minecraft version.
*
* @return a copy of the cached data to prevent
* ConcurrentModificationException.
*/
public List<InstallerVersion> getVersions(String mcVersion) {
List<InstallerVersion> a = getVersionsImpl(mcVersion);
if (a == null) {
return null;
} else {
return new ArrayList<>(a);
}
}
public static int compareVersion(String verOne, String verTwo) {
String[] verInfoOne = verOne.split("\\.");
String[] verInfoTwo = verTwo.split("\\.");
int idx = 0;
int minLength = Math.min(verInfoOne.length, verInfoTwo.length);
int diff = 0;
while (idx < minLength
&& (diff = verInfoOne[idx].length() - verInfoTwo[idx].length()) == 0
&& (diff = verInfoOne[idx].compareTo(verInfoTwo[idx])) == 0) {
++idx;
}
diff = (diff != 0) ? diff : verInfoOne.length - verInfoTwo.length;
return (diff == 0) ? 0 : (diff < 0 ? -1 : 1);
}
public static class InstallerVersion implements Comparable<InstallerVersion> {
public String selfVersion, mcVersion;
public String installer, universal;
public String changelog;
public InstallerVersion(String selfVersion, String mcVersion) {
this.selfVersion = selfVersion;
this.mcVersion = mcVersion;
}
@Override
public int compareTo(InstallerVersion o) {
return compareVersion(selfVersion, o.selfVersion);
}
@Override
public int hashCode() {
return selfVersion.hashCode();
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
final InstallerVersion other = (InstallerVersion) obj;
return Objects.equals(this.selfVersion, other.selfVersion);
}
}
public static class InstallerVersionComparator implements Comparator<InstallerVersion>, Serializable {
private static final long serialVersionUID = 3276198781795213723L;
public static final InstallerVersionComparator INSTANCE = new InstallerVersionComparator();
@Override
public int compare(InstallerVersion o1, InstallerVersion o2) {
return o2.compareTo(o1);
}
}
}
@@ -27,10 +27,9 @@ import org.jackhuang.hellominecraft.launcher.core.install.liteloader.LiteLoaderV
import org.jackhuang.hellominecraft.launcher.core.install.optifine.OptiFineInstaller; import org.jackhuang.hellominecraft.launcher.core.install.optifine.OptiFineInstaller;
import org.jackhuang.hellominecraft.launcher.core.install.optifine.vanilla.OptiFineDownloadFormatter; import org.jackhuang.hellominecraft.launcher.core.install.optifine.vanilla.OptiFineDownloadFormatter;
import org.jackhuang.hellominecraft.util.tasks.Task; import org.jackhuang.hellominecraft.util.tasks.Task;
import org.jackhuang.hellominecraft.util.tasks.TaskInfo;
import org.jackhuang.hellominecraft.util.tasks.TaskWindow;
import org.jackhuang.hellominecraft.util.tasks.download.FileDownloadTask; import org.jackhuang.hellominecraft.util.tasks.download.FileDownloadTask;
import org.jackhuang.hellominecraft.util.system.IOUtils; import org.jackhuang.hellominecraft.util.system.IOUtils;
import org.jackhuang.hellominecraft.util.tasks.DeleteFileTask;
/** /**
* *
@@ -58,47 +57,31 @@ public final class MinecraftInstallerService extends IMinecraftInstallerService
@Override @Override
public Task downloadForge(String installId, InstallerVersion v) { public Task downloadForge(String installId, InstallerVersion v) {
return new TaskInfo("Forge Downloader") { File filepath = IOUtils.tryGetCanonicalFile("forge-installer.jar");
@Override if (v.installer == null)
public void executeTask() { return null;
File filepath = IOUtils.tryGetCanonicalFile(IOUtils.currentDirWithSeparator() + "forge-installer.jar"); else
if (v.installer != null) return new FileDownloadTask(service.getDownloadType().getProvider().getParsedDownloadURL(v.installer), filepath).setTag("forge")
TaskWindow.factory() .after(new ForgeInstaller(service, filepath))
.append(new FileDownloadTask(service.getDownloadType().getProvider().getParsedDownloadURL(v.installer), filepath).setTag("forge")) .after(new DeleteFileTask(filepath));
.append(new ForgeInstaller(service, filepath))
.create();
}
};
} }
@Override @Override
public Task downloadOptiFine(String installId, InstallerVersion v) { public Task downloadOptiFine(String installId, InstallerVersion v) {
return new TaskInfo("OptiFine Downloader") { File filepath = IOUtils.tryGetCanonicalFile("optifine-installer.jar");
@Override if (v.installer == null)
public void executeTask() { return null;
File filepath = IOUtils.tryGetCanonicalFile(IOUtils.currentDirWithSeparator() + "optifine-installer.jar"); OptiFineDownloadFormatter task = new OptiFineDownloadFormatter(v.installer);
if (v.installer != null) { return task.after(new FileDownloadTask(filepath).registerPreviousResult(task).setTag("optifine"))
OptiFineDownloadFormatter task = new OptiFineDownloadFormatter(v.installer); .after(new OptiFineInstaller(service, installId, v, filepath))
TaskWindow.factory().append(task) .after(new DeleteFileTask(filepath));
.append(new FileDownloadTask(filepath).registerPreviousResult(task).setTag("optifine"))
.append(new OptiFineInstaller(service, installId, v, filepath))
.create();
}
}
};
} }
@Override @Override
public Task downloadLiteLoader(String installId, InstallerVersion v) { public Task downloadLiteLoader(String installId, InstallerVersion v) {
return new TaskInfo("LiteLoader Downloader") { File filepath = IOUtils.tryGetCanonicalFile("liteloader-universal.jar");
@Override FileDownloadTask task = (FileDownloadTask) new FileDownloadTask(v.universal, filepath).setTag("LiteLoader");
public void executeTask() { return task.after(new LiteLoaderInstaller(service, installId, (LiteLoaderVersionList.LiteLoaderInstallerVersion) v).registerPreviousResult(task))
File filepath = IOUtils.tryGetCanonicalFile(IOUtils.currentDirWithSeparator() + "liteloader-universal.jar"); .after(new DeleteFileTask(filepath));
FileDownloadTask task = (FileDownloadTask) new FileDownloadTask(v.universal, filepath).setTag("LiteLoader");
TaskWindow.factory()
.append(task).append(new LiteLoaderInstaller(service, installId, (LiteLoaderVersionList.LiteLoaderInstallerVersion) v).registerPreviousResult(task))
.create();
}
};
} }
} }
@@ -23,7 +23,6 @@ import java.util.ArrayList;
import org.jackhuang.hellominecraft.util.logging.HMCLog; import org.jackhuang.hellominecraft.util.logging.HMCLog;
import org.jackhuang.hellominecraft.util.system.Compressor; import org.jackhuang.hellominecraft.util.system.Compressor;
import org.jackhuang.hellominecraft.util.system.FileUtils; import org.jackhuang.hellominecraft.util.system.FileUtils;
import org.jackhuang.hellominecraft.util.system.IOUtils;
/** /**
* *
@@ -40,7 +39,7 @@ public class PackMinecraftInstaller {
} }
public void install() throws IOException { public void install() throws IOException {
File file = new File(IOUtils.currentDir(), "HMCL-MERGE-TEMP"); File file = new File("HMCL-MERGE-TEMP");
if (!file.exists() && !file.mkdirs()) if (!file.exists() && !file.mkdirs())
HMCLog.warn("Failed to make directories: " + file); HMCLog.warn("Failed to make directories: " + file);
for (String src1 : src) for (String src1 : src)
@@ -18,7 +18,6 @@
package org.jackhuang.hellominecraft.launcher.core.install.forge; package org.jackhuang.hellominecraft.launcher.core.install.forge;
import org.jackhuang.hellominecraft.launcher.core.install.InstallProfile; import org.jackhuang.hellominecraft.launcher.core.install.InstallProfile;
import java.io.BufferedOutputStream;
import java.io.File; import java.io.File;
import java.io.FileOutputStream; import java.io.FileOutputStream;
import java.io.InputStream; import java.io.InputStream;
@@ -32,6 +31,7 @@ import org.jackhuang.hellominecraft.util.system.FileUtils;
import org.jackhuang.hellominecraft.util.NetUtils; import org.jackhuang.hellominecraft.util.NetUtils;
import org.jackhuang.hellominecraft.launcher.core.version.MinecraftLibrary; import org.jackhuang.hellominecraft.launcher.core.version.MinecraftLibrary;
import org.jackhuang.hellominecraft.util.MessageBox; import org.jackhuang.hellominecraft.util.MessageBox;
import org.jackhuang.hellominecraft.util.system.IOUtils;
/** /**
* *
@@ -79,10 +79,8 @@ public class ForgeInstaller extends Task {
File file = new File(gameDir, "libraries/" + forge.getDownloadInfo().path); File file = new File(gameDir, "libraries/" + forge.getDownloadInfo().path);
if (file.getParentFile().mkdirs()) if (file.getParentFile().mkdirs())
HMCLog.warn("Failed to make library directory " + file.getParent()); HMCLog.warn("Failed to make library directory " + file.getParent());
try (FileOutputStream fos = new FileOutputStream(file); BufferedOutputStream bos = new BufferedOutputStream(fos)) { try (FileOutputStream fos = new FileOutputStream(file)) {
int c; IOUtils.copyStream(is, fos);
while ((c = is.read()) != -1)
bos.write((byte) c);
} }
mp.version().refreshVersions(); mp.version().refreshVersions();
} }
@@ -17,20 +17,31 @@
*/ */
package org.jackhuang.hellominecraft.launcher.core.install.forge; package org.jackhuang.hellominecraft.launcher.core.install.forge;
import com.google.gson.annotations.SerializedName;
/** /**
* *
* @author huangyuhui * @author huangyuhui
*/ */
public class Install { public class Install {
@SerializedName("profileName")
private String profileName; private String profileName;
@SerializedName("target")
private String target; private String target;
@SerializedName("path")
private String path; private String path;
@SerializedName("version")
private String version; private String version;
@SerializedName("filePath")
private String filePath; private String filePath;
@SerializedName("welcome")
private String welcome; private String welcome;
@SerializedName("minecraft")
private String minecraft; private String minecraft;
@SerializedName("mirrorList")
private String mirrorList; private String mirrorList;
@SerializedName("logo")
private String logo; private String logo;
public Install() { public Install() {
@@ -0,0 +1,139 @@
/*
* Hello Minecraft! Launcher.
* Copyright (C) 2013 huangyuhui <huanghongxun2008@126.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see {http://www.gnu.org/licenses/}.
*/
package org.jackhuang.hellominecraft.launcher.core.install.forge;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.jackhuang.hellominecraft.util.C;
import org.jackhuang.hellominecraft.launcher.core.download.DownloadType;
import org.jackhuang.hellominecraft.util.StrUtils;
import org.jackhuang.hellominecraft.launcher.core.install.InstallerVersionList;
import org.jackhuang.hellominecraft.launcher.core.install.InstallerVersionNewerComparator;
import org.jackhuang.hellominecraft.util.tasks.Task;
import org.jackhuang.hellominecraft.util.tasks.TaskInfo;
import org.jackhuang.hellominecraft.util.tasks.download.HTTPGetTask;
/**
*
* @author huangyuhui
*/
public class MinecraftForgeVersionList extends InstallerVersionList {
private static volatile MinecraftForgeVersionList instance;
public static MinecraftForgeVersionList getInstance() {
if (instance == null)
instance = new MinecraftForgeVersionList();
return instance;
}
public MinecraftForgeVersionRoot root;
public Map<String, List<InstallerVersion>> versionMap;
public List<InstallerVersion> versions;
@Override
public Task refresh(String[] needed) {
if (root != null)
return null;
return new TaskInfo(C.i18n("install.forge.get_list")) {
HTTPGetTask task = new HTTPGetTask(DownloadType.getSuggestedDownloadType().getProvider().getParsedDownloadURL(C.URL_FORGE_LIST));
@Override
public Collection<Task> getDependTasks() {
return Arrays.asList(task);
}
@Override
public void executeTask() throws Throwable {
if (!areDependTasksSucceeded)
return;
String s = task.getResult();
root = C.GSON.fromJson(s, MinecraftForgeVersionRoot.class);
versionMap = new HashMap<>();
versions = new ArrayList<>();
for (Map.Entry<String, int[]> arr : root.mcversion.entrySet()) {
String mcver = StrUtils.formatVersion(arr.getKey());
if (mcver == null) {
mcver = arr.getKey();
}
ArrayList<InstallerVersion> al = new ArrayList<>();
for (int num : arr.getValue()) {
MinecraftForgeVersion v = root.number.get(num);
InstallerVersion iv = new InstallerVersion(v.version, 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 = DownloadType.getSuggestedDownloadType().getProvider().getParsedDownloadURL(root.webpath + ver + "/" + filename);
switch (f[1]) {
case "installer":
iv.installer = url;
break;
case "universal":
iv.universal = url;
break;
case "changelog":
iv.changelog = url;
break;
default:
break;
}
}
if (StrUtils.isBlank(iv.installer) || StrUtils.isBlank(iv.universal))
continue;
Collections.sort(al, new InstallerVersionNewerComparator());
al.add(iv);
versions.add(iv);
}
versionMap.put(mcver, al);
}
Collections.sort(versions, new InstallerVersionComparator());
}
};
}
@Override
public List<InstallerVersion> getVersionsImpl(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";
}
}
@@ -17,6 +17,7 @@
*/ */
package org.jackhuang.hellominecraft.launcher.core.install.forge; package org.jackhuang.hellominecraft.launcher.core.install.forge;
import com.google.gson.annotations.SerializedName;
import java.util.Map; import java.util.Map;
/** /**
@@ -25,8 +26,22 @@ import java.util.Map;
*/ */
public class MinecraftForgeVersionRoot { public class MinecraftForgeVersionRoot {
public String artifact, webpath, adfly, homepage, name; @SerializedName("artifact")
public Map<String, int[]> branches, mcversion; public String artifact;
@SerializedName("webpath")
public String webpath;
@SerializedName("adfly")
public String adfly;
@SerializedName("homepage")
public String homepage;
@SerializedName("name")
public String name;
@SerializedName("branches")
public Map<String, int[]> branches;
@SerializedName("mcversion")
public Map<String, int[]> mcversion;
@SerializedName("promos")
public Map<String, Integer> promos; public Map<String, Integer> promos;
@SerializedName("number")
public Map<Integer, MinecraftForgeVersion> number; public Map<Integer, MinecraftForgeVersion> number;
} }
@@ -17,6 +17,7 @@
*/ */
package org.jackhuang.hellominecraft.launcher.core.install.liteloader; package org.jackhuang.hellominecraft.launcher.core.install.liteloader;
import com.google.gson.annotations.SerializedName;
import java.util.Map; import java.util.Map;
/** /**
@@ -25,5 +26,6 @@ import java.util.Map;
*/ */
public class LiteLoaderMCVersions { public class LiteLoaderMCVersions {
@SerializedName("artefacts")
public Map<String, Map<String, LiteLoaderVersion>> artefacts; public Map<String, Map<String, LiteLoaderVersion>> artefacts;
} }
@@ -17,6 +17,7 @@
*/ */
package org.jackhuang.hellominecraft.launcher.core.install.liteloader; package org.jackhuang.hellominecraft.launcher.core.install.liteloader;
import com.google.gson.annotations.SerializedName;
import org.jackhuang.hellominecraft.launcher.core.version.MinecraftLibrary; import org.jackhuang.hellominecraft.launcher.core.version.MinecraftLibrary;
/** /**
@@ -25,6 +26,16 @@ import org.jackhuang.hellominecraft.launcher.core.version.MinecraftLibrary;
*/ */
public class LiteLoaderVersion { public class LiteLoaderVersion {
public String tweakClass, file, version, md5, timestamp; @SerializedName("tweakClass")
public String tweakClass;
@SerializedName("file")
public String file;
@SerializedName("version")
public String version;
@SerializedName("md5")
public String md5;
@SerializedName("timestamp")
public String timestamp;
@SerializedName("libraries")
public MinecraftLibrary[] libraries; public MinecraftLibrary[] libraries;
} }
@@ -19,6 +19,7 @@ package org.jackhuang.hellominecraft.launcher.core.install.liteloader;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
@@ -28,8 +29,10 @@ import org.jackhuang.hellominecraft.launcher.core.version.MinecraftLibrary;
import org.jackhuang.hellominecraft.launcher.core.install.InstallerVersionList; import org.jackhuang.hellominecraft.launcher.core.install.InstallerVersionList;
import org.jackhuang.hellominecraft.launcher.core.install.InstallerVersionList.InstallerVersion; import org.jackhuang.hellominecraft.launcher.core.install.InstallerVersionList.InstallerVersion;
import org.jackhuang.hellominecraft.launcher.core.install.InstallerVersionNewerComparator; import org.jackhuang.hellominecraft.launcher.core.install.InstallerVersionNewerComparator;
import org.jackhuang.hellominecraft.util.NetUtils;
import org.jackhuang.hellominecraft.util.StrUtils; import org.jackhuang.hellominecraft.util.StrUtils;
import org.jackhuang.hellominecraft.util.tasks.Task;
import org.jackhuang.hellominecraft.util.tasks.TaskInfo;
import org.jackhuang.hellominecraft.util.tasks.download.HTTPGetTask;
/** /**
* *
@@ -50,38 +53,52 @@ public class LiteLoaderVersionList extends InstallerVersionList {
public List<InstallerVersion> versions; public List<InstallerVersion> versions;
@Override @Override
public void refreshList(String[] needed) throws Exception { public Task refresh(String[] needed) {
String s = NetUtils.get(C.URL_LITELOADER_LIST);
if (root != null) if (root != null)
return; return null;
return new TaskInfo(C.i18n("install.liteloader.get_list")) {
HTTPGetTask task = new HTTPGetTask(C.URL_LITELOADER_LIST);
root = C.GSON.fromJson(s, LiteLoaderVersionsRoot.class); @Override
public Collection<Task> getDependTasks() {
versionMap = new HashMap<>(); return Arrays.asList(task);
versions = new ArrayList<>();
for (Map.Entry<String, LiteLoaderMCVersions> arr : root.versions.entrySet()) {
ArrayList<InstallerVersion> al = new ArrayList<>();
LiteLoaderMCVersions mcv = arr.getValue();
if (mcv == null || mcv.artefacts == null || mcv.artefacts.get("com.mumfrey:liteloader") == null)
continue;
for (Map.Entry<String, LiteLoaderVersion> entry : mcv.artefacts.get("com.mumfrey:liteloader").entrySet()) {
if ("latest".equals(entry.getKey()))
continue;
LiteLoaderVersion v = entry.getValue();
LiteLoaderInstallerVersion iv = new LiteLoaderInstallerVersion(v.version, StrUtils.formatVersion(arr.getKey()));
iv.universal = "http://dl.liteloader.com/versions/com/mumfrey/liteloader/" + arr.getKey() + "/" + v.file;
iv.tweakClass = v.tweakClass;
iv.libraries = Arrays.copyOf(v.libraries, v.libraries.length);
iv.installer = "http://dl.liteloader.com/redist/" + iv.mcVersion + "/liteloader-installer-" + iv.selfVersion.replace("_", "-") + ".jar";
al.add(iv);
versions.add(iv);
} }
Collections.sort(al, new InstallerVersionNewerComparator());
versionMap.put(StrUtils.formatVersion(arr.getKey()), al);
}
Collections.sort(versions, InstallerVersionComparator.INSTANCE); @Override
public void executeTask() throws Throwable {
if (!areDependTasksSucceeded)
return;
String s = task.getResult();
root = C.GSON.fromJson(s, LiteLoaderVersionsRoot.class);
versionMap = new HashMap<>();
versions = new ArrayList<>();
for (Map.Entry<String, LiteLoaderMCVersions> arr : root.versions.entrySet()) {
ArrayList<InstallerVersion> al = new ArrayList<>();
LiteLoaderMCVersions mcv = arr.getValue();
if (mcv == null || mcv.artefacts == null || mcv.artefacts.get("com.mumfrey:liteloader") == null)
continue;
for (Map.Entry<String, LiteLoaderVersion> entry : mcv.artefacts.get("com.mumfrey:liteloader").entrySet()) {
if ("latest".equals(entry.getKey()))
continue;
LiteLoaderVersion v = entry.getValue();
LiteLoaderInstallerVersion iv = new LiteLoaderInstallerVersion(v.version, StrUtils.formatVersion(arr.getKey()));
iv.universal = "http://dl.liteloader.com/versions/com/mumfrey/liteloader/" + arr.getKey() + "/" + v.file;
iv.tweakClass = v.tweakClass;
iv.libraries = Arrays.copyOf(v.libraries, v.libraries.length);
iv.installer = "http://dl.liteloader.com/redist/" + iv.mcVersion + "/liteloader-installer-" + iv.selfVersion.replace("_", "-") + ".jar";
al.add(iv);
versions.add(iv);
}
Collections.sort(al, new InstallerVersionNewerComparator());
versionMap.put(StrUtils.formatVersion(arr.getKey()), al);
}
Collections.sort(versions, InstallerVersionComparator.INSTANCE);
}
};
} }
@Override @Override
@@ -17,13 +17,20 @@
*/ */
package org.jackhuang.hellominecraft.launcher.core.install.liteloader; package org.jackhuang.hellominecraft.launcher.core.install.liteloader;
import com.google.gson.annotations.SerializedName;
/** /**
* *
* @author huangyuhui * @author huangyuhui
*/ */
public class LiteLoaderVersionsMeta { public class LiteLoaderVersionsMeta {
private String description, authors, url; @SerializedName("versions")
private String description;
@SerializedName("authors")
private String authors;
@SerializedName("url")
private String url;
public LiteLoaderVersionsMeta() { public LiteLoaderVersionsMeta() {
} }
@@ -17,6 +17,7 @@
*/ */
package org.jackhuang.hellominecraft.launcher.core.install.liteloader; package org.jackhuang.hellominecraft.launcher.core.install.liteloader;
import com.google.gson.annotations.SerializedName;
import java.util.Map; import java.util.Map;
/** /**
@@ -25,6 +26,8 @@ import java.util.Map;
*/ */
public class LiteLoaderVersionsRoot { public class LiteLoaderVersionsRoot {
@SerializedName("versions")
public Map<String, LiteLoaderMCVersions> versions; public Map<String, LiteLoaderMCVersions> versions;
@SerializedName("meta")
public LiteLoaderVersionsMeta meta; public LiteLoaderVersionsMeta meta;
} }
@@ -72,14 +72,15 @@ public class OptiFineInstaller extends Task implements PreviousResultRegistrar<F
mv.mainClass = "net.minecraft.launchwrapper.Launch"; mv.mainClass = "net.minecraft.launchwrapper.Launch";
mv.libraries.add(1, new MinecraftLibrary("net.minecraft:launchwrapper:1.7")); mv.libraries.add(1, new MinecraftLibrary("net.minecraft:launchwrapper:1.7"));
} }
mv.minecraftArguments += " --tweakClass optifine.OptiFineTweaker"; if (!mv.minecraftArguments.contains("FMLTweaker"))
mv.minecraftArguments += " --tweakClass optifine.OptiFineTweaker";
} }
} }
File loc = new File(service.baseDirectory(), "versions/" + mv.id); File loc = new File(service.baseDirectory(), "versions/" + mv.id);
if (!loc.exists() && loc.mkdirs()) if (!loc.exists() && loc.mkdirs())
HMCLog.warn("Failed to make directories: " + loc); HMCLog.warn("Failed to make directories: " + loc);
File json = new File(loc, mv.id + ".json"); File json = new File(loc, mv.id + ".json");
FileUtils.writeStringToFile(json, C.GSON.toJson(mv, MinecraftVersion.class)); FileUtils.write(json, C.GSON.toJson(mv, MinecraftVersion.class));
service.version().refreshVersions(); service.version().refreshVersions();
} }
@@ -20,6 +20,8 @@ package org.jackhuang.hellominecraft.launcher.core.install.optifine.bmcl;
import com.google.gson.reflect.TypeToken; import com.google.gson.reflect.TypeToken;
import java.lang.reflect.Type; import java.lang.reflect.Type;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
@@ -30,8 +32,10 @@ import org.jackhuang.hellominecraft.util.C;
import org.jackhuang.hellominecraft.util.ArrayUtils; import org.jackhuang.hellominecraft.util.ArrayUtils;
import org.jackhuang.hellominecraft.launcher.core.install.InstallerVersionList; import org.jackhuang.hellominecraft.launcher.core.install.InstallerVersionList;
import org.jackhuang.hellominecraft.launcher.core.install.optifine.OptiFineVersion; import org.jackhuang.hellominecraft.launcher.core.install.optifine.OptiFineVersion;
import org.jackhuang.hellominecraft.util.NetUtils;
import org.jackhuang.hellominecraft.util.StrUtils; import org.jackhuang.hellominecraft.util.StrUtils;
import org.jackhuang.hellominecraft.util.tasks.Task;
import org.jackhuang.hellominecraft.util.tasks.TaskInfo;
import org.jackhuang.hellominecraft.util.tasks.download.HTTPGetTask;
/** /**
* *
@@ -55,34 +59,46 @@ public class OptiFineBMCLVersionList extends InstallerVersionList {
}.getType(); }.getType();
@Override @Override
public void refreshList(String[] needed) throws Exception { public Task refresh(String[] needed) {
String s = NetUtils.get("http://bmclapi.bangbang93.com/optifine/versionlist"); return new TaskInfo(C.i18n("install.optifine.get_list")) {
HTTPGetTask task = new HTTPGetTask("http://bmclapi.bangbang93.com/optifine/versionlist");
versionMap = new HashMap<>(); @Override
versions = new ArrayList<>(); public Collection<Task> getDependTasks() {
return Arrays.asList(task);
if (s == null)
return;
root = C.GSON.fromJson(s, TYPE);
for (OptiFineVersion v : root) {
v.setMirror(v.getMirror().replace("http://optifine.net/http://optifine.net/", "http://optifine.net/"));
if (StrUtils.isBlank(v.getMCVersion())) {
Pattern p = Pattern.compile("OptiFine (.*) HD");
Matcher m = p.matcher(v.getVersion());
while (m.find())
v.setMCVersion(m.group(1));
} }
InstallerVersion iv = new InstallerVersion(v.getVersion(), StrUtils.formatVersion(v.getMCVersion()));
List<InstallerVersion> al = ArrayUtils.tryGetMapWithList(versionMap, StrUtils.formatVersion(v.getMCVersion())); @Override
//String url = "http://bmclapi.bangbang93.com/optifine/" + iv.selfVersion.replace(" ", "%20"); public void executeTask() throws Throwable {
iv.installer = iv.universal = v.getMirror(); String s = task.getResult();
al.add(iv);
versions.add(iv);
}
Collections.sort(versions, InstallerVersionComparator.INSTANCE); versionMap = new HashMap<>();
versions = new ArrayList<>();
if (s == null)
return;
root = C.GSON.fromJson(s, TYPE);
for (OptiFineVersion v : root) {
v.setMirror(v.getMirror().replace("http://optifine.net/http://optifine.net/", "http://optifine.net/"));
if (StrUtils.isBlank(v.getMCVersion())) {
Pattern p = Pattern.compile("OptiFine (.*) HD");
Matcher m = p.matcher(v.getVersion());
while (m.find())
v.setMCVersion(m.group(1));
}
InstallerVersion iv = new InstallerVersion(v.getVersion(), StrUtils.formatVersion(v.getMCVersion()));
List<InstallerVersion> al = ArrayUtils.tryGetMapWithList(versionMap, StrUtils.formatVersion(v.getMCVersion()));
//String url = "http://bmclapi.bangbang93.com/optifine/" + iv.selfVersion.replace(" ", "%20");
iv.installer = iv.universal = v.getMirror();
al.add(iv);
versions.add(iv);
}
Collections.sort(versions, InstallerVersionComparator.INSTANCE);
}
};
} }
@Override @Override
@@ -0,0 +1,155 @@
/*
* Hello Minecraft! Launcher.
* Copyright (C) 2013 huangyuhui <huanghongxun2008@126.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see {http://www.gnu.org/licenses/}.
*/
package org.jackhuang.hellominecraft.launcher.core.install.optifine.vanilla;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
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 javax.xml.parsers.ParserConfigurationException;
import org.jackhuang.hellominecraft.launcher.core.install.InstallerVersionList;
import org.jackhuang.hellominecraft.launcher.core.install.optifine.OptiFineVersion;
import org.jackhuang.hellominecraft.util.ArrayUtils;
import org.jackhuang.hellominecraft.util.C;
import org.jackhuang.hellominecraft.util.StrUtils;
import org.jackhuang.hellominecraft.util.tasks.Task;
import org.jackhuang.hellominecraft.util.tasks.TaskInfo;
import org.jackhuang.hellominecraft.util.tasks.download.HTTPGetTask;
import org.w3c.dom.DOMException;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;
/**
*
* @author huangyuhui
*/
public class OptiFineVersionList extends InstallerVersionList {
private static OptiFineVersionList instance;
public static OptiFineVersionList getInstance() {
if (null == instance)
instance = new OptiFineVersionList();
return instance;
}
public ArrayList<OptiFineVersion> root = new ArrayList();
public Map<String, List<InstallerVersion>> versionMap;
public List<InstallerVersion> versions;
@Override
public Task refresh(String[] sss) {
if (versions != null)
return null;
return new TaskInfo(C.i18n("install.optifine.get_list")) {
HTTPGetTask task = new HTTPGetTask("http://optifine.net/downloads");
@Override
public Collection<Task> getDependTasks() {
return Arrays.asList(task);
}
@Override
public void executeTask() throws Throwable {
if (!areDependTasksSucceeded)
return;
String content = task.getResult();
versionMap = new HashMap<>();
versions = new ArrayList<>();
content = content.replace("&nbsp;", " ").replace("&gt;", ">").replace("&lt;", "<").replace("<br>", "<br />");
try {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder db = factory.newDocumentBuilder();
Document doc = db.parse(new ByteArrayInputStream(content.getBytes("UTF-8")));
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.setMirror(((Element) td.getElementsByTagName("a").item(0)).getAttribute("href"));
if (StrUtils.startsWith(td.getAttribute("class"), "downloadLineDownload"))
v.setDownloadLink(((Element) td.getElementsByTagName("a").item(0)).getAttribute("href"));
if (StrUtils.startsWith(td.getAttribute("class"), "downloadLineDate"))
v.setDate(td.getTextContent());
if (StrUtils.startsWith(td.getAttribute("class"), "downloadLineFile"))
v.setVersion(td.getTextContent());
}
if (StrUtils.isBlank(v.getMCVersion())) {
Pattern p = Pattern.compile("OptiFine (.*?) ");
Matcher m = p.matcher(v.getVersion());
while (m.find())
v.setMCVersion(StrUtils.formatVersion(m.group(1)));
}
InstallerVersion iv = new InstallerVersion(v.getVersion(), StrUtils.formatVersion(v.getMCVersion()));
iv.installer = iv.universal = v.getMirror();
root.add(v);
versions.add(iv);
List<InstallerVersion> ivl = ArrayUtils.tryGetMapWithList(versionMap, StrUtils.formatVersion(v.getMCVersion()));
ivl.add(iv);
}
}
}
} catch (ParserConfigurationException | SAXException | IOException | DOMException ex) {
throw new RuntimeException(ex);
}
Collections.sort(versions, InstallerVersionComparator.INSTANCE);
}
};
}
@Override
public String getName() {
return "OptiFine - OptiFine Official Site";
}
@Override
public List<InstallerVersion> getVersionsImpl(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;
}
}
@@ -29,7 +29,6 @@ import org.jackhuang.hellominecraft.util.MessageBox;
import org.jackhuang.hellominecraft.util.system.OS; import org.jackhuang.hellominecraft.util.system.OS;
import org.jackhuang.hellominecraft.util.system.Platform; import org.jackhuang.hellominecraft.util.system.Platform;
import org.jackhuang.hellominecraft.util.StrUtils; import org.jackhuang.hellominecraft.util.StrUtils;
import org.jackhuang.hellominecraft.util.Utils;
import org.jackhuang.hellominecraft.launcher.core.GameException; import org.jackhuang.hellominecraft.launcher.core.GameException;
import org.jackhuang.hellominecraft.launcher.core.auth.UserProfileProvider; import org.jackhuang.hellominecraft.launcher.core.auth.UserProfileProvider;
import org.jackhuang.hellominecraft.launcher.core.version.MinecraftVersion; import org.jackhuang.hellominecraft.launcher.core.version.MinecraftVersion;
@@ -96,10 +96,12 @@ public class GameLauncher {
if (file != null) if (file != null)
FileUtils.cleanDirectoryQuietly(file); FileUtils.cleanDirectoryQuietly(file);
HMCLog.log("Detecting libraries..."); if (!options.isNotCheckGame()) {
launchingStateChangedEvent.execute(LaunchingState.DownloadingLibraries); HMCLog.log("Detecting libraries...");
if (!downloadLibrariesEvent.execute(service.download().getDownloadLibraries(loader.getMinecraftVersion()))) launchingStateChangedEvent.execute(LaunchingState.DownloadingLibraries);
throw new GameException("Failed to download libraries"); if (!downloadLibrariesEvent.execute(service.download().getDownloadLibraries(loader.getMinecraftVersion())))
throw new GameException("Failed to download libraries");
}
HMCLog.log("Unpacking natives..."); HMCLog.log("Unpacking natives...");
launchingStateChangedEvent.execute(LaunchingState.DecompressingNatives); launchingStateChangedEvent.execute(LaunchingState.DecompressingNatives);
@@ -118,8 +120,8 @@ public class GameLauncher {
* *
* @throws IOException failed creating process * @throws IOException failed creating process
*/ */
public void launch(List str) throws IOException { public void launch(List<String> str) throws IOException {
if (!service.version().onLaunch()) if (!service.version().onLaunch(options.getLaunchVersion()))
return; return;
if (StrUtils.isNotBlank(options.getPrecalledCommand())) { if (StrUtils.isNotBlank(options.getPrecalledCommand())) {
Process p = Runtime.getRuntime().exec(options.getPrecalledCommand()); Process p = Runtime.getRuntime().exec(options.getPrecalledCommand());
@@ -131,6 +133,7 @@ public class GameLauncher {
} }
} }
HMCLog.log("Starting process"); HMCLog.log("Starting process");
HMCLog.log(str.toString());
ProcessBuilder builder = new ProcessBuilder(str); ProcessBuilder builder = new ProcessBuilder(str);
if (options.getLaunchVersion() == null || service.baseDirectory() == null) if (options.getLaunchVersion() == null || service.baseDirectory() == null)
throw new Error("Fucking bug!"); throw new Error("Fucking bug!");
@@ -153,7 +156,7 @@ public class GameLauncher {
*/ */
public File makeLauncher(String launcherName, List str) throws IOException { public File makeLauncher(String launcherName, List str) throws IOException {
HMCLog.log("Making shell launcher..."); HMCLog.log("Making shell launcher...");
service.version().onLaunch(); service.version().onLaunch(options.getLaunchVersion());
boolean isWin = OS.os() == OS.WINDOWS; boolean isWin = OS.os() == OS.WINDOWS;
File f = new File(launcherName + (isWin ? ".bat" : ".sh")); File f = new File(launcherName + (isWin ? ".bat" : ".sh"));
if (!f.exists() && !f.createNewFile()) if (!f.exists() && !f.createNewFile())
@@ -172,6 +175,8 @@ public class GameLauncher {
if (appdata != null) { if (appdata != null) {
writer.write("set appdata=" + appdata); writer.write("set appdata=" + appdata);
writer.newLine(); writer.newLine();
writer.write("cd /D %appdata%");
writer.newLine();
} }
} }
if (StrUtils.isNotBlank(options.getPrecalledCommand())) { if (StrUtils.isNotBlank(options.getPrecalledCommand())) {
@@ -30,7 +30,7 @@ public class LaunchOptions {
private String name, versionName, javaArgs, minecraftArgs, maxMemory, permSize, width, height, serverIp, wrapper; private String name, versionName, javaArgs, minecraftArgs, maxMemory, permSize, width, height, serverIp, wrapper;
private String proxyHost, proxyPort, proxyUser, proxyPass, javaDir, launchVersion, type, precalledCommand; private String proxyHost, proxyPort, proxyUser, proxyPass, javaDir, launchVersion, type, precalledCommand;
private boolean fullscreen, noJVMArgs; private boolean fullscreen, noJVMArgs, notCheckGame;
private JdkVersion java; private JdkVersion java;
private File gameDir; private File gameDir;
private GameDirType gameDirType; private GameDirType gameDirType;
@@ -222,4 +222,12 @@ public class LaunchOptions {
public void setType(String type) { public void setType(String type) {
this.type = type; this.type = type;
} }
public boolean isNotCheckGame() {
return notCheckGame;
}
public void setNotCheckGame(boolean notCheckGame) {
this.notCheckGame = notCheckGame;
}
} }
@@ -21,6 +21,8 @@ import java.io.File;
import java.net.URL; import java.net.URL;
import org.jackhuang.hellominecraft.util.C; import org.jackhuang.hellominecraft.util.C;
import org.jackhuang.hellominecraft.launcher.core.download.DownloadLibraryJob; import org.jackhuang.hellominecraft.launcher.core.download.DownloadLibraryJob;
import org.jackhuang.hellominecraft.util.StrUtils;
import org.jackhuang.hellominecraft.util.func.Function;
import org.jackhuang.hellominecraft.util.tasks.download.FileDownloadTask; import org.jackhuang.hellominecraft.util.tasks.download.FileDownloadTask;
/** /**
@@ -49,12 +51,20 @@ public class LibraryDownloadTask extends FileDownloadTask {
if (s.length == 3 && s[2].length() > 3) if (s.length == 3 && s[2].length() > 3)
job.url = "http://dl.liteloader.com/versions/com/mumfrey/liteloader/" + s[2].substring(0, s[2].length() - 3) + "/liteloader-" + s[2] + ".jar"; job.url = "http://dl.liteloader.com/versions/com/mumfrey/liteloader/" + s[2].substring(0, s[2].length() - 3) + "/liteloader-" + s[2] + ".jar";
} }
download(new URL(job.url), job.path); download(new URL(job.url), job.retryUrl, job.path);
} }
void download(URL url, File filePath) throws Throwable { void download(URL url, String retryUrl, File filePath) throws Throwable {
this.url = url; this.url = url;
this.filePath = filePath; this.filePath = filePath;
if (StrUtils.isNotBlank(retryUrl)) {
this.failedCallbackReturnsNewURL = new Function<Integer, String>() {
@Override
public String apply(Integer t) {
return retryUrl;
}
};
}
super.executeTask(); super.executeTask();
} }
@@ -19,9 +19,9 @@ package org.jackhuang.hellominecraft.launcher.core.launch;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList;
import java.util.List; import java.util.List;
import org.jackhuang.hellominecraft.util.StrUtils; import org.jackhuang.hellominecraft.util.StrUtils;
import org.jackhuang.hellominecraft.util.func.Function;
import org.jackhuang.hellominecraft.util.logging.HMCLog; import org.jackhuang.hellominecraft.util.logging.HMCLog;
import org.jackhuang.hellominecraft.util.system.IOUtils; import org.jackhuang.hellominecraft.util.system.IOUtils;
import org.jackhuang.hellominecraft.util.system.OS; import org.jackhuang.hellominecraft.util.system.OS;
@@ -30,6 +30,7 @@ import org.jackhuang.hellominecraft.launcher.core.auth.UserProfileProvider;
import org.jackhuang.hellominecraft.launcher.core.version.MinecraftLibrary; import org.jackhuang.hellominecraft.launcher.core.version.MinecraftLibrary;
import org.jackhuang.hellominecraft.launcher.core.version.MinecraftVersion; import org.jackhuang.hellominecraft.launcher.core.version.MinecraftVersion;
import org.jackhuang.hellominecraft.launcher.core.service.IMinecraftService; import org.jackhuang.hellominecraft.launcher.core.service.IMinecraftService;
import org.jackhuang.hellominecraft.util.func.BiFunction;
/** /**
* *
@@ -44,9 +45,24 @@ public class MinecraftLoader extends AbstractMinecraftLoader {
@Override @Override
protected void makeSelf(List<String> res) throws GameException { protected void makeSelf(List<String> res) throws GameException {
StringBuilder library = new StringBuilder(""); StringBuilder library = new StringBuilder("");
ArrayList<MinecraftLibrary> opt = new ArrayList<>();
for (MinecraftLibrary l : version.libraries) for (MinecraftLibrary l : version.libraries)
if (l.allow() && !l.isRequiredToUnzip()) if (l.allow() && !l.isRequiredToUnzip()) {
library.append(l.getFilePath(gameDir).getAbsolutePath()).append(File.pathSeparator); if (l.name.toLowerCase().contains("optifine")) {
opt.add(l);
continue;
}
File f = l.getFilePath(gameDir);
if (f == null)
continue;
library.append(f.getAbsolutePath()).append(File.pathSeparator);
}
for (MinecraftLibrary l : opt) {
File f = l.getFilePath(gameDir);
if (f == null)
continue;
library.append(f.getAbsolutePath()).append(File.pathSeparator);
}
File f = version.getJar(service.baseDirectory()); File f = version.getJar(service.baseDirectory());
if (!f.exists()) if (!f.exists())
throw new GameException("Minecraft jar does not exists"); throw new GameException("Minecraft jar does not exists");
@@ -55,9 +71,11 @@ public class MinecraftLoader extends AbstractMinecraftLoader {
res.add(library.toString().substring(0, library.length() - File.pathSeparator.length())); res.add(library.toString().substring(0, library.length() - File.pathSeparator.length()));
res.add(version.mainClass); res.add(version.mainClass);
if (version.minecraftArguments == null)
throw new GameException(new NullPointerException("Minecraft Arguments can not be null."));
String[] splitted = StrUtils.tokenize(version.minecraftArguments); String[] splitted = StrUtils.tokenize(version.minecraftArguments);
String game_assets = assetProvider.apply(version); String game_assets = assetProvider.apply(version, !options.isNotCheckGame());
for (String t : splitted) { for (String t : splitted) {
t = t.replace("${auth_player_name}", lr.getUserName()); t = t.replace("${auth_player_name}", lr.getUserName());
@@ -96,13 +114,13 @@ public class MinecraftLoader extends AbstractMinecraftLoader {
} }
} }
private final Function<MinecraftVersion, String> DEFAULT_ASSET_PROVIDER = t -> { private final BiFunction<MinecraftVersion, Boolean, String> DEFAULT_ASSET_PROVIDER = (t, allow) -> {
return new File(service.baseDirectory(), "assets").getAbsolutePath(); return new File(service.baseDirectory(), "assets").getAbsolutePath();
}; };
private Function<MinecraftVersion, String> assetProvider = DEFAULT_ASSET_PROVIDER; private BiFunction<MinecraftVersion, Boolean, String> assetProvider = DEFAULT_ASSET_PROVIDER;
public void setAssetProvider(Function<MinecraftVersion, String> assetProvider) { public void setAssetProvider(BiFunction<MinecraftVersion, Boolean, String> assetProvider) {
if (assetProvider == null) if (assetProvider == null)
this.assetProvider = DEFAULT_ASSET_PROVIDER; this.assetProvider = DEFAULT_ASSET_PROVIDER;
else else
@@ -17,12 +17,15 @@
*/ */
package org.jackhuang.hellominecraft.launcher.core.mod; package org.jackhuang.hellominecraft.launcher.core.mod;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import com.google.gson.JsonSyntaxException; import com.google.gson.JsonSyntaxException;
import com.google.gson.annotations.SerializedName;
import com.google.gson.reflect.TypeToken; import com.google.gson.reflect.TypeToken;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.io.InputStreamReader; import java.io.InputStreamReader;
import java.lang.reflect.Type;
import java.util.List; import java.util.List;
import java.util.zip.ZipEntry; import java.util.zip.ZipEntry;
import java.util.zip.ZipFile; import java.util.zip.ZipFile;
@@ -37,9 +40,30 @@ import org.jackhuang.hellominecraft.util.system.FileUtils;
*/ */
public class ModInfo implements Comparable<ModInfo> { public class ModInfo implements Comparable<ModInfo> {
@SerializedName("location")
public File location; public File location;
public String modid, name, description, author, version, mcversion, url, updateUrl, credits; @SerializedName("modid")
public String modid;
@SerializedName("name")
public String name;
@SerializedName("description")
public String description;
@SerializedName("author")
public String author;
@SerializedName("version")
public String version;
@SerializedName("mcversion")
public String mcversion;
@SerializedName("url")
public String url;
@SerializedName("updateUrl")
public String updateUrl;
@SerializedName("credits")
public String credits;
@SerializedName("authorList")
public String[] authorList; public String[] authorList;
@SerializedName("authors")
public String[] authors;
public boolean isActive() { public boolean isActive() {
return !location.getName().endsWith(".disabled"); return !location.getName().endsWith(".disabled");
@@ -67,6 +91,8 @@ public class ModInfo implements Comparable<ModInfo> {
public String getAuthor() { public String getAuthor() {
if (authorList != null && authorList.length > 0) if (authorList != null && authorList.length > 0)
return StrUtils.parseParams("", authorList, ", "); return StrUtils.parseParams("", authorList, ", ");
else if (authors != null && authors.length > 0)
return StrUtils.parseParams("", authors, ", ");
else if (StrUtils.isNotBlank(author)) else if (StrUtils.isNotBlank(author))
return author; return author;
else else
@@ -103,18 +129,30 @@ public class ModInfo implements Comparable<ModInfo> {
return name.endsWith(".zip") || name.endsWith(".jar") || name.endsWith("litemod"); return name.endsWith(".zip") || name.endsWith(".jar") || name.endsWith("litemod");
} }
private static final Type TYPE = new TypeToken<List<ModInfo>>() {
}.getType();
private static ModInfo getForgeModInfo(File f, ZipFile jar, ZipEntry entry) throws IOException { private static ModInfo getForgeModInfo(File f, ZipFile jar, ZipEntry entry) throws IOException {
ModInfo i = new ModInfo(); ModInfo i = new ModInfo();
i.location = f; i.location = f;
List<ModInfo> m = C.GSON.fromJson(new InputStreamReader(jar.getInputStream(entry), "UTF-8"), TYPE);
if (m != null && m.size() > 0) { InputStreamReader streamReader = new InputStreamReader(jar.getInputStream(entry), "UTF-8");
i = m.get(0);
i.location = f; JsonParser parser = new JsonParser();
} JsonElement element = parser.parse(streamReader);
return i; List<ModInfo> m = null;
if (element.isJsonArray()) {
m = C.GSON.fromJson(element, new TypeToken<List<ModInfo>>(){}.getType());
} else if (element.isJsonObject()) {
JsonObject modInfo = element.getAsJsonObject();
if (modInfo.has("modList") && modInfo.get("modList").isJsonArray()) {
m = C.GSON.fromJson(modInfo.get("modList"), new TypeToken<List<ModInfo>>(){}.getType());
}
}
if (m != null && m.size() > 0) {
i = m.get(0);
i.location = f;
}
return i;
} }
private static ModInfo getLiteLoaderModInfo(File f, ZipFile jar, ZipEntry entry) throws IOException { private static ModInfo getLiteLoaderModInfo(File f, ZipFile jar, ZipEntry entry) throws IOException {
@@ -164,13 +164,13 @@ public final class ModpackManager {
HMCLog.warn("Failed to rename incorrect json " + oldFile + " to " + nowFile); HMCLog.warn("Failed to rename incorrect json " + oldFile + " to " + nowFile);
File json = new File(nowFile, "pack.json"); File json = new File(nowFile, "pack.json");
MinecraftVersion mv = C.GSON.fromJson(FileUtils.readFileToString(json), MinecraftVersion.class); MinecraftVersion mv = C.GSON.fromJson(FileUtils.read(json), MinecraftVersion.class);
if (mv.jar == null) if (mv.jar == null)
throw new FileNotFoundException(C.i18n("modpack.incorrect_format.no_jar")); throw new FileNotFoundException(C.i18n("modpack.incorrect_format.no_jar"));
c.add(service.download().downloadMinecraftJar(mv, new File(nowFile, id + ".jar"))); c.add(service.download().downloadMinecraftJar(mv, new File(nowFile, id + ".jar")));
mv.jar = null; mv.jar = null;
FileUtils.writeStringToFile(json, C.GSON.toJson(mv)); FileUtils.write(json, C.GSON.toJson(mv));
if (!json.renameTo(new File(nowFile, id + ".json"))) if (!json.renameTo(new File(nowFile, id + ".json")))
HMCLog.warn("Failed to rename pack.json to new id"); HMCLog.warn("Failed to rename pack.json to new id");
@@ -72,13 +72,6 @@ public abstract class IMinecraftProvider {
*/ */
public abstract boolean install(String version, Consumer<MinecraftVersion> callback); public abstract boolean install(String version, Consumer<MinecraftVersion> callback);
/**
* Returns the thing like ".minecraft/resourcepacks".
*
* @return the thing
*/
public abstract File getResourcePacks();
/** /**
* *
* @param v should be resolved * @param v should be resolved
@@ -164,7 +157,7 @@ public abstract class IMinecraftProvider {
* *
* @return if false, will break the launch process. * @return if false, will break the launch process.
*/ */
public abstract boolean onLaunch(); public abstract boolean onLaunch(String id);
public File baseDirectory() { public File baseDirectory() {
return service.baseDirectory(); return service.baseDirectory();
@@ -17,6 +17,7 @@
*/ */
package org.jackhuang.hellominecraft.launcher.core.version; package org.jackhuang.hellominecraft.launcher.core.version;
import com.google.gson.annotations.SerializedName;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import org.jackhuang.hellominecraft.util.StrUtils; import org.jackhuang.hellominecraft.util.StrUtils;
@@ -27,6 +28,7 @@ import org.jackhuang.hellominecraft.util.StrUtils;
*/ */
public class Extract implements Cloneable { public class Extract implements Cloneable {
@SerializedName("exclude")
public List<String> exclude = new ArrayList<>(); public List<String> exclude = new ArrayList<>();
public boolean allow(String path) { public boolean allow(String path) {
@@ -17,6 +17,7 @@
*/ */
package org.jackhuang.hellominecraft.launcher.core.version; package org.jackhuang.hellominecraft.launcher.core.version;
import com.google.gson.annotations.SerializedName;
import org.jackhuang.hellominecraft.launcher.core.download.DownloadType; import org.jackhuang.hellominecraft.launcher.core.download.DownloadType;
/** /**
@@ -25,8 +26,11 @@ import org.jackhuang.hellominecraft.launcher.core.download.DownloadType;
*/ */
public class GameDownloadInfo implements Cloneable { public class GameDownloadInfo implements Cloneable {
@SerializedName("sha1")
public String sha1; public String sha1;
@SerializedName("size")
public int size; public int size;
@SerializedName("url")
protected String url; protected String url;
/** /**
@@ -17,6 +17,7 @@
*/ */
package org.jackhuang.hellominecraft.launcher.core.version; package org.jackhuang.hellominecraft.launcher.core.version;
import com.google.gson.annotations.SerializedName;
import java.util.Map; import java.util.Map;
/** /**
@@ -25,6 +26,8 @@ import java.util.Map;
*/ */
public class LibrariesDownloadInfo { public class LibrariesDownloadInfo {
@SerializedName("classifiers")
Map<String, LibraryDownloadInfo> classifiers; Map<String, LibraryDownloadInfo> classifiers;
@SerializedName("artifact")
LibraryDownloadInfo artifact; LibraryDownloadInfo artifact;
} }
@@ -0,0 +1,78 @@
/*
* Hello Minecraft! Launcher.
* Copyright (C) 2013 huangyuhui <huanghongxun2008@126.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see {http://www.gnu.org/licenses/}.
*/
package org.jackhuang.hellominecraft.launcher.core.version;
import com.google.gson.annotations.SerializedName;
import org.jackhuang.hellominecraft.launcher.core.download.DownloadType;
import org.jackhuang.hellominecraft.launcher.core.download.IDownloadProvider;
import org.jackhuang.hellominecraft.util.StrUtils;
import org.jackhuang.hellominecraft.util.system.IOUtils;
/**
*
* @author huangyuhui
*/
public class LibraryDownloadInfo extends GameDownloadInfo {
@SerializedName("path")
public String path;
@SerializedName("forgeURL")
public String forgeURL;
@Override
public String getUrl(DownloadType dt, boolean allowSelf) {
IDownloadProvider provider = dt.getProvider();
String downloadUrl = (forgeURL == null ? provider.getLibraryDownloadURL() : forgeURL);
if (StrUtils.isNotBlank(url) && allowSelf) {
downloadUrl = url;
} // forced replace: Let different download sources into force
return provider.getParsedDownloadURL(getUrlWithBaseUrl(downloadUrl));
}
public String getRetryUrl(DownloadType dt) {
IDownloadProvider provider = dt.getProvider();
String retryBaseUrl = provider.getRetryLibraryDownloadURL();
String downloadUrl = (forgeURL == null ? retryBaseUrl : forgeURL);
if (StrUtils.isNotBlank(url) && provider.isAllowedToUseSelfURL()) {
downloadUrl = url;
}
if (StrUtils.isBlank(downloadUrl)) {
return null;
}
downloadUrl = getUrlWithBaseUrl(downloadUrl);
if (downloadUrl.contains("minecraftforge")) { // fix forge url
downloadUrl = provider.getParsedDownloadURL(downloadUrl);
}
return downloadUrl;
}
private String getUrlWithBaseUrl(String baseUrl) {
if (!baseUrl.endsWith(".jar")) {
if (path == null) {
return null;
} else {
baseUrl = IOUtils.addURLSeparator(baseUrl) + path.replace('\\', '/');
}
}
return baseUrl;
}
}
@@ -17,6 +17,7 @@
*/ */
package org.jackhuang.hellominecraft.launcher.core.version; package org.jackhuang.hellominecraft.launcher.core.version;
import com.google.gson.annotations.SerializedName;
import java.io.File; import java.io.File;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
@@ -30,10 +31,15 @@ import org.jackhuang.hellominecraft.util.StrUtils;
*/ */
public class MinecraftLibrary extends IMinecraftLibrary { public class MinecraftLibrary extends IMinecraftLibrary {
@SerializedName("rules")
public ArrayList<Rules> rules; public ArrayList<Rules> rules;
@SerializedName("url")
public String url; public String url;
@SerializedName("natives")
public Natives natives; public Natives natives;
@SerializedName("extract")
public Extract extract; public Extract extract;
@SerializedName("downloads")
public LibrariesDownloadInfo downloads; public LibrariesDownloadInfo downloads;
public MinecraftLibrary(String name) { public MinecraftLibrary(String name) {
@@ -42,29 +48,25 @@ public class MinecraftLibrary extends IMinecraftLibrary {
public MinecraftLibrary(ArrayList<Rules> rules, String url, Natives natives, String name, Extract extract, LibraryDownloadInfo downloads) { public MinecraftLibrary(ArrayList<Rules> rules, String url, Natives natives, String name, Extract extract, LibraryDownloadInfo downloads) {
super(name); super(name);
this.rules = rules == null ? null : (ArrayList<Rules>) rules.clone(); this.rules = (rules == null) ? null : (ArrayList<Rules>) rules.clone();
this.url = url; this.url = url;
this.natives = natives == null ? null : (Natives) natives.clone(); this.natives = (natives == null) ? null : (Natives) natives.clone();
this.extract = extract == null ? null : (Extract) extract.clone(); this.extract = (extract == null) ? null : (Extract) extract.clone();
} }
/**
* is the library allowed to load.
*
* @return
*/
@Override @Override
public boolean allow() { public boolean allow() {
if (rules != null) { if (rules != null) {
boolean flag = false; boolean flag = false;
for (Rules r : rules) for (Rules r : rules) {
if ("disallow".equals(r.action())) if ("disallow".equals(r.action()))
return false; return false;
else if ("allow".equals(r.action())) else if ("allow".equals(r.action()))
flag = true; flag = true;
}
return flag; return flag;
} else }
return true; return true;
} }
private String formatArch(String nati) { private String formatArch(String nati) {
@@ -89,15 +91,25 @@ public class MinecraftLibrary extends IMinecraftLibrary {
public String formatName() { public String formatName() {
String[] s = name.split(":"); String[] s = name.split(":");
if (s.length < 3) {
return null;
}
StringBuilder sb = new StringBuilder(s[0].replace('.', '/')).append('/').append(s[1]).append('/').append(s[2]).append('/').append(s[1]).append('-').append(s[2]); StringBuilder sb = new StringBuilder(s[0].replace('.', '/')).append('/').append(s[1]).append('/').append(s[2]).append('/').append(s[1]).append('-').append(s[2]);
if (natives != null) if (natives != null) {
sb.append('-').append(getNative()); sb.append('-').append(getNative());
}
return sb.append(".jar").toString(); return sb.append(".jar").toString();
} }
@Override @Override
public File getFilePath(File gameDir) { public File getFilePath(File gameDir) {
return new File(gameDir, "libraries/" + getDownloadInfo().path); LibraryDownloadInfo info = getDownloadInfo();
if (info == null) {
return null;
}
return new File(gameDir, "libraries/" + info.path);
} }
@Override @Override
@@ -106,22 +118,34 @@ public class MinecraftLibrary extends IMinecraftLibrary {
} }
public LibraryDownloadInfo getDownloadInfo() { public LibraryDownloadInfo getDownloadInfo() {
if (downloads == null) if (downloads == null) {
downloads = new LibrariesDownloadInfo(); downloads = new LibrariesDownloadInfo();
LibraryDownloadInfo info; }
LibraryDownloadInfo info = null;
if (natives != null) { if (natives != null) {
if (downloads.classifiers == null) if (downloads.classifiers == null) {
downloads.classifiers = new HashMap<>(); downloads.classifiers = new HashMap<>();
if (!downloads.classifiers.containsKey(getNative())) } else {
downloads.classifiers.put(getNative(), info = new LibraryDownloadInfo()); if (!downloads.classifiers.containsKey(getNative())) {
else downloads.classifiers.put(getNative(), info = new LibraryDownloadInfo());
info = downloads.classifiers.get(getNative()); } else {
} else if (downloads.artifact == null) info = downloads.classifiers.get(getNative());
}
}
} else if (downloads.artifact == null) {
downloads.artifact = info = new LibraryDownloadInfo(); downloads.artifact = info = new LibraryDownloadInfo();
else } else {
info = downloads.artifact; info = downloads.artifact;
if (StrUtils.isBlank(info.path)) }
if (StrUtils.isBlank(info.path)) {
info.path = formatName(); info.path = formatName();
if (info.path == null) {
return null;
}
}
info.forgeURL = this.url; info.forgeURL = this.url;
return info; return info;
} }
@@ -17,6 +17,7 @@
*/ */
package org.jackhuang.hellominecraft.launcher.core.version; package org.jackhuang.hellominecraft.launcher.core.version;
import com.google.gson.annotations.SerializedName;
import java.io.File; import java.io.File;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
@@ -37,14 +38,37 @@ import org.jackhuang.hellominecraft.util.Utils;
*/ */
public class MinecraftVersion implements Cloneable, Comparable<MinecraftVersion> { public class MinecraftVersion implements Cloneable, Comparable<MinecraftVersion> {
public String minecraftArguments, mainClass, time, id, type, processArguments, @SerializedName("minecraftArguments")
releaseTime, jar, inheritsFrom, runDir; public String minecraftArguments;
@SerializedName("mainClass")
public String mainClass;
@SerializedName("time")
public String time;
@SerializedName("id")
public String id;
@SerializedName("type")
public String type;
@SerializedName("processArguments")
public String processArguments;
@SerializedName("releaseTime")
public String releaseTime;
@SerializedName("jar")
public String jar;
@SerializedName("inheritsFrom")
public String inheritsFrom;
@SerializedName("runDir")
public String runDir;
@SerializedName("assets")
protected String assets; protected String assets;
@SerializedName("minimumLauncherVersion")
public int minimumLauncherVersion; public int minimumLauncherVersion;
@SerializedName("hidden")
public boolean hidden; public boolean hidden;
@SerializedName("assetIndex")
public AssetIndexDownloadInfo assetIndex; public AssetIndexDownloadInfo assetIndex;
@SerializedName("downloads")
private Map<String, GameDownloadInfo> downloads; private Map<String, GameDownloadInfo> downloads;
@SerializedName("libraries")
public ArrayList<MinecraftLibrary> libraries; public ArrayList<MinecraftLibrary> libraries;
public MinecraftVersion() { public MinecraftVersion() {
@@ -111,7 +111,7 @@ public class MinecraftVersionManager extends IMinecraftProvider {
} }
MinecraftVersion mcVersion; MinecraftVersion mcVersion;
try { try {
mcVersion = C.GSON.fromJson(FileUtils.readFileToString(jsonFile), MinecraftVersion.class); mcVersion = C.GSON.fromJson(FileUtils.read(jsonFile), MinecraftVersion.class);
if (mcVersion == null) if (mcVersion == null)
throw new GameException("Wrong json format, got null."); throw new GameException("Wrong json format, got null.");
} catch (Exception e) { } catch (Exception e) {
@@ -119,7 +119,7 @@ public class MinecraftVersionManager extends IMinecraftProvider {
if (MessageBox.Show(C.i18n("launcher.versions_json_not_formatted", id), MessageBox.YES_NO_OPTION) == MessageBox.YES_OPTION) { if (MessageBox.Show(C.i18n("launcher.versions_json_not_formatted", id), MessageBox.YES_NO_OPTION) == MessageBox.YES_OPTION) {
service.download().downloadMinecraftVersionJson(id); service.download().downloadMinecraftVersionJson(id);
try { try {
mcVersion = C.GSON.fromJson(FileUtils.readFileToString(jsonFile), MinecraftVersion.class); mcVersion = C.GSON.fromJson(FileUtils.read(jsonFile), MinecraftVersion.class);
if (mcVersion == null) if (mcVersion == null)
throw new GameException("Wrong json format, got null."); throw new GameException("Wrong json format, got null.");
} catch (IOException | GameException | JsonSyntaxException ex) { } catch (IOException | GameException | JsonSyntaxException ex) {
@@ -164,7 +164,7 @@ public class MinecraftVersionManager extends IMinecraftProvider {
public boolean renameVersion(String from, String to) { public boolean renameVersion(String from, String to) {
try { try {
File fromJson = new File(versionRoot(from), from + ".json"); File fromJson = new File(versionRoot(from), from + ".json");
MinecraftVersion mcVersion = C.GSON.fromJson(FileUtils.readFileToString(fromJson), MinecraftVersion.class); MinecraftVersion mcVersion = C.GSON.fromJson(FileUtils.read(fromJson), MinecraftVersion.class);
mcVersion.id = to; mcVersion.id = to;
FileUtils.writeQuietly(fromJson, C.GSON.toJson(mcVersion)); FileUtils.writeQuietly(fromJson, C.GSON.toJson(mcVersion));
File toDir = versionRoot(to); File toDir = versionRoot(to);
@@ -198,7 +198,7 @@ public class MinecraftVersionManager extends IMinecraftProvider {
return false; return false;
if (callback != null) { if (callback != null) {
File mvt = new File(versionRoot(id), id + ".json"); File mvt = new File(versionRoot(id), id + ".json");
MinecraftVersion v = C.GSON.fromJson(FileUtils.readFileToStringQuietly(mvt), MinecraftVersion.class); MinecraftVersion v = C.GSON.fromJson(FileUtils.readQuietly(mvt), MinecraftVersion.class);
if (v == null) if (v == null)
return false; return false;
callback.accept(v); callback.accept(v);
@@ -254,13 +254,8 @@ public class MinecraftVersionManager extends IMinecraftProvider {
} }
@Override @Override
public File getResourcePacks() { public boolean onLaunch(String id) {
return new File(service.baseDirectory(), "resourcepacks"); File resourcePacks = new File(getRunDirectory(id), "resourcepacks");
}
@Override
public boolean onLaunch() {
File resourcePacks = getResourcePacks();
if (!resourcePacks.exists() && !resourcePacks.mkdirs()) if (!resourcePacks.exists() && !resourcePacks.mkdirs())
HMCLog.warn("Failed to make resourcePacks: " + resourcePacks); HMCLog.warn("Failed to make resourcePacks: " + resourcePacks);
return true; return true;
@@ -17,13 +17,20 @@
*/ */
package org.jackhuang.hellominecraft.launcher.core.version; package org.jackhuang.hellominecraft.launcher.core.version;
import com.google.gson.annotations.SerializedName;
/** /**
* *
* @author huangyuhui * @author huangyuhui
*/ */
public class Natives implements Cloneable { public class Natives implements Cloneable {
public String windows, osx, linux; @SerializedName("windows")
public String windows;
@SerializedName("osx")
public String osx;
@SerializedName("linux")
public String linux;
@Override @Override
@SuppressWarnings("CloneDeclaresCloneNotSupported") @SuppressWarnings("CloneDeclaresCloneNotSupported")
Loaded 100 of 339 files, more files were not shown because too many files have changed in this diff. Show more