Compare commits

...
150 Commits
Author SHA1 Message Date
南宫临风 5d2b4d435f Modify download type 2016-07-11 16:59:06 +08:00
南宫临风 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
huangyuhui e7d0624b96 Added default profile: Home whose default game directory is $USER/.minecraft 2016-03-11 23:05:31 +08:00
huangyuhui 156de2457d Fixed wrong path in modpack zip on Linux/Mac 2016-03-11 20:13:10 +08:00
huangyuhui c839d045cc Might fix some problems 2016-03-09 13:14:53 +08:00
huangyuhui 2eaf32b23d Fixed BMCLAPI 2016-03-06 14:45:42 +08:00
huangyuhui 5899c73ab8 Should fixed #46 2016-03-05 21:43:54 +08:00
huangyuhui 6c0a446692 Fixed: Cannot cancel modpack installing 2016-03-05 14:31:32 +08:00
huangyuhui 7c2cfc171e Switch to CountDownLatch 2016-03-05 13:23:16 +08:00
huangyuhui 5d4a3c1df6 Fixed null when invoking some server commands 2016-03-04 20:18:25 +08:00
huangyuhui 587df1f5bb Fixed #45 2016-03-04 19:30:58 +08:00
huangyuhui 019fcf314b Added wrapper launcher 2016-03-04 14:06:11 +08:00
huangyuhui 1818b3575c Fixed infinite-recursion 2016-03-04 12:59:37 +08:00
huangyuhui afde41135a Fixed #42 2016-03-03 20:26:04 +08:00
huangyuhui 5dc812072f Fixed NullPointerException when only hidden version here 2016-03-01 12:40:25 +08:00
huangyuhui 3ba75d2de3 Fixed #39 2016-03-01 12:37:12 +08:00
huangyuhui dfc6e91321 Adds some suggested files to remove 2016-02-28 14:47:31 +08:00
huangyuhui a5504a4b74 Added font anti-aliasing 2016-02-28 13:49:22 +08:00
huangyuhui d10a7fad20 Fixed #38 2016-02-28 13:43:03 +08:00
huangyuhui f811d4c89f Adds some localization items 2016-02-27 17:08:29 +08:00
huangyuhui dcaa6241ec Testtest 2016-02-27 14:14:23 +08:00
huangyuhui 9527783cdb Fixed #31 2016-02-26 23:59:36 +08:00
huangyuhui db2b0cb159 Fixed #36 2016-02-26 23:42:45 +08:00
huangyuhui 09dbade477 Update README.md 2016-02-26 13:40:41 +08:00
huangyuhui 0817b9aebb Update README.md 2016-02-26 13:22:26 +08:00
huangyuhui e3c923e268 Update README.md 2016-02-25 23:16:28 +08:00
huangyuhui 761e671ecf Update .travis.yml 2016-02-25 23:02:23 +08:00
huangyuhui fe019b8f0f Supported new version json 2016-02-25 22:44:32 +08:00
huangyuhui 55af958792 ci test 2016-02-25 13:43:18 +08:00
huangyuhui da1bdb1322 Oops, invalid yml? 2016-02-25 13:27:07 +08:00
huangyuhui 892d8fe09c Try to fix RejectedExecutionException on OSX 2016-02-25 13:24:23 +08:00
huangyuhui 89fcf4526c Test travis ci again 2016-02-25 13:14:42 +08:00
huangyuhui 5d037b5f0e Test travis ci 2016-02-25 12:46:29 +08:00
huangyuhui 1bb7f8ac60 Might fix #34 2016-02-24 14:10:15 +08:00
huangyuhui 52f761095a Fixed button animation & performance problem 2016-02-23 22:09:17 +08:00
huangyuhui 770ec3ab97 Fixed #33 2016-02-23 20:32:24 +08:00
huangyuhui 7c3159fc23 Dont know update what? 2016-02-22 18:30:58 +08:00
huangyuhui d5924fa6ab May fix missing hmclversion.cfg 2016-02-19 11:14:41 +08:00
huangyuhui 295f44b947 forgot to copy assetIndex, downloads in MinecraftVersion 2016-02-19 11:08:25 +08:00
huangyuhui 115bc85c58 Fix switching download source problem 2016-02-19 10:24:58 +08:00
huangyuhui 6aaad71126 Thanks to gonglinyuan again 2016-02-19 10:16:11 +08:00
huangyuhui 24b4004fd9 Add gradle files 2016-02-18 20:52:16 +08:00
huangyuhui dd0cdb5c83 Fixed #26 2016-02-18 20:00:03 +08:00
huanghongxun 48f14e193a Merge pull request #28 from gonglinyuan/master
Fixed the name rule of a mod pack.
2016-02-18 17:50:20 +08:00
gonglinyuan 7076272768 Fixed the name rule of a mod pack. 2016-02-18 15:11:25 +08:00
huangyuhui bef6a2d61b Fix 2016-02-18 14:32:27 +08:00
huangyuhui 84c6723adc Switch to use oschina instead of minecraftforge maven 2016-02-18 14:28:02 +08:00
huangyuhui 61a179ba67 Thanks to gonglinyuan 2016-02-18 14:24:00 +08:00
huangyuhui afecb87c6d Might fix game log watcher? 2016-02-16 18:57:26 +08:00
huangyuhui cb125b83cb Fixed wrong path in modpack selection ui 2016-02-15 20:37:45 +08:00
huangyuhui cb337fc22f Added markdown support 2016-02-15 19:39:13 +08:00
huangyuhui 781c7369fb Fixed hidden version selection 2016-02-15 13:26:30 +08:00
huangyuhui 5281fc6a69 Fixed stackoverflow 2016-02-14 19:38:05 +08:00
huangyuhui 814d137084 Added game files descriptions in modpack file selection ui 2016-02-14 13:03:22 +08:00
huangyuhui a567ab1984 Fixed #25 2016-02-13 18:04:44 +08:00
huangyuhui 69eaa04ff6 Fixed lots of bugs 2016-02-13 18:02:25 +08:00
huangyuhui d0c8a95f57 Fixed #24 2016-02-12 15:19:06 +08:00
huangyuhui d09607766b Fixed username missing 2016-02-12 13:03:19 +08:00
huangyuhui 8f90d56e0f change version 2016-02-12 11:35:05 +08:00
huangyuhui d20d06ace7 Fixed a lot of bugs 2016-02-12 11:30:02 +08:00
huangyuhui 98282fd319 Fixed #23 2016-02-10 23:08:58 +08:00
huangyuhui 8e8584656e Fix issue #22 2016-02-10 18:15:28 +08:00
huangyuhui 2f97cd8104 try to fix mis-loading library problem 2016-02-10 17:28:33 +08:00
huangyuhui 8b1ff94c5f Added 'remove library files' 2016-02-10 16:36:02 +08:00
huangyuhui c67e7c0d3a fixed issue #20 2016-02-10 14:58:03 +08:00
huangyuhui 21dcb477dc for darkyoooooo's advice 2016-02-09 22:28:36 +08:00
huangyuhui cb5391ed28 Fix mis-encoding in Windows 2016-02-08 12:06:39 +08:00
huangyuhui fdc2570945 Now supports modpack description! 2016-02-07 14:39:47 +08:00
huangyuhui c60b04caf6 accident 2016-02-06 23:48:07 +08:00
huangyuhui fc0c99b436 The version will automatically use the BUILD_NUMBER now! 2016-02-06 23:44:49 +08:00
huangyuhui 0e4c38d99e Supported 16w05a version json 2016-02-06 12:56:16 +08:00
huangyuhui b0845c700f Fix problems with launching 2016-02-06 00:02:35 +08:00
huangyuhui 27a013450e Might fix some bugs? 2016-02-05 17:03:25 +08:00
huangyuhui d4dccd1391 used findbugs 2016-02-05 13:10:22 +08:00
huangyuhui cd972f5945 moved some buttons! 2016-02-05 11:30:42 +08:00
huangyuhui ed876fa607 Fix Issue #18 2016-02-04 10:04:43 +08:00
huangyuhui 06d15b045e Auto-refresh versions after installing 2016-02-02 19:39:20 +08:00
huangyuhui 0821b67019 Fix snapshot version wrong gathering 2016-02-02 19:12:05 +08:00
huangyuhui 0f18e7c1a1 supported lang files 2016-02-01 15:21:38 +08:00
huangyuhui ac7f025952 Added options for localization 2016-02-01 15:11:03 +08:00
huangyuhui 05382a0354 fix crash 2016-01-30 17:54:01 +08:00
huangyuhui 55b200dec4 modify license header 2016-01-30 14:43:13 +08:00
huangyuhui 587abda389 rename packages 2 2016-01-30 10:48:22 +08:00
huangyuhui da0cc62f16 rename packages 2016-01-30 10:41:41 +08:00
huangyuhui 80e60d2753 change version to 2.3.5.9 2016-01-29 22:25:14 +08:00
huangyuhui ff0750f1f7 To make death, I removed xz processor 2016-01-29 22:23:50 +08:00
huangyuhui f8eec1b7d5 Each version has its own settings 2016-01-29 22:21:13 +08:00
huangyuhui d2162f31e4 Clean tukaani.xz 2016-01-26 20:54:52 +08:00
huangyuhui fee3e5251d Try to fix warnings by NetBeans 2016-01-26 20:17:05 +08:00
huangyuhui 409fc83819 To make death I removed RxJava 2016-01-26 19:50:26 +08:00
huangyuhui 54e14a25da choosing files for modpack 2016-01-24 19:54:02 +08:00
624 changed files with 13683 additions and 42416 deletions

No files matched your search

Executable → Regular
+4
View File
@@ -25,3 +25,7 @@ HMCL/build/
HMCLServer/
HMCSM/build/
MetroLookAndFeel/build/
/HMCUtils/build/
/HMCLaF/build/
HMCL/version.properties
.idea/
+10 -1
View File
@@ -14,6 +14,15 @@
<task-args/>
<task-jvm-args/>
</task>
<task>
<display-name>createApp</display-name>
<non-blocking>no</non-blocking>
<task-names>
<name must-exist="yes">createApp</name>
</task-names>
<task-args/>
<task-jvm-args/>
</task>
</common-tasks>
<script-platform>
<spec-name>j2se</spec-name>
@@ -22,6 +31,6 @@
<license-header>
<name>GNU General Public License</name>
<template>license-header.txt</template>
<property name="organization">huangyuhui</property>
<property name="organization">HMCLSoft</property>
</license-header>
</gradle-project-properties>
+32
View File
@@ -0,0 +1,32 @@
language: java
jdk:
- oraclejdk8
branches:
only:
- master
before_deploy:
- git config --global user.email ${GITHUB_EMAIL}
- git config --global user.name ${GITHUB_NAME}
- git tag ${TRAVIS_BUILD_NUMBER}
- git push -q ${REPO} --tags
deploy:
provider: releases
api_key: ${DEPLOY_REPO}
file:
- 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}-MacOSApp.zip
- 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}-MacOSApp.zip
on:
tags: false
skip_cleanup: true
install: echo "skip 'gradle assemble' step"
script: gradle build --continue
before_cache:
- rm -f $HOME/.gradle/caches/modules-2/modules-2.lock
cache:
directories:
- "$HOME/.gradle/caches/"
- "$HOME/.gradle/wrapper/"
Binary file not shown.

After

Width:  |  Height:  |  Size: 383 KiB

+130 -29
View File
@@ -15,28 +15,6 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see {http://www.gnu.org/licenses/}.
*/
import java.util.jar.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("BUILD_NUMBER") == null ? ".7" : "."+System.getenv("BUILD_NUMBER")
String mavenGroupId = 'HMCL'
String mavenVersion = '2.3.5' + buildnumber
String bundleName = "Hello Minecraft! Launcher"
group = mavenGroupId
version = mavenVersion
String mavenArtifactId = name
buildscript {
repositories {
mavenCentral();
@@ -49,10 +27,131 @@ buildscript {
classpath 'net.sf.proguard:proguard-gradle:4.10'
classpath 'edu.sc.seis.gradle:launch4j:1.0.6'
classpath 'me.tatarka:gradle-retrolambda:3.1.0'
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) {
pom.project {
groupId = mavenGroupId
@@ -62,8 +161,9 @@ configure(install.repositories.mavenInstaller) {
}
dependencies {
compile project(":MetroLookAndFeel")
compile project(":HMCLAPI")
compile project(":HMCLaF")
compile project(":HMCUtils")
compile group: "org.commonjava.googlecode.markdown4j", name: "markdown4j", version: "2.2-cj-1.0"
}
retrolambda {
@@ -74,22 +174,20 @@ jar {
from { configurations.compile.collect { it.isDirectory() ? it : zipTree(it) } }
manifest {
attributes 'Created-By' : 'Copyright(c) 2013-2016 huangyuhui.',
attributes 'Created-By' : 'Copyright(c) 2013-2016 HMCLSoft.',
'Main-Class' : mainClass
}
}
launch4j {
launch4jCmd = 'D:\\Develop\\Java\\Launch4j\\launch4j.exe'
//launch4jCmd = '/home/huangyuhui/softwares/launch4j/launch4j'
supportUrl = 'http://www.mcbbs.net/thread-142335-1-1.html'
supportUrl = 'http://www.hmclsoft.com'
jreMinVersion = '1.6.0'
mainClassName = mainClass
icon = new File(project.buildDir, '../icon.ico').absolutePath
version = mavenVersion
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
outfile = mavenGroupId + '-' + mavenVersion + '.exe'
@@ -102,4 +200,7 @@ processResources {
}
}
build.dependsOn cleanVersionFile
build.dependsOn makeExecutable
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
Executable
BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 46 KiB

@@ -17,12 +17,13 @@
*/
package org.jackhuang.hellominecraft.launcher.api;
import org.jackhuang.hellominecraft.launcher.core.GameException;
import org.jackhuang.hellominecraft.launcher.core.service.IMinecraftService;
import org.jackhuang.hellominecraft.launcher.settings.Profile;
import org.jackhuang.hellominecraft.launcher.core.auth.AuthenticationException;
import org.jackhuang.hellominecraft.launcher.core.auth.IAuthenticator;
import org.jackhuang.hellominecraft.launcher.core.auth.UserProfileProvider;
import org.jackhuang.hellominecraft.utils.functions.Consumer;
import org.jackhuang.hellominecraft.launcher.core.launch.LaunchOptions;
import org.jackhuang.hellominecraft.util.func.Consumer;
/**
*
@@ -33,12 +34,12 @@ public interface IPlugin {
/**
* 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
* MultiMC
*/
IMinecraftService provideMinecraftService(Profile profile);
IMinecraftService provideMinecraftService(Object obj);
/**
* Register authenticators by calling IAuthenticator.LOGINS.add.
@@ -59,5 +60,5 @@ public interface IPlugin {
*/
void onProcessingLoginResult(UserProfileProvider result) throws AuthenticationException;
void onInitializingProfile(Profile p);
void onProcessingLaunchOptions(LaunchOptions p) throws GameException;
}
@@ -17,8 +17,7 @@
*/
package org.jackhuang.hellominecraft.launcher.api;
import org.jackhuang.hellominecraft.utils.logging.HMCLog;
import org.jackhuang.hellominecraft.launcher.settings.DefaultPlugin;
import org.jackhuang.hellominecraft.util.logging.HMCLog;
/**
*
@@ -26,18 +25,26 @@ import org.jackhuang.hellominecraft.launcher.settings.DefaultPlugin;
*/
public class PluginManager {
public static IPlugin NOW_PLUGIN = new DefaultPlugin();
private static IPlugin NOW_PLUGIN;
public static void getServerPlugin() {
try {
ClassLoader cl = Thread.currentThread().getContextClassLoader();
Class c = cl.loadClass("org.jackhuang.hellominecraft.launcher.servers.ServerPlugin");
IPlugin p = (IPlugin) c.newInstance();
NOW_PLUGIN = p;
getPlugin(Thread.currentThread().getContextClassLoader().loadClass("org.jackhuang.hellominecraft.launcher.server.ServerPlugin"));
} catch (ClassNotFoundException ignore) {
} catch (Exception e) {
HMCLog.err("Failed to new instance");
}
}
public static void getPlugin(Class<?> cls) {
try {
IPlugin p = (IPlugin) cls.newInstance();
NOW_PLUGIN = p;
} catch (Exception e) {
HMCLog.err("Failed to new instance");
}
}
public static IPlugin plugin() {
return NOW_PLUGIN;
}
}
@@ -19,9 +19,8 @@ package org.jackhuang.hellominecraft.launcher.core;
import java.io.File;
import java.io.IOException;
import org.jackhuang.hellominecraft.utils.system.FileUtils;
import org.jackhuang.hellominecraft.utils.system.IOUtils;
import org.jackhuang.hellominecraft.utils.system.OS;
import org.jackhuang.hellominecraft.util.system.FileUtils;
import org.jackhuang.hellominecraft.util.system.OS;
/**
*
@@ -56,11 +55,6 @@ public final class MCUtils {
return getWorkingDirectory("minecraft");
}
public static boolean is16Folder(String path) {
path = IOUtils.addSeparator(path);
return new File(path, "versions").exists();
}
public static String minecraft() {
if (OS.os() == OS.OSX)
return "minecraft";
@@ -68,23 +62,20 @@ public final class MCUtils {
}
public static File getInitGameDir() {
File gameDir = IOUtils.currentDir();
if (gameDir.exists()) {
gameDir = new File(gameDir, MCUtils.minecraft());
if (!gameDir.exists()) {
File newFile = MCUtils.getLocation();
if (newFile.exists())
gameDir = newFile;
}
File gameDir = new File(MCUtils.minecraft());
if (!gameDir.exists()) {
File newFile = MCUtils.getLocation();
if (newFile.exists())
gameDir = newFile;
}
return gameDir;
}
public static String profile = "{\"selectedProfile\": \"(Default)\",\"profiles\": {\"(Default)\": {\"name\": \"(Default)\"}},\"clientToken\": \"88888888-8888-8888-8888-888888888888\"}";
public static final String PROFILE = "{\"selectedProfile\": \"(Default)\",\"profiles\": {\"(Default)\": {\"name\": \"(Default)\"}},\"clientToken\": \"88888888-8888-8888-8888-888888888888\"}";
public static void tryWriteProfile(File gameDir) throws IOException {
File file = new File(gameDir, "launcher_profiles.json");
if (!file.exists())
FileUtils.writeStringToFile(file, profile);
FileUtils.write(file, PROFILE);
}
}
@@ -15,8 +15,9 @@
* 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.assets;
package org.jackhuang.hellominecraft.launcher.core.asset;
import com.google.gson.annotations.SerializedName;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.Map;
@@ -29,8 +30,12 @@ import java.util.Set;
public class AssetsIndex {
public static final String DEFAULT_ASSET_NAME = "legacy";
private Map<String, AssetsObject> objects;
private boolean virtual;
@SerializedName("objects")
public Map<String, AssetsObject> objects;
@SerializedName("virtual")
public boolean virtual;
public AssetsIndex() {
this.objects = new LinkedHashMap();
@@ -0,0 +1,111 @@
/*
* 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.asset;
import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashSet;
import java.util.Map;
import org.jackhuang.hellominecraft.util.C;
import org.jackhuang.hellominecraft.util.logging.HMCLog;
import org.jackhuang.hellominecraft.launcher.core.service.IMinecraftAssetService;
import org.jackhuang.hellominecraft.util.tasks.Task;
import org.jackhuang.hellominecraft.util.system.FileUtils;
import org.jackhuang.hellominecraft.util.system.IOUtils;
import org.jackhuang.hellominecraft.util.StrUtils;
import org.jackhuang.hellominecraft.launcher.core.download.IDownloadProvider;
import org.jackhuang.hellominecraft.launcher.core.version.MinecraftVersion;
import org.jackhuang.hellominecraft.util.Utils;
import org.jackhuang.hellominecraft.util.VersionNumber;
import org.jackhuang.hellominecraft.util.tasks.TaskInfo;
/**
*
* @author huangyuhui
*/
public class AssetsMojangLoader extends IAssetsHandler {
public AssetsMojangLoader(String name) {
super(name);
}
@Override
public Task getList(final MinecraftVersion mv, final IMinecraftAssetService mp) {
Utils.requireNonNull(mv);
String assetsId = mv.getAssetsIndex().getId();
File assets = mp.getAssets();
HMCLog.log("Gathering asset index: " + assetsId);
File f = IOUtils.tryGetCanonicalFile(new File(assets, "indexes/" + assetsId + ".json"));
return new TaskInfo("Gather asset index") {
@Override
public Collection<Task> getDependTasks() {
if (!f.exists())
return Arrays.asList(mp.downloadMinecraftAssetsIndex(mv.getAssetsIndex()));
else
return null;
}
@Override
public void executeTask() throws Throwable {
if (!areDependTasksSucceeded)
throw new IllegalStateException("Failed to get asset index");
String result = FileUtils.read(f);
if (StrUtils.isBlank(result))
throw new IllegalStateException("Index json is empty, please redownload it!");
AssetsIndex o = C.GSON.fromJson(result, AssetsIndex.class);
assetsDownloadURLs = new ArrayList<>();
assetsLocalNames = new ArrayList<>();
ArrayList<String> al = new ArrayList<>();
contents = new ArrayList<>();
HashSet<String> loadedHashes = new HashSet<>();
int pgs = 0;
if (o != null && o.getFileMap() != null)
for (Map.Entry<String, AssetsObject> e : o.getFileMap().entrySet()) {
if (loadedHashes.contains(e.getValue().getHash()))
continue;
loadedHashes.add(e.getValue().getHash());
Contents c = new Contents();
c.eTag = e.getValue().getHash();
c.key = c.eTag.substring(0, 2) + "/" + e.getValue().getHash();
c.size = e.getValue().getSize();
contents.add(c);
assetsDownloadURLs.add(c.key);
assetsLocalNames.add(new File(assets, "objects" + File.separator + c.key.replace("/", File.separator)));
al.add(e.getKey());
if (ppl != null)
ppl.setProgress(this, ++pgs, o.getFileMap().size());
}
}
};
}
@Override
public Task getDownloadTask(IDownloadProvider sourceType) {
return new AssetsTask(sourceType.getAssetsDownloadURL(), sourceType.getRetryAssetsDownloadURL());
}
@Override
public boolean isVersionAllowed(String formattedVersion) {
VersionNumber ur = VersionNumber.check(formattedVersion);
if (ur == null)
return false;
return VersionNumber.check("1.6.0").compareTo(ur) <= 0;
}
}
@@ -15,7 +15,7 @@
* 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.assets;
package org.jackhuang.hellominecraft.launcher.core.asset;
/**
*
@@ -26,6 +26,19 @@ public class AssetsObject {
private String hash;
private long size;
public AssetsObject(String hash, long size) {
this.hash = hash;
this.size = size;
}
public void setHash(String hash) {
this.hash = hash;
}
public void setSize(long size) {
this.size = size;
}
public AssetsObject() {
}
@@ -0,0 +1,81 @@
/*
* 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.asset;
/**
*
* @author huangyuhui
*/
public class Contents {
public String key, eTag, lastModified, storageClass;
public Contents() {
}
public Contents(String key, String eTag, String lastModified, String storageClass, long size) {
this();
this.key = key;
this.eTag = eTag;
this.lastModified = lastModified;
this.storageClass = storageClass;
this.size = size;
}
public String getKey() {
return key;
}
public void setKey(String key) {
this.key = key;
}
public String geteTag() {
return eTag;
}
public void seteTag(String eTag) {
this.eTag = eTag;
}
public String getLastModified() {
return lastModified;
}
public void setLastModified(String lastModified) {
this.lastModified = lastModified;
}
public String getStorageClass() {
return storageClass;
}
public void setStorageClass(String storageClass) {
this.storageClass = storageClass;
}
public long getSize() {
return size;
}
public void setSize(long size) {
this.size = size;
}
public long size;
}
@@ -15,7 +15,7 @@
* 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.assets;
package org.jackhuang.hellominecraft.launcher.core.asset;
import java.io.File;
import java.io.FileInputStream;
@@ -23,17 +23,20 @@ import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import org.jackhuang.hellominecraft.utils.C;
import org.jackhuang.hellominecraft.utils.logging.HMCLog;
import org.jackhuang.hellominecraft.util.C;
import org.jackhuang.hellominecraft.util.logging.HMCLog;
import org.jackhuang.hellominecraft.launcher.core.service.IMinecraftAssetService;
import org.jackhuang.hellominecraft.launcher.core.download.IDownloadProvider;
import org.jackhuang.hellominecraft.launcher.core.version.MinecraftVersion;
import org.jackhuang.hellominecraft.utils.tasks.Task;
import org.jackhuang.hellominecraft.utils.tasks.download.FileDownloadTask;
import org.jackhuang.hellominecraft.utils.code.DigestUtils;
import org.jackhuang.hellominecraft.utils.system.IOUtils;
import org.jackhuang.hellominecraft.utils.NetUtils;
import rx.Observable;
import org.jackhuang.hellominecraft.util.tasks.Task;
import org.jackhuang.hellominecraft.util.tasks.download.FileDownloadTask;
import org.jackhuang.hellominecraft.util.code.DigestUtils;
import org.jackhuang.hellominecraft.util.system.IOUtils;
import org.jackhuang.hellominecraft.util.NetUtils;
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;
/**
* Assets
@@ -73,7 +76,7 @@ public abstract class IAssetsHandler {
* @param mp Asset Service
* @param x finished event
*/
public abstract Observable<String[]> getList(MinecraftVersion mv, IMinecraftAssetService mp);
public abstract Task getList(MinecraftVersion mv, IMinecraftAssetService mp);
/**
* Will be invoked when the user invoked "Download all assets".
@@ -86,61 +89,80 @@ public abstract class IAssetsHandler {
public abstract boolean isVersionAllowed(String formattedVersion);
protected class AssetsTask extends Task {
protected class AssetsTask extends TaskInfo {
ArrayList<Task> al;
String u;
ArrayList<Task> tasks;
String baseUrl;
String retryBaseUrl;
public AssetsTask(String url) {
this.u = url;
public AssetsTask(String url, String retryUrl) {
super(C.i18n("assets.download"));
this.baseUrl = url;
this.retryBaseUrl = retryUrl;
}
@Override
public void executeTask() {
if (assetsDownloadURLs == null)
if (assetsDownloadURLs == null || assetsLocalNames == null || contents == null)
throw new IllegalStateException(C.i18n("assets.not_refreshed"));
tasks = new ArrayList<>();
int max = assetsDownloadURLs.size();
al = new ArrayList<>();
int hasDownloaded = 0;
for (int i = 0; i < max; 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);
if (!location.getParentFile().exists())
location.getParentFile().mkdirs();
if (!location.getParentFile().exists() && !location.getParentFile().mkdirs())
HMCLog.warn("Failed to make directories: " + location.getParent());
if (location.isDirectory())
continue;
boolean need = true;
boolean needDownload = true;
try {
if (location.exists()) {
FileInputStream fis = new FileInputStream(location);
String sha = DigestUtils.sha1Hex(NetUtils.getBytesFromStream(fis));
IOUtils.closeQuietly(fis);
if (contents.get(i).eTag.equals(sha)) {
hasDownloaded++;
HMCLog.log("File " + assetsLocalNames.get(i) + " has downloaded successfully, skipped downloading.");
if (ppl != null)
if (contents.get(i).geteTag().equals(sha)) {
++hasDownloaded;
HMCLog.log("File " + assetsLocalNames.get(i) + " has been downloaded successfully, skipped downloading.");
if (ppl != null) {
ppl.setProgress(this, hasDownloaded, max);
}
continue;
}
}
} catch (IOException 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
public Collection<Task> getAfterTasks() {
return al;
}
@Override
public String getInfo() {
return C.i18n("assets.download");
return tasks;
}
}
}
@@ -0,0 +1,219 @@
/*
* 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.asset;
import com.google.gson.JsonSyntaxException;
import java.io.File;
import java.io.IOException;
import java.util.Arrays;
import java.util.Collection;
import java.util.Map;
import org.jackhuang.hellominecraft.util.C;
import org.jackhuang.hellominecraft.launcher.core.service.IMinecraftAssetService;
import org.jackhuang.hellominecraft.launcher.core.service.IMinecraftService;
import org.jackhuang.hellominecraft.launcher.core.version.AssetIndexDownloadInfo;
import org.jackhuang.hellominecraft.launcher.core.version.MinecraftVersion;
import org.jackhuang.hellominecraft.util.MessageBox;
import org.jackhuang.hellominecraft.util.func.BiFunction;
import org.jackhuang.hellominecraft.util.logging.HMCLog;
import org.jackhuang.hellominecraft.util.tasks.Task;
import org.jackhuang.hellominecraft.util.tasks.TaskWindow;
import org.jackhuang.hellominecraft.util.tasks.download.FileDownloadTask;
import org.jackhuang.hellominecraft.util.system.FileUtils;
import org.jackhuang.hellominecraft.util.system.IOUtils;
import org.jackhuang.hellominecraft.util.tasks.TaskInfo;
/**
*
* @author huangyuhui
*/
public class MinecraftAssetService extends IMinecraftAssetService {
public MinecraftAssetService(IMinecraftService service) {
super(service);
}
@Override
public Task downloadAssets(final String mcVersion) {
return downloadAssets(service.version().getVersionById(mcVersion));
}
public Task downloadAssets(final MinecraftVersion mv) {
if (mv == null)
return null;
return IAssetsHandler.ASSETS_HANDLER.getList(mv, service.asset())
.after(IAssetsHandler.ASSETS_HANDLER.getDownloadTask(service.getDownloadType().getProvider()));
}
@Override
public boolean refreshAssetsIndex(String id) {
MinecraftVersion mv = service.version().getVersionById(id);
if (mv == null)
return false;
return downloadMinecraftAssetsIndexAsync(mv.getAssetsIndex());
}
@Override
public Task downloadMinecraftAssetsIndex(AssetIndexDownloadInfo assets) {
File assetsLocation = getAssets();
if (!assetsLocation.exists() && !assetsLocation.mkdirs())
HMCLog.warn("Failed to make directories: " + assetsLocation);
File assetsIndex = new File(assetsLocation, "indexes/" + assets.getId() + ".json");
File renamed = null;
if (assetsIndex.exists()) {
renamed = new File(assetsLocation, "indexes/" + assets.getId() + "-renamed.json");
if (assetsIndex.renameTo(renamed))
HMCLog.warn("Failed to rename " + assetsIndex + " to " + renamed);
}
File renamedFinal = renamed;
return new TaskInfo("Download Asset Index") {
@Override
public Collection<Task> getDependTasks() {
return Arrays.asList(new FileDownloadTask(assets.getUrl(service.getDownloadType()), IOUtils.tryGetCanonicalFile(assetsIndex), assets.sha1).setTag(assets.getId() + ".json"));
}
@Override
public void executeTask() throws Throwable {
if (areDependTasksSucceeded) {
if (renamedFinal != null && !renamedFinal.delete())
HMCLog.warn("Failed to delete " + renamedFinal + ", maybe you should do it.");
} else if (renamedFinal != null && !renamedFinal.renameTo(assetsIndex))
HMCLog.warn("Failed to rename " + renamedFinal + " to " + assetsIndex);
}
};
}
@Override
public boolean downloadMinecraftAssetsIndexAsync(AssetIndexDownloadInfo assets) {
File assetsLocation = getAssets();
if (!assetsLocation.exists() && !assetsLocation.mkdirs())
HMCLog.warn("Failed to make directories: " + assetsLocation);
File assetsIndex = new File(assetsLocation, "indexes/" + assets.getId() + ".json");
File renamed = null;
if (assetsIndex.exists()) {
renamed = new File(assetsLocation, "indexes/" + assets.getId() + "-renamed.json");
if (assetsIndex.renameTo(renamed))
HMCLog.warn("Failed to rename " + assetsIndex + " to " + renamed);
}
if (TaskWindow.factory()
.append(new FileDownloadTask(assets.getUrl(service.getDownloadType()), IOUtils.tryGetCanonicalFile(assetsIndex), assets.sha1).setTag(assets.getId() + ".json"))
.create()) {
if (renamed != null && !renamed.delete())
HMCLog.warn("Failed to delete " + renamed + ", maybe you should do it.");
return true;
}
if (renamed != null && !renamed.renameTo(assetsIndex))
HMCLog.warn("Failed to rename " + renamed + " to " + assetsIndex);
return false;
}
@Override
public File getAssets() {
return new File(service.baseDirectory(), "assets");
}
@Override
public File getAssetObject(String assetVersion, String name) throws IOException {
File assetsDir = getAssets();
File indexDir = new File(assetsDir, "indexes");
File objectsDir = new File(assetsDir, "objects");
File indexFile = new File(indexDir, assetVersion + ".json");
try {
AssetsIndex index = (AssetsIndex) C.GSON.fromJson(FileUtils.read(indexFile, "UTF-8"), AssetsIndex.class);
String hash = ((AssetsObject) index.getFileMap().get(name)).getHash();
return new File(objectsDir, hash.substring(0, 2) + "/" + hash);
} catch (JsonSyntaxException e) {
throw new IOException("Assets file format malformed.", e);
}
}
private boolean checkAssetsExistance(AssetIndexDownloadInfo assetIndex) {
File assetsDir = getAssets();
File indexDir = new File(assetsDir, "indexes");
File objectDir = new File(assetsDir, "objects");
File indexFile = new File(indexDir, assetIndex.getId() + ".json");
if (!assetsDir.exists() || !indexFile.isFile())
return false;
try {
String assetIndexContent = FileUtils.read(indexFile, "UTF-8");
AssetsIndex index = (AssetsIndex) C.GSON.fromJson(assetIndexContent, AssetsIndex.class);
if (index == null)
return false;
for (Map.Entry entry : index.getFileMap().entrySet())
if (!new File(new File(objectDir, ((AssetsObject) entry.getValue()).getHash().substring(0, 2)), ((AssetsObject) entry.getValue()).getHash()).exists())
return false;
return true;
} catch (IOException | JsonSyntaxException e) {
return false;
}
}
private File reconstructAssets(AssetIndexDownloadInfo assetIndex) {
File assetsDir = getAssets();
File indexDir = new File(assetsDir, "indexes");
File objectDir = new File(assetsDir, "objects");
String assetVersion = assetIndex.getId();
File indexFile = new File(indexDir, assetVersion + ".json");
File virtualRoot = new File(new File(assetsDir, "virtual"), assetVersion);
if (!indexFile.isFile()) {
HMCLog.warn("No assets index file " + virtualRoot + "; can't reconstruct assets");
return assetsDir;
}
try {
String assetIndexContent = FileUtils.read(indexFile, "UTF-8");
AssetsIndex index = (AssetsIndex) C.GSON.fromJson(assetIndexContent, AssetsIndex.class);
if (index == null)
return assetsDir;
if (index.isVirtual()) {
int cnt = 0;
HMCLog.log("Reconstructing virtual assets folder at " + virtualRoot);
int tot = index.getFileMap().entrySet().size();
for (Map.Entry entry : index.getFileMap().entrySet()) {
File target = new File(virtualRoot, (String) entry.getKey());
File original = new File(new File(objectDir, ((AssetsObject) entry.getValue()).getHash().substring(0, 2)), ((AssetsObject) entry.getValue()).getHash());
if (original.exists()) {
cnt++;
if (!target.isFile())
FileUtils.copyFile(original, target);
}
}
// If the scale new format existent file is lower then 0.1, use the old format.
if (cnt * 10 < tot)
return assetsDir;
}
} catch (IOException | JsonSyntaxException e) {
HMCLog.warn("Failed to create virutal assets.", e);
}
return virtualRoot;
}
public final BiFunction<MinecraftVersion, Boolean, String> ASSET_PROVIDER_IMPL = (t, allow) -> {
if (allow && !checkAssetsExistance(t.getAssetsIndex()))
if (MessageBox.Show(C.i18n("assets.no_assets"), MessageBox.YES_NO_OPTION) == MessageBox.YES_OPTION)
TaskWindow.execute(downloadAssets(t));
return reconstructAssets(t.getAssetsIndex()).getAbsolutePath();
};
}
@@ -21,7 +21,8 @@ import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import org.jackhuang.hellominecraft.utils.code.DigestUtils;
import java.nio.charset.Charset;
import org.jackhuang.hellominecraft.util.code.DigestUtils;
/**
*
@@ -41,7 +42,7 @@ public final class BestLogin extends IAuthenticator {
Socket socket = new Socket("auth.zhh0000zhh.com", 8);
OutputStream os = socket.getOutputStream();
os.write(request.length());
os.write(request.getBytes());
os.write(request.getBytes(Charset.forName("UTF-8")));
UserProfileProvider lr = new UserProfileProvider();
@@ -64,13 +65,17 @@ public final class BestLogin extends IAuthenticator {
throw new AuthenticationException("server reloading.");
case 0:
byte[] b = new byte[64];
is.read(b, 0, b.length);
String[] ss = new String(b).split(":");
int x = is.read(b, 0, b.length);
if (x != -1)
throw new AuthenticationException("server response does not follow the protocol.");
String[] ss = new String(b, Charset.forName("UTF-8")).split(":");
lr.setUserName(info.username);
lr.setUserId(ss[1]);
lr.setSession(ss[0]);
lr.setAccessToken(ss[0]);
break;
default:
break;
}
lr.setUserType("Legacy");
return lr;
@@ -95,7 +100,7 @@ public final class BestLogin extends IAuthenticator {
}
@Override
public void logout() {
public void logOut() {
}
}
@@ -33,15 +33,19 @@ public abstract class IAuthenticator {
public static final List<IAuthenticator> LOGINS = new ArrayList<>();
static {
PluginManager.NOW_PLUGIN.onRegisterAuthenticators(LOGINS::add);
PluginManager.plugin().onRegisterAuthenticators(LOGINS::add);
}
protected String clientToken, username;
protected String clientToken, username, password;
public IAuthenticator(String clientToken) {
this.clientToken = clientToken;
}
public String getClientToken() {
return clientToken;
}
/**
* Login Method
*
@@ -81,10 +85,10 @@ public abstract class IAuthenticator {
public abstract UserProfileProvider loginBySettings() throws AuthenticationException;
public abstract void logout();
public abstract void logOut();
public Map onSaveSettings() {
HashMap m = new HashMap();
HashMap<String, String> m = new HashMap<>();
m.put("IAuthenticator_UserName", username);
return m;
}
@@ -92,14 +96,23 @@ public abstract class IAuthenticator {
public void onLoadSettings(Map m) {
if (m == null)
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() {
return username;
}
public void setUsername(String s) {
public void setUserName(String s) {
username = s;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
@@ -19,9 +19,9 @@ package org.jackhuang.hellominecraft.launcher.core.auth;
import java.util.HashMap;
import java.util.Map;
import org.jackhuang.hellominecraft.utils.C;
import org.jackhuang.hellominecraft.utils.StrUtils;
import org.jackhuang.hellominecraft.utils.code.DigestUtils;
import org.jackhuang.hellominecraft.util.C;
import org.jackhuang.hellominecraft.util.StrUtils;
import org.jackhuang.hellominecraft.util.code.DigestUtils;
/**
*
@@ -48,7 +48,7 @@ public final class OfflineAuthenticator extends IAuthenticator {
@Override
public Map onSaveSettings() {
Map m = super.onSaveSettings();
m.put("uuidMap", m);
m.put("uuidMap", uuidMap);
return m;
}
@@ -98,7 +98,7 @@ public final class OfflineAuthenticator extends IAuthenticator {
}
@Override
public void logout() {
public void logOut() {
}
}
@@ -17,10 +17,11 @@
*/
package org.jackhuang.hellominecraft.launcher.core.auth;
import org.jackhuang.hellominecraft.utils.C;
import org.jackhuang.hellominecraft.utils.code.DigestUtils;
import org.jackhuang.hellominecraft.utils.NetUtils;
import org.jackhuang.hellominecraft.utils.views.Selector;
import org.jackhuang.hellominecraft.util.C;
import org.jackhuang.hellominecraft.util.code.DigestUtils;
import org.jackhuang.hellominecraft.util.NetUtils;
import org.jackhuang.hellominecraft.util.lang.SupportedLocales;
import org.jackhuang.hellominecraft.util.ui.SwingUtils;
/**
*
@@ -47,7 +48,7 @@ public final class SkinmeAuthenticator extends IAuthenticator {
if (info.username == null || !info.username.contains("@"))
throw new AuthenticationException(C.i18n("login.not_email"));
try {
String usr = info.username.toLowerCase();
String usr = info.username.toLowerCase(SupportedLocales.NOW_LOCALE.self);
String pwd = info.password;
String str = DigestUtils.sha1Hex(usr);
@@ -60,15 +61,14 @@ public final class SkinmeAuthenticator extends IAuthenticator {
if (sl[1].contains("No Valid Character"))
sl[1] = C.i18n("login.no_valid_character");
throw new AuthenticationException(sl[1]);
case "1": {
case "1":
String[] s = parseType1(sl[1]);
req.setUserName(s[0]);
req.setSession(s[1]);
req.setUserId(s[1]);
req.setAccessToken(s[1]);
break;
}
case "2": {
case "2":
String[] charators = sl[1].split(";");
int len = charators.length;
String[] $char = new String[len];
@@ -79,12 +79,10 @@ public final class SkinmeAuthenticator extends IAuthenticator {
$char[i] = charator[0];
user[i] = charator[1];
}
Selector s = new Selector(null, user, C.i18n("login.choose_charactor"));
s.setVisible(true);
if (s.sel == Selector.FAILED_TO_SELECT)
int index = SwingUtils.select(user, C.i18n("login.choose_charactor"));
if (index == -1)
throw new AuthenticationException(C.i18n("message.cancelled"));
else {
int index = s.sel;
String character = $char[index];
sl = getCharacter(usr, hashCode, character).split(":");
String[] s2 = parseType1(sl[1]);
@@ -95,7 +93,6 @@ public final class SkinmeAuthenticator extends IAuthenticator {
}
break;
}
}
req.setUserType("Legacy");
return req;
@@ -120,7 +117,7 @@ public final class SkinmeAuthenticator extends IAuthenticator {
}
@Override
public void logout() {
public void logOut() {
}
}
@@ -17,8 +17,6 @@
*/
package org.jackhuang.hellominecraft.launcher.core.auth;
import org.jackhuang.hellominecraft.launcher.core.version.ServerInfo;
/**
*
* @author huangyuhui
@@ -108,13 +106,4 @@ public final class UserProfileProvider {
private String otherInfo = "";
private String clientIdentifier = "";
private String userType = "Offline";
private ServerInfo server = null;
public ServerInfo getServer() {
return server;
}
public void setServer(ServerInfo server) {
this.server = server;
}
}
@@ -21,13 +21,13 @@ import com.google.gson.GsonBuilder;
import java.net.Proxy;
import java.util.Map;
import javax.swing.JOptionPane;
import org.jackhuang.hellominecraft.utils.C;
import org.jackhuang.hellominecraft.utils.ArrayUtils;
import org.jackhuang.hellominecraft.utils.views.Selector;
import org.jackhuang.hellominecraft.util.C;
import org.jackhuang.hellominecraft.util.ArrayUtils;
import org.jackhuang.hellominecraft.launcher.core.auth.yggdrasil.GameProfile;
import org.jackhuang.hellominecraft.launcher.core.auth.yggdrasil.PropertyMap;
import org.jackhuang.hellominecraft.launcher.core.auth.yggdrasil.YggdrasilAuthentication;
import org.jackhuang.hellominecraft.launcher.core.auth.yggdrasil.UUIDTypeAdapter;
import org.jackhuang.hellominecraft.util.ui.SwingUtils;
/**
*
@@ -57,7 +57,7 @@ public final class YggdrasilAuthenticator extends IAuthenticator {
if (!ua.isLoggedIn())
ua.setPassword(pwd);
ua.setUsername(usr);
ua.setUserName(usr);
ua.logIn();
if (!ua.isLoggedIn())
throw new AuthenticationException(C.i18n("login.wrong_password"));
@@ -69,14 +69,17 @@ public final class YggdrasilAuthenticator extends IAuthenticator {
String[] names = new String[profiles.length];
for (int i = 0; i < profiles.length; i++)
names[i] = profiles[i].name;
Selector s = new Selector(null, names, C.i18n("login.choose_charactor"));
s.setVisible(true);
selectedProfile = profiles[s.sel];
username = names[s.sel];
int sel = SwingUtils.select(names, C.i18n("login.choose_charactor"));
if (sel == -1)
throw new AuthenticationException("No selection");
selectedProfile = profiles[sel];
username = names[sel];
} else
username = JOptionPane.showInputDialog(C.i18n("login.no_charactor"));
else
username = selectedProfile.name;
if (username == null)
throw new AuthenticationException("No player");
result.setUserName(username);
result.setUserId(selectedProfile == null ? OfflineAuthenticator.getUUIDFromUserName(username) : UUIDTypeAdapter.fromUUID(selectedProfile.id));
}
@@ -134,7 +137,7 @@ public final class YggdrasilAuthenticator extends IAuthenticator {
}
@Override
public void logout() {
public void logOut() {
ua.logOut();
}
}
@@ -21,9 +21,49 @@ import java.util.HashMap;
public class AuthenticationRequest {
public HashMap<String, Object> agent;
public String username, password, clientToken;
public boolean requestUser = true;
private HashMap<String, Object> agent;
private String username, password, clientToken;
private boolean requestUser = true;
public HashMap<String, Object> getAgent() {
return agent;
}
public void setAgent(HashMap<String, Object> agent) {
this.agent = agent;
}
public String getUserName() {
return username;
}
public void setUserName(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getClientToken() {
return clientToken;
}
public void setClientToken(String clientToken) {
this.clientToken = clientToken;
}
public boolean isRequestUser() {
return requestUser;
}
public void setRequestUser(boolean requestUser) {
this.requestUser = requestUser;
}
public AuthenticationRequest(String username, String password, String clientToken) {
agent = new HashMap<>();
@@ -25,8 +25,9 @@ import com.google.gson.JsonParseException;
import com.google.gson.JsonSerializationContext;
import com.google.gson.JsonSerializer;
import java.lang.reflect.Type;
import java.util.Objects;
import java.util.UUID;
import org.jackhuang.hellominecraft.utils.StrUtils;
import org.jackhuang.hellominecraft.util.StrUtils;
public class GameProfile {
@@ -46,9 +47,16 @@ public class GameProfile {
return id != null && StrUtils.isNotBlank(name);
}
@Override
public int hashCode() {
int hash = 7;
hash = 29 * hash + Objects.hashCode(this.id);
hash = 29 * hash + Objects.hashCode(this.name);
return hash;
}
@Override
public boolean equals(Object o) {
System.out.println("hello?");
if (this == o)
return true;
if (o == null || getClass() != o.getClass())
@@ -65,6 +73,8 @@ public class GameProfile {
@Override
public GameProfile deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
if (!(json instanceof JsonObject))
throw new JsonParseException("The json element is not a JsonObject.");
JsonObject object = (JsonObject) json;
UUID id = object.has("id") ? (UUID) context.deserialize(object.get("id"), UUID.class) : null;
String name = object.has("name") ? object.getAsJsonPrimitive("name").getAsString() : null;
@@ -31,10 +31,12 @@ import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.jackhuang.hellominecraft.utils.logging.HMCLog;
import org.jackhuang.hellominecraft.util.logging.HMCLog;
public class PropertyMap extends HashMap<String, Property> {
private static final long serialVersionUID = 362498820763181265L;
public List<Map<String, String>> list() {
List<Map<String, String>> properties = new ArrayList<>();
for (Property profileProperty : values()) {
@@ -51,6 +53,7 @@ public class PropertyMap extends HashMap<String, Property> {
for (Map<String, String> propertyMap : list) {
String name = propertyMap.get("name");
String value = propertyMap.get("value");
put(name, new Property(name, value));
}
} catch (Throwable t) {
HMCLog.warn("Failed to deserialize properties", t);
@@ -76,6 +79,7 @@ public class PropertyMap extends HashMap<String, Property> {
JsonObject object = (JsonObject) element;
String name = object.getAsJsonPrimitive("name").getAsString();
String value = object.getAsJsonPrimitive("value").getAsString();
result.put(name, new Property(name, value));
}
return result;
@@ -101,10 +105,10 @@ public class PropertyMap extends HashMap<String, Property> {
@Override
public JsonElement serialize(PropertyMap src, Type typeOfSrc, JsonSerializationContext context) {
JsonObject result = new JsonObject();
for (String key : src.keySet()) {
for (PropertyMap.Entry<String, Property> entry : src.entrySet()) {
JsonArray values = new JsonArray();
values.add(new JsonPrimitive(src.get(key).value));
result.add(key, values);
values.add(new JsonPrimitive(entry.getValue().value));
result.add(entry.getKey(), values);
}
return result;
}
@@ -19,13 +19,46 @@ package org.jackhuang.hellominecraft.launcher.core.auth.yggdrasil;
public class RefreshRequest {
public String clientToken;
public String accessToken;
public GameProfile selectedProfile;
public boolean requestUser = true;
private String clientToken;
private String accessToken;
private GameProfile selectedProfile;
private boolean requestUser = true;
public RefreshRequest(String accessToken, String clientToken) {
this.clientToken = clientToken;
this.accessToken = accessToken;
}
public String getClientToken() {
return clientToken;
}
public void setClientToken(String clientToken) {
this.clientToken = clientToken;
}
public String getAccessToken() {
return accessToken;
}
public void setAccessToken(String accessToken) {
this.accessToken = accessToken;
}
public GameProfile getSelectedProfile() {
return selectedProfile;
}
public void setSelectedProfile(GameProfile selectedProfile) {
this.selectedProfile = selectedProfile;
}
public boolean isRequestUser() {
return requestUser;
}
public void setRequestUser(boolean requestUser) {
this.requestUser = requestUser;
}
}
@@ -17,14 +17,24 @@
*/
package org.jackhuang.hellominecraft.launcher.core.auth.yggdrasil;
import com.google.gson.annotations.SerializedName;
public class Response {
public String accessToken, clientToken;
@SerializedName("accessToken")
public String accessToken;
@SerializedName("clientToken")
public String clientToken;
@SerializedName("selectedProfile")
public GameProfile selectedProfile;
@SerializedName("availableProfiles")
public GameProfile[] availableProfiles;
@SerializedName("user")
public User user;
@SerializedName("error")
public String error;
@SerializedName("errorMessage")
public String errorMessage;
@SerializedName("cause")
public String cause;
}
@@ -19,6 +19,31 @@ package org.jackhuang.hellominecraft.launcher.core.auth.yggdrasil;
public class User {
public String id;
public PropertyMap properties;
private String id;
private PropertyMap properties;
public User() {
}
public User(String id, PropertyMap properties) {
this.id = id;
this.properties = properties;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public PropertyMap getProperties() {
return properties;
}
public void setProperties(PropertyMap properties) {
this.properties = properties;
}
}
@@ -28,10 +28,10 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import org.jackhuang.hellominecraft.utils.C;
import org.jackhuang.hellominecraft.utils.logging.HMCLog;
import org.jackhuang.hellominecraft.utils.NetUtils;
import org.jackhuang.hellominecraft.utils.StrUtils;
import org.jackhuang.hellominecraft.util.C;
import org.jackhuang.hellominecraft.util.logging.HMCLog;
import org.jackhuang.hellominecraft.util.NetUtils;
import org.jackhuang.hellominecraft.util.StrUtils;
public class YggdrasilAuthentication {
@@ -67,7 +67,7 @@ public class YggdrasilAuthentication {
}
// <editor-fold defaultstate="collapsed" desc="Get/Set">
public void setUsername(String username) {
public void setUserName(String username) {
if ((isLoggedIn()) && (canPlayOnline()))
throw new IllegalStateException("Cannot change username while logged in & online");
@@ -96,7 +96,10 @@ public class YggdrasilAuthentication {
}
public GameProfile[] getAvailableProfiles() {
return profiles;
if (profiles == null)
return null;
else
return profiles.clone();
}
public String getAuthenticatedToken() {
@@ -140,9 +143,12 @@ public class YggdrasilAuthentication {
String jsonResult = input == null ? NetUtils.get(url) : NetUtils.post(url, GSON.toJson(input), "application/json", proxy);
Response response = (Response) GSON.fromJson(jsonResult, Response.class);
if (response == null)
throw new AuthenticationException("No valid response here");
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);
if (response.errorMessage.contains("Invalid token"))
if (response.errorMessage != null && response.errorMessage.contains("Invalid token"))
response.errorMessage = C.i18n("login.invalid_token");
throw new AuthenticationException("Request error: " + response.errorMessage);
}
@@ -151,7 +157,7 @@ public class YggdrasilAuthentication {
throw new AuthenticationException(C.i18n("login.changed_client_token"));
User user = response.user;
userid = user != null && user.id != null ? user.id : username;
userid = user != null && user.getId() != null ? user.getId() : username;
isOnline = true;
profiles = response.availableProfiles;
@@ -159,8 +165,8 @@ public class YggdrasilAuthentication {
userProperties.clear();
this.accessToken = response.accessToken;
if (user != null && user.properties != null)
userProperties.putAll(user.properties);
if (user != null && user.getProperties() != null)
userProperties.putAll(user.getProperties());
} catch (IOException | IllegalStateException | JsonParseException e) {
throw new AuthenticationException(C.i18n("login.failed.connect_authentication_server"), e);
}
@@ -182,7 +188,7 @@ public class YggdrasilAuthentication {
public void loadFromStorage(Map<String, Object> credentials) {
logOut();
setUsername((String) credentials.get(STORAGE_KEY_USER_NAME));
setUserName((String) credentials.get(STORAGE_KEY_USER_NAME));
if (credentials.containsKey(STORAGE_KEY_USER_ID))
userid = (String) credentials.get(STORAGE_KEY_USER_ID);
@@ -17,7 +17,7 @@
*/
package org.jackhuang.hellominecraft.launcher.core.download;
import org.jackhuang.hellominecraft.launcher.core.installers.InstallerVersionList;
import org.jackhuang.hellominecraft.launcher.core.install.InstallerVersionList;
/**
*
@@ -27,17 +27,17 @@ public class BMCLAPIDownloadProvider extends IDownloadProvider {
@Override
public InstallerVersionList getForgeInstaller() {
return org.jackhuang.hellominecraft.launcher.core.installers.forge.MinecraftForgeVersionList.getInstance();
return org.jackhuang.hellominecraft.launcher.core.install.forge.MinecraftForgeVersionList.getInstance();
}
@Override
public InstallerVersionList getLiteLoaderInstaller() {
return org.jackhuang.hellominecraft.launcher.core.installers.liteloader.LiteLoaderVersionList.getInstance();
return org.jackhuang.hellominecraft.launcher.core.install.liteloader.LiteLoaderVersionList.getInstance();
}
@Override
public InstallerVersionList getOptiFineInstaller() {
return org.jackhuang.hellominecraft.launcher.core.installers.optifine.bmcl.OptiFineBMCLVersionList.getInstance();
return org.jackhuang.hellominecraft.launcher.core.install.optifine.bmcl.OptiFineBMCLVersionList.getInstance();
}
@Override
@@ -57,7 +57,7 @@ public class BMCLAPIDownloadProvider extends IDownloadProvider {
@Override
public String getVersionsListDownloadURL() {
return "http://bmclapi2.bangbang93.com/versions/versions.json";
return "http://bmclapi2.bangbang93.com/mc/game/version_manifest.json";
}
@Override
@@ -66,13 +66,17 @@ public class BMCLAPIDownloadProvider extends IDownloadProvider {
}
@Override
public String getParsedLibraryDownloadURL(String str) {
return str == null ? null : str.replace("http://files.minecraftforge.net/maven", "http://bmclapi2.bangbang93.com/maven");
public String getParsedDownloadURL(String str) {
return str == null ? null
: str.replace("https://launchermeta.mojang.com", "http://bmclapi2.bangbang93.com")
.replace("https://launcher.mojang.com", "http://bmclapi2.bangbang93.com")
.replace("https://libraries.minecraft.net", "http://bmclapi2.bangbang93.com/libraries")
.replace("http://files.minecraftforge.net/maven", "http://bmclapi2.bangbang93.com/maven");
}
@Override
public boolean isAllowedToUseSelfURL() {
return false;
return true;
}
}
@@ -24,8 +24,8 @@ package org.jackhuang.hellominecraft.launcher.core.download;
public class CurseDownloadProvider extends MojangDownloadProvider {
@Override
public String getParsedLibraryDownloadURL(String str) {
return str == null ? null : str.replace("http://files.minecraftforge.net/maven", "http://ftb.cursecdn.com/FTB2/maven/");
public String getParsedDownloadURL(String str) {
return str == null ? null : str.replace("http://files.minecraftforge.net/maven", "http://ftb.cursecdn.com/FTB2/maven");
}
}
@@ -18,7 +18,8 @@
package org.jackhuang.hellominecraft.launcher.core.download;
import java.io.File;
import org.jackhuang.hellominecraft.utils.system.IOUtils;
import org.jackhuang.hellominecraft.launcher.core.version.IMinecraftLibrary;
import org.jackhuang.hellominecraft.util.system.IOUtils;
/**
*
@@ -26,12 +27,15 @@ import org.jackhuang.hellominecraft.utils.system.IOUtils;
*/
public class DownloadLibraryJob {
public String url, name;
public IMinecraftLibrary lib;
public String url;
public String retryUrl;
public File path;
public DownloadLibraryJob(String n, String u, File p) {
public DownloadLibraryJob(IMinecraftLibrary n, String u, String retry, File p) {
url = u;
name = n;
retryUrl = retry;
lib = n;
path = IOUtils.tryGetCanonicalFile(p);
}
}
@@ -17,7 +17,8 @@
*/
package org.jackhuang.hellominecraft.launcher.core.download;
import org.jackhuang.hellominecraft.utils.C;
import org.jackhuang.hellominecraft.util.C;
import org.jackhuang.hellominecraft.util.tasks.TaskWindow;
/**
*
@@ -25,10 +26,11 @@ import org.jackhuang.hellominecraft.utils.C;
*/
public enum DownloadType {
Mojang(C.i18n("download.mojang"), new MojangDownloadProvider()),
BMCL(C.i18n("download.BMCL"), new BMCLAPIDownloadProvider()),
RapidData(C.i18n("download.rapid_data"), new RapidDataDownloadProvider()),
Curse("Curse CDN", new CurseDownloadProvider());
Mojang("download.mojang", new MojangDownloadProvider()),
BMCL("download.BMCL", new BMCLAPIDownloadProvider()),
//RapidData("download.rapid_data", new RapidDataDownloadProvider()),
Curse("Curse CDN", new CurseDownloadProvider()),
Dynamic("HMCLSoft", DynamicDownloadProvider.getInstance());
private final String name;
private final IDownloadProvider provider;
@@ -43,10 +45,10 @@ public enum DownloadType {
}
public String getName() {
return name;
return C.i18n(name);
}
private static DownloadType suggestedDownloadType = Mojang;
private static DownloadType suggestedDownloadType = Dynamic;
public static DownloadType getSuggestedDownloadType() {
return suggestedDownloadType;
@@ -55,6 +57,7 @@ public enum DownloadType {
public static void setSuggestedDownloadType(DownloadType suggestedDownloadType) {
if (suggestedDownloadType == null)
throw new IllegalArgumentException("download type should not be null.");
TaskWindow.downloadSource = suggestedDownloadType.getName();
DownloadType.suggestedDownloadType = 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();
}
}
@@ -17,8 +17,8 @@
*/
package org.jackhuang.hellominecraft.launcher.core.download;
import org.jackhuang.hellominecraft.launcher.core.installers.InstallerType;
import org.jackhuang.hellominecraft.launcher.core.installers.InstallerVersionList;
import org.jackhuang.hellominecraft.launcher.core.install.InstallerType;
import org.jackhuang.hellominecraft.launcher.core.install.InstallerVersionList;
/**
*
@@ -32,13 +32,13 @@ public abstract class IDownloadProvider {
return getForgeInstaller();
case LiteLoader:
return getLiteLoaderInstaller();
case Optifine:
case OptiFine:
return getOptiFineInstaller();
default:
return null;
}
}
public abstract InstallerVersionList getForgeInstaller();
public abstract InstallerVersionList getLiteLoaderInstaller();
@@ -46,6 +46,10 @@ public abstract class IDownloadProvider {
public abstract InstallerVersionList getOptiFineInstaller();
public abstract String getLibraryDownloadURL();
public String getRetryLibraryDownloadURL() {
return "";
}
public abstract String getVersionsDownloadURL();
@@ -55,7 +59,19 @@ public abstract class IDownloadProvider {
public abstract String getAssetsDownloadURL();
public abstract String getParsedLibraryDownloadURL(String str);
public String getRetryAssetsDownloadURL() {
return "";
}
/**
* For example, minecraft.json/assetIndex/url or
* minecraft.json/downloads/client/url
*
* @param str baseURL
*
* @return parsedURL
*/
public abstract String getParsedDownloadURL(String str);
public abstract boolean isAllowedToUseSelfURL();
}
@@ -0,0 +1,170 @@
/*
* 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 org.jackhuang.hellominecraft.launcher.core.service.IMinecraftDownloadService;
import com.google.gson.JsonSyntaxException;
import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import org.jackhuang.hellominecraft.util.C;
import org.jackhuang.hellominecraft.util.logging.HMCLog;
import org.jackhuang.hellominecraft.launcher.core.GameException;
import org.jackhuang.hellominecraft.launcher.core.service.IMinecraftService;
import org.jackhuang.hellominecraft.launcher.core.version.GameDownloadInfo;
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.util.tasks.download.FileDownloadTask;
import org.jackhuang.hellominecraft.util.func.Function;
import org.jackhuang.hellominecraft.util.system.FileUtils;
import org.jackhuang.hellominecraft.util.tasks.Task;
import org.jackhuang.hellominecraft.util.tasks.TaskInfo;
/**
*
* @author huangyuhui
*/
public class MinecraftDownloadService extends IMinecraftDownloadService {
public MinecraftDownloadService(IMinecraftService service) {
super(service);
}
@Override
public List<DownloadLibraryJob> getDownloadLibraries(MinecraftVersion mv) throws GameException {
ArrayList<DownloadLibraryJob> downloadLibraries = new ArrayList<>();
if (mv == null)
return downloadLibraries;
MinecraftVersion v = mv.resolve(service.version());
for (IMinecraftLibrary libraryInfo : v.getLibraries())
if (libraryInfo != null && libraryInfo.allow() && libraryInfo.getDownloadInfo() != null) {
File ff = libraryInfo.getFilePath(service.baseDirectory());
if (!ff.exists()) {
LibraryDownloadInfo downloadInfo = libraryInfo.getDownloadInfo();
String downloadUrl = downloadInfo.getUrl(service.getDownloadType());
String retryDownloadUrl = downloadInfo.getRetryUrl(service.getDownloadType());
if (downloadUrl != null)
downloadLibraries.add(new DownloadLibraryJob(libraryInfo, downloadUrl, retryDownloadUrl, ff));
}
}
return downloadLibraries;
}
@Override
public Task downloadMinecraft(String id) {
return new TaskInfo("Download Minecraft") {
@Override
public Collection<Task> getDependTasks() {
return Arrays.asList(downloadMinecraftVersionJson(id));
}
@Override
public void executeTask() throws Throwable {
File vpath = new File(service.baseDirectory(), "versions/" + id);
if (!areDependTasksSucceeded) {
FileUtils.deleteDirectory(vpath);
throw new RuntimeException("Cannot continue because of download failing.");
}
File mvj = new File(vpath, id + ".jar");
if (mvj.exists() && !mvj.delete())
HMCLog.warn("Failed to delete " + mvj);
try {
MinecraftVersion mv = C.GSON.fromJson(FileUtils.readQuietly(new File(vpath, id + ".json")), MinecraftVersion.class);
if (mv == null)
throw new JsonSyntaxException("incorrect version");
afters.add(downloadMinecraftJar(mv, mvj));
} catch (JsonSyntaxException ex) {
HMCLog.err("Failed to parse minecraft version json.", ex);
FileUtils.deleteDirectory(vpath);
}
}
Collection<Task> afters = new HashSet<>();
@Override
public Collection<Task> getAfterTasks() {
return afters;
}
};
}
private static class DownloadTypeSwitcher implements Function<Integer, String> {
String suffix;
public DownloadTypeSwitcher(String suffix) {
this.suffix = suffix;
}
@Override
public String apply(Integer repeat) {
int index = repeat / 2;
if (index > DownloadType.values().length) {
index = 0;
}
return DownloadType.values()[index].getProvider().getVersionsDownloadURL() + suffix;
}
}
@Override
public Task downloadMinecraftJar(MinecraftVersion mv, File mvj) {
GameDownloadInfo i = mv.getClientDownloadInfo();
return new FileDownloadTask(i.getUrl(service.getDownloadType()), mvj, i.sha1)
.setFailedCallbackReturnsNewURL(new DownloadTypeSwitcher(mv.id + "/" + mv.id + ".jar")).setTag(mv.id + ".jar");
}
@Override
public Task downloadMinecraftVersionJson(String id) {
return new TaskInfo("Download Minecraft Json") {
@Override
public void executeTask() throws Throwable {
List<MinecraftRemoteVersion> versions = MinecraftRemoteVersions.getRemoteVersions(service.getDownloadType()).justDo();
MinecraftRemoteVersion currentVersion = null;
for (MinecraftRemoteVersion v : versions)
if (id.equals(v.id)) {
currentVersion = v;
break;
}
if (currentVersion == null)
throw new RuntimeException("Cannot find version: " + id + " in remote repository.");
String jsonURL = currentVersion.getUrl(service.getDownloadType());
File vpath = new File(service.baseDirectory(), "versions/" + id);
File mvt = new File(vpath, id + ".json");
if (!vpath.exists() && !vpath.mkdirs())
HMCLog.warn("Failed to make directories: " + vpath);
if (mvt.exists() && !mvt.delete())
HMCLog.warn("Failed to delete " + mvt);
afters.add(new FileDownloadTask(jsonURL, mvt).setTag(id + ".json"));
}
Collection<Task> afters = new HashSet<>();
@Override
public Collection<Task> getAfterTasks() {
return afters;
}
};
}
}
@@ -1,5 +1,5 @@
/*
* Hello Minecraft! Launcher.
* Hello Minecraft!.
* Copyright (C) 2013 huangyuhui <huanghongxun2008@126.com>
*
* This program is free software: you can redistribute it and/or modify
@@ -15,7 +15,7 @@
* 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.utils.version;
package org.jackhuang.hellominecraft.launcher.core.download;
/**
*
@@ -1,5 +1,5 @@
/*
* Hello Minecraft! Launcher.
* Hello Minecraft!.
* Copyright (C) 2013 huangyuhui <huanghongxun2008@126.com>
*
* This program is free software: you can redistribute it and/or modify
@@ -15,7 +15,7 @@
* 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.utils.version;
package org.jackhuang.hellominecraft.launcher.core.download;
/**
*
@@ -24,4 +24,11 @@ package org.jackhuang.hellominecraft.utils.version;
public class MinecraftRemoteVersion {
public String id, time, releaseTime, type;
private String url;
public String getUrl(DownloadType type) {
if (url == null)
return type.getProvider().getVersionsDownloadURL() + id + "/" + id + ".json";
return type.getProvider().getParsedDownloadURL(url);
}
}
@@ -0,0 +1,77 @@
/*
* Hello Minecraft!.
* Copyright (C) 2013 huangyuhui <huanghongxun2008@126.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see {http://www.gnu.org/licenses/}.
*/
package org.jackhuang.hellominecraft.launcher.core.download;
import com.google.gson.annotations.SerializedName;
import java.util.ArrayList;
import org.jackhuang.hellominecraft.util.C;
import org.jackhuang.hellominecraft.util.NetUtils;
import org.jackhuang.hellominecraft.util.OverridableSwingWorker;
/**
*
* @author huangyuhui
*/
public class MinecraftRemoteVersions {
@SerializedName("versions")
public ArrayList<MinecraftRemoteVersion> versions;
@SerializedName("latest")
public MinecraftRemoteLatestVersion latest;
private static volatile MinecraftRemoteVersions INSTANCE = null;
private static final Object INSTANCE_LOCK = new Object();
public static RemoteVersionsTask getRemoteVersions(DownloadType type) {
return new RemoteVersionsTask(type) {
@Override
public void work() throws Exception {
synchronized (INSTANCE_LOCK) {
if (INSTANCE != null)
send(INSTANCE.versions.toArray(new MinecraftRemoteVersion[INSTANCE.versions.size()]));
else
super.work();
}
}
};
}
public static RemoteVersionsTask refreshRomoteVersions(DownloadType type) {
return new RemoteVersionsTask(type);
}
public static class RemoteVersionsTask extends OverridableSwingWorker<MinecraftRemoteVersion> {
DownloadType type;
public RemoteVersionsTask(DownloadType type) {
this.type = type;
}
@Override
public void work() throws Exception {
MinecraftRemoteVersions r = C.GSON.fromJson(NetUtils.get(type.getProvider().getVersionsListDownloadURL()), MinecraftRemoteVersions.class);
if (r != null && r.versions != null) {
INSTANCE = r;
send(r.versions.toArray(new MinecraftRemoteVersion[r.versions.size()]));
}
}
}
}
@@ -17,7 +17,9 @@
*/
package org.jackhuang.hellominecraft.launcher.core.download;
import org.jackhuang.hellominecraft.launcher.core.installers.InstallerVersionList;
import java.util.Locale;
import org.jackhuang.hellominecraft.launcher.core.install.InstallerVersionList;
import org.jackhuang.hellominecraft.util.lang.SupportedLocales;
/**
*
@@ -27,42 +29,47 @@ public class MojangDownloadProvider extends IDownloadProvider {
@Override
public InstallerVersionList getForgeInstaller() {
return org.jackhuang.hellominecraft.launcher.core.installers.forge.MinecraftForgeVersionList.getInstance();
return org.jackhuang.hellominecraft.launcher.core.install.forge.MinecraftForgeVersionList.getInstance();
}
@Override
public InstallerVersionList getLiteLoaderInstaller() {
return org.jackhuang.hellominecraft.launcher.core.installers.liteloader.LiteLoaderVersionList.getInstance();
return org.jackhuang.hellominecraft.launcher.core.install.liteloader.LiteLoaderVersionList.getInstance();
}
@Override
public InstallerVersionList getOptiFineInstaller() {
return org.jackhuang.hellominecraft.launcher.core.installers.optifine.vanilla.OptiFineVersionList.getInstance();
return org.jackhuang.hellominecraft.launcher.core.install.optifine.vanilla.OptiFineVersionList.getInstance();
}
// jars
@Override
public String getLibraryDownloadURL() {
return "https://libraries.minecraft.net";
}
// jars
@Override
public String getVersionsDownloadURL() {
return "http://s3.amazonaws.com/Minecraft.Download/versions/";
}
// resource
@Override
public String getIndexesDownloadURL() {
return "http://s3.amazonaws.com/Minecraft.Download/indexes/";
}
// game versions json
@Override
public String getVersionsListDownloadURL() {
return "http://s3.amazonaws.com/Minecraft.Download/versions/versions.json";
return "https://launchermeta.mojang.com/mc/game/version_manifest.json";
}
// resource
@Override
public String getAssetsDownloadURL() {
return "http://resources.download.minecraft.net/";
return "https://resources.download.minecraft.net/";
}
@Override
@@ -71,8 +78,17 @@ public class MojangDownloadProvider extends IDownloadProvider {
}
@Override
public String getParsedLibraryDownloadURL(String str) {
return str;
public String getParsedDownloadURL(String str) {
if (str == null)
return null;
else if (str.contains("scala-swing") || str.contains("scala-xml") || str.contains("scala-parser-combinators"))
return str.replace("http://files.minecraftforge.net/maven", "http://ftb.cursecdn.com/FTB2/maven/");
else if (str.contains("typesafe") || str.contains("scala"))
if (SupportedLocales.NOW_LOCALE.self == Locale.CHINA)
return str.replace("http://files.minecraftforge.net/maven", "http://maven.oschina.net/content/groups/public");
else
return str.replace("http://files.minecraftforge.net/maven", "http://repo1.maven.org/maven2");
else
return str;
}
}
@@ -49,7 +49,7 @@ public class RapidDataDownloadProvider extends MojangDownloadProvider {
}
@Override
public String getParsedLibraryDownloadURL(String str) {
public String getParsedDownloadURL(String str) {
return str == null ? null : str.replace("http://files.minecraftforge.net/maven", "http://mirrors.rapiddata.org/forge/maven");
}
@@ -15,11 +15,11 @@
* 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.installers;
package org.jackhuang.hellominecraft.launcher.core.install;
import com.google.gson.annotations.SerializedName;
import org.jackhuang.hellominecraft.launcher.core.version.MinecraftVersion;
import org.jackhuang.hellominecraft.launcher.core.installers.forge.Install;
import org.jackhuang.hellominecraft.launcher.core.install.forge.Install;
/**
*
@@ -15,14 +15,14 @@
* 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.installers;
package org.jackhuang.hellominecraft.launcher.core.install;
/**
*
* @author huangyuhui
*/
public enum InstallerType {
Forge("forge"), Optifine("optifine"), LiteLoader("liteloader");
Forge("forge"), OptiFine("optifine"), LiteLoader("liteloader");
public final String id;
@@ -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);
}
}
}
@@ -15,19 +15,22 @@
* 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.installers;
package org.jackhuang.hellominecraft.launcher.core.install;
import java.io.Serializable;
import java.util.Comparator;
import org.jackhuang.hellominecraft.launcher.core.installers.InstallerVersionList.InstallerVersion;
import org.jackhuang.hellominecraft.launcher.core.install.InstallerVersionList.InstallerVersion;
/**
*
* @author huangyuhui
*/
public class InstallerVersionNewerComparator implements Comparator<InstallerVersion> {
public class InstallerVersionNewerComparator implements Comparator<InstallerVersion>, Serializable {
private static final long serialVersionUID = 14758562453742645L;
@Override
public int compare(InstallerVersion o1, InstallerVersion o2) {
return -o1.compareTo(o2);
return o2.compareTo(o1);
}
}
@@ -0,0 +1,87 @@
/*
* 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 org.jackhuang.hellominecraft.launcher.core.service.IMinecraftInstallerService;
import java.io.File;
import org.jackhuang.hellominecraft.launcher.core.service.IMinecraftService;
import org.jackhuang.hellominecraft.launcher.core.install.InstallerVersionList.InstallerVersion;
import org.jackhuang.hellominecraft.launcher.core.install.forge.ForgeInstaller;
import org.jackhuang.hellominecraft.launcher.core.install.liteloader.LiteLoaderInstaller;
import org.jackhuang.hellominecraft.launcher.core.install.liteloader.LiteLoaderVersionList;
import org.jackhuang.hellominecraft.launcher.core.install.optifine.OptiFineInstaller;
import org.jackhuang.hellominecraft.launcher.core.install.optifine.vanilla.OptiFineDownloadFormatter;
import org.jackhuang.hellominecraft.util.tasks.Task;
import org.jackhuang.hellominecraft.util.tasks.download.FileDownloadTask;
import org.jackhuang.hellominecraft.util.system.IOUtils;
import org.jackhuang.hellominecraft.util.tasks.DeleteFileTask;
/**
*
* @author huangyuhui
*/
public final class MinecraftInstallerService extends IMinecraftInstallerService {
public MinecraftInstallerService(IMinecraftService service) {
super(service);
}
@Override
public Task download(String installId, InstallerVersion v, InstallerType type) {
switch (type) {
case Forge:
return downloadForge(installId, v);
case OptiFine:
return downloadOptiFine(installId, v);
case LiteLoader:
return downloadLiteLoader(installId, v);
default:
return null;
}
}
@Override
public Task downloadForge(String installId, InstallerVersion v) {
File filepath = IOUtils.tryGetCanonicalFile("forge-installer.jar");
if (v.installer == null)
return null;
else
return new FileDownloadTask(service.getDownloadType().getProvider().getParsedDownloadURL(v.installer), filepath).setTag("forge")
.after(new ForgeInstaller(service, filepath))
.after(new DeleteFileTask(filepath));
}
@Override
public Task downloadOptiFine(String installId, InstallerVersion v) {
File filepath = IOUtils.tryGetCanonicalFile("optifine-installer.jar");
if (v.installer == null)
return null;
OptiFineDownloadFormatter task = new OptiFineDownloadFormatter(v.installer);
return task.after(new FileDownloadTask(filepath).registerPreviousResult(task).setTag("optifine"))
.after(new OptiFineInstaller(service, installId, v, filepath))
.after(new DeleteFileTask(filepath));
}
@Override
public Task downloadLiteLoader(String installId, InstallerVersion v) {
File filepath = IOUtils.tryGetCanonicalFile("liteloader-universal.jar");
FileDownloadTask task = (FileDownloadTask) new FileDownloadTask(v.universal, filepath).setTag("LiteLoader");
return task.after(new LiteLoaderInstaller(service, installId, (LiteLoaderVersionList.LiteLoaderInstallerVersion) v).registerPreviousResult(task))
.after(new DeleteFileTask(filepath));
}
}
@@ -15,14 +15,14 @@
* 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.installers;
package org.jackhuang.hellominecraft.launcher.core.install;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import org.jackhuang.hellominecraft.utils.system.Compressor;
import org.jackhuang.hellominecraft.utils.system.FileUtils;
import org.jackhuang.hellominecraft.utils.system.IOUtils;
import org.jackhuang.hellominecraft.util.logging.HMCLog;
import org.jackhuang.hellominecraft.util.system.Compressor;
import org.jackhuang.hellominecraft.util.system.FileUtils;
/**
*
@@ -39,8 +39,9 @@ public class PackMinecraftInstaller {
}
public void install() throws IOException {
File file = new File(IOUtils.currentDir(), "HMCL-MERGE-TEMP");
file.mkdirs();
File file = new File("HMCL-MERGE-TEMP");
if (!file.exists() && !file.mkdirs())
HMCLog.warn("Failed to make directories: " + file);
for (String src1 : src)
Compressor.unzip(new File(src1), file);
Compressor.zip(file.getAbsolutePath(), dest.getAbsolutePath());
@@ -0,0 +1,94 @@
/*
* 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 org.jackhuang.hellominecraft.launcher.core.install.InstallProfile;
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import org.jackhuang.hellominecraft.util.C;
import org.jackhuang.hellominecraft.util.logging.HMCLog;
import org.jackhuang.hellominecraft.launcher.core.service.IMinecraftService;
import org.jackhuang.hellominecraft.util.tasks.Task;
import org.jackhuang.hellominecraft.util.system.FileUtils;
import org.jackhuang.hellominecraft.util.NetUtils;
import org.jackhuang.hellominecraft.launcher.core.version.MinecraftLibrary;
import org.jackhuang.hellominecraft.util.MessageBox;
import org.jackhuang.hellominecraft.util.system.IOUtils;
/**
*
* @author huangyuhui
*/
public class ForgeInstaller extends Task {
public File gameDir;
public File forgeInstaller;
public IMinecraftService mp;
public ForgeInstaller(IMinecraftService mp, File forgeInstaller) {
this.gameDir = mp.baseDirectory();
this.forgeInstaller = forgeInstaller;
this.mp = mp;
}
@Override
public void executeTask() throws Exception {
HMCLog.log("Extracting install profiles...");
try (ZipFile zipFile = new ZipFile(forgeInstaller)) {
ZipEntry entry = zipFile.getEntry("install_profile.json");
String content = NetUtils.getStreamContent(zipFile.getInputStream(entry));
InstallProfile profile = C.GSON.fromJson(content, InstallProfile.class);
File from = new File(gameDir, "versions" + File.separator + profile.install.getMinecraft());
if (!from.exists())
if (MessageBox.Show(C.i18n("install.no_version_if_intall")) == MessageBox.YES_OPTION) {
if (!mp.version().install(profile.install.getMinecraft(), null))
throw new IllegalStateException(C.i18n("install.no_version"));
} else
throw new IllegalStateException(C.i18n("install.no_version"));
File to = new File(gameDir, "versions" + File.separator + profile.install.getTarget());
if (!to.exists() && !to.mkdirs())
HMCLog.warn("Failed to make new version folder " + to);
HMCLog.log("Copying jar..." + profile.install.getMinecraft() + ".jar to " + profile.install.getTarget() + ".jar");
FileUtils.copyFile(new File(from, profile.install.getMinecraft() + ".jar"),
new File(to, profile.install.getTarget() + ".jar"));
HMCLog.log("Creating new version profile..." + profile.install.getTarget() + ".json");
FileUtils.write(new File(to, profile.install.getTarget() + ".json"), C.GSON.toJson(profile.versionInfo));
HMCLog.log("Extracting universal forge pack..." + profile.install.getFilePath());
entry = zipFile.getEntry(profile.install.getFilePath());
InputStream is = zipFile.getInputStream(entry);
MinecraftLibrary forge = new MinecraftLibrary(profile.install.getPath());
File file = new File(gameDir, "libraries/" + forge.getDownloadInfo().path);
if (file.getParentFile().mkdirs())
HMCLog.warn("Failed to make library directory " + file.getParent());
try (FileOutputStream fos = new FileOutputStream(file)) {
IOUtils.copyStream(is, fos);
}
mp.version().refreshVersions();
}
}
@Override
public String getInfo() {
return C.i18n("install.forge.install");
}
}
@@ -15,12 +15,12 @@
* 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.installers.forge;
package org.jackhuang.hellominecraft.launcher.core.install.forge;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import org.jackhuang.hellominecraft.launcher.core.installers.PackMinecraftInstaller;
import org.jackhuang.hellominecraft.launcher.core.install.PackMinecraftInstaller;
/**
*
@@ -0,0 +1,135 @@
/*
* 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 com.google.gson.annotations.SerializedName;
/**
*
* @author huangyuhui
*/
public class Install {
@SerializedName("profileName")
private String profileName;
@SerializedName("target")
private String target;
@SerializedName("path")
private String path;
@SerializedName("version")
private String version;
@SerializedName("filePath")
private String filePath;
@SerializedName("welcome")
private String welcome;
@SerializedName("minecraft")
private String minecraft;
@SerializedName("mirrorList")
private String mirrorList;
@SerializedName("logo")
private String logo;
public Install() {
}
public Install(String profileName, String target, String path, String version, String filePath, String welcome, String minecraft, String mirrorList, String logo) {
this();
this.profileName = profileName;
this.target = target;
this.path = path;
this.version = version;
this.filePath = filePath;
this.welcome = welcome;
this.minecraft = minecraft;
this.mirrorList = mirrorList;
this.logo = logo;
}
public String getProfileName() {
return profileName;
}
public void setProfileName(String profileName) {
this.profileName = profileName;
}
public String getTarget() {
return target;
}
public void setTarget(String target) {
this.target = target;
}
public String getPath() {
return path;
}
public void setPath(String path) {
this.path = path;
}
public String getVersion() {
return version;
}
public void setVersion(String version) {
this.version = version;
}
public String getFilePath() {
return filePath;
}
public void setFilePath(String filePath) {
this.filePath = filePath;
}
public String getWelcome() {
return welcome;
}
public void setWelcome(String welcome) {
this.welcome = welcome;
}
public String getMinecraft() {
return minecraft;
}
public void setMinecraft(String minecraft) {
this.minecraft = minecraft;
}
public String getMirrorList() {
return mirrorList;
}
public void setMirrorList(String mirrorList) {
this.mirrorList = mirrorList;
}
public String getLogo() {
return logo;
}
public void setLogo(String logo) {
this.logo = logo;
}
}
@@ -0,0 +1,91 @@
/*
* 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;
/**
*
* @author huangyuhui
*/
public class MinecraftForgeVersion {
public String branch, mcversion, jobver, version;
public int build;
public double modified;
public String[][] files;
public String getBranch() {
return branch;
}
public void setBranch(String branch) {
this.branch = branch;
}
public String getMCVersion() {
return mcversion;
}
public void setMCVersion(String mcversion) {
this.mcversion = mcversion;
}
public String getJobver() {
return jobver;
}
public void setJobver(String jobver) {
this.jobver = jobver;
}
public String getVersion() {
return version;
}
public void setVersion(String version) {
this.version = version;
}
public int getBuild() {
return build;
}
public void setBuild(int build) {
this.build = build;
}
public double getModified() {
return modified;
}
public void setModified(double modified) {
this.modified = modified;
}
public MinecraftForgeVersion() {
}
public MinecraftForgeVersion(String branch, String mcversion, String jobver, String version, int build, double modified) {
this.branch = branch;
this.mcversion = mcversion;
this.jobver = jobver;
this.version = version;
this.build = build;
this.modified = modified;
}
}
@@ -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";
}
}
@@ -15,8 +15,9 @@
* 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.installers.forge;
package org.jackhuang.hellominecraft.launcher.core.install.forge;
import com.google.gson.annotations.SerializedName;
import java.util.Map;
/**
@@ -25,8 +26,22 @@ import java.util.Map;
*/
public class MinecraftForgeVersionRoot {
public String artifact, webpath, adfly, homepage, name;
public Map<String, int[]> branches, mcversion;
@SerializedName("artifact")
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;
@SerializedName("number")
public Map<Integer, MinecraftForgeVersion> number;
}
@@ -15,18 +15,18 @@
* 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.installers.liteloader;
package org.jackhuang.hellominecraft.launcher.core.install.liteloader;
import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import org.jackhuang.hellominecraft.utils.C;
import org.jackhuang.hellominecraft.utils.logging.HMCLog;
import org.jackhuang.hellominecraft.util.C;
import org.jackhuang.hellominecraft.util.logging.HMCLog;
import org.jackhuang.hellominecraft.launcher.core.service.IMinecraftService;
import org.jackhuang.hellominecraft.utils.tasks.Task;
import org.jackhuang.hellominecraft.utils.tasks.communication.PreviousResult;
import org.jackhuang.hellominecraft.utils.tasks.communication.PreviousResultRegistrar;
import org.jackhuang.hellominecraft.utils.system.FileUtils;
import org.jackhuang.hellominecraft.util.tasks.Task;
import org.jackhuang.hellominecraft.util.tasks.communication.PreviousResult;
import org.jackhuang.hellominecraft.util.tasks.communication.PreviousResultRegistrar;
import org.jackhuang.hellominecraft.util.system.FileUtils;
import org.jackhuang.hellominecraft.launcher.core.version.MinecraftLibrary;
import org.jackhuang.hellominecraft.launcher.core.version.MinecraftVersion;
@@ -75,10 +75,13 @@ public class LiteLoaderInstaller extends Task implements PreviousResultRegistrar
mv.mainClass = "net.minecraft.launchwrapper.Launch";
mv.minecraftArguments += " --tweakClass " + version.tweakClass;
File folder = new File(service.baseDirectory(), "versions/" + mv.id);
folder.mkdirs();
if (!folder.exists() && folder.mkdirs())
HMCLog.warn("Failed to create new liteloader version " + folder);
File json = new File(folder, mv.id + ".json");
HMCLog.log("Creating new version profile..." + mv.id + ".json");
FileUtils.write(json, C.gsonPrettyPrinting.toJson(mv));
FileUtils.write(json, C.GSON.toJson(mv));
service.version().refreshVersions();
}
@Override
@@ -15,8 +15,9 @@
* 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.installers.liteloader;
package org.jackhuang.hellominecraft.launcher.core.install.liteloader;
import com.google.gson.annotations.SerializedName;
import java.util.Map;
/**
@@ -25,5 +26,6 @@ import java.util.Map;
*/
public class LiteLoaderMCVersions {
@SerializedName("artefacts")
public Map<String, Map<String, LiteLoaderVersion>> artefacts;
}
@@ -15,8 +15,9 @@
* 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.installers.liteloader;
package org.jackhuang.hellominecraft.launcher.core.install.liteloader;
import com.google.gson.annotations.SerializedName;
import org.jackhuang.hellominecraft.launcher.core.version.MinecraftLibrary;
/**
@@ -25,6 +26,16 @@ import org.jackhuang.hellominecraft.launcher.core.version.MinecraftLibrary;
*/
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;
}
@@ -0,0 +1,133 @@
/*
* 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.liteloader;
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.version.MinecraftLibrary;
import org.jackhuang.hellominecraft.launcher.core.install.InstallerVersionList;
import org.jackhuang.hellominecraft.launcher.core.install.InstallerVersionList.InstallerVersion;
import org.jackhuang.hellominecraft.launcher.core.install.InstallerVersionNewerComparator;
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;
/**
*
* @author huangyuhui
*/
public class LiteLoaderVersionList extends InstallerVersionList {
private static volatile LiteLoaderVersionList instance = null;
public static LiteLoaderVersionList getInstance() {
if (instance == null)
instance = new LiteLoaderVersionList();
return instance;
}
public LiteLoaderVersionsRoot root;
public Map<String, List<InstallerVersion>> versionMap;
public List<InstallerVersion> versions;
@Override
public Task refresh(String[] needed) {
if (root != null)
return null;
return new TaskInfo(C.i18n("install.liteloader.get_list")) {
HTTPGetTask task = new HTTPGetTask(C.URL_LITELOADER_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, 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
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 "LiteLoader - LiteLoader Official Site(By: Mumfrey)";
}
public static class LiteLoaderInstallerVersion extends InstallerVersion {
public MinecraftLibrary[] libraries;
public String tweakClass;
public LiteLoaderInstallerVersion(String selfVersion, String mcVersion) {
super(selfVersion, mcVersion);
}
}
}
@@ -0,0 +1,68 @@
/*
* 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.liteloader;
import com.google.gson.annotations.SerializedName;
/**
*
* @author huangyuhui
*/
public class LiteLoaderVersionsMeta {
@SerializedName("versions")
private String description;
@SerializedName("authors")
private String authors;
@SerializedName("url")
private String url;
public LiteLoaderVersionsMeta() {
}
public LiteLoaderVersionsMeta(String description, String authors, String url) {
this();
this.description = description;
this.authors = authors;
this.url = url;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public String getAuthors() {
return authors;
}
public void setAuthors(String authors) {
this.authors = authors;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
}
@@ -15,8 +15,9 @@
* 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.installers.liteloader;
package org.jackhuang.hellominecraft.launcher.core.install.liteloader;
import com.google.gson.annotations.SerializedName;
import java.util.Map;
/**
@@ -25,6 +26,8 @@ import java.util.Map;
*/
public class LiteLoaderVersionsRoot {
@SerializedName("versions")
public Map<String, LiteLoaderMCVersions> versions;
@SerializedName("meta")
public LiteLoaderVersionsMeta meta;
}
@@ -15,20 +15,21 @@
* 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.installers.optifine;
package org.jackhuang.hellominecraft.launcher.core.install.optifine;
import java.io.File;
import java.util.ArrayList;
import java.util.zip.ZipFile;
import org.jackhuang.hellominecraft.utils.C;
import org.jackhuang.hellominecraft.launcher.core.installers.InstallerVersionList;
import org.jackhuang.hellominecraft.util.C;
import org.jackhuang.hellominecraft.launcher.core.install.InstallerVersionList;
import org.jackhuang.hellominecraft.launcher.core.service.IMinecraftService;
import org.jackhuang.hellominecraft.utils.tasks.Task;
import org.jackhuang.hellominecraft.utils.tasks.communication.PreviousResult;
import org.jackhuang.hellominecraft.utils.tasks.communication.PreviousResultRegistrar;
import org.jackhuang.hellominecraft.utils.system.FileUtils;
import org.jackhuang.hellominecraft.util.tasks.Task;
import org.jackhuang.hellominecraft.util.tasks.communication.PreviousResult;
import org.jackhuang.hellominecraft.util.tasks.communication.PreviousResultRegistrar;
import org.jackhuang.hellominecraft.util.system.FileUtils;
import org.jackhuang.hellominecraft.launcher.core.version.MinecraftLibrary;
import org.jackhuang.hellominecraft.launcher.core.version.MinecraftVersion;
import org.jackhuang.hellominecraft.util.logging.HMCLog;
/**
*
@@ -65,22 +66,28 @@ public class OptiFineInstaller extends Task implements PreviousResultRegistrar<F
FileUtils.copyFile(installer, new File(service.baseDirectory(), "libraries/optifine/OptiFine/" + selfId + "/OptiFine-" + selfId + ".jar"));
mv.id += "-" + selfId;
if (new ZipFile(installer).getEntry("optifine/OptiFineTweaker.class") != null) {
if (!mv.mainClass.startsWith("net.minecraft.launchwrapper.")) {
mv.mainClass = "net.minecraft.launchwrapper.Launch";
mv.libraries.add(1, new MinecraftLibrary("net.minecraft:launchwrapper:1.7"));
try (ZipFile zipFile = new ZipFile(installer)) {
if (zipFile.getEntry("optifine/OptiFineTweaker.class") != null) {
if (!mv.mainClass.startsWith("net.minecraft.launchwrapper.")) {
mv.mainClass = "net.minecraft.launchwrapper.Launch";
mv.libraries.add(1, new MinecraftLibrary("net.minecraft:launchwrapper:1.7"));
}
if (!mv.minecraftArguments.contains("FMLTweaker"))
mv.minecraftArguments += " --tweakClass optifine.OptiFineTweaker";
}
mv.minecraftArguments += " --tweakClass optifine.OptiFineTweaker";
}
File loc = new File(service.baseDirectory(), "versions/" + mv.id);
loc.mkdirs();
if (!loc.exists() && loc.mkdirs())
HMCLog.warn("Failed to make directories: " + loc);
File json = new File(loc, mv.id + ".json");
FileUtils.writeStringToFile(json, C.gsonPrettyPrinting.toJson(mv, MinecraftVersion.class));
FileUtils.write(json, C.GSON.toJson(mv, MinecraftVersion.class));
service.version().refreshVersions();
}
@Override
public String getInfo() {
return "Optifine Installer";
return "OptiFine Installer";
}
ArrayList<PreviousResult<File>> pre = new ArrayList();
@@ -15,7 +15,7 @@
* 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.installers.optifine;
package org.jackhuang.hellominecraft.launcher.core.install.optifine;
/**
*
@@ -23,5 +23,45 @@ package org.jackhuang.hellominecraft.launcher.core.installers.optifine;
*/
public class OptiFineVersion {
public String dl, ver, date, mirror, mcver;
private String dl, ver, date, mirror, mcver;
public String getDownloadLink() {
return dl;
}
public void setDownloadLink(String dl) {
this.dl = dl;
}
public String getVersion() {
return ver;
}
public void setVersion(String ver) {
this.ver = ver;
}
public String getDate() {
return date;
}
public void setDate(String date) {
this.date = date;
}
public String getMirror() {
return mirror;
}
public void setMirror(String mirror) {
this.mirror = mirror;
}
public String getMCVersion() {
return mcver;
}
public void setMCVersion(String mcver) {
this.mcver = mcver;
}
}
@@ -0,0 +1,122 @@
/*
* 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.bmcl;
import com.google.gson.reflect.TypeToken;
import java.lang.reflect.Type;
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 org.jackhuang.hellominecraft.util.C;
import org.jackhuang.hellominecraft.util.ArrayUtils;
import org.jackhuang.hellominecraft.launcher.core.install.InstallerVersionList;
import org.jackhuang.hellominecraft.launcher.core.install.optifine.OptiFineVersion;
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;
/**
*
* @author huangyuhui
*/
public class OptiFineBMCLVersionList extends InstallerVersionList {
private static OptiFineBMCLVersionList instance;
public static OptiFineBMCLVersionList getInstance() {
if (null == instance)
instance = new OptiFineBMCLVersionList();
return instance;
}
public ArrayList<OptiFineVersion> root;
public Map<String, List<InstallerVersion>> versionMap;
public List<InstallerVersion> versions;
private static final Type TYPE = new TypeToken<ArrayList<OptiFineVersion>>() {
}.getType();
@Override
public Task refresh(String[] needed) {
return new TaskInfo(C.i18n("install.optifine.get_list")) {
HTTPGetTask task = new HTTPGetTask("http://bmclapi.bangbang93.com/optifine/versionlist");
@Override
public Collection<Task> getDependTasks() {
return Arrays.asList(task);
}
@Override
public void executeTask() throws Throwable {
String s = task.getResult();
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
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 "OptiFine - BMCLAPI(By: bangbang93)";
}
}
@@ -15,14 +15,14 @@
* 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.installers.optifine.vanilla;
package org.jackhuang.hellominecraft.launcher.core.install.optifine.vanilla;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.jackhuang.hellominecraft.utils.C;
import org.jackhuang.hellominecraft.utils.tasks.Task;
import org.jackhuang.hellominecraft.utils.tasks.communication.PreviousResult;
import org.jackhuang.hellominecraft.utils.NetUtils;
import org.jackhuang.hellominecraft.util.C;
import org.jackhuang.hellominecraft.util.tasks.Task;
import org.jackhuang.hellominecraft.util.tasks.communication.PreviousResult;
import org.jackhuang.hellominecraft.util.NetUtils;
/**
*
@@ -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;
}
}
@@ -17,25 +17,23 @@
*/
package org.jackhuang.hellominecraft.launcher.core.launch;
import org.jackhuang.hellominecraft.launcher.core.service.IMinecraftService;
import org.jackhuang.hellominecraft.launcher.core.service.IMinecraftLoader;
import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import org.jackhuang.hellominecraft.utils.C;
import org.jackhuang.hellominecraft.utils.logging.HMCLog;
import org.jackhuang.hellominecraft.launcher.Launcher;
import org.jackhuang.hellominecraft.util.C;
import org.jackhuang.hellominecraft.util.logging.HMCLog;
import org.jackhuang.hellominecraft.util.system.JdkVersion;
import org.jackhuang.hellominecraft.util.MathUtils;
import org.jackhuang.hellominecraft.util.MessageBox;
import org.jackhuang.hellominecraft.util.system.OS;
import org.jackhuang.hellominecraft.util.system.Platform;
import org.jackhuang.hellominecraft.util.StrUtils;
import org.jackhuang.hellominecraft.launcher.core.GameException;
import org.jackhuang.hellominecraft.launcher.core.auth.UserProfileProvider;
import org.jackhuang.hellominecraft.launcher.core.version.MinecraftVersion;
import org.jackhuang.hellominecraft.utils.system.JdkVersion;
import org.jackhuang.hellominecraft.utils.MathUtils;
import org.jackhuang.hellominecraft.utils.MessageBox;
import org.jackhuang.hellominecraft.utils.system.OS;
import org.jackhuang.hellominecraft.utils.system.Platform;
import org.jackhuang.hellominecraft.utils.StrUtils;
import org.jackhuang.hellominecraft.utils.Utils;
import org.jackhuang.hellominecraft.launcher.core.service.IMinecraftService;
import org.jackhuang.hellominecraft.launcher.core.service.IMinecraftLoader;
/**
*
@@ -50,6 +48,8 @@ public abstract class AbstractMinecraftLoader implements IMinecraftLoader {
protected final MinecraftVersion version;
public AbstractMinecraftLoader(LaunchOptions options, IMinecraftService service, String versionId, UserProfileProvider lr) throws GameException {
if (service.version().getVersionById(versionId) == null)
throw new GameException("No version: " + versionId);
this.lr = lr;
this.options = options;
@@ -66,6 +66,9 @@ public abstract class AbstractMinecraftLoader implements IMinecraftLoader {
public void makeHeadCommand(List<String> res) {
HMCLog.log("On making head command.");
if (StrUtils.isNotBlank(options.getWrapper()))
res.add(options.getWrapper());
JdkVersion jv = options.getJava();
res.add(options.getJavaDir());
@@ -78,8 +81,10 @@ public abstract class AbstractMinecraftLoader implements IMinecraftLoader {
if (jv == null || !jv.isEarlyAccess()) {
if (OS.os() == OS.WINDOWS)
res.add("-XX:HeapDumpPath=MojangTricksIntelDriversForPerformance_javaw.exe_minecraft.exe.heapdump");
res.add("-XX:+UseConcMarkSweepGC");
res.add("-XX:+CMSIncrementalMode");
if (jv != null && jv.getParsedVersion() >= JdkVersion.JAVA_17)
res.add("-XX:+UseG1GC");
else
res.add("-Xincgc");
res.add("-XX:-UseAdaptiveSizePolicy");
res.add("-XX:-OmitStackTraceInFastThrow");
@@ -123,12 +128,6 @@ public abstract class AbstractMinecraftLoader implements IMinecraftLoader {
if (OS.os() != OS.WINDOWS)
res.add("-Duser.home=" + gameDir.getParent());
if (!options.isCanceledWrapper()) {
res.add("-cp");
res.add(StrUtils.parseParams("", Utils.getURL(), File.pathSeparator));
res.add(Launcher.class.getCanonicalName());
}
}
@Override
@@ -150,8 +149,6 @@ public abstract class AbstractMinecraftLoader implements IMinecraftLoader {
}
String serverIp = options.getServerIp();
if (lr.getServer() != null)
serverIp = lr.getServer().addr;
if (StrUtils.isNotBlank(serverIp)) {
String[] args = serverIp.split(":");
res.add("--server");
@@ -163,15 +160,16 @@ public abstract class AbstractMinecraftLoader implements IMinecraftLoader {
if (options.isFullscreen())
res.add("--fullscreen");
if (options.isDebug() && !options.isCanceledWrapper())
res.add("-debug");
if (StrUtils.isNotBlank(options.getProxyHost()) && StrUtils.isNotBlank(options.getProxyPort()) && MathUtils.canParseInt(options.getProxyPort())) {
res.add("-proxyHost=" + options.getProxyHost());
res.add("-proxyPort=" + options.getProxyPort());
res.add("--proxyHost");
res.add(options.getProxyHost());
res.add("--proxyPort");
res.add(options.getProxyPort());
if (StrUtils.isNotBlank(options.getProxyUser()) && StrUtils.isNotBlank(options.getProxyPass())) {
res.add("-proxyUsername=" + options.getProxyUser());
res.add("-proxyPassword=" + options.getProxyPass());
res.add("--proxyUser");
res.add(options.getProxyUser());
res.add("-=proxyPass");
res.add(options.getProxyPass());
}
}
@@ -18,17 +18,17 @@
package org.jackhuang.hellominecraft.launcher.core.launch;
import java.io.IOException;
import org.jackhuang.hellominecraft.utils.C;
import org.jackhuang.hellominecraft.utils.logging.HMCLog;
import java.util.HashSet;
import org.jackhuang.hellominecraft.util.C;
import org.jackhuang.hellominecraft.util.logging.HMCLog;
import org.jackhuang.hellominecraft.launcher.core.auth.IAuthenticator;
import org.jackhuang.hellominecraft.launcher.core.auth.LoginInfo;
import org.jackhuang.hellominecraft.launcher.core.download.DownloadLibraryJob;
import org.jackhuang.hellominecraft.launcher.core.service.IMinecraftService;
import org.jackhuang.hellominecraft.utils.tasks.ParallelTask;
import org.jackhuang.hellominecraft.utils.tasks.TaskWindow;
import org.jackhuang.hellominecraft.utils.system.Compressor;
import org.jackhuang.hellominecraft.utils.MessageBox;
import org.jackhuang.hellominecraft.utils.StrUtils;
import org.jackhuang.hellominecraft.util.tasks.ParallelTask;
import org.jackhuang.hellominecraft.util.tasks.TaskWindow;
import org.jackhuang.hellominecraft.util.system.Compressor;
import org.jackhuang.hellominecraft.util.MessageBox;
public class DefaultGameLauncher extends GameLauncher {
@@ -39,14 +39,19 @@ public class DefaultGameLauncher extends GameLauncher {
private void register() {
downloadLibrariesEvent.register((sender, t) -> {
final TaskWindow.TaskWindowFactory dw = TaskWindow.getInstance();
final TaskWindow.TaskWindowFactory dw = TaskWindow.factory();
ParallelTask parallelTask = new ParallelTask();
for (DownloadLibraryJob s : t)
HashSet<String> names = new HashSet<>();
for (DownloadLibraryJob s : t) {
if (names.contains(s.lib.name))
continue;
names.add(s.lib.name);
parallelTask.addDependsTask(new LibraryDownloadTask(s));
dw.addTask(parallelTask);
}
dw.append(parallelTask);
boolean flag = true;
if (t.size() > 0)
flag = dw.start();
flag = dw.create();
if (!flag && MessageBox.Show(C.i18n("launch.not_finished_downloading_libraries"), MessageBox.YES_NO_OPTION) == MessageBox.YES_OPTION)
flag = true;
return flag;
@@ -56,10 +61,9 @@ public class DefaultGameLauncher extends GameLauncher {
return false;
for (int i = 0; i < value.decompressFiles.length; i++)
try {
String[] rules = value.extractRules[i];
Compressor.unzip(value.decompressFiles[i], value.decompressTo, t -> !StrUtils.startsWithOne(rules, t), false);
Compressor.unzip(value.decompressFiles[i], value.getDecompressTo(), value.extractRules[i]::allow, false);
} catch (IOException ex) {
HMCLog.err("Unable to decompress library file: " + value.decompressFiles[i] + " to " + value.decompressTo, ex);
HMCLog.err("Unable to decompress library: " + value.decompressFiles[i] + " to " + value.getDecompressTo(), ex);
}
return true;
});
@@ -26,8 +26,8 @@ import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.UnsupportedEncodingException;
import java.util.List;
import org.jackhuang.hellominecraft.utils.C;
import org.jackhuang.hellominecraft.utils.logging.HMCLog;
import org.jackhuang.hellominecraft.util.C;
import org.jackhuang.hellominecraft.util.logging.HMCLog;
import org.jackhuang.hellominecraft.launcher.api.PluginManager;
import org.jackhuang.hellominecraft.launcher.core.GameException;
import org.jackhuang.hellominecraft.launcher.core.auth.IAuthenticator;
@@ -36,14 +36,14 @@ import org.jackhuang.hellominecraft.launcher.core.auth.UserProfileProvider;
import org.jackhuang.hellominecraft.launcher.core.auth.AuthenticationException;
import org.jackhuang.hellominecraft.launcher.core.download.DownloadLibraryJob;
import org.jackhuang.hellominecraft.launcher.core.version.DecompressLibraryJob;
import org.jackhuang.hellominecraft.utils.system.FileUtils;
import org.jackhuang.hellominecraft.utils.system.IOUtils;
import org.jackhuang.hellominecraft.utils.system.JavaProcess;
import org.jackhuang.hellominecraft.utils.MessageBox;
import org.jackhuang.hellominecraft.utils.system.OS;
import org.jackhuang.hellominecraft.utils.StrUtils;
import org.jackhuang.hellominecraft.utils.EventHandler;
import org.jackhuang.hellominecraft.utils.system.ProcessManager;
import org.jackhuang.hellominecraft.util.system.FileUtils;
import org.jackhuang.hellominecraft.util.system.IOUtils;
import org.jackhuang.hellominecraft.util.system.JavaProcess;
import org.jackhuang.hellominecraft.util.MessageBox;
import org.jackhuang.hellominecraft.util.system.OS;
import org.jackhuang.hellominecraft.util.StrUtils;
import org.jackhuang.hellominecraft.util.EventHandler;
import org.jackhuang.hellominecraft.util.system.ProcessManager;
public class GameLauncher {
@@ -53,10 +53,11 @@ public class GameLauncher {
LoginInfo info;
UserProfileProvider result;
IAuthenticator login;
public final EventHandler<List<DownloadLibraryJob>> downloadLibrariesEvent = new EventHandler(this);
public final EventHandler<List<String>> successEvent = new EventHandler(this);
public final EventHandler<JavaProcess> launchEvent = new EventHandler(this);
public final EventHandler<DecompressLibraryJob> decompressNativesEvent = new EventHandler(this);
public final EventHandler<List<DownloadLibraryJob>> downloadLibrariesEvent = new EventHandler<>(this);
public final EventHandler<List<String>> successEvent = new EventHandler<>(this);
public final EventHandler<JavaProcess> launchEvent = new EventHandler<>(this);
public final EventHandler<LaunchingState> launchingStateChangedEvent = new EventHandler<>(this);
public final EventHandler<DecompressLibraryJob> decompressNativesEvent = new EventHandler<>(this);
public GameLauncher(LaunchOptions options, IMinecraftService version, LoginInfo info, IAuthenticator lg) {
this.options = options;
@@ -76,7 +77,9 @@ public class GameLauncher {
}
public IMinecraftLoader makeLaunchCommand() throws AuthenticationException, GameException {
HMCLog.log("Building process");
HMCLog.log("Logging in...");
launchingStateChangedEvent.execute(LaunchingState.LoggingIn);
IMinecraftLoader loader;
if (info != null)
result = login.login(info);
@@ -84,19 +87,24 @@ public class GameLauncher {
result = login.loginBySettings();
if (result == null)
throw new AuthenticationException("Result can not be null.");
PluginManager.NOW_PLUGIN.onProcessingLoginResult(result);
PluginManager.plugin().onProcessingLoginResult(result);
launchingStateChangedEvent.execute(LaunchingState.GeneratingLaunchingCodes);
loader = service.launch(options, result);
File file = service.version().getDecompressNativesToLocation(loader.getMinecraftVersion());
if (file != null)
FileUtils.cleanDirectoryQuietly(file);
HMCLog.log("Detecting libraries...");
if (!downloadLibrariesEvent.execute(service.download().getDownloadLibraries(loader.getMinecraftVersion())))
throw new GameException("Failed to download libraries");
if (!options.isNotCheckGame()) {
HMCLog.log("Detecting libraries...");
launchingStateChangedEvent.execute(LaunchingState.DownloadingLibraries);
if (!downloadLibrariesEvent.execute(service.download().getDownloadLibraries(loader.getMinecraftVersion())))
throw new GameException("Failed to download libraries");
}
HMCLog.log("Unpacking natives...");
launchingStateChangedEvent.execute(LaunchingState.DecompressingNatives);
DecompressLibraryJob job = service.version().getDecompressLibraries(loader.getMinecraftVersion());
if (!decompressNativesEvent.execute(job))
throw new GameException("Failed to decompress natives");
@@ -112,26 +120,27 @@ public class GameLauncher {
*
* @throws IOException failed creating process
*/
public void launch(List str) throws IOException {
if (!service.version().onLaunch())
public void launch(List<String> str) throws IOException {
if (!service.version().onLaunch(options.getLaunchVersion()))
return;
if (StrUtils.isNotBlank(options.getPrecalledCommand())) {
Process p = Runtime.getRuntime().exec(options.getPrecalledCommand());
try {
if (p != null && p.isAlive())
if (p.isAlive())
p.waitFor();
} catch (InterruptedException ex) {
HMCLog.warn("Failed to invoke precalled command", ex);
}
}
HMCLog.log("Starting process");
HMCLog.log(str.toString());
ProcessBuilder builder = new ProcessBuilder(str);
if (options.getLaunchVersion() == null || service.baseDirectory() == null)
throw new Error("Fucking bug!");
builder.directory(service.version().getRunDirectory(options.getLaunchVersion()))
builder.redirectErrorStream(true).directory(service.version().getRunDirectory(options.getLaunchVersion()))
.environment().put("APPDATA", service.baseDirectory().getAbsolutePath());
JavaProcess jp = new JavaProcess(str, builder.start(), PROCESS_MANAGER);
HMCLog.log("The game process have been started");
HMCLog.log("Have started the process");
launchEvent.execute(jp);
}
@@ -147,11 +156,11 @@ public class GameLauncher {
*/
public File makeLauncher(String launcherName, List str) throws IOException {
HMCLog.log("Making shell launcher...");
service.version().onLaunch();
service.version().onLaunch(options.getLaunchVersion());
boolean isWin = OS.os() == OS.WINDOWS;
File f = new File(launcherName + (isWin ? ".bat" : ".sh"));
if (!f.exists())
f.createNewFile();
if (!f.exists() && !f.createNewFile())
HMCLog.warn("Failed to create " + f);
BufferedWriter writer;
try {
writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(f), System.getProperty("sun.jnu.encoding", "UTF-8")));
@@ -166,6 +175,8 @@ public class GameLauncher {
if (appdata != null) {
writer.write("set appdata=" + appdata);
writer.newLine();
writer.write("cd /D %appdata%");
writer.newLine();
}
}
if (StrUtils.isNotBlank(options.getPrecalledCommand())) {
@@ -18,10 +18,9 @@
package org.jackhuang.hellominecraft.launcher.core.launch;
import java.io.File;
import org.jackhuang.hellominecraft.launcher.core.service.IMinecraftService;
import org.jackhuang.hellominecraft.launcher.core.version.GameDirType;
import org.jackhuang.hellominecraft.utils.StrUtils;
import org.jackhuang.hellominecraft.utils.system.JdkVersion;
import org.jackhuang.hellominecraft.util.StrUtils;
import org.jackhuang.hellominecraft.util.system.JdkVersion;
/**
*
@@ -29,15 +28,13 @@ import org.jackhuang.hellominecraft.utils.system.JdkVersion;
*/
public class LaunchOptions {
private String name, versionName, javaArgs, minecraftArgs, maxMemory, permSize, width, height, userProperties, serverIp;
private String proxyHost, proxyPort, proxyUser, proxyPass, javaDir, launchVersion;
private boolean fullscreen, debug, noJVMArgs, canceledWrapper;
private String name, versionName, javaArgs, minecraftArgs, maxMemory, permSize, width, height, serverIp, wrapper;
private String proxyHost, proxyPort, proxyUser, proxyPass, javaDir, launchVersion, type, precalledCommand;
private boolean fullscreen, noJVMArgs, notCheckGame;
private JdkVersion java;
private File gameDir;
private GameDirType gameDirType;
protected transient IMinecraftService service;
public String getVersionName() {
return versionName;
}
@@ -98,6 +95,14 @@ public class LaunchOptions {
this.maxMemory = maxMemory;
}
public String getWrapper() {
return wrapper;
}
public void setWrapper(String wrapper) {
this.wrapper = wrapper;
}
public String getWidth() {
return width;
}
@@ -114,16 +119,6 @@ public class LaunchOptions {
this.height = height;
}
public String getUserProperties() {
if (userProperties == null)
return "";
return userProperties;
}
public void setUserProperties(String userProperties) {
this.userProperties = userProperties;
}
public boolean isFullscreen() {
return fullscreen;
}
@@ -132,14 +127,6 @@ public class LaunchOptions {
this.fullscreen = fullscreen;
}
public boolean isDebug() {
return debug;
}
public void setDebug(boolean debug) {
this.debug = debug;
}
public GameDirType getGameDirType() {
return gameDirType;
}
@@ -172,14 +159,6 @@ public class LaunchOptions {
this.minecraftArgs = minecraftArgs;
}
public boolean isCanceledWrapper() {
return canceledWrapper;
}
public void setCanceledWrapper(boolean canceledWrapper) {
this.canceledWrapper = canceledWrapper;
}
public String getServerIp() {
return serverIp;
}
@@ -220,8 +199,6 @@ public class LaunchOptions {
this.proxyPass = proxyPass;
}
private String precalledCommand;
public String getPrecalledCommand() {
return precalledCommand;
}
@@ -237,4 +214,20 @@ public class LaunchOptions {
public void setLaunchVersion(String launchVersion) {
this.launchVersion = launchVersion;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public boolean isNotCheckGame() {
return notCheckGame;
}
public void setNotCheckGame(boolean notCheckGame) {
this.notCheckGame = notCheckGame;
}
}
@@ -15,15 +15,15 @@
* 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.assets;
package org.jackhuang.hellominecraft.launcher.core.launch;
/**
*
* @author huangyuhui
*/
public class Contents {
public String key, eTag, lastModified, storageClass;
public long size;
public enum LaunchingState {
LoggingIn,
GeneratingLaunchingCodes,
DownloadingLibraries,
DecompressingNatives
}
@@ -0,0 +1,76 @@
/*
* Hello Minecraft! Launcher.
* Copyright (C) 2013 huangyuhui
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see {http://www.gnu.org/licenses/}.
*/
package org.jackhuang.hellominecraft.launcher.core.launch;
import java.io.File;
import java.net.URL;
import org.jackhuang.hellominecraft.util.C;
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;
/**
*
* @author huangyuhui
*/
public class LibraryDownloadTask extends FileDownloadTask {
DownloadLibraryJob job;
public LibraryDownloadTask(DownloadLibraryJob job) {
super();
this.job = job;
}
@Override
public void executeTask() throws Throwable {
String name = job.lib.name;
if (name.startsWith("net.minecraftforge:forge:")) {
String[] s = name.split(":");
if (s.length == 3)
job.url = "http://files.minecraftforge.net/maven/net/minecraftforge/forge/" + s[2] + "/forge-" + s[2] + "-universal.jar";
}
if (name.startsWith("com.mumfrey:liteloader:")) {
String[] s = name.split(":");
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";
}
download(new URL(job.url), job.retryUrl, job.path);
}
void download(URL url, String retryUrl, File filePath) throws Throwable {
this.url = url;
this.filePath = filePath;
if (StrUtils.isNotBlank(retryUrl)) {
this.failedCallbackReturnsNewURL = new Function<Integer, String>() {
@Override
public String apply(Integer t) {
return retryUrl;
}
};
}
super.executeTask();
}
@Override
public String getInfo() {
return C.i18n("download") + ": " + job.lib.name;
}
}
@@ -0,0 +1,129 @@
/*
* Hello Minecraft! Launcher.
* Copyright (C) 2013 huangyuhui
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see {http://www.gnu.org/licenses/}.
*/
package org.jackhuang.hellominecraft.launcher.core.launch;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import org.jackhuang.hellominecraft.util.StrUtils;
import org.jackhuang.hellominecraft.util.logging.HMCLog;
import org.jackhuang.hellominecraft.util.system.IOUtils;
import org.jackhuang.hellominecraft.util.system.OS;
import org.jackhuang.hellominecraft.launcher.core.GameException;
import org.jackhuang.hellominecraft.launcher.core.auth.UserProfileProvider;
import org.jackhuang.hellominecraft.launcher.core.version.MinecraftLibrary;
import org.jackhuang.hellominecraft.launcher.core.version.MinecraftVersion;
import org.jackhuang.hellominecraft.launcher.core.service.IMinecraftService;
import org.jackhuang.hellominecraft.util.func.BiFunction;
/**
*
* @author huangyuhui
*/
public class MinecraftLoader extends AbstractMinecraftLoader {
public MinecraftLoader(LaunchOptions p, IMinecraftService provider, UserProfileProvider lr) throws GameException {
super(p, provider, p.getLaunchVersion(), lr);
}
@Override
protected void makeSelf(List<String> res) throws GameException {
StringBuilder library = new StringBuilder("");
ArrayList<MinecraftLibrary> opt = new ArrayList<>();
for (MinecraftLibrary l : version.libraries)
if (l.allow() && !l.isRequiredToUnzip()) {
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());
if (!f.exists())
throw new GameException("Minecraft jar does not exists");
library.append(IOUtils.tryGetCanonicalFilePath(f)).append(File.pathSeparator);
res.add("-cp");
res.add(library.toString().substring(0, library.length() - File.pathSeparator.length()));
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 game_assets = assetProvider.apply(version, !options.isNotCheckGame());
for (String t : splitted) {
t = t.replace("${auth_player_name}", lr.getUserName());
t = t.replace("${auth_session}", lr.getSession());
t = t.replace("${auth_uuid}", lr.getUserId());
t = t.replace("${version_name}", options.getVersionName());
t = t.replace("${profile_name}", options.getName());
t = t.replace("${version_type}", options.getType());
t = t.replace("${game_directory}", service.version().getRunDirectory(version.id).getAbsolutePath());
t = t.replace("${game_assets}", game_assets);
t = t.replace("${assets_root}", service.asset().getAssets().getAbsolutePath());
t = t.replace("${auth_access_token}", lr.getAccessToken());
t = t.replace("${user_type}", lr.getUserType());
t = t.replace("${assets_index_name}", version.getAssetsIndex().getId());
t = t.replace("${user_properties}", lr.getUserProperties());
res.add(t);
}
if (res.indexOf("--gameDir") != -1 && res.indexOf("--workDir") != -1) {
res.add("--workDir");
res.add(gameDir.getAbsolutePath());
}
}
@Override
protected void appendJVMArgs(List<String> list) {
super.appendJVMArgs(list);
try {
if (OS.os() == OS.OSX) {
list.add("-Xdock:icon=" + service.asset().getAssetObject(version.getAssetsIndex().getId(), "icons/minecraft.icns").getAbsolutePath());
list.add("-Xdock:name=Minecraft");
}
} catch (IOException e) {
HMCLog.err("Failed to append jvm arguments when searching for asset objects.", e);
}
}
private final BiFunction<MinecraftVersion, Boolean, String> DEFAULT_ASSET_PROVIDER = (t, allow) -> {
return new File(service.baseDirectory(), "assets").getAbsolutePath();
};
private BiFunction<MinecraftVersion, Boolean, String> assetProvider = DEFAULT_ASSET_PROVIDER;
public void setAssetProvider(BiFunction<MinecraftVersion, Boolean, String> assetProvider) {
if (assetProvider == null)
this.assetProvider = DEFAULT_ASSET_PROVIDER;
else
this.assetProvider = assetProvider;
}
}
@@ -25,12 +25,11 @@ import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.jackhuang.hellominecraft.utils.logging.HMCLog;
import org.jackhuang.hellominecraft.util.logging.HMCLog;
import org.jackhuang.hellominecraft.launcher.core.service.IMinecraftModService;
import org.jackhuang.hellominecraft.launcher.core.service.IMinecraftService;
import org.jackhuang.hellominecraft.launcher.core.ModInfo;
import org.jackhuang.hellominecraft.utils.code.DigestUtils;
import org.jackhuang.hellominecraft.utils.system.FileUtils;
import org.jackhuang.hellominecraft.util.code.DigestUtils;
import org.jackhuang.hellominecraft.util.system.FileUtils;
/**
*
@@ -59,22 +58,18 @@ public class MinecraftModService extends IMinecraftModService {
File[] fs = modsFolder.listFiles();
if (fs != null)
for (File f : fs)
if (ModInfo.isFileMod(f)) {
ModInfo m = ModInfo.readModInfo(f);
if (m != null)
mods.add(m);
} else if (f.isDirectory()) {
if (ModInfo.isFileMod(f))
mods.add(ModInfo.readModInfo(f));
else if (f.isDirectory()) {
File[] ss = f.listFiles();
if (ss != null)
for (File ff : ss)
if (ModInfo.isFileMod(ff)) {
ModInfo m = ModInfo.readModInfo(ff);
if (m != null)
mods.add(m);
}
if (ModInfo.isFileMod(ff))
mods.add(ModInfo.readModInfo(ff));
}
Collections.sort(mods);
return modCache.put(id, mods);
modCache.put(id, mods);
return mods;
}
@Override
@@ -82,10 +77,11 @@ public class MinecraftModService extends IMinecraftModService {
try {
if (!ModInfo.isFileMod(f))
return false;
if (!modCache.containsKey(id))
recacheMods(id);
File modsFolder = service.version().getRunDirectory(id, "mods");
if (modsFolder == null)
return false;
modsFolder.mkdirs();
if (!modsFolder.exists() && !modsFolder.mkdirs())
HMCLog.warn("Failed to make directories: " + modsFolder);
File newf = new File(modsFolder, f.getName());
FileUtils.copyFile(f, newf);
ModInfo i = ModInfo.readModInfo(f);
@@ -102,10 +98,12 @@ public class MinecraftModService extends IMinecraftModService {
if (rows.length == 0)
return;
for (Object r : rows)
if (r instanceof ModInfo)
((ModInfo) r).location.delete();
else if (r instanceof Number)
getMods(id).get(((Number) r).intValue()).location.delete();
if (r instanceof ModInfo) {
if (!((ModInfo) r).location.delete())
HMCLog.warn("Failed to delete mod" + r);
} else if (r instanceof Number)
if (!getMods(id).get(((Number) r).intValue()).location.delete())
HMCLog.warn("Failed to delete mod " + r + ", maybe not a file?");
recacheMods(id);
}
@@ -15,9 +15,13 @@
* 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;
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.annotations.SerializedName;
import com.google.gson.reflect.TypeToken;
import java.io.File;
import java.io.IOException;
@@ -25,10 +29,10 @@ import java.io.InputStreamReader;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import org.jackhuang.hellominecraft.utils.C;
import org.jackhuang.hellominecraft.utils.logging.HMCLog;
import org.jackhuang.hellominecraft.utils.StrUtils;
import org.jackhuang.hellominecraft.utils.system.FileUtils;
import org.jackhuang.hellominecraft.util.C;
import org.jackhuang.hellominecraft.util.logging.HMCLog;
import org.jackhuang.hellominecraft.util.StrUtils;
import org.jackhuang.hellominecraft.util.system.FileUtils;
/**
*
@@ -36,9 +40,30 @@ import org.jackhuang.hellominecraft.utils.system.FileUtils;
*/
public class ModInfo implements Comparable<ModInfo> {
@SerializedName("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;
@SerializedName("authors")
public String[] authors;
public boolean isActive() {
return !location.getName().endsWith(".disabled");
@@ -56,7 +81,7 @@ public class ModInfo implements Comparable<ModInfo> {
@Override
public int compareTo(ModInfo o) {
return getFileName().toLowerCase().compareTo(o.getFileName().toLowerCase());
return getFileName().compareToIgnoreCase(o.getFileName());
}
public String getName() {
@@ -66,6 +91,8 @@ public class ModInfo implements Comparable<ModInfo> {
public String getAuthor() {
if (authorList != null && authorList.length > 0)
return StrUtils.parseParams("", authorList, ", ");
else if (authors != null && authors.length > 0)
return StrUtils.parseParams("", authors, ", ");
else if (StrUtils.isNotBlank(author))
return author;
else
@@ -103,21 +130,33 @@ public class ModInfo implements Comparable<ModInfo> {
}
private static ModInfo getForgeModInfo(File f, ZipFile jar, ZipEntry entry) throws IOException {
ModInfo i = new ModInfo();
i.location = f;
List<ModInfo> m = C.gson.fromJson(new InputStreamReader(jar.getInputStream(entry)),
new TypeToken<List<ModInfo>>() {
}.getType());
if (m != null && m.size() > 0) {
i = m.get(0);
i.location = f;
}
return i;
ModInfo i = new ModInfo();
i.location = f;
InputStreamReader streamReader = new InputStreamReader(jar.getInputStream(entry), "UTF-8");
JsonParser parser = new JsonParser();
JsonElement element = parser.parse(streamReader);
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 {
ModInfo m = C.gson.fromJson(new InputStreamReader(jar.getInputStream(entry)),
ModInfo.class);
ModInfo m = C.GSON.fromJson(new InputStreamReader(jar.getInputStream(entry), "UTF-8"), ModInfo.class);
if (m == null)
m = new ModInfo();
m.location = f;
@@ -0,0 +1,283 @@
/*
* 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.mod;
import java.awt.Dimension;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.file.FileSystemException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.zip.ZipFile;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import org.jackhuang.hellominecraft.util.C;
import org.jackhuang.hellominecraft.util.logging.HMCLog;
import org.jackhuang.hellominecraft.launcher.core.GameException;
import org.jackhuang.hellominecraft.launcher.core.service.IMinecraftProvider;
import org.jackhuang.hellominecraft.launcher.core.service.IMinecraftService;
import org.jackhuang.hellominecraft.launcher.core.version.MinecraftVersion;
import org.jackhuang.hellominecraft.util.func.BiFunction;
import org.jackhuang.hellominecraft.util.func.CallbackIO;
import org.jackhuang.hellominecraft.util.system.Compressor;
import org.jackhuang.hellominecraft.util.system.FileUtils;
import org.jackhuang.hellominecraft.util.system.ZipEngine;
import org.jackhuang.hellominecraft.util.tasks.Task;
import org.jackhuang.hellominecraft.util.ui.WebPage;
import org.jackhuang.hellominecraft.util.MinecraftVersionRequest;
import org.jackhuang.hellominecraft.util.tasks.NoShownTaskException;
/**
* A mod pack(*.zip) includes these things:
* <ul>
* <li>sth created by the game automatically, including "mods", "scripts",
* "config", etc..
* <li>pack.json, the same as Minecraft version configuration file:
* "gameDir/versions/{MCVER}/{MCVER}.json", will be renamed to that one.
* <li>all things should be included in "minecraft" folder under the root
* folder.
* </ul>
*
* This class can manage mod packs, for example, importing and exporting, the
* format of game is the offical one.
* Not compatible with MultiMC(no instance.cfg processor) & FTB(not leaving
* mcversion(jar) in pack.json).
*
* @author huangyuhui
*/
public final class ModpackManager {
/**
* Install the compressed modpack.
*
* @param input modpack.zip
* @param service MinecraftService, whose version service only supports
* MinecraftVersionManager.
* @param id new version id, if null, will use suggested name from
* modpack
*
* @return The installing Task, may take long time, please consider
* TaskWindow.
*/
public static Task install(JFrame parFrame, final File input, final IMinecraftService service, final String idFUCK) {
return new Task() {
Collection<Task> c = new ArrayList<>();
@Override
public void executeTask() throws Throwable {
String id = idFUCK;
String description = C.i18n("modpack.task.install.will");
// Read modpack name and description from `modpack.json`
try (ZipFile zip = new ZipFile(input)) {
HashMap map = C.GSON.fromJson(new InputStreamReader(zip.getInputStream(zip.getEntry("modpack.json")), "UTF-8"), HashMap.class);
if (map != null) {
if (id == null)
if (map.containsKey("name") && map.get("name") instanceof String)
id = (String) map.get("name");
if (id != null)
description += id;
if (map.containsKey("description") && map.get("description") instanceof String)
description += "\n" + (String) map.get("description");
}
if (id == null)
throw new IllegalStateException("Illegal modpack id!");
}
// Show a window to let the user know that what and how the modpack is.
Object msgs[] = new Object[2];
msgs[0] = C.i18n("modpack.task.install");
msgs[1] = new WebPage(description);
((WebPage) msgs[1]).setPreferredSize(new Dimension(800, 350));
int result = JOptionPane.showOptionDialog(parFrame, msgs, (String) msgs[0], JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE, null, null, null);
if (result == JOptionPane.NO_OPTION)
throw new NoShownTaskException("Operation was canceled by user.");
File versions = new File(service.baseDirectory(), "versions");
// `minecraft` folder is the existent root folder of the modpack
// Then we will decompress the modpack and there would be a folder named `minecraft`
// So if `minecraft` folder does exist, backup it and then restore it.
File oldFile = new File(versions, "minecraft"), newFile = null;
if (oldFile.exists()) {
newFile = new File(versions, "minecraft-" + System.currentTimeMillis());
if (newFile.isDirectory())
FileUtils.deleteDirectory(newFile);
else if (newFile.isFile())
if (!newFile.delete())
HMCLog.warn("Failed to delete file " + newFile);
if (!oldFile.renameTo(newFile))
HMCLog.warn("Failed to rename " + oldFile + " to " + newFile);
}
// If the user install the modpack into an existent version, maybe it wants to update the modpack
// So backup the game, copy the saved games.
File preVersion = new File(versions, id), preVersionRenamed = null;
if (preVersion.exists()) {
HMCLog.log("Backing up the game");
String preId = id + "-" + System.currentTimeMillis();
if (!preVersion.renameTo(preVersionRenamed = new File(versions, preId)))
HMCLog.warn("Failed to rename pre-version folder " + preVersion + " to a temp folder " + preVersionRenamed);
if (!new File(preVersionRenamed, id + ".json").renameTo(new File(preVersionRenamed, preId + ".json")))
HMCLog.warn("Failed to rename pre json to new json");
if (!new File(preVersionRenamed, id + ".jar").renameTo(new File(preVersionRenamed, preId + ".jar")))
HMCLog.warn("Failed to rename pre jar to new jar");
}
try {
final AtomicInteger b = new AtomicInteger(0);
HMCLog.log("Decompressing modpack");
Compressor.unzip(input, versions, t -> {
if (t.equals("minecraft/pack.json"))
b.incrementAndGet();
return true;
}, true);
// No pack.json here, illegal modpack.
if (b.get() < 1)
throw new FileNotFoundException(C.i18n("modpack.incorrect_format.no_json"));
File nowFile = new File(versions, id);
if (oldFile.exists() && !oldFile.renameTo(nowFile))
HMCLog.warn("Failed to rename incorrect json " + oldFile + " to " + nowFile);
File json = new File(nowFile, "pack.json");
MinecraftVersion mv = C.GSON.fromJson(FileUtils.read(json), MinecraftVersion.class);
if (mv.jar == null)
throw new FileNotFoundException(C.i18n("modpack.incorrect_format.no_jar"));
c.add(service.download().downloadMinecraftJar(mv, new File(nowFile, id + ".jar")));
mv.jar = null;
FileUtils.write(json, C.GSON.toJson(mv));
if (!json.renameTo(new File(nowFile, id + ".json")))
HMCLog.warn("Failed to rename pack.json to new id");
// Restore the saved game from the old version.
if (preVersionRenamed != null) {
HMCLog.log("Restoring saves");
File presaves = new File(preVersionRenamed, "saves");
File saves = new File(nowFile, "saves");
if (presaves.exists()) {
FileUtils.deleteDirectory(saves);
FileUtils.copyDirectory(presaves, saves);
}
}
} finally {
FileUtils.deleteDirectoryQuietly(oldFile);
if (newFile != null)
newFile.renameTo(oldFile);
}
}
@Override
public String getInfo() {
return C.i18n("modpack.task.install");
}
@Override
public Collection<Task> getAfterTasks() {
return c;
}
};
}
public static final List<String> MODPACK_BLACK_LIST = Arrays.asList(new String[] { "usernamecache.json", "asm", "logs", "backups", "versions", "assets", "usercache.json", "libraries", "crash-reports", "launcher_profiles.json", "NVIDIA", "AMD", "TCNodeTracker", "screenshots", "natives", "native", "$native", "pack.json", "launcher.jar", "minetweaker.log", "launcher.pack.lzma", "hmclmc.log" });
public static final List<String> MODPACK_SUGGESTED_BLACK_LIST = Arrays.asList(new String[] { "fonts", "saves", "servers.dat", "options.txt", "optionsof.txt", "journeymap", "optionsshaders.txt", "mods/VoxelMods" });
/**
* &lt; String, Boolean, Boolean &gt;: Folder/File name, Is Directory,
* Return 0: non blocked, 1: non shown, 2: suggested, checked.
*/
public static final BiFunction<String, Boolean, Integer> MODPACK_PREDICATE = (String x, Boolean y) -> {
if (ModpackManager.MODPACK_BLACK_LIST_PREDICATE.apply(x, y))
return 1;
if (ModpackManager.MODPACK_SUGGESTED_BLACK_LIST_PREDICATE.apply(x, y))
return 2;
return 0;
};
public static final BiFunction<String, Boolean, Boolean> MODPACK_BLACK_LIST_PREDICATE = modpackPredicateMaker(MODPACK_BLACK_LIST);
public static final BiFunction<String, Boolean, Boolean> MODPACK_SUGGESTED_BLACK_LIST_PREDICATE = modpackPredicateMaker(MODPACK_SUGGESTED_BLACK_LIST);
private static BiFunction<String, Boolean, Boolean> modpackPredicateMaker(final List<String> l) {
return (String x, Boolean y) -> {
for (String s : l)
if (y) {
if (x.startsWith(s + "/"))
return true;
} else if (x.equals(s))
return true;
return false;
};
}
/**
* Export the game to a mod pack file.
*
* @param output mod pack file.
* @param baseFolder if the game dir type is ROOT_FOLDER, use ".minecraft",
* or use ".minecraft/versions/{MCVER}/"
* @param version to locate version.json
*
* @throws IOException if create tmp directory failed
*/
public static void export(File output, IMinecraftProvider provider, String version, List<String> blacklist, Map modpackJson, CallbackIO<ZipEngine> callback) throws IOException, GameException {
final ArrayList<String> b = new ArrayList<>(MODPACK_BLACK_LIST);
if (blacklist != null)
b.addAll(blacklist);
b.add(version + ".jar");
b.add(version + ".json");
HMCLog.log("Compressing game files without some files in blacklist, including files or directories: usernamecache.json, asm, logs, backups, versions, assets, usercache.json, libraries, crash-reports, launcher_profiles.json, NVIDIA, TCNodeTracker");
ZipEngine zip = null;
try {
zip = new ZipEngine(output);
zip.putDirectory(provider.getRunDirectory(version), (String x, Boolean y) -> {
for (String s : b)
if (y) {
if (x.startsWith(s + "/"))
return null;
} else if (x.equals(s))
return null;
return "minecraft/" + x;
});
MinecraftVersion mv = provider.getVersionById(version).resolve(provider);
MinecraftVersionRequest r = MinecraftVersionRequest.minecraftVersion(provider.getMinecraftJar(version));
if (r.type != MinecraftVersionRequest.OK)
throw new FileSystemException(C.i18n("modpack.cannot_read_version") + ": " + MinecraftVersionRequest.getResponse(r));
mv.jar = r.version;
mv.runDir = "version";
zip.putTextFile(C.GSON.toJson(mv), "minecraft/pack.json");
zip.putTextFile(C.GSON.toJson(modpackJson), "modpack.json");
if (callback != null)
callback.call(zip);
} finally {
if (zip != null)
zip.closeFile();
}
}
}
@@ -19,7 +19,8 @@ package org.jackhuang.hellominecraft.launcher.core.service;
import java.io.File;
import java.io.IOException;
import org.jackhuang.hellominecraft.utils.tasks.Task;
import org.jackhuang.hellominecraft.launcher.core.version.AssetIndexDownloadInfo;
import org.jackhuang.hellominecraft.util.tasks.Task;
/**
*
@@ -44,7 +45,9 @@ public abstract class IMinecraftAssetService extends IMinecraftBasicService {
*/
public abstract boolean refreshAssetsIndex(String a);
public abstract boolean downloadMinecraftAssetsIndex(String assetsId);
public abstract boolean downloadMinecraftAssetsIndexAsync(AssetIndexDownloadInfo assetsId);
public abstract Task downloadMinecraftAssetsIndex(AssetIndexDownloadInfo assetsId);
public abstract File getAssetObject(String assetVersion, String name) throws IOException;
}
@@ -22,8 +22,7 @@ import java.util.List;
import org.jackhuang.hellominecraft.launcher.core.GameException;
import org.jackhuang.hellominecraft.launcher.core.download.DownloadLibraryJob;
import org.jackhuang.hellominecraft.launcher.core.version.MinecraftVersion;
import org.jackhuang.hellominecraft.utils.version.MinecraftRemoteVersion;
import rx.Observable;
import org.jackhuang.hellominecraft.util.tasks.Task;
/**
*
@@ -35,13 +34,11 @@ public abstract class IMinecraftDownloadService extends IMinecraftBasicService {
super(service);
}
public abstract MinecraftVersion downloadMinecraft(String id);
public abstract Task downloadMinecraft(String id);
public abstract boolean downloadMinecraftJar(String id);
public abstract Task downloadMinecraftJar(MinecraftVersion mv, File f);
public abstract boolean downloadMinecraftJarTo(String id, File f);
public abstract boolean downloadMinecraftVersionJson(String id);
public abstract Task downloadMinecraftVersionJson(String id);
/**
* Get the libraries that need to download.
@@ -50,6 +47,4 @@ public abstract class IMinecraftDownloadService extends IMinecraftBasicService {
*/
public abstract List<DownloadLibraryJob> getDownloadLibraries(MinecraftVersion mv) throws GameException;
public abstract Observable<MinecraftRemoteVersion> getRemoteVersions();
}
@@ -17,9 +17,9 @@
*/
package org.jackhuang.hellominecraft.launcher.core.service;
import org.jackhuang.hellominecraft.launcher.core.installers.InstallerType;
import org.jackhuang.hellominecraft.launcher.core.installers.InstallerVersionList;
import org.jackhuang.hellominecraft.utils.tasks.Task;
import org.jackhuang.hellominecraft.launcher.core.install.InstallerType;
import org.jackhuang.hellominecraft.launcher.core.install.InstallerVersionList;
import org.jackhuang.hellominecraft.util.tasks.Task;
/**
*
@@ -35,7 +35,7 @@ public abstract class IMinecraftInstallerService extends IMinecraftBasicService
public abstract Task downloadForge(String installId, InstallerVersionList.InstallerVersion v);
public abstract Task downloadOptifine(String installId, InstallerVersionList.InstallerVersion v);
public abstract Task downloadOptiFine(String installId, InstallerVersionList.InstallerVersion v);
public abstract Task downloadLiteLoader(String installId, InstallerVersionList.InstallerVersion v);
@@ -19,7 +19,7 @@ package org.jackhuang.hellominecraft.launcher.core.service;
import java.io.File;
import java.util.List;
import org.jackhuang.hellominecraft.launcher.core.ModInfo;
import org.jackhuang.hellominecraft.launcher.core.mod.ModInfo;
/**
*
@@ -21,9 +21,10 @@ import java.io.File;
import java.util.Collection;
import org.jackhuang.hellominecraft.launcher.core.GameException;
import org.jackhuang.hellominecraft.launcher.core.version.DecompressLibraryJob;
import org.jackhuang.hellominecraft.launcher.core.version.GameDirType;
import org.jackhuang.hellominecraft.launcher.core.version.MinecraftVersion;
import org.jackhuang.hellominecraft.utils.functions.Consumer;
import org.jackhuang.hellominecraft.util.EventHandler;
import org.jackhuang.hellominecraft.util.func.Consumer;
import org.jackhuang.hellominecraft.util.func.Predicate;
/**
* Provide everything of the Minecraft of a Profile.
@@ -54,6 +55,8 @@ public abstract class IMinecraftProvider {
*/
public abstract File getRunDirectory(String id);
public abstract File versionRoot(String id);
public File getRunDirectory(String id, String subFolder) {
return new File(getRunDirectory(id), subFolder);
}
@@ -69,13 +72,6 @@ public abstract class IMinecraftProvider {
*/
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
@@ -91,12 +87,6 @@ public abstract class IMinecraftProvider {
*/
public abstract File getMinecraftJar(String id);
protected GameDirType gameDirType = GameDirType.ROOT_FOLDER;
public void setGameDirType(GameDirType gameDirType) {
this.gameDirType = gameDirType;
}
/**
* Rename version
*
@@ -121,7 +111,7 @@ public abstract class IMinecraftProvider {
*
* @return the version
*/
public abstract MinecraftVersion getOneVersion();
public abstract MinecraftVersion getOneVersion(Predicate<MinecraftVersion> p);
/**
* All Minecraft version in this profile.
@@ -148,9 +138,15 @@ public abstract class IMinecraftProvider {
/**
* Refind the versions in this profile.
* Must call onRefreshingVersions, onRefreshedVersions, onLoadedVersion
* Events.
*/
public abstract void refreshVersions();
public final EventHandler<IMinecraftService> onRefreshingVersions = new EventHandler<>(this),
onRefreshedVersions = new EventHandler<>(this);
public final EventHandler<String> onLoadedVersion = new EventHandler<>(this);
/**
* Clean redundant files.
*/
@@ -161,6 +157,10 @@ public abstract class IMinecraftProvider {
*
* @return if false, will break the launch process.
*/
public abstract boolean onLaunch();
public abstract boolean onLaunch(String id);
public File baseDirectory() {
return service.baseDirectory();
}
}
@@ -0,0 +1,50 @@
/*
* 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 org.jackhuang.hellominecraft.launcher.core.download.DownloadType;
/**
*
* @author huangyuhui
*/
public class AssetIndexDownloadInfo extends GameDownloadInfo {
int totalSize;
public AssetIndexDownloadInfo() {
}
public AssetIndexDownloadInfo(String id) {
this.id = id;
url = null;
}
@Override
public String getCustomizedURL(DownloadType dt) {
return dt.getProvider().getIndexesDownloadURL() + id + ".json";
}
public String getId() {
return id;
}
public int getTotalSize() {
return totalSize;
}
}
@@ -26,12 +26,20 @@ import java.io.File;
public class DecompressLibraryJob {
public File[] decompressFiles;
public String[][] extractRules;
public File decompressTo;
public Extract[] extractRules;
private File decompressTo;
public DecompressLibraryJob(File[] decompressFiles, String[][] extractRules, File decompressTo) {
this.decompressFiles = decompressFiles;
this.extractRules = extractRules;
public DecompressLibraryJob(File[] decompressFiles, Extract[] extractRules, File decompressTo) {
this.decompressFiles = decompressFiles.clone();
this.extractRules = extractRules.clone();
this.decompressTo = decompressTo;
}
public File getDecompressTo() {
return decompressTo;
}
public void setDecompressTo(File decompressTo) {
this.decompressTo = decompressTo;
}
@@ -0,0 +1,48 @@
/*
* 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 java.util.ArrayList;
import java.util.List;
import org.jackhuang.hellominecraft.util.StrUtils;
/**
*
* @author huangyuhui
*/
public class Extract implements Cloneable {
@SerializedName("exclude")
public List<String> exclude = new ArrayList<>();
public boolean allow(String path) {
return !StrUtils.startsWithOne(exclude, path);
}
@Override
@SuppressWarnings("CloneDeclaresCloneNotSupported")
public Object clone() {
try {
return super.clone();
} catch (CloneNotSupportedException ex) {
throw new InternalError(ex);
}
}
}
@@ -0,0 +1,79 @@
/*
* 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;
/**
*
* @author huangyuhui
*/
public class GameDownloadInfo implements Cloneable {
@SerializedName("sha1")
public String sha1;
@SerializedName("size")
public int size;
@SerializedName("url")
protected String url;
/**
* Ready for AssetIndexDownloadInfo, and GameDownloadInfo also need this.
*/
public String id = null;
/**
* Get the game download url.
*
* @param dt where to download?
*
* @return the download url
*/
public String getUrl(DownloadType dt) {
return getUrl(dt, dt.getProvider().isAllowedToUseSelfURL());
}
/**
* Get the game download url.
*
* @param dt where to download?
* @param allowSelf allow this game to be downloaded from its modified url?
*
* @return the download url
*/
public String getUrl(DownloadType dt, boolean allowSelf) {
if (url != null && allowSelf)
return dt.getProvider().getParsedDownloadURL(url);
else
return getCustomizedURL(dt);
}
protected String getCustomizedURL(DownloadType dt) {
return dt.getProvider().getVersionsDownloadURL() + id + "/" + id + ".jar";
}
@Override
public Object clone() {
try {
return super.clone();
} catch (CloneNotSupportedException ex) {
throw new Error(ex);
}
}
}
@@ -18,7 +18,6 @@
package org.jackhuang.hellominecraft.launcher.core.version;
import java.io.File;
import org.jackhuang.hellominecraft.launcher.core.download.DownloadType;
/**
*
@@ -34,16 +33,14 @@ public abstract class IMinecraftLibrary implements Cloneable {
public abstract boolean isRequiredToUnzip();
public abstract String[] getDecompressExtractRules();
public abstract Extract getDecompressExtractRules();
public abstract void init();
public abstract LibraryDownloadInfo getDownloadInfo();
public abstract boolean allow();
public abstract File getFilePath(File gameDir);
public abstract String getDownloadURL(String urlBase, DownloadType downloadType);
@Override
public boolean equals(Object obj) {
if (obj instanceof MinecraftLibrary)
@@ -59,5 +56,12 @@ public abstract class IMinecraftLibrary implements Cloneable {
}
@Override
public abstract Object clone();
@SuppressWarnings("CloneDeclaresCloneNotSupported")
public Object clone() {
try {
return super.clone();
} catch (CloneNotSupportedException ex) {
throw new InternalError(ex);
}
}
}
@@ -17,20 +17,17 @@
*/
package org.jackhuang.hellominecraft.launcher.core.version;
import com.google.gson.annotations.SerializedName;
import java.util.Map;
/**
*
* @author huangyuhui
*/
public class Natives implements Cloneable {
public class LibrariesDownloadInfo {
public String windows, osx, linux;
@Override
protected Object clone() {
Natives n = new Natives();
n.windows = windows;
n.osx = osx;
n.linux = linux;
return n;
}
@SerializedName("classifiers")
Map<String, LibraryDownloadInfo> classifiers;
@SerializedName("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;
}
}
@@ -0,0 +1,152 @@
/*
* 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 java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import org.jackhuang.hellominecraft.util.system.OS;
import org.jackhuang.hellominecraft.util.system.Platform;
import org.jackhuang.hellominecraft.util.StrUtils;
/**
*
* @author huangyuhui
*/
public class MinecraftLibrary extends IMinecraftLibrary {
@SerializedName("rules")
public ArrayList<Rules> rules;
@SerializedName("url")
public String url;
@SerializedName("natives")
public Natives natives;
@SerializedName("extract")
public Extract extract;
@SerializedName("downloads")
public LibrariesDownloadInfo downloads;
public MinecraftLibrary(String name) {
super(name);
}
public MinecraftLibrary(ArrayList<Rules> rules, String url, Natives natives, String name, Extract extract, LibraryDownloadInfo downloads) {
super(name);
this.rules = (rules == null) ? null : (ArrayList<Rules>) rules.clone();
this.url = url;
this.natives = (natives == null) ? null : (Natives) natives.clone();
this.extract = (extract == null) ? null : (Extract) extract.clone();
}
@Override
public boolean allow() {
if (rules != null) {
boolean flag = false;
for (Rules r : rules) {
if ("disallow".equals(r.action()))
return false;
else if ("allow".equals(r.action()))
flag = true;
}
return flag;
}
return true;
}
private String formatArch(String nati) {
return nati == null ? "" : nati.replace("${arch}", Platform.getPlatform().getBit());
}
private String getNative() {
switch (OS.os()) {
case WINDOWS:
return formatArch(natives.windows);
case OSX:
return formatArch(natives.osx);
default:
return formatArch(natives.linux);
}
}
@Override
public boolean isRequiredToUnzip() {
return natives != null && allow();
}
public String formatName() {
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]);
if (natives != null) {
sb.append('-').append(getNative());
}
return sb.append(".jar").toString();
}
@Override
public File getFilePath(File gameDir) {
LibraryDownloadInfo info = getDownloadInfo();
if (info == null) {
return null;
}
return new File(gameDir, "libraries/" + info.path);
}
@Override
public Extract getDecompressExtractRules() {
return extract == null ? new Extract() : extract;
}
public LibraryDownloadInfo getDownloadInfo() {
if (downloads == null) {
downloads = new LibrariesDownloadInfo();
}
LibraryDownloadInfo info = null;
if (natives != null) {
if (downloads.classifiers == null) {
downloads.classifiers = new HashMap<>();
} else {
if (!downloads.classifiers.containsKey(getNative())) {
downloads.classifiers.put(getNative(), info = new LibraryDownloadInfo());
} else {
info = downloads.classifiers.get(getNative());
}
}
} else if (downloads.artifact == null) {
downloads.artifact = info = new LibraryDownloadInfo();
} else {
info = downloads.artifact;
}
if (StrUtils.isBlank(info.path)) {
info.path = formatName();
if (info.path == null) {
return null;
}
}
info.forgeURL = this.url;
return info;
}
}
@@ -18,7 +18,6 @@
package org.jackhuang.hellominecraft.launcher.core.version;
import java.io.File;
import org.jackhuang.hellominecraft.launcher.core.download.DownloadType;
/**
*
@@ -35,10 +34,6 @@ public class MinecraftOldLibrary extends MinecraftLibrary {
return false;
}
@Override
public void init() {
}
@Override
public boolean allow() {
return true;
@@ -51,12 +46,12 @@ public class MinecraftOldLibrary extends MinecraftLibrary {
@Override
public Object clone() {
return new MinecraftOldLibrary(name);
return super.clone();
}
@Override
public String getDownloadURL(String urlBase, DownloadType downloadType) {
return null;
public LibraryDownloadInfo getDownloadInfo() {
return new LibraryDownloadInfo();
}
}
@@ -17,16 +17,20 @@
*/
package org.jackhuang.hellominecraft.launcher.core.version;
import com.google.gson.annotations.SerializedName;
import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.jackhuang.hellominecraft.utils.C;
import org.jackhuang.hellominecraft.util.C;
import org.jackhuang.hellominecraft.launcher.core.GameException;
import org.jackhuang.hellominecraft.launcher.core.service.IMinecraftProvider;
import org.jackhuang.hellominecraft.launcher.core.assets.AssetsIndex;
import org.jackhuang.hellominecraft.utils.ArrayUtils;
import org.jackhuang.hellominecraft.launcher.core.asset.AssetsIndex;
import org.jackhuang.hellominecraft.util.ArrayUtils;
import org.jackhuang.hellominecraft.util.Utils;
/**
*
@@ -34,17 +38,43 @@ import org.jackhuang.hellominecraft.utils.ArrayUtils;
*/
public class MinecraftVersion implements Cloneable, Comparable<MinecraftVersion> {
public String minecraftArguments, mainClass, time, id, type, processArguments,
releaseTime, assets, jar, inheritsFrom, runDir;
@SerializedName("minecraftArguments")
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;
@SerializedName("minimumLauncherVersion")
public int minimumLauncherVersion;
@SerializedName("hidden")
public boolean hidden;
public List<MinecraftLibrary> libraries;
@SerializedName("assetIndex")
public AssetIndexDownloadInfo assetIndex;
@SerializedName("downloads")
private Map<String, GameDownloadInfo> downloads;
@SerializedName("libraries")
public ArrayList<MinecraftLibrary> libraries;
public MinecraftVersion() {
}
public MinecraftVersion(String minecraftArguments, String mainClass, String time, String id, String type, String processArguments, String releaseTime, String assets, String jar, String inheritsFrom, String runDir, int minimumLauncherVersion, List<MinecraftLibrary> libraries, boolean hidden) {
public MinecraftVersion(String minecraftArguments, String mainClass, String time, String id, String type, String processArguments, String releaseTime, String assets, String jar, String inheritsFrom, String runDir, int minimumLauncherVersion, List<MinecraftLibrary> libraries, boolean hidden, Map<String, GameDownloadInfo> downloads, AssetIndexDownloadInfo assetIndexDownloadInfo) {
this();
this.minecraftArguments = minecraftArguments;
this.mainClass = mainClass;
@@ -59,18 +89,36 @@ public class MinecraftVersion implements Cloneable, Comparable<MinecraftVersion>
this.minimumLauncherVersion = minimumLauncherVersion;
this.hidden = hidden;
this.runDir = runDir;
if (assetIndexDownloadInfo == null)
this.assetIndex = null;
else
this.assetIndex = (AssetIndexDownloadInfo) assetIndexDownloadInfo.clone();
if (libraries == null)
this.libraries = new ArrayList<>();
else {
this.libraries = new ArrayList<>(libraries.size());
for (IMinecraftLibrary library : libraries)
this.libraries.add((MinecraftLibrary) library.clone());
for (MinecraftLibrary library : libraries)
if (library != null)
this.libraries.add((MinecraftLibrary) library.clone());
}
if (downloads == null)
this.downloads = null;
else {
this.downloads = new HashMap<>(downloads.size());
for (Map.Entry<String, GameDownloadInfo> entry : downloads.entrySet())
this.downloads.put(entry.getKey(), (GameDownloadInfo) entry.getValue().clone());
}
}
@Override
public Object clone() {
return new MinecraftVersion(minecraftArguments, mainClass, time, id, type, processArguments, releaseTime, assets, jar, inheritsFrom, runDir, minimumLauncherVersion, libraries, hidden);
try {
MinecraftVersion mv = (MinecraftVersion) super.clone();
mv.libraries = (ArrayList<MinecraftLibrary>) mv.libraries.clone();
return mv;
} catch (CloneNotSupportedException ex) {
throw new InternalError();
}
}
public MinecraftVersion resolve(IMinecraftProvider provider) throws GameException {
@@ -97,7 +145,9 @@ public class MinecraftVersion implements Cloneable, Comparable<MinecraftVersion>
this.assets != null ? this.assets : parent.assets,
this.jar != null ? this.jar : parent.jar,
null, this.runDir, parent.minimumLauncherVersion,
this.libraries != null ? ArrayUtils.merge(this.libraries, parent.libraries) : parent.libraries, this.hidden);
this.libraries != null ? ArrayUtils.merge(this.libraries, parent.libraries) : parent.libraries, this.hidden,
this.downloads != null ? this.downloads : parent.downloads,
this.assetIndex != null ? this.assetIndex : parent.assetIndex);
return result;
}
@@ -121,12 +171,29 @@ public class MinecraftVersion implements Cloneable, Comparable<MinecraftVersion>
return true;
}
public String getAssets() {
return assets == null ? AssetsIndex.DEFAULT_ASSET_NAME : assets;
}
@Override
public int compareTo(MinecraftVersion o) {
return id.compareTo(((MinecraftVersion) o).id);
return id.compareTo(o.id);
}
public AssetIndexDownloadInfo getAssetsIndex() {
if (assetIndex == null)
assetIndex = new AssetIndexDownloadInfo((String) Utils.firstNonNull(assets, AssetsIndex.DEFAULT_ASSET_NAME));
return assetIndex;
}
public GameDownloadInfo getClientDownloadInfo() {
if (downloads == null)
downloads = new HashMap<>();
if (!downloads.containsKey("client"))
downloads.put("client", new GameDownloadInfo());
GameDownloadInfo i = downloads.get("client");
if (i.id == null)
i.id = id;
return i;
}
public Set<IMinecraftLibrary> getLibraries() {
return libraries == null ? new HashSet() : new HashSet(libraries);
}
}
Loaded 100 of 624 files, more files were not shown because too many files have changed in this diff. Show more