Compare commits

..
230 Commits
Author SHA1 Message Date
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
huangyuhui 005589955c modpack update 2016-01-23 19:49:12 +08:00
huangyuhui 3bdaaddcd8 add some localization items 2016-01-23 18:04:30 +08:00
huangyuhui 08301bed8d test ModpackManager 2016-01-23 16:52:40 +08:00
huangyuhui 102205de40 initializing modpack coding process 2016-01-23 12:23:56 +08:00
huangyuhui 0da589374a reconstruct code 2016-01-20 19:24:35 +08:00
huangyuhui ab08a8d3f5 getting core 4 2016-01-19 23:16:13 +08:00
huangyuhui ec5bb40758 getting core 3 2016-01-19 22:44:09 +08:00
huangyuhui bbf7f2f3f0 getting core 2 2016-01-19 22:42:06 +08:00
huangyuhui d488df81a6 getting core 2016-01-19 22:40:23 +08:00
huangyuhui d207fa3dfb reconstruct codes 2016-01-19 22:28:50 +08:00
huangyuhui f32ce42af3 Added a console log to warn the user when "always close the launcher" option turned on 2016-01-12 21:54:20 +08:00
huangyuhui 9835aa4110 Fix 'refreshVersions' calling too many times 2016-01-10 10:04:50 +08:00
huangyuhui 6c8c189b72 fix IllegalStateException crashes the application 2016-01-09 13:24:40 +08:00
huangyuhui 296df23e15 Added uuid storage in order to prevent uuid problem 2016-01-08 19:55:52 +08:00
huangyuhui 38027fc5af Fix stackoverflow 2016-01-03 22:50:58 +08:00
huangyuhui 90ab9c088e Merge branch 'master' of https://github.com/huanghongxun/HMCL 2016-01-03 19:22:40 +08:00
huangyuhui 93d747f080 add a link about mod pack 2016-01-03 19:21:52 +08:00
unknown 66c502d424 fix lookandfeel crash in windows 2016-01-02 22:56:46 +08:00
huangyuhui 3e5823b647 commit 2016-01-02 21:06:39 +08:00
huangyuhui c33383733f Changed --version 2016-01-02 12:54:24 +08:00
huangyuhui a62848d4fa each authenticator has its own username now 2016-01-02 10:26:48 +08:00
huangyuhui b82243a9c0 update code style 2016-01-01 11:03:09 +08:00
huangyuhui 1f7eb04215 Fix NullPointerException in SwingUtils.invokeAndWait 2016-01-01 10:51:44 +08:00
huangyuhui 6968809499 supported linux memory reading 2015-12-31 21:30:39 +08:00
huangyuhui 5f78f2725a fix some bugs 2015-12-30 18:51:38 +08:00
huangyuhui 3471b4fec7 fixed crashing when removing mods 2015-12-29 20:35:40 +08:00
huangyuhui e3f0254736 fix some ui problems 2015-12-29 13:57:15 +08:00
huangyuhui 07357db42d why does the ui crash 2015-12-27 10:59:03 +08:00
huanghongxun b1c6c3549f fix hmcsm 2015-12-17 22:25:03 +08:00
huanghongxun 7174e117e3 clean up 2015-12-17 22:12:01 +08:00
huanghongxun eff087d9f0 change to C.i18n 2015-12-17 20:35:23 +08:00
huanghongxun 38460678db change to C.i18n 2015-12-17 19:37:48 +08:00
huanghongxun d3372e6a60 Merge branch 'master' of https://github.com/huanghongxun/HMCL
修改:     HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/utils/auth/SkinmeAuthenticator.java
	修改:     HMCLAPI/src/main/resources/org/jackhuang/hellominecraft/launcher/I18N.properties
	修改:     HMCLAPI/src/main/resources/org/jackhuang/hellominecraft/launcher/I18N_zh_CN.properties
	修改:     README.md
2015-12-17 18:13:30 +08:00
huanghongxun 2b17095c88 add i18n 2015-12-17 18:06:19 +08:00
huanghongxun 4e5fd99a3c Merge pull request #12 from LasmGratel/master
Change the format of lang files.
2015-12-17 12:47:10 +08:00
LasmGratel 02e94da4b8 remove useless files 2015-12-16 21:15:54 +08:00
LasmGratel c6fc2cc685 convert I18N from latin2 format to utf-8 format
edit README.md
2015-12-16 21:14:29 +08:00
huanghongxun 81443b8252 Add an option to disable animations 2015-12-16 12:35:04 +08:00
huanghongxun 713a0171cc Reconstruct codes 2015-12-15 21:39:53 +08:00
huanghongxun b3fb372e3b New animationsublime_text launch4jlinux.cpp 2015-12-12 21:00:32 +08:00
huanghongxun 68a734adb0 Removed redundant codes 2015-12-12 13:01:18 +08:00
huanghongxun 8186482a11 Extracted the codes about installing 2.0 2015-12-11 21:18:51 +08:00
huanghongxun d052442aea Extracted the codes about installing 2015-12-11 21:15:56 +08:00
huanghongxun 78c46aeb64 Add --proxy 2015-12-10 20:34:02 +08:00
huanghongxun e91d4c5477 Try to fix some problems 2015-12-10 14:06:56 +08:00
huanghongxun 52c43bde06 Fixed swing syncing bugs 2015-12-09 23:24:24 +08:00
huanghongxun a436e10d93 Reconstructed too many codes 2015-12-09 21:03:56 +08:00
huanghongxun 8e2fa57868 Removed AssetsMojangOldLoader.java 2015-12-07 13:41:13 +08:00
huanghongxun d3ad805ad3 Change the license to GPL v3 to be compatible with Apache License 2.0. 2015-12-05 21:41:50 +08:00
huanghongxun f0212ea4eb Reconstruct codes. 2015-12-03 20:11:52 +08:00
huanghongxun b6cb5f0bee add lite mod description in mod panel. 2015-12-01 18:20:03 +08:00
huanghongxun 73a9fbb1c4 localized some items in English. 2015-11-30 20:27:24 +08:00
huanghongxun 626cc2f6ed why is a non-null variable null? 2015-11-29 18:19:50 +08:00
huanghongxun 151b865dc5 fix performance problem about downloading file. 2015-11-23 18:28:16 +08:00
huanghongxun c76b0e0ffb add debug information. 2015-11-22 17:50:00 +08:00
huanghongxun 2dede7dea1 clean 2015-11-22 16:07:39 +08:00
huanghongxun 159a992081 format 2015-11-17 12:51:04 +08:00
huanghongxun 39b6d68006 Fixed logging conflicting with Log4j and Minecraft. 2015-11-16 23:26:23 +08:00
huanghongxun b7aa99550d Added logging highlight. 2015-11-16 18:41:28 +08:00
huanghongxun 990f830300 Fixed many bugs 2015-11-15 16:19:10 +08:00
huanghongxun f508645496 cleaning codes. 2015-11-11 22:07:01 +08:00
huanghongxun b65be375e7 Clean redundancy codes. 2015-10-26 13:02:06 +08:00
huanghongxun b9c03d6ec3 clean code. 2015-10-05 21:55:30 +08:00
huanghongxun 1d252ea71c clean 2015-10-05 16:41:36 +08:00
huanghongxun c561faf1f7 fix git. 2015-10-04 23:40:42 +08:00
huanghongxun a58aeee40c test 2015-10-04 09:31:07 +08:00
huanghongxun 9b95f9d2d7 rapiddata 2015-09-29 13:48:12 +08:00
huanghongxun 7916715efa fix CI. 2015-09-07 13:28:56 +08:00
huanghongxun 01526546b1 Fix: TaskWindow causes NullPointerException. 2015-09-07 13:00:54 +08:00
huanghongxun 6e003a7364 Fixed wrong action in mod management. 2015-09-04 19:24:26 +08:00
huanghongxun e727ca331f Fix syncing TaskWindow. 2015-09-02 18:57:24 +08:00
huanghongxun f9968580af Redesign the UI. 2015-08-31 21:06:35 +08:00
huanghongxun 981a11d98b Fix Minecraft crashing when in offline & multiplayer mode. 2015-08-27 13:02:55 +08:00
huanghongxun fef88c0144 Add #5 (1) 2015-08-26 20:23:41 +08:00
huanghongxun db24280400 Update native launcher for HMCL. 2015-08-25 18:34:26 +08:00
huanghongxun 10bb60f998 Reset the java directory when javadir is wrong. 2015-08-25 09:11:29 +08:00
huanghongxun 9fc1470a63 add precalled command 2015-08-17 13:40:24 +08:00
huanghongxun 9ae9b5b912 fix bugs 2015-08-16 17:29:09 +08:00
huanghongxun a77275cfc0 fix bugs 2015-08-14 21:23:50 +08:00
huanghongxun a5388e790f fix bugs with Swing. 2015-08-13 20:54:42 +08:00
huanghongxun f63f888daf crash report uploading system & fix crashing when no version here. 2015-08-11 19:38:28 +08:00
huanghongxun 70f0383b1d Add mod modification. 2015-08-11 13:02:02 +08:00
huanghongxun 798d933079 Fixed finding Java problem with Windows XP. 2015-08-07 21:49:18 +08:00
huanghongxun 1d915194c2 The launching button will disable while launching game. 2015-08-07 10:41:15 +08:00
huanghongxun 92ca0075df Fix StringOutOfBoundException 2015-08-04 20:01:49 +08:00
huanghongxun 95598df273 Now can choose Java Installation in Windows 2015-08-04 15:13:04 +08:00
huanghongxun 4a167253db Update for CI. 2015-07-31 18:06:31 +08:00
huanghongxun 022c1ade39 reconstruct the codes. 2015-07-30 08:53:52 +08:00
huanghongxun bfcad25dee fix ArrayOutOfBoundsException & shows "task aborted". 2015-07-29 23:28:13 +08:00
huanghongxun 7e781dd24c fix wrong recognized java platform. 2015-07-29 23:18:05 +08:00
huanghongxun e4335cf1f0 Now installer will set the url of base jar of Forge and LiteLoader. 2015-07-28 22:56:31 +08:00
huanghongxun c3008ec294 Now have a choosing pane for java directory. 2015-07-28 20:50:31 +08:00
huanghongxun e31b5e3a28 Now can download .pack.xz file for Forge library. 2015-07-28 20:36:41 +08:00
huanghongxun bc8cc93bd9 update gitignore 2015-07-28 14:08:35 +08:00
huanghongxun 482c8e50bb fix installing liteloader without tweakclass 2015-07-28 14:08:08 +08:00
huanghongxun 369fe5e164 TaskWindow now shows progress of each task. 2015-07-28 13:50:14 +08:00
huanghongxun 538688c8f1 fix prompting no jar file when renaming version like Forge or LiteLoader version. 2015-07-24 07:52:20 +08:00
huanghongxun abb17dd05d test for new launcher for java && forgot to add license... 2015-07-14 17:36:04 +08:00
huanghongxun c321cb5f91 fix null field of asset index of 1.7.2 2015-07-13 13:11:01 +08:00
huanghongxun 2434e069f5 Fix the wrong AppData path 2015-07-11 22:29:49 +08:00
huanghongxun 2b63d46ffd Reconstruct the codes. 2015-07-11 17:34:25 +08:00
huanghongxun 0be056ac04 Reconstruct the codes && fix wrong file separator when switch to anther os from Windows. 2015-07-10 22:53:18 +08:00
huanghongxun 244b646225 reconstruct code && add advice for out of memory error. 2015-07-06 12:50:02 +08:00
huanghongxun d398de5d4e Fix no cancel when closing task window. 2015-07-05 11:53:34 +08:00
huanghongxun 01aaa38f81 reconstruct code, update crash suggestions & fix crash when minecraft.json -> libraries is lost 2015-07-04 17:17:41 +08:00
huanghongxun cdb78a31e9 update crash suggestions. 2015-07-03 12:50:11 +08:00
huanghongxun 07b8c5777a Asynchronized UI loading. 2015-07-02 13:17:59 +08:00
huanghongxun 67056f4849 Reconstruct the codes. 2015-07-01 21:27:08 +08:00
huanghongxun dace6ab223 Change the default authenticated token to 0 2015-07-01 20:42:55 +08:00
huanghongxun 25b6d7297c fix platform's bug 2015-06-30 20:43:05 +08:00
huanghongxun bba82f5e24 Mojang Download Source: https -> http 2015-06-29 18:17:27 +08:00
huanghongxun e6c954ae0d Fix JSON Exception. 2015-06-29 12:57:02 +08:00
huanghongxun 5f29c7e711 2.3.3 2015-06-28 23:28:56 +08:00
huanghongxun b069753d07 Test 2.3.3 2015-06-28 23:13:01 +08:00
huanghongxun 5bc76299af optimize the code. 2015-06-28 18:55:36 +08:00
huanghongxun 42ef2fe128 Fix a unlocalized string. 2015-06-27 14:00:15 +08:00
huanghongxun 2f0d80cb26 Merge branch 'master' of https://github.com/huanghongxun/HMCL 2015-06-27 13:43:41 +08:00
huanghongxun 57f69d0cbe Merge pull request #3 from Meow-J/master
Change alignment of profile and version to LEADING
2015-06-27 13:41:59 +08:00
Meow J 782627dd12 Change alignment of profile and version to LEADING 2015-06-27 11:45:43 +08:00
huanghongxun e5acf99b09 check the format of asset for 1.7.2~1.6.0. 2015-06-26 23:22:42 +08:00
huanghongxun 9220a818b3 optimize code. 2015-06-26 23:00:55 +08:00
huanghongxun db8e425b2b Additional: license-header.txt 2015-06-26 18:56:35 +08:00
huanghongxun 0df7479e64 Fix FileNotFoundException *.hmc when launching. 2015-06-26 18:55:36 +08:00
huanghongxun bee81fd6d9 Settings.s() -> Settings.getInstance() 2015-06-25 23:08:05 +08:00
huanghongxun fb7bbbcaaf Merge branch 'master' of https://github.com/huanghongxun/HMCL 2015-06-24 13:46:08 +08:00
huanghongxun e5621d1a58 Fixed Issue #1 & Added proxy support 2015-06-24 13:45:00 +08:00
huanghongxun 7344b1ae05 Update README.md 2015-06-22 17:43:38 +08:00
huanghongxun 7bfe7c3432 it seems that i forgot something i should do. 2015-06-22 17:35:23 +08:00
huanghongxun c760461f91 modify the license. 2015-06-22 17:25:47 +08:00
huanghongxun 0656227183 HMCL 2.3.2 2015-06-22 16:47:05 +08:00
huanghongxun 0693d12f6b Initial commit 2015-06-22 16:06:03 +08:00
718 changed files with 71152 additions and 48322 deletions

No files matched your search

Executable
+27
View File
@@ -0,0 +1,27 @@
*.class
# Mobile Tools for Java (J2ME)
.mtj.tmp/
# Package Files #
*.jar
*.war
*.ear
# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
hs_err_pid*
.gradle
.nb-gradle
*.bat
*.log
.mine*
*.json
*.hmd
HMCLAPI/build/
HMCL/build/
HMCLServer/
HMCSM/build/
MetroLookAndFeel/build/
+27
View File
@@ -0,0 +1,27 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<gradle-project-properties>
<!--DO NOT EDIT THIS FILE! - Used by the Gradle plugin of NetBeans.-->
<target-platform-name>j2se</target-platform-name>
<target-platform>1.8</target-platform>
<source-level>1.8</source-level>
<common-tasks>
<task>
<display-name>launch4j</display-name>
<non-blocking>no</non-blocking>
<task-names>
<name must-exist="yes">launch4j</name>
</task-names>
<task-args/>
<task-jvm-args/>
</task>
</common-tasks>
<script-platform>
<spec-name>j2se</spec-name>
<spec-version>1.8</spec-version>
</script-platform>
<license-header>
<name>GNU General Public License</name>
<template>license-header.txt</template>
<property name="organization">huangyuhui</property>
</license-header>
</gradle-project-properties>
+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:
secure: lfFEwKtij/s9Ao/SKL7oVdsWcfASshZuwT27gllMrTx1ZQqLCG2I5mGJOp5ukx7lb3y4Tu316nFasLjy9NI3eLXSx9f0w4q+wMf0K5Yj9iOwu/TIn7JkLyHDMQ20qRwGxZplS2WUb669gIRg+l6jUHeTBW+dlTxr0mMa6WHIl8UDpHwfFrGC3i6dL4y6WlDwGl2rYktvOoA/iqvtglBcHuXaL2sDfhp5MXRcYULTIw+b9zmiQXP665DQN+Su5I3gwB4y5X8RH72GAacZn13fEIo5i8UUoHM7UQxM8y8DKSO3avyFCfpUle9+9sErQVW7b6JV1c+AoLWuAhNJLMlUTKarZE7UMqfjvoQHxX5hp2B2WHLEON/UJiGf25HJWx6VhJitE0/odujqnG/umesqki2jMTs6gPcxbc9iBjzUg+ZmFztdtC+Emnni7lpqVVl+Y5hsJRn3Z6rIiNgwmaE0r2OQgAm1vRYFc7jvOdRfyFG+uCRZF6nS56BzJ7dLc0WW8dTgSft6YFll4ZYL6hiI9qiIaBAK948y5HV+6VBWuO3xf/G2CUFbE1Y9qUCjToh3ahxNDzZvXB+rXqvlvNQOi5l8n594oQ61n45qIHSKlMBn9Bxhw29oWT5mo1aYIaNXbpzKam2w4mK0T3VrgTszu/3282wRbNr+VAwdGMfwW1s=
file:
- HMCL/build/libs/HMCL-${HMCL_VERSION_ROOT}.${TRAVIS_BUILD_NUMBER}.jar
- HMCL/build/libs/HMCL-${HMCL_VERSION_ROOT}.${TRAVIS_BUILD_NUMBER}.exe
- HMCSM/build/libs/HMCSM-${HMCSM_VERSION_ROOT}.${TRAVIS_BUILD_NUMBER}.jar
- HMCSM/build/libs/HMCSM-${HMCSM_VERSION_ROOT}.${TRAVIS_BUILD_NUMBER}.exe
on:
repo: huanghongxun/HMCL
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

BIN
View File
Binary file not shown.
+125
View File
@@ -0,0 +1,125 @@
/*
* Hello Minecraft! Launcher.
* Copyright (C) 2013 huangyuhui <huanghongxun2008@126.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see {http://www.gnu.org/licenses/}.
*/
import java.util.jar.JarOutputStream
import java.util.zip.ZipEntry
import java.util.zip.ZipFile
apply plugin: 'launch4j'
apply plugin: 'me.tatarka.retrolambda'
if (!hasProperty('mainClass')) {
ext.mainClass = 'org.jackhuang.hellominecraft.launcher.Main'
}
def buildnumber = System.getenv("TRAVIS_BUILD_NUMBER")
if (buildnumber == null)
buildnumber = System.getenv("BUILD_NUMBER")
if (buildnumber == null)
buildnumber = "233"
def versionroot = System.getenv("VERSION_ROOT")
if (versionroot == null)
versionroot = "2.4.1"
String mavenGroupId = 'HMCL'
String mavenVersion = versionroot + '.' + buildnumber
String bundleName = "Hello Minecraft! Launcher"
group = mavenGroupId
version = mavenVersion
String mavenArtifactId = name
task generateSources(type: Copy) {
from 'src/main/java'
into "$buildDir/generated-src"
filter(org.apache.tools.ant.filters.ReplaceTokens, tokens: [
'HELLO_MINECRAFT_LAUNCHER_VERSION_FOR_GRADLE_REPLACING': mavenVersion
])
}
compileJava.setSource "$buildDir/generated-src"
compileJava.dependsOn generateSources
buildscript {
repositories {
mavenCentral();
maven {
url "https://libraries.minecraft.net"
}
dependencies {
classpath 'net.sf.proguard:proguard-gradle:4.10'
classpath 'edu.sc.seis.gradle:launch4j:1.0.6'
classpath 'me.tatarka:gradle-retrolambda:3.1.0'
}
}
}
configure(install.repositories.mavenInstaller) {
pom.project {
groupId = mavenGroupId
artifactId = mavenArtifactId
version = mavenVersion
}
}
dependencies {
compile project(":MetroLookAndFeel")
compile project(":HMCLAPI")
compile group: "org.commonjava.googlecode.markdown4j", name: "markdown4j", version: "2.2-cj-1.0"
}
retrolambda {
javaVersion = JavaVersion.VERSION_1_6
}
jar {
from { configurations.compile.collect { it.isDirectory() ? it : zipTree(it) } }
manifest {
attributes 'Created-By' : 'Copyright(c) 2013-2016 huangyuhui.',
'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'
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."
jar = new File(project.buildDir, 'libs/' + mavenGroupId + '-' + mavenVersion + '.jar').absolutePath
outfile = mavenGroupId + '-' + mavenVersion + '.exe'
messagesJreVersionError = 'This application requires a Java Runtime Environment installation, or the runtime is corrupted.\n\u6ca1\u6709\u627e\u5230\u004a\u0061\u0076\u0061\u8fd0\u884c\u65f6\uff0c\u8bf7\u4e0d\u8981\u4f7f\u7528\u7eff\u8272\u004a\u0061\u0076\u0061\uff0c\u8bf7\u4f7f\u7528\u5b89\u88c5\u7248\u7684\u004a\u0061\u0076\u0061\uff0c\u70b9\u51fb\u786e\u5b9a\u8fdb\u5165\u004a\u0061\u0076\u0061\u5b89\u88c5\u9875\u9762\u3002'
}
processResources {
from(sourceSets.main.resources.srcDirs) {
exclude 'icon.icns'
}
}
build.dependsOn makeExecutable
build.dependsOn makePackGZ
Executable
BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

+5461
View File
File diff suppressed because it is too large. Load diff
+5591
View File
File diff suppressed because it is too large. Load diff
Executable
BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 46 KiB

Vendored Executable
+81
View File
@@ -0,0 +1,81 @@
-libraryjars <java.home>/lib/rt.jar
-libraryjars <java.home>/lib/jce.jar
-libraryjars <java.home>/lib/jsse.jar
-dontoptimize
-dontshrink
-dontwarn java.lang.invoke.*
-overloadaggressively
-repackageclasses 'org.jackhuang.hellominecraft.launcher'
-allowaccessmodification
-renamesourcefileattribute SourceFile
-keepattributes *Annotation*,SourceFile,LineNumberTable,Signature
-keep class com.** { *; }
-keep class org.jackhuang.hellominecraft.lookandfeel.* { *; }
-keep class org.jackhuang.hellominecraft.lookandfeel.painters.* { *; }
-keep class org.jackhuang.hellominecraft.lookandfeel.ui.* { *; }
-keepclassmembers class org.jackhuang.mojang.authlib.Agent { *; }
-keepclassmembers class org.jackhuang.mojang.authlib.UserType { *; }
-keepclassmembers class org.jackhuang.mojang.authlib.properties.Property { *; }
-keepclassmembers class org.jackhuang.mojang.authlib.minecraft.MinecraftProfileTexture$Type { *; }
-keepclassmembers class org.jackhuang.mojang.authlib.minecraft.MinecraftProfileTexture { *; }
-keepclassmembers class org.jackhuang.mojang.authlib.yggdrasil.request.AuthenticationRequest { *; }
-keepclassmembers class org.jackhuang.mojang.authlib.yggdrasil.request.InvalidateRequest { *; }
-keepclassmembers class org.jackhuang.mojang.authlib.yggdrasil.request.JoinMinecraftServerRequest { *; }
-keepclassmembers class org.jackhuang.mojang.authlib.yggdrasil.request.RefreshRequest { *; }
-keepclassmembers class org.jackhuang.mojang.authlib.yggdrasil.response.AuthenticationResponse { *; }
-keepclassmembers class org.jackhuang.mojang.authlib.yggdrasil.response.HasJoinedMinecraftServerResponse { *; }
-keepclassmembers class org.jackhuang.mojang.authlib.yggdrasil.response.MinecraftProfilePropertiesResponse { *; }
-keepclassmembers class org.jackhuang.mojang.authlib.yggdrasil.response.MinecraftTexturesPayload { *; }
-keepclassmembers class org.jackhuang.mojang.authlib.yggdrasil.response.ProfileSearchResultsResponse { *; }
-keepclassmembers class org.jackhuang.mojang.authlib.yggdrasil.response.RefreshResponse { *; }
-keepclassmembers class org.jackhuang.mojang.authlib.yggdrasil.response.Response { *; }
-keepclassmembers class org.jackhuang.mojang.authlib.yggdrasil.response.User { *; }
-keep class org.jackhuang.hellominecraft.launcher.Main { public static void main(java.lang.String[]); }
-keep class org.jackhuang.hellominecraft.launcher.Launcher { public static void main(java.lang.String[]); }
-keepclassmembers class org.jackhuang.hellominecraft.launcher.settings.Profile { private <fields>; public <fields>; }
-keepclassmembers class org.jackhuang.hellominecraft.launcher.settings.Config { private <fields>; }
-keepclassmembers class org.jackhuang.hellominecraft.launcher.version.MinecraftLibrary { public <fields>; }
-keepclassmembers class org.jackhuang.hellominecraft.launcher.version.IMinecraftLibrary { public <fields>; }
-keepclassmembers class org.jackhuang.hellominecraft.launcher.version.Natives { public <fields>; }
-keepclassmembers class org.jackhuang.hellominecraft.launcher.version.OS { public <fields>; }
-keepclassmembers class org.jackhuang.hellominecraft.launcher.version.Rules { public <fields>; }
-keepclassmembers class org.jackhuang.hellominecraft.launcher.version.MinecraftVersion { public <fields>; }
-keepclassmembers class org.jackhuang.hellominecraft.launcher.utils.assets.AssetsObject { <fields>; }
-keepclassmembers class org.jackhuang.hellominecraft.launcher.utils.assets.AssetsIndex { <fields>; }
-keepclassmembers class org.jackhuang.hellominecraft.launcher.utils.ModInfo { <fields>; }
-keepclassmembers class org.jackhuang.hellominecraft.launcher.utils.installers.forge.InstallProfile { public <fields>; }
-keepclassmembers class org.jackhuang.hellominecraft.launcher.utils.installers.forge.Install { public <fields>; }
-keepclassmembers class org.jackhuang.hellominecraft.launcher.utils.installers.forge.vanilla.MinecraftForgeVersionRoot { public <fields>; }
-keepclassmembers class org.jackhuang.hellominecraft.launcher.utils.installers.forge.vanilla.MinecraftForgeVersion { public <fields>; }
-keepclassmembers class org.jackhuang.hellominecraft.launcher.utils.installers.forge.bmcl.ForgeVersion { public <fields>; }
-keepclassmembers class org.jackhuang.hellominecraft.launcher.utils.installers.forge.bmcl.Downloads { public <fields>; }
-keepclassmembers class org.jackhuang.hellominecraft.launcher.utils.installers.optifine.OptiFineVersion { public <fields>; }
-keepclassmembers class org.jackhuang.hellominecraft.launcher.utils.installers.liteloader.LiteLoaderVersionsRoot { public <fields>; }
-keepclassmembers class org.jackhuang.hellominecraft.launcher.utils.installers.liteloader.LiteLoaderMCVersions { public <fields>; }
-keepclassmembers class org.jackhuang.hellominecraft.launcher.utils.installers.liteloader.LiteLoaderVersion { public <fields>; }
-keepclassmembers class org.jackhuang.hellominecraft.launcher.utils.installers.liteloader.LiteLoaderVersionsMeta { public <fields>; }
-keepclassmembers class org.jackhuang.hellominecraft.utils.system.JdkVersion { private <fields>; }
-keepclassmembers class org.jackhuang.hellominecraft.version.MinecraftRemoteLatestVersion { public <fields>; }
-keepclassmembers class org.jackhuang.hellominecraft.version.MinecraftRemoteVersion { public <fields>; }
-keepclassmembers class org.jackhuang.hellominecraft.version.MinecraftRemoteVersions { public <fields>; }
BIN
View File
Binary file not shown.
@@ -0,0 +1,201 @@
/*
* 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;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.Authenticator;
import java.net.PasswordAuthentication;
import java.security.GeneralSecurityException;
import java.security.cert.X509Certificate;
import java.text.ParseException;
import java.util.Locale;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.X509TrustManager;
import javax.swing.ImageIcon;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import org.jackhuang.hellominecraft.util.logging.HMCLog;
import org.jackhuang.hellominecraft.launcher.api.PluginManager;
import org.jackhuang.hellominecraft.launcher.core.launch.GameLauncher;
import org.jackhuang.hellominecraft.launcher.util.CrashReporter;
import org.jackhuang.hellominecraft.util.logging.Configuration;
import org.jackhuang.hellominecraft.util.logging.appender.ConsoleAppender;
import org.jackhuang.hellominecraft.util.logging.layout.DefaultLayout;
import org.jackhuang.hellominecraft.util.ui.LogWindow;
import org.jackhuang.hellominecraft.launcher.setting.Settings;
import org.jackhuang.hellominecraft.launcher.util.upgrade.IUpgrader;
import org.jackhuang.hellominecraft.launcher.ui.MainFrame;
import org.jackhuang.hellominecraft.lookandfeel.HelloMinecraftLookAndFeel;
import org.jackhuang.hellominecraft.util.MathUtils;
import org.jackhuang.hellominecraft.util.StrUtils;
import org.jackhuang.hellominecraft.util.lang.SupportedLocales;
import org.jackhuang.hellominecraft.util.VersionNumber;
/**
*
* @author huangyuhui
*/
public final class Main implements Runnable {
private static final X509TrustManager XTM = new X509TrustManager() {
@Override
public void checkClientTrusted(X509Certificate[] chain, String authType) {
}
@Override
public void checkServerTrusted(X509Certificate[] chain, String authType) {
}
@Override
public X509Certificate[] getAcceptedIssuers() {
return new X509Certificate[0];
}
};
private static final HostnameVerifier HNV = (hostname, session) -> true;
static {
SSLContext sslContext = null;
try {
sslContext = SSLContext.getInstance("TLS");
X509TrustManager[] xtmArray = new X509TrustManager[] { XTM };
sslContext.init(null, xtmArray, new java.security.SecureRandom());
} catch (GeneralSecurityException gse) {
}
if (sslContext != null)
HttpsURLConnection.setDefaultSSLSocketFactory(sslContext.getSocketFactory());
HttpsURLConnection.setDefaultHostnameVerifier(HNV);
}
public static final String LAUNCHER_NAME = "Hello Minecraft! Launcher";
public static final String LAUNCHER_VERSION = "@HELLO_MINECRAFT_LAUNCHER_VERSION_FOR_GRADLE_REPLACING@";
public static final int MINIMUM_LAUNCHER_VERSION = 16;
public static VersionNumber getVersionNumber() {
return VersionNumber.check(LAUNCHER_VERSION);
}
/**
* Make the main window title.
*
* @return the MainWindow title.
*/
public static String makeTitle() {
return LAUNCHER_NAME + ' ' + LAUNCHER_VERSION;
}
public static String shortTitle() {
return "HMCL" + ' ' + LAUNCHER_VERSION;
}
public static final Main INSTANCE = new Main();
private static HelloMinecraftLookAndFeel LOOK_AND_FEEL;
private static final Logger LOGGER = Logger.getLogger(Main.class.getName());
@SuppressWarnings({ "CallToPrintStackTrace", "UseSpecificCatch" })
public static void main(String[] args) throws IOException {
{
//PluginManager.getServerPlugin();
if (IUpgrader.NOW_UPGRADER.parseArguments(getVersionNumber(), args))
return;
System.setProperty("awt.useSystemAAFontSettings", "on");
System.setProperty("swing.aatext", "true");
System.setProperty("sun.java2d.noddraw", "true");
System.setProperty("sun.java2d.dpiaware", "false");
Thread.setDefaultUncaughtExceptionHandler(new CrashReporter(true));
try {
File file = new File("hmcl.log");
if (!file.exists() && !file.createNewFile())
HMCLog.warn("Failed to create log file " + file);
Configuration.DEFAULT.appenders.add(new ConsoleAppender("File", new DefaultLayout(), true, new FileOutputStream(file), true));
} catch (IOException ex) {
LOGGER.log(Level.SEVERE, "Failed to add log appender File because an error occurred while creating or opening hmcl.log", ex);
}
HMCLog.log("*** " + Main.makeTitle() + " ***");
String s = Settings.getInstance().getLocalization();
for (SupportedLocales sl : SupportedLocales.values())
if (sl.name().equals(s)) {
SupportedLocales.NOW_LOCALE = sl;
Locale.setDefault(sl.self);
}
LogWindow.INSTANCE.clean();
LogWindow.INSTANCE.setTerminateGame(GameLauncher.PROCESS_MANAGER::stopAllProcesses);
try {
LOOK_AND_FEEL = new HelloMinecraftLookAndFeel(Settings.getInstance().getTheme().settings);
UIManager.setLookAndFeel(LOOK_AND_FEEL);
} catch (ParseException | UnsupportedLookAndFeelException ex) {
HMCLog.warn("Failed to set look and feel...", ex);
}
Settings.UPDATE_CHECKER.outdated.register(IUpgrader.NOW_UPGRADER);
Settings.UPDATE_CHECKER.process(false).reg(t -> Main.invokeUpdate()).execute();
if (StrUtils.isNotBlank(Settings.getInstance().getProxyHost()) && StrUtils.isNotBlank(Settings.getInstance().getProxyPort()) && MathUtils.canParseInt(Settings.getInstance().getProxyPort())) {
HMCLog.log("Initializing customized proxy");
System.setProperty("http.proxyHost", Settings.getInstance().getProxyHost());
System.setProperty("http.proxyPort", Settings.getInstance().getProxyPort());
if (StrUtils.isNotBlank(Settings.getInstance().getProxyUserName()) && StrUtils.isNotBlank(Settings.getInstance().getProxyPassword()))
Authenticator.setDefault(new Authenticator() {
@Override
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(Settings.getInstance().getProxyUserName(), Settings.getInstance().getProxyPassword().toCharArray());
}
});
}
try {
PluginManager.plugin().showUI();
} catch (Throwable t) {
new CrashReporter(false).uncaughtException(Thread.currentThread(), t);
System.exit(1);
}
}
}
@Override
public void run() {
GameLauncher.PROCESS_MANAGER.stopAllProcesses();
}
public static void invokeUpdate() {
MainFrame.INSTANCE.invokeUpdate();
}
public static ImageIcon getIcon(String path) {
try {
return new ImageIcon(Main.class.getResource("/org/jackhuang/hellominecraft/launcher/" + path));
} catch (Exception e) {
HMCLog.err("Failed to load icon", e);
return null;
}
}
}
@@ -0,0 +1,65 @@
/*
* 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.api;
import org.jackhuang.hellominecraft.launcher.core.GameException;
import org.jackhuang.hellominecraft.launcher.core.service.IMinecraftService;
import org.jackhuang.hellominecraft.launcher.setting.Profile;
import org.jackhuang.hellominecraft.launcher.core.auth.AuthenticationException;
import org.jackhuang.hellominecraft.launcher.core.auth.IAuthenticator;
import org.jackhuang.hellominecraft.launcher.core.auth.UserProfileProvider;
import org.jackhuang.hellominecraft.launcher.core.launch.LaunchOptions;
import org.jackhuang.hellominecraft.util.func.Consumer;
/**
*
* @author huangyuhui
*/
public interface IPlugin {
/**
* You can modify the application actions by this method.
*
* @param profile info to the Minecraft Loader
*
* @return For example, you can implement IMinecraftProvider to support
* MultiMC
*/
IMinecraftService provideMinecraftService(Profile profile);
/**
* Register authenticators by calling IAuthenticator.LOGINS.add.
*
* @param apply call apply.accept(your authenticator)
*/
void onRegisterAuthenticators(Consumer<IAuthenticator> apply);
/**
* Open your customized UI.
*/
void showUI();
/**
* Add your server ip or modify the access token.
*
* @param result What you want.
*/
void onProcessingLoginResult(UserProfileProvider result) throws AuthenticationException;
void onProcessingLaunchOptions(LaunchOptions p) throws GameException;
}
@@ -0,0 +1,47 @@
/*
* 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.api;
import org.jackhuang.hellominecraft.util.logging.HMCLog;
import org.jackhuang.hellominecraft.launcher.util.DefaultPlugin;
/**
*
* @author huangyuhui
*/
public class PluginManager {
private static IPlugin NOW_PLUGIN = new DefaultPlugin();
public static void getServerPlugin() {
try {
ClassLoader cl = Thread.currentThread().getContextClassLoader();
Class c = cl.loadClass("org.jackhuang.hellominecraft.launcher.server.ServerPlugin");
IPlugin p = (IPlugin) c.newInstance();
NOW_PLUGIN = p;
} catch (ClassNotFoundException ignore) {
} catch (Exception e) {
HMCLog.err("Failed to new instance");
}
}
public static IPlugin plugin() {
return NOW_PLUGIN;
}
}
@@ -0,0 +1,41 @@
/*
* 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;
/**
*
* @author huangyuhui
*/
public class GameException extends Exception {
public GameException() {
}
public GameException(String message) {
super(message);
}
public GameException(String message, Throwable cause) {
super(message, cause);
}
public GameException(Throwable cause) {
super(cause);
}
}
@@ -0,0 +1,85 @@
/*
* 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;
import java.io.File;
import java.io.IOException;
import org.jackhuang.hellominecraft.util.system.FileUtils;
import org.jackhuang.hellominecraft.util.system.IOUtils;
import org.jackhuang.hellominecraft.util.system.OS;
/**
*
* @author huang
*/
public final class MCUtils {
public static File getWorkingDirectory(String baseName) {
String userhome = System.getProperty("user.home", ".");
File file;
switch (OS.os()) {
case LINUX:
file = new File(userhome, '.' + baseName + '/');
break;
case WINDOWS:
String appdata = System.getenv("APPDATA");
if (appdata != null)
file = new File(appdata, "." + baseName + '/');
else
file = new File(userhome, '.' + baseName + '/');
break;
case OSX:
file = new File(userhome, "Library/Application Support/" + baseName);
break;
default:
file = new File(userhome, baseName + '/');
}
return file;
}
public static File getLocation() {
return getWorkingDirectory("minecraft");
}
public static String minecraft() {
if (OS.os() == OS.OSX)
return "minecraft";
return ".minecraft";
}
public static File getInitGameDir() {
File gameDir = IOUtils.currentDir();
if (gameDir.exists()) {
gameDir = new File(gameDir, MCUtils.minecraft());
if (!gameDir.exists()) {
File newFile = MCUtils.getLocation();
if (newFile.exists())
gameDir = newFile;
}
}
return gameDir;
}
public static 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);
}
}
@@ -0,0 +1,50 @@
/*
* 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.asset;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Set;
/**
*
* @author huangyuhui
*/
public class AssetsIndex {
public static final String DEFAULT_ASSET_NAME = "legacy";
public Map<String, AssetsObject> objects;
public boolean virtual;
public AssetsIndex() {
this.objects = new LinkedHashMap();
}
public Map<String, AssetsObject> getFileMap() {
return this.objects;
}
public Set<AssetsObject> getUniqueObjects() {
return new HashSet(this.objects.values());
}
public boolean isVirtual() {
return this.virtual;
}
}
@@ -0,0 +1,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.readFileToString(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());
}
@Override
public boolean isVersionAllowed(String formattedVersion) {
VersionNumber ur = VersionNumber.check(formattedVersion);
if (ur == null)
return false;
return VersionNumber.check("1.6.0").compareTo(ur) <= 0;
}
}
@@ -0,0 +1,71 @@
/*
* 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 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() {
}
public String getHash() {
return this.hash;
}
public long getSize() {
return this.size;
}
@Override
public boolean equals(Object o) {
if (this == o)
return true;
if (o == null || getClass() != o.getClass())
return false;
AssetsObject that = (AssetsObject) o;
if (this.size != that.size)
return false;
return this.hash.equals(that.hash);
}
@Override
public int hashCode() {
int result = this.hash.hashCode();
result = 31 * result + (int) (this.size ^ this.size >>> 32);
return result;
}
}
@@ -0,0 +1,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;
}
@@ -0,0 +1,143 @@
/*
* 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.io.FileInputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
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.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.tasks.TaskInfo;
/**
* Assets
*
* @author huangyuhui
*/
public abstract class IAssetsHandler {
protected ArrayList<String> assetsDownloadURLs;
protected ArrayList<File> assetsLocalNames;
protected final String name;
protected List<Contents> contents;
public IAssetsHandler(String name) {
this.name = name;
}
public static final IAssetsHandler ASSETS_HANDLER;
static {
ASSETS_HANDLER = new AssetsMojangLoader(C.i18n("assets.list.1_7_3_after"));
}
/**
* interface name
*
* @return
*/
public String getName() {
return name;
}
/**
* All the files assets needed
*
* @param mv The version that needs assets
* @param mp Asset Service
* @param x finished event
*/
public abstract Task getList(MinecraftVersion mv, IMinecraftAssetService mp);
/**
* Will be invoked when the user invoked "Download all assets".
*
* @param sourceType Download Source
*
* @return Download File Task
*/
public abstract Task getDownloadTask(IDownloadProvider sourceType);
public abstract boolean isVersionAllowed(String formattedVersion);
protected class AssetsTask extends TaskInfo {
ArrayList<Task> al;
String u;
public AssetsTask(String url) {
super(C.i18n("assets.download"));
this.u = url;
}
@Override
public void executeTask() {
if (assetsDownloadURLs == null || assetsLocalNames == null || contents == null)
throw new IllegalStateException(C.i18n("assets.not_refreshed"));
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;
File location = assetsLocalNames.get(i);
if (!location.getParentFile().exists() && !location.getParentFile().mkdirs())
HMCLog.warn("Failed to make directories: " + location.getParent());
if (location.isDirectory())
continue;
boolean need = true;
try {
if (location.exists()) {
FileInputStream fis = new FileInputStream(location);
String sha = DigestUtils.sha1Hex(NetUtils.getBytesFromStream(fis));
IOUtils.closeQuietly(fis);
if (contents.get(i).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();
}
if (need)
al.add(new FileDownloadTask(url, location).setTag(mark));
}
}
@Override
public Collection<Task> getAfterTasks() {
return al;
}
}
}
@@ -0,0 +1,218 @@
/*
* 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.Function;
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.readFileToString(indexFile, "UTF-8"), AssetsIndex.class);
String hash = ((AssetsObject) index.getFileMap().get(name)).getHash();
return new File(objectsDir, hash.substring(0, 2) + "/" + hash);
} catch (JsonSyntaxException e) {
throw new IOException("Assets file format malformed.", e);
}
}
private 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.readFileToString(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.readFileToString(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, false);
}
}
// 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 Function<MinecraftVersion, String> ASSET_PROVIDER_IMPL = t -> {
if (!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();
};
}
@@ -0,0 +1,36 @@
/*
* 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.auth;
public class AuthenticationException extends Exception {
public AuthenticationException() {
}
public AuthenticationException(String message) {
super(message);
}
public AuthenticationException(String message, Throwable cause) {
super(message, cause);
}
public AuthenticationException(Throwable cause) {
super(cause);
}
}
@@ -0,0 +1,106 @@
/*
* 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.auth;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.nio.charset.Charset;
import org.jackhuang.hellominecraft.util.code.DigestUtils;
/**
*
* @author huangyuhui
*/
public final class BestLogin extends IAuthenticator {
public BestLogin(String clientToken) {
super(clientToken);
}
@Override
public UserProfileProvider login(LoginInfo info) throws AuthenticationException {
try {
String request = "bl:l:" + info.username + ":" + DigestUtils.sha1Hex(info.password);
Socket socket = new Socket("auth.zhh0000zhh.com", 8);
OutputStream os = socket.getOutputStream();
os.write(request.length());
os.write(request.getBytes(Charset.forName("UTF-8")));
UserProfileProvider lr = new UserProfileProvider();
InputStream is = socket.getInputStream();
int code = is.read();
switch (code) {
case -1:
throw new AuthenticationException("internet error.");
case 200:
throw new AuthenticationException("server restarting.");
case 255:
throw new AuthenticationException("unknown error");
case 3:
throw new AuthenticationException("unregistered.");
case 50:
throw new AuthenticationException("please update your launcher and act your account.");
case 2:
throw new AuthenticationException("wrong password.");
case 100:
throw new AuthenticationException("server reloading.");
case 0:
byte[] b = new byte[64];
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;
} catch (IOException t) {
throw new AuthenticationException(t);
}
}
@Override
public String id() {
return "best";
}
@Override
public String getName() {
return "BestLogin";
}
@Override
public UserProfileProvider loginBySettings() {
return null;
}
@Override
public void logOut() {
}
}
@@ -0,0 +1,117 @@
/*
* 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.auth;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.jackhuang.hellominecraft.launcher.api.PluginManager;
/**
* Login interface
*
* @author huangyuhui
*/
public abstract class IAuthenticator {
public static final List<IAuthenticator> LOGINS = new ArrayList<>();
static {
PluginManager.plugin().onRegisterAuthenticators(LOGINS::add);
}
protected String clientToken, username, password;
public IAuthenticator(String clientToken) {
this.clientToken = clientToken;
}
public String getClientToken() {
return clientToken;
}
/**
* Login Method
*
* @param info username & password
*
* @return login result
*
* @throws
* org.jackhuang.hellominecraft.launcher.core.auth.AuthenticationException
*/
public abstract UserProfileProvider login(LoginInfo info) throws AuthenticationException;
public abstract String id();
/**
*
* @return the name of login method.
*/
public abstract String getName();
/**
* Has password?
*
* @return has password?
*/
public boolean hasPassword() {
return true;
}
public boolean isLoggedIn() {
return false;
}
public void setRememberMe(boolean is) {
}
public abstract UserProfileProvider loginBySettings() throws AuthenticationException;
public abstract void logOut();
public Map onSaveSettings() {
HashMap<String, String> m = new HashMap<>();
m.put("IAuthenticator_UserName", username);
return m;
}
public void onLoadSettings(Map m) {
if (m == null)
return;
username = (String) m.get("IAuthenticator_UserName");
}
public String getUserName() {
return username;
}
public void setUserName(String s) {
username = s;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
@@ -0,0 +1,32 @@
/*
* 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.auth;
/**
*
* @author huangyuhui
*/
public final class LoginInfo {
public String username, password;
public LoginInfo(String username, String password) {
this.username = username;
this.password = password;
}
}
@@ -0,0 +1,104 @@
/*
* 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.auth;
import java.util.HashMap;
import java.util.Map;
import org.jackhuang.hellominecraft.util.C;
import org.jackhuang.hellominecraft.util.StrUtils;
import org.jackhuang.hellominecraft.util.code.DigestUtils;
/**
*
* @author huangyuhui
*/
public final class OfflineAuthenticator extends IAuthenticator {
Map<String, String> uuidMap = new HashMap<>();
public OfflineAuthenticator(String clientToken) {
super(clientToken);
}
@Override
public void onLoadSettings(Map m) {
super.onLoadSettings(m);
if (m == null)
return;
Object o = m.get("uuidMap");
if (o != null && o instanceof Map)
uuidMap = (Map<String, String>) o;
}
@Override
public Map onSaveSettings() {
Map m = super.onSaveSettings();
m.put("uuidMap", uuidMap);
return m;
}
@Override
public UserProfileProvider login(LoginInfo info) throws AuthenticationException {
if (StrUtils.isBlank(info.username))
throw new AuthenticationException(C.i18n("login.no_Player007"));
UserProfileProvider result = new UserProfileProvider();
result.setUserName(info.username);
String uuid = getUUIDFromUserName(info.username);
if (uuidMap != null && uuidMap.containsKey(uuid))
uuid = uuidMap.get(info.username);
else {
if (uuidMap == null)
uuidMap = new HashMap<>();
uuidMap.put(info.username, uuid);
}
result.setSession(uuid);
result.setUserId(uuid);
result.setAccessToken(uuid);
result.setUserType("Legacy");
return result;
}
public static String getUUIDFromUserName(String str) {
return DigestUtils.md5Hex(str);
}
@Override
public String id() {
return "offline";
}
@Override
public String getName() {
return C.i18n("login.methods.offline");
}
@Override
public boolean hasPassword() {
return false;
}
@Override
public UserProfileProvider loginBySettings() {
return null;
}
@Override
public void logOut() {
}
}
@@ -0,0 +1,123 @@
/*
* 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.auth;
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;
/**
*
* @author huangyuhui
*/
public final class SkinmeAuthenticator extends IAuthenticator {
public SkinmeAuthenticator(String clientToken) {
super(clientToken);
}
public String[] parseType1(String s) {
return s.split(",");
}
public String getCharacter(String user, String hash, String $char) throws Exception {
return NetUtils.get(
"http://www.skinme.cc/api/login.php?user=" + user + "&hash=" + hash + (($char == null) ? "" : ("&char=" + $char)));
}
@Override
public UserProfileProvider login(LoginInfo info) throws AuthenticationException {
UserProfileProvider req = new UserProfileProvider();
if (info.username == null || !info.username.contains("@"))
throw new AuthenticationException(C.i18n("login.not_email"));
try {
String usr = info.username.toLowerCase(SupportedLocales.NOW_LOCALE.self);
String pwd = info.password;
String str = DigestUtils.sha1Hex(usr);
String hashCode = DigestUtils.sha1Hex(DigestUtils.md5Hex(DigestUtils.sha1Hex(pwd) + pwd) + str);
String data = getCharacter(usr, hashCode, null);
String[] sl = data.split(":");
if (null != sl[0])
switch (sl[0]) {
case "0":
if (sl[1].contains("No Valid Character"))
sl[1] = C.i18n("login.no_valid_character");
throw new AuthenticationException(sl[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":
String[] charators = sl[1].split(";");
int len = charators.length;
String[] $char = new String[len];
String[] user = new String[len];
System.out.println(sl[1]);
for (int i = 0; i < len; i++) {
String[] charator = charators[i].split(",");
$char[i] = charator[0];
user[i] = charator[1];
}
int index = SwingUtils.select(user, C.i18n("login.choose_charactor"));
if (index == -1)
throw new AuthenticationException(C.i18n("message.cancelled"));
else {
String character = $char[index];
sl = getCharacter(usr, hashCode, character).split(":");
String[] s2 = parseType1(sl[1]);
req.setUserName(s2[0]);
req.setSession(s2[1]);
req.setUserId(s2[1]);
req.setAccessToken(s2[1]);
}
break;
}
req.setUserType("Legacy");
return req;
} catch (Exception e) {
throw new AuthenticationException(e);
}
}
@Override
public String id() {
return "skinme";
}
@Override
public String getName() {
return "Skinme";
}
@Override
public UserProfileProvider loginBySettings() {
return null;
}
@Override
public void logOut() {
}
}
@@ -0,0 +1,109 @@
/*
* 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.auth;
/**
*
* @author huangyuhui
*/
public final class UserProfileProvider {
public String getUserName() {
return username;
}
public void setUserName(String username) {
this.username = username;
}
public String getUserId() {
return userId;
}
public void setUserId(String userId) {
this.userId = userId;
}
public String getSession() {
return session;
}
public void setSession(String session) {
this.session = session;
}
public String getAccessToken() {
return accessToken;
}
public void setAccessToken(String accessToken) {
if (accessToken == null)
accessToken = "0";
this.accessToken = accessToken;
}
public String getUserProperties() {
return userProperties;
}
public void setUserProperties(String userProperties) {
this.userProperties = userProperties;
}
public String getUserPropertyMap() {
return userPropertyMap;
}
public void setUserPropertyMap(String userPropertyMap) {
this.userPropertyMap = userPropertyMap;
}
public String getOtherInfo() {
return otherInfo;
}
public void setOtherInfo(String otherInfo) {
this.otherInfo = otherInfo;
}
public String getClientIdentifier() {
return clientIdentifier;
}
public void setClientIdentifier(String clientIdentifier) {
this.clientIdentifier = clientIdentifier;
}
public String getUserType() {
return userType;
}
public void setUserType(String userType) {
this.userType = userType;
}
private String username = "";
private String userId = "";
private String session = "";
private String accessToken = "";
private String userProperties = "{}";
private String userPropertyMap = "{}";
private String otherInfo = "";
private String clientIdentifier = "";
private String userType = "Offline";
}
@@ -0,0 +1,143 @@
/*
* 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.auth;
import com.google.gson.GsonBuilder;
import java.net.Proxy;
import java.util.Map;
import javax.swing.JOptionPane;
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;
/**
*
* @author huangyuhui
*/
public final class YggdrasilAuthenticator extends IAuthenticator {
YggdrasilAuthentication ua;
public YggdrasilAuthenticator(String clientToken) {
super(clientToken);
ua = new YggdrasilAuthentication(Proxy.NO_PROXY, clientToken);
}
@Override
public UserProfileProvider login(LoginInfo info) throws AuthenticationException {
UserProfileProvider result = new UserProfileProvider();
result.setUserType("mojang");
if (ua.canPlayOnline()) {
result.setUserName(info.username);
result.setUserId(UUIDTypeAdapter.fromUUID(ua.getSelectedProfile().id));
} else {
String usr = info.username;
if (info.username == null || !info.username.contains("@"))
throw new AuthenticationException(C.i18n("login.not_email"));
String pwd = info.password;
if (!ua.isLoggedIn())
ua.setPassword(pwd);
ua.setUserName(usr);
ua.logIn();
if (!ua.isLoggedIn())
throw new AuthenticationException(C.i18n("login.wrong_password"));
GameProfile selectedProfile = ua.getSelectedProfile();
GameProfile[] profiles = ua.getAvailableProfiles();
String username;
if (selectedProfile == null)
if (ArrayUtils.isNotEmpty(profiles)) {
String[] names = new String[profiles.length];
for (int i = 0; i < profiles.length; i++)
names[i] = profiles[i].name;
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));
}
result.setUserProperties(new GsonBuilder().registerTypeAdapter(PropertyMap.class, new PropertyMap.LegacySerializer()).create().toJson(ua.getUserProperties()));
result.setUserPropertyMap(new GsonBuilder().registerTypeAdapter(PropertyMap.class, new PropertyMap.Serializer()).create().toJson(ua.getUserProperties()));
result.setAccessToken(ua.getAuthenticatedToken());
result.setSession(ua.getAuthenticatedToken());
return result;
}
@Override
public boolean isLoggedIn() {
return ua.isLoggedIn();
}
@Override
public String id() {
return "yggdrasil";
}
@Override
public String getName() {
return C.i18n("login.methods.yggdrasil");
}
@Override
public Map onSaveSettings() {
Map m = ua.saveForStorage();
m.putAll(super.onSaveSettings());
return m;
}
@Override
public void onLoadSettings(Map settings) {
super.onLoadSettings(settings);
if (settings == null)
return;
ua.loadFromStorage(settings);
}
@Override
public UserProfileProvider loginBySettings() throws AuthenticationException {
UserProfileProvider result = new UserProfileProvider();
ua.logIn();
if (!ua.isLoggedIn())
throw new AuthenticationException(C.i18n("login.wrong_password"));
GameProfile profile = ua.getSelectedProfile();
result.setUserName(profile.name);
result.setUserId(profile.id.toString());
result.setUserProperties(new GsonBuilder().registerTypeAdapter(PropertyMap.class, new PropertyMap.LegacySerializer()).create().toJson(ua.getUserProperties()));
result.setUserPropertyMap(new GsonBuilder().registerTypeAdapter(PropertyMap.class, new PropertyMap.Serializer()).create().toJson(ua.getUserProperties()));
result.setAccessToken(ua.getAuthenticatedToken());
result.setSession(ua.getAuthenticatedToken());
return result;
}
@Override
public void logOut() {
ua.logOut();
}
}
@@ -0,0 +1,77 @@
/*
* 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.auth.yggdrasil;
import java.util.HashMap;
public class AuthenticationRequest {
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<>();
agent.put("name", "Minecraft");
agent.put("version", 1);
this.username = username;
this.password = password;
this.clientToken = clientToken;
}
}
@@ -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.auth.yggdrasil;
import com.google.gson.JsonDeserializationContext;
import com.google.gson.JsonDeserializer;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParseException;
import com.google.gson.JsonSerializationContext;
import com.google.gson.JsonSerializer;
import java.lang.reflect.Type;
import java.util.Objects;
import java.util.UUID;
import org.jackhuang.hellominecraft.util.StrUtils;
public class GameProfile {
public final UUID id;
public final String name;
public final PropertyMap properties = new PropertyMap();
public GameProfile(UUID id, String name) {
if (id == null && StrUtils.isBlank(name))
throw new IllegalArgumentException("Name and ID cannot both be blank");
this.id = id;
this.name = name;
}
public boolean isComplete() {
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) {
if (this == o)
return true;
if (o == null || getClass() != o.getClass())
return false;
GameProfile that = (GameProfile) o;
if (id != null ? !id.equals(that.id) : that.id != null)
return false;
return name != null ? name.equals(that.name) : that.name == null;
}
public static class GameProfileSerializer implements JsonSerializer<GameProfile>, JsonDeserializer<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;
return new GameProfile(id, name);
}
@Override
public JsonElement serialize(GameProfile src, Type typeOfSrc, JsonSerializationContext context) {
JsonObject result = new JsonObject();
if (src.id != null)
result.add("id", context.serialize(src.id));
if (src.name != null)
result.addProperty("name", src.name);
return result;
}
}
}
@@ -0,0 +1,28 @@
/*
* 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.auth.yggdrasil;
public class Property {
public final String name, value;
public Property(String name, String value) {
this.name = name;
this.value = value;
}
}
@@ -0,0 +1,116 @@
/*
* 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.auth.yggdrasil;
import com.google.gson.JsonArray;
import com.google.gson.JsonDeserializationContext;
import com.google.gson.JsonDeserializer;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParseException;
import com.google.gson.JsonPrimitive;
import com.google.gson.JsonSerializationContext;
import com.google.gson.JsonSerializer;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
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()) {
Map<String, String> property = new HashMap<>();
property.put("name", profileProperty.name);
property.put("value", profileProperty.value);
properties.add(property);
}
return properties;
}
public void fromList(List<Map<String, String>> list) {
try {
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);
}
}
public static class Serializer implements JsonSerializer<PropertyMap>, JsonDeserializer<PropertyMap> {
@Override
public PropertyMap deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
PropertyMap result = new PropertyMap();
if ((json instanceof JsonObject)) {
JsonObject object = (JsonObject) json;
for (Map.Entry<String, JsonElement> entry : object.entrySet())
if (entry.getValue() instanceof JsonArray)
for (JsonElement element : (JsonArray) entry.getValue())
result.put(entry.getKey(),
new Property((String) entry.getKey(), element.getAsString()));
} else if ((json instanceof JsonArray))
for (JsonElement element : (JsonArray) json)
if ((element instanceof JsonObject)) {
JsonObject object = (JsonObject) element;
String name = object.getAsJsonPrimitive("name").getAsString();
String value = object.getAsJsonPrimitive("value").getAsString();
result.put(name, new Property(name, value));
}
return result;
}
@Override
public JsonElement serialize(PropertyMap src, Type typeOfSrc, JsonSerializationContext context) {
JsonArray result = new JsonArray();
for (Property property : src.values()) {
JsonObject object = new JsonObject();
object.addProperty("name", property.name);
object.addProperty("value", property.value);
result.add(object);
}
return result;
}
}
public static class LegacySerializer
implements JsonSerializer<PropertyMap> {
@Override
public JsonElement serialize(PropertyMap src, Type typeOfSrc, JsonSerializationContext context) {
JsonObject result = new JsonObject();
for (PropertyMap.Entry<String, Property> entry : src.entrySet()) {
JsonArray values = new JsonArray();
values.add(new JsonPrimitive(entry.getValue().value));
result.add(entry.getKey(), values);
}
return result;
}
}
}
@@ -0,0 +1,64 @@
/*
* 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.auth.yggdrasil;
public class RefreshRequest {
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;
}
}
@@ -0,0 +1,30 @@
/*
* 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.auth.yggdrasil;
public class Response {
public String accessToken, clientToken;
public GameProfile selectedProfile;
public GameProfile[] availableProfiles;
public User user;
public String error;
public String errorMessage;
public String cause;
}
@@ -0,0 +1,45 @@
/*
* 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.auth.yggdrasil;
import com.google.gson.TypeAdapter;
import com.google.gson.stream.JsonReader;
import com.google.gson.stream.JsonWriter;
import java.io.IOException;
import java.util.UUID;
public class UUIDTypeAdapter extends TypeAdapter<UUID> {
@Override
public void write(JsonWriter out, UUID value) throws IOException {
out.value(fromUUID(value));
}
@Override
public UUID read(JsonReader in) throws IOException {
return fromString(in.nextString());
}
public static String fromUUID(UUID value) {
return value.toString().replace("-", "");
}
public static UUID fromString(String input) {
return UUID.fromString(input.replaceFirst("(\\w{8})(\\w{4})(\\w{4})(\\w{4})(\\w{12})", "$1-$2-$3-$4-$5"));
}
}
@@ -0,0 +1,49 @@
/*
* 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.auth.yggdrasil;
public class User {
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;
}
}
@@ -0,0 +1,237 @@
/*
* 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.auth.yggdrasil;
import org.jackhuang.hellominecraft.launcher.core.auth.AuthenticationException;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonParseException;
import java.io.IOException;
import java.net.Proxy;
import java.net.URL;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
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 {
public static final Gson GSON = new GsonBuilder()
.registerTypeAdapter(GameProfile.class, new GameProfile.GameProfileSerializer())
.registerTypeAdapter(PropertyMap.class, new PropertyMap.Serializer())
.registerTypeAdapter(UUID.class, new UUIDTypeAdapter()).create();
protected static final String BASE_URL = "https://authserver.mojang.com/";
protected static final URL ROUTE_AUTHENTICATE = NetUtils.constantURL(BASE_URL + "authenticate");
protected static final URL ROUTE_REFRESH = NetUtils.constantURL(BASE_URL + "refresh");
protected static final String STORAGE_KEY_ACCESS_TOKEN = "accessToken";
protected static final String STORAGE_KEY_PROFILE_NAME = "displayName";
protected static final String STORAGE_KEY_PROFILE_ID = "uuid";
protected static final String STORAGE_KEY_PROFILE_PROPERTIES = "profileProperties";
protected static final String STORAGE_KEY_USER_NAME = "username";
protected static final String STORAGE_KEY_USER_ID = "userid";
protected static final String STORAGE_KEY_USER_PROPERTIES = "userProperties";
private final Proxy proxy;
private final String clientToken;
private final PropertyMap userProperties = new PropertyMap();
private String userid, username, password, accessToken;
private GameProfile selectedProfile;
private GameProfile[] profiles;
private boolean isOnline;
public YggdrasilAuthentication(Proxy proxy, String clientToken) {
this.proxy = proxy;
this.clientToken = clientToken;
}
// <editor-fold defaultstate="collapsed" desc="Get/Set">
public void setUserName(String username) {
if ((isLoggedIn()) && (canPlayOnline()))
throw new IllegalStateException("Cannot change username while logged in & online");
this.username = username;
}
public void setPassword(String password) {
if ((isLoggedIn()) && (canPlayOnline()) && (StrUtils.isNotBlank(password)))
throw new IllegalStateException("Cannot set password while logged in & online");
this.password = password;
}
public GameProfile getSelectedProfile() {
return this.selectedProfile;
}
public String getUserId() {
return this.userid;
}
public PropertyMap getUserProperties() {
if (isLoggedIn())
return (PropertyMap) userProperties.clone();
return new PropertyMap();
}
public GameProfile[] getAvailableProfiles() {
if (profiles == null)
return null;
else
return profiles.clone();
}
public String getAuthenticatedToken() {
return this.accessToken;
}
// </editor-fold>
// <editor-fold defaultstate="collapsed" desc="Log In/Out">
public boolean canPlayOnline() {
return isLoggedIn() && getSelectedProfile() != null && this.isOnline;
}
public boolean canLogIn() {
return !canPlayOnline() && StrUtils.isNotBlank(username) && (StrUtils.isNotBlank(password) || StrUtils.isNotBlank(getAuthenticatedToken()));
}
public boolean isLoggedIn() {
return StrUtils.isNotBlank(this.accessToken);
}
public void logIn() throws AuthenticationException {
if (StrUtils.isBlank(username))
throw new AuthenticationException(C.i18n("login.invalid_username"));
if (StrUtils.isNotBlank(getAuthenticatedToken())) {
if (StrUtils.isBlank(getUserId()))
if (StrUtils.isBlank(username))
userid = username;
else
throw new AuthenticationException(C.i18n("login.invalid_uuid_and_username"));
loggedIn(ROUTE_REFRESH, new RefreshRequest(getAuthenticatedToken(), clientToken));
} else if (StrUtils.isNotBlank(password))
loggedIn(ROUTE_AUTHENTICATE, new AuthenticationRequest(username, password, clientToken));
else
throw new AuthenticationException(C.i18n("login.invalid_password"));
}
private void loggedIn(URL url, Object input) throws AuthenticationException {
try {
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"))
response.errorMessage = C.i18n("login.invalid_token");
throw new AuthenticationException("Request error: " + response.errorMessage);
}
if (!clientToken.equals(response.clientToken))
throw new AuthenticationException(C.i18n("login.changed_client_token"));
User user = response.user;
userid = user != null && user.getId() != null ? user.getId() : username;
isOnline = true;
profiles = response.availableProfiles;
selectedProfile = response.selectedProfile;
userProperties.clear();
this.accessToken = response.accessToken;
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);
}
}
public void logOut() {
password = null;
userid = null;
selectedProfile = null;
userProperties.clear();
accessToken = null;
profiles = null;
isOnline = false;
}
// </editor-fold>
// <editor-fold defaultstate="collapsed" desc="Settings Storage">
public void loadFromStorage(Map<String, Object> credentials) {
logOut();
setUserName((String) credentials.get(STORAGE_KEY_USER_NAME));
if (credentials.containsKey(STORAGE_KEY_USER_ID))
userid = (String) credentials.get(STORAGE_KEY_USER_ID);
else
userid = username;
if (credentials.containsKey(STORAGE_KEY_USER_PROPERTIES))
userProperties.fromList((List<Map<String, String>>) credentials.get(STORAGE_KEY_USER_PROPERTIES));
if ((credentials.containsKey(STORAGE_KEY_PROFILE_NAME)) && (credentials.containsKey(STORAGE_KEY_PROFILE_ID))) {
GameProfile profile = new GameProfile(UUIDTypeAdapter.fromString((String) credentials.get(STORAGE_KEY_PROFILE_ID)), (String) credentials.get(STORAGE_KEY_PROFILE_NAME));
if (credentials.containsKey(STORAGE_KEY_PROFILE_PROPERTIES))
profile.properties.fromList((List<Map<String, String>>) credentials.get(STORAGE_KEY_PROFILE_PROPERTIES));
selectedProfile = profile;
}
this.accessToken = (String) credentials.get(STORAGE_KEY_ACCESS_TOKEN);
}
public Map<String, Object> saveForStorage() {
Map<String, Object> result = new HashMap<>();
if (username != null)
result.put(STORAGE_KEY_USER_NAME, username);
if (getUserId() != null)
result.put(STORAGE_KEY_USER_ID, getUserId());
if (!getUserProperties().isEmpty())
result.put(STORAGE_KEY_USER_PROPERTIES, getUserProperties().list());
GameProfile sel = getSelectedProfile();
if (sel != null) {
result.put(STORAGE_KEY_PROFILE_NAME, sel.name);
result.put(STORAGE_KEY_PROFILE_ID, sel.id);
if (!sel.properties.isEmpty())
result.put(STORAGE_KEY_PROFILE_PROPERTIES, sel.properties.list());
}
if (StrUtils.isNotBlank(getAuthenticatedToken()))
result.put(STORAGE_KEY_ACCESS_TOKEN, getAuthenticatedToken());
return result;
}
// </editor-fold>
}
@@ -0,0 +1,82 @@
/*
* 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.install.InstallerVersionList;
/**
*
* @author huangyuhui
*/
public class BMCLAPIDownloadProvider extends IDownloadProvider {
@Override
public InstallerVersionList getForgeInstaller() {
return org.jackhuang.hellominecraft.launcher.core.install.forge.MinecraftForgeVersionList.getInstance();
}
@Override
public InstallerVersionList getLiteLoaderInstaller() {
return org.jackhuang.hellominecraft.launcher.core.install.liteloader.LiteLoaderVersionList.getInstance();
}
@Override
public InstallerVersionList getOptiFineInstaller() {
return org.jackhuang.hellominecraft.launcher.core.install.optifine.bmcl.OptiFineBMCLVersionList.getInstance();
}
@Override
public String getLibraryDownloadURL() {
return "http://bmclapi2.bangbang93.com/libraries";
}
@Override
public String getVersionsDownloadURL() {
return "http://bmclapi2.bangbang93.com/versions/";
}
@Override
public String getIndexesDownloadURL() {
return "http://bmclapi2.bangbang93.com/indexes/";
}
@Override
public String getVersionsListDownloadURL() {
return "http://bmclapi2.bangbang93.com/mc/game/version_manifest.json";
}
@Override
public String getAssetsDownloadURL() {
return "http://bmclapi2.bangbang93.com/assets/";
}
@Override
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 true;
}
}
@@ -0,0 +1,31 @@
/*
* 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;
/**
*
* @author huangyuhui
*/
public class CurseDownloadProvider extends MojangDownloadProvider {
@Override
public String getParsedDownloadURL(String str) {
return str == null ? null : str.replace("http://files.minecraftforge.net/maven", "http://ftb.cursecdn.com/FTB2/maven");
}
}
@@ -0,0 +1,39 @@
/*
* 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 java.io.File;
import org.jackhuang.hellominecraft.launcher.core.version.IMinecraftLibrary;
import org.jackhuang.hellominecraft.util.system.IOUtils;
/**
*
* @author huangyuhui
*/
public class DownloadLibraryJob {
public IMinecraftLibrary lib;
public String url;
public File path;
public DownloadLibraryJob(IMinecraftLibrary n, String u, File p) {
url = u;
lib = n;
path = IOUtils.tryGetCanonicalFile(p);
}
}
@@ -0,0 +1,63 @@
/*
* 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.util.C;
import org.jackhuang.hellominecraft.util.tasks.TaskWindow;
/**
*
* @author huangyuhui
*/
public enum DownloadType {
Mojang("download.mojang", new MojangDownloadProvider()),
BMCL("download.BMCL", new BMCLAPIDownloadProvider()),
//RapidData("download.rapid_data", new RapidDataDownloadProvider()),
Curse("Curse CDN", new CurseDownloadProvider());
private final String name;
private final IDownloadProvider provider;
DownloadType(String a, IDownloadProvider provider) {
name = a;
this.provider = provider;
}
public IDownloadProvider getProvider() {
return provider;
}
public String getName() {
return C.i18n(name);
}
private static DownloadType suggestedDownloadType = Mojang;
public static DownloadType getSuggestedDownloadType() {
return suggestedDownloadType;
}
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,69 @@
/*
* 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.install.InstallerType;
import org.jackhuang.hellominecraft.launcher.core.install.InstallerVersionList;
/**
*
* @author huangyuhui
*/
public abstract class IDownloadProvider {
public InstallerVersionList getInstallerByType(InstallerType type) {
switch (type) {
case Forge:
return getForgeInstaller();
case LiteLoader:
return getLiteLoaderInstaller();
case OptiFine:
return getOptiFineInstaller();
default:
return null;
}
}
public abstract InstallerVersionList getForgeInstaller();
public abstract InstallerVersionList getLiteLoaderInstaller();
public abstract InstallerVersionList getOptiFineInstaller();
public abstract String getLibraryDownloadURL();
public abstract String getVersionsDownloadURL();
public abstract String getIndexesDownloadURL();
public abstract String getVersionsListDownloadURL();
public abstract String getAssetsDownloadURL();
/**
* 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,163 @@
/*
* 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.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 l : v.getLibraries())
if (l != null && l.allow() && l.getDownloadInfo() != null) {
File ff = l.getFilePath(service.baseDirectory());
if (!ff.exists()) {
String libURL = l.getDownloadInfo().getUrl(service.getDownloadType());
if (libURL != null)
downloadLibraries.add(new DownloadLibraryJob(l, libURL, 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.readFileToStringQuietly(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 t) {
return DownloadType.values()[t / 2].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;
}
};
}
}
@@ -0,0 +1,28 @@
/*
* 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;
/**
*
* @author huangyuhui
*/
public class MinecraftRemoteLatestVersion {
public String snapshot, release;
}
@@ -0,0 +1,34 @@
/*
* 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;
/**
*
* @author huangyuhui
*/
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,74 @@
/*
* 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 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 {
public ArrayList<MinecraftRemoteVersion> versions;
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()]));
}
}
}
}
@@ -0,0 +1,89 @@
/*
* 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 java.util.Locale;
import org.jackhuang.hellominecraft.launcher.core.install.InstallerVersionList;
import org.jackhuang.hellominecraft.util.lang.SupportedLocales;
/**
*
* @author huangyuhui
*/
public class MojangDownloadProvider extends IDownloadProvider {
@Override
public InstallerVersionList getForgeInstaller() {
return org.jackhuang.hellominecraft.launcher.core.install.forge.MinecraftForgeVersionList.getInstance();
}
@Override
public InstallerVersionList getLiteLoaderInstaller() {
return org.jackhuang.hellominecraft.launcher.core.install.liteloader.LiteLoaderVersionList.getInstance();
}
@Override
public InstallerVersionList getOptiFineInstaller() {
return org.jackhuang.hellominecraft.launcher.core.install.optifine.vanilla.OptiFineVersionList.getInstance();
}
@Override
public String getLibraryDownloadURL() {
return "https://libraries.minecraft.net";
}
@Override
public String getVersionsDownloadURL() {
return "http://s3.amazonaws.com/Minecraft.Download/versions/";
}
@Override
public String getIndexesDownloadURL() {
return "http://s3.amazonaws.com/Minecraft.Download/indexes/";
}
@Override
public String getVersionsListDownloadURL() {
return "https://launchermeta.mojang.com/mc/game/version_manifest.json";
}
@Override
public String getAssetsDownloadURL() {
return "http://resources.download.minecraft.net/";
}
@Override
public boolean isAllowedToUseSelfURL() {
return true;
}
@Override
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;
}
}
@@ -0,0 +1,56 @@
/*
* 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;
/**
*
* @author huangyuhui
*/
public class RapidDataDownloadProvider extends MojangDownloadProvider {
@Override
public String getAssetsDownloadURL() {
return "http://mirrors.rapiddata.org/resources.download.minecraft.net/";
}
@Override
public String getLibraryDownloadURL() {
return "http://mirrors.rapiddata.org/libraries.minecraft.net";
}
@Override
public String getIndexesDownloadURL() {
return "http://mirrors.rapiddata.org/Minecraft.Download/indexes/";
}
@Override
public String getVersionsDownloadURL() {
return "http://mirrors.rapiddata.org/Minecraft.Download/versions/";
}
@Override
public String getVersionsListDownloadURL() {
return "http://mirrors.rapiddata.org/Minecraft.Download/versions/versions.json";
}
@Override
public String getParsedDownloadURL(String str) {
return str == null ? null : str.replace("http://files.minecraftforge.net/maven", "http://mirrors.rapiddata.org/forge/maven");
}
}
@@ -0,0 +1,34 @@
/*
* 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 com.google.gson.annotations.SerializedName;
import org.jackhuang.hellominecraft.launcher.core.version.MinecraftVersion;
import org.jackhuang.hellominecraft.launcher.core.install.forge.Install;
/**
*
* @author huangyuhui
*/
public class InstallProfile {
@SerializedName("install")
public Install install;
@SerializedName("versionInfo")
public MinecraftVersion versionInfo;
}
@@ -0,0 +1,36 @@
/*
* 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;
/**
*
* @author huangyuhui
*/
public enum InstallerType {
Forge("forge"), OptiFine("optifine"), LiteLoader("liteloader");
public final String id;
private InstallerType(String id) {
this.id = id;
}
public String getLocalizedName() {
return this.name();
}
}
@@ -0,0 +1,120 @@
/*
* 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 class InstallerVersion implements Comparable<InstallerVersion> {
public String selfVersion, mcVersion;
public String installer, universal;
public String changelog;
public InstallerVersion(String selfVersion, String mcVersion) {
this.selfVersion = selfVersion;
this.mcVersion = mcVersion;
}
@Override
public int compareTo(InstallerVersion o) {
return selfVersion.compareTo(o.selfVersion);
}
@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);
}
}
}
@@ -0,0 +1,36 @@
/*
* 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.Comparator;
import org.jackhuang.hellominecraft.launcher.core.install.InstallerVersionList.InstallerVersion;
/**
*
* @author huangyuhui
*/
public class InstallerVersionNewerComparator implements Comparator<InstallerVersion>, Serializable {
private static final long serialVersionUID = 14758562453742645L;
@Override
public int compare(InstallerVersion o1, InstallerVersion 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(IOUtils.currentDirWithSeparator() + "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(IOUtils.currentDirWithSeparator() + "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(IOUtils.currentDirWithSeparator() + "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));
}
}
@@ -0,0 +1,51 @@
/*
* 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.File;
import java.io.IOException;
import java.util.ArrayList;
import org.jackhuang.hellominecraft.util.logging.HMCLog;
import org.jackhuang.hellominecraft.util.system.Compressor;
import org.jackhuang.hellominecraft.util.system.FileUtils;
import org.jackhuang.hellominecraft.util.system.IOUtils;
/**
*
* @author huangyuhui
*/
public class PackMinecraftInstaller {
File dest;
ArrayList<String> src;
public PackMinecraftInstaller(ArrayList<String> src, File dest) {
this.dest = dest;
this.src = src;
}
public void install() throws IOException {
File file = new File(IOUtils.currentDir(), "HMCL-MERGE-TEMP");
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());
FileUtils.deleteDirectory(file);
}
}
@@ -0,0 +1,96 @@
/*
* 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.BufferedOutputStream;
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;
/**
*
* @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); BufferedOutputStream bos = new BufferedOutputStream(fos)) {
int c;
while ((c = is.read()) != -1)
bos.write((byte) c);
}
mp.version().refreshVersions();
}
}
@Override
public String getInfo() {
return C.i18n("install.forge.install");
}
}
@@ -0,0 +1,38 @@
/*
* 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.io.File;
import java.io.IOException;
import java.util.ArrayList;
import org.jackhuang.hellominecraft.launcher.core.install.PackMinecraftInstaller;
/**
*
* @author huangyuhui
*/
public class ForgeOldInstaller {
public static void install(String destMinecraftJar, String srcMinecraftJar, String forgeUniversal) throws IOException {
ArrayList<String> al = new ArrayList<>();
al.add(srcMinecraftJar);
al.add(forgeUniversal);
new PackMinecraftInstaller(al, new File(destMinecraftJar)).install();
}
}
@@ -0,0 +1,124 @@
/*
* 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 Install {
private String profileName;
private String target;
private String path;
private String version;
private String filePath;
private String welcome;
private String minecraft;
private String mirrorList;
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,136 @@
/*
* 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());
ArrayList<InstallerVersion> al = new ArrayList<>();
for (int num : arr.getValue()) {
MinecraftForgeVersion v = root.number.get(num);
InstallerVersion iv = new InstallerVersion(v.version, StrUtils.formatVersion(v.mcversion));
for (String[] f : v.files) {
String ver = v.mcversion + "-" + v.version;
if (!StrUtils.isBlank(v.branch))
ver = ver + "-" + v.branch;
String filename = root.artifact + "-" + ver + "-" + f[1] + "." + f[0];
String url = 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(StrUtils.formatVersion(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";
}
}
@@ -0,0 +1,32 @@
/*
* 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.Map;
/**
*
* @author huangyuhui
*/
public class MinecraftForgeVersionRoot {
public String artifact, webpath, adfly, homepage, name;
public Map<String, int[]> branches, mcversion;
public Map<String, Integer> promos;
public Map<Integer, MinecraftForgeVersion> number;
}
@@ -0,0 +1,100 @@
/*
* 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.io.File;
import java.util.ArrayList;
import java.util.Arrays;
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.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;
/**
*
* @author huangyuhui
*/
public class LiteLoaderInstaller extends Task implements PreviousResultRegistrar<File> {
public LiteLoaderVersionList.LiteLoaderInstallerVersion version;
public File installer;
public String installId;
public IMinecraftService service;
public LiteLoaderInstaller(IMinecraftService service, String installId, LiteLoaderVersionList.LiteLoaderInstallerVersion v) {
this(service, installId, v, null);
}
public LiteLoaderInstaller(IMinecraftService service, String installId, LiteLoaderVersionList.LiteLoaderInstallerVersion v, File installer) {
this.service = service;
this.installId = installId;
this.version = v;
this.installer = installer;
}
@Override
public void executeTask() throws Exception {
if (installId == null)
throw new IllegalStateException(C.i18n("install.no_version"));
if (pre.size() != 1 && installer == null)
throw new IllegalStateException("No registered previous task.");
if (installer == null)
installer = pre.get(pre.size() - 1).getResult();
MinecraftVersion mv = (MinecraftVersion) service.version().getVersionById(installId).clone();
mv.inheritsFrom = mv.id;
mv.jar = mv.jar == null ? mv.id : mv.jar;
mv.libraries = new ArrayList(Arrays.asList(version.libraries));
MinecraftLibrary ml = new MinecraftLibrary("com.mumfrey:liteloader:" + version.selfVersion);
//ml.url = "http://dl.liteloader.com/versions/com/mumfrey/liteloader/" + version.mcVersion + "/liteloader-" + version.selfVersion + ".jar";
mv.libraries.add(0, ml);
FileUtils.copyFile(installer, new File(service.baseDirectory(), "libraries/com/mumfrey/liteloader/" + version.selfVersion + "/liteloader-" + version.selfVersion + ".jar"));
mv.id += "-LiteLoader" + version.selfVersion;
mv.mainClass = "net.minecraft.launchwrapper.Launch";
mv.minecraftArguments += " --tweakClass " + version.tweakClass;
File folder = new File(service.baseDirectory(), "versions/" + mv.id);
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.GSON.toJson(mv));
service.version().refreshVersions();
}
@Override
public String getInfo() {
return C.i18n("install.liteloader.install");
}
ArrayList<PreviousResult<File>> pre = new ArrayList<>();
@Override
public Task registerPreviousResult(PreviousResult pr) {
pre.add(pr);
return this;
}
}
@@ -0,0 +1,29 @@
/*
* 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.Map;
/**
*
* @author huangyuhui
*/
public class LiteLoaderMCVersions {
public Map<String, Map<String, LiteLoaderVersion>> artefacts;
}
@@ -0,0 +1,30 @@
/*
* 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 org.jackhuang.hellominecraft.launcher.core.version.MinecraftLibrary;
/**
*
* @author huangyuhui
*/
public class LiteLoaderVersion {
public String tweakClass, file, version, md5, timestamp;
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,61 @@
/*
* 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;
/**
*
* @author huangyuhui
*/
public class LiteLoaderVersionsMeta {
private String description, authors, 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;
}
}
@@ -0,0 +1,30 @@
/*
* 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.Map;
/**
*
* @author huangyuhui
*/
public class LiteLoaderVersionsRoot {
public Map<String, LiteLoaderMCVersions> versions;
public LiteLoaderVersionsMeta meta;
}
@@ -0,0 +1,100 @@
/*
* 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;
import java.io.File;
import java.util.ArrayList;
import java.util.zip.ZipFile;
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.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;
/**
*
* @author huangyuhui
*/
public class OptiFineInstaller extends Task implements PreviousResultRegistrar<File> {
public File installer;
public IMinecraftService service;
public InstallerVersionList.InstallerVersion version;
public String installId;
public OptiFineInstaller(IMinecraftService service, String installId, InstallerVersionList.InstallerVersion version) {
this(service, installId, version, null);
}
public OptiFineInstaller(IMinecraftService service, String installId, InstallerVersionList.InstallerVersion version, File installer) {
this.service = service;
this.installId = installId;
this.installer = installer;
this.version = version;
}
@Override
public void executeTask() throws Exception {
if (installId == null)
throw new Exception(C.i18n("install.no_version"));
String selfId = version.selfVersion;
MinecraftVersion mv = (MinecraftVersion) service.version().getVersionById(installId).clone();
mv.inheritsFrom = mv.id;
mv.jar = mv.jar == null ? mv.id : mv.jar;
mv.libraries.clear();
mv.libraries.add(0, new MinecraftLibrary("optifine:OptiFine:" + selfId));
FileUtils.copyFile(installer, new File(service.baseDirectory(), "libraries/optifine/OptiFine/" + selfId + "/OptiFine-" + selfId + ".jar"));
mv.id += "-" + selfId;
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"));
}
mv.minecraftArguments += " --tweakClass optifine.OptiFineTweaker";
}
}
File loc = new File(service.baseDirectory(), "versions/" + mv.id);
if (!loc.exists() && loc.mkdirs())
HMCLog.warn("Failed to make directories: " + loc);
File json = new File(loc, mv.id + ".json");
FileUtils.writeStringToFile(json, C.GSON.toJson(mv, MinecraftVersion.class));
service.version().refreshVersions();
}
@Override
public String getInfo() {
return "OptiFine Installer";
}
ArrayList<PreviousResult<File>> pre = new ArrayList();
@Override
public Task registerPreviousResult(PreviousResult pr) {
pre.add(pr);
return this;
}
}
@@ -0,0 +1,67 @@
/*
* 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;
/**
*
* @author huangyuhui
*/
public class OptiFineVersion {
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)";
}
}
@@ -0,0 +1,58 @@
/*
* 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.util.regex.Matcher;
import java.util.regex.Pattern;
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;
/**
*
* @author huangyuhui
*/
public class OptiFineDownloadFormatter extends Task implements PreviousResult<String> {
String url, result;
public OptiFineDownloadFormatter(String url) {
this.url = url;
}
@Override
public void executeTask() throws Exception {
String content = NetUtils.get(url);
Pattern p = Pattern.compile("\"downloadx\\?f=OptiFine(.*)\"");
Matcher m = p.matcher(content);
while (m.find())
result = m.group(1);
result = "http://optifine.net/downloadx?f=OptiFine" + result;
}
@Override
public String getInfo() {
return C.i18n("install.optifine.get_download_link");
}
@Override
public String getResult() {
return result;
}
}
@@ -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;
}
}
@@ -0,0 +1,197 @@
/*
* 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.util.ArrayList;
import java.util.Arrays;
import java.util.List;
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.util.Utils;
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.launcher.core.service.IMinecraftService;
import org.jackhuang.hellominecraft.launcher.core.service.IMinecraftLoader;
/**
*
* @author huangyuhui
*/
public abstract class AbstractMinecraftLoader implements IMinecraftLoader {
protected LaunchOptions options;
protected UserProfileProvider lr;
protected File gameDir;
protected IMinecraftService service;
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;
this.service = service;
this.gameDir = service.baseDirectory();
this.version = service.version().getVersionById(versionId).resolve(service.version());
}
@Override
public MinecraftVersion getMinecraftVersion() {
return version;
}
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());
if (options.hasJavaArgs())
res.addAll(Arrays.asList(StrUtils.tokenize(options.getJavaArgs())));
if (!options.isNoJVMArgs()) {
appendJVMArgs(res);
if (jv == null || !jv.isEarlyAccess()) {
if (OS.os() == OS.WINDOWS)
res.add("-XX:HeapDumpPath=MojangTricksIntelDriversForPerformance_javaw.exe_minecraft.exe.heapdump");
if (jv != null && jv.getParsedVersion() >= JdkVersion.JAVA_17)
res.add("-XX:+UseG1GC");
else
res.add("-Xincgc");
res.add("-XX:-UseAdaptiveSizePolicy");
res.add("-XX:-OmitStackTraceInFastThrow");
res.add("-Xmn128m");
}
if (!StrUtils.isBlank(options.getPermSize()))
if (jv == null || jv.getParsedVersion() < JdkVersion.JAVA_18)
res.add("-XX:PermSize=" + options.getPermSize() + "m");
else if (jv.getParsedVersion() >= JdkVersion.JAVA_18)
res.add("-XX:MetaspaceSize=" + options.getPermSize() + "m");
}
if (jv != null) {
HMCLog.log("Java Version: " + jv.getVersion());
HMCLog.log("Java Platform: " + jv.getPlatform().getBit());
}
HMCLog.log("System Platform: " + Platform.getPlatform().getBit());
if (jv != null && jv.getPlatform() == Platform.BIT_32 && Platform.getPlatform() == Platform.BIT_64)
MessageBox.Show(C.i18n("advice.os64butjdk32"));
if (!StrUtils.isBlank(options.getMaxMemory())) {
int mem = MathUtils.parseMemory(options.getMaxMemory(), 2147483647);
if (jv != null && jv.getPlatform() == Platform.BIT_32 && mem > 1024)
MessageBox.Show(C.i18n("launch.too_big_memory_alloc_64bit"));
else {
long a = OS.getTotalPhysicalMemory() / 1024 / 1024;
HMCLog.log("System Physical Memory: " + a);
if (a > 0 && a < mem)
MessageBox.Show(C.i18n("launch.too_big_memory_alloc_free_space_too_low", a));
}
String a = "-Xmx" + options.getMaxMemory();
if (MathUtils.canParseInt(options.getMaxMemory()))
a += "m";
res.add(a);
}
res.add("-Djava.library.path=" + service.version().getDecompressNativesToLocation(version).getPath());
res.add("-Dfml.ignoreInvalidMinecraftCertificates=true");
res.add("-Dfml.ignorePatchDiscrepancies=true");
if (OS.os() != OS.WINDOWS)
res.add("-Duser.home=" + gameDir.getParent());
}
@Override
public List<String> makeLaunchingCommand() throws GameException {
HMCLog.log("*** Make shell command ***");
ArrayList<String> res = new ArrayList<>();
makeHeadCommand(res);
makeSelf(res);
HMCLog.log("On making launcher args.");
if (StrUtils.isNotBlank(options.getHeight()) && StrUtils.isNotBlank(options.getWidth())) {
res.add("--height");
res.add(options.getHeight());
res.add("--width");
res.add(options.getWidth());
}
String serverIp = options.getServerIp();
if (StrUtils.isNotBlank(serverIp)) {
String[] args = serverIp.split(":");
res.add("--server");
res.add(args[0]);
res.add("--port");
res.add(args.length > 1 ? args[1] : "25565");
}
if (options.isFullscreen())
res.add("--fullscreen");
if (StrUtils.isNotBlank(options.getProxyHost()) && StrUtils.isNotBlank(options.getProxyPort()) && MathUtils.canParseInt(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("--proxyUser");
res.add(options.getProxyUser());
res.add("-=proxyPass");
res.add(options.getProxyPass());
}
}
if (StrUtils.isNotBlank(options.getMinecraftArgs()))
res.addAll(Arrays.asList(options.getMinecraftArgs().split(" ")));
return res;
}
/**
* You must do these things:
* <ul>
* <li>minecraft class path</li>
* <li>main class</li>
* <li>minecraft arguments</li>
* </ul>
*
* @param list the command list you shoud edit.
*/
protected abstract void makeSelf(List<String> list) throws GameException;
protected void appendJVMArgs(List<String> list) {
}
}
@@ -0,0 +1,72 @@
/*
* 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.IOException;
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.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 {
public DefaultGameLauncher(LaunchOptions options, IMinecraftService service, LoginInfo info, IAuthenticator lg) {
super(options, service, info, lg);
register();
}
private void register() {
downloadLibrariesEvent.register((sender, t) -> {
final TaskWindow.TaskWindowFactory dw = TaskWindow.factory();
ParallelTask parallelTask = new ParallelTask();
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.append(parallelTask);
boolean flag = true;
if (t.size() > 0)
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;
});
decompressNativesEvent.register((sender, value) -> {
if (value == null)
return false;
for (int i = 0; i < value.decompressFiles.length; i++)
try {
Compressor.unzip(value.decompressFiles[i], value.getDecompressTo(), value.extractRules[i]::allow, false);
} catch (IOException ex) {
HMCLog.err("Unable to decompress library: " + value.decompressFiles[i] + " to " + value.getDecompressTo(), ex);
}
return true;
});
}
}
@@ -0,0 +1,192 @@
/*
* 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 org.jackhuang.hellominecraft.launcher.core.service.IMinecraftLoader;
import org.jackhuang.hellominecraft.launcher.core.service.IMinecraftService;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.UnsupportedEncodingException;
import java.util.List;
import org.jackhuang.hellominecraft.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;
import org.jackhuang.hellominecraft.launcher.core.auth.LoginInfo;
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.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 {
public static final ProcessManager PROCESS_MANAGER = new ProcessManager();
LaunchOptions options;
IMinecraftService service;
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<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;
this.service = version;
this.info = info;
this.login = lg;
}
private Object tag;
public Object getTag() {
return tag;
}
public void setTag(Object tag) {
this.tag = tag;
}
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);
else
result = login.loginBySettings();
if (result == null)
throw new AuthenticationException("Result can not be null.");
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...");
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");
successEvent.execute(loader.makeLaunchingCommand());
return loader;
}
/**
* Launch the game "as soon as possible".
*
* @param str launch command
*
* @throws IOException failed creating process
*/
public void launch(List str) throws IOException {
if (!service.version().onLaunch())
return;
if (StrUtils.isNotBlank(options.getPrecalledCommand())) {
Process p = Runtime.getRuntime().exec(options.getPrecalledCommand());
try {
if (p.isAlive())
p.waitFor();
} catch (InterruptedException ex) {
HMCLog.warn("Failed to invoke precalled command", ex);
}
}
HMCLog.log("Starting process");
ProcessBuilder builder = new ProcessBuilder(str);
if (options.getLaunchVersion() == null || service.baseDirectory() == null)
throw new Error("Fucking bug!");
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("Have started the process");
launchEvent.execute(jp);
}
/**
* According to the name...
*
* @param launcherName the name of launch bat/sh
* @param str launch command
*
* @return launcher location
*
* @throws java.io.IOException write contents failed.
*/
public File makeLauncher(String launcherName, List str) throws IOException {
HMCLog.log("Making shell launcher...");
service.version().onLaunch();
boolean isWin = OS.os() == OS.WINDOWS;
File f = new File(launcherName + (isWin ? ".bat" : ".sh"));
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")));
} catch (UnsupportedEncodingException ex) {
HMCLog.warn("Failed to create writer, will try again.", ex);
writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(f)));
}
if (isWin) {
writer.write("@echo off");
writer.newLine();
String appdata = IOUtils.tryGetCanonicalFilePath(service.baseDirectory());
if (appdata != null) {
writer.write("set appdata=" + appdata);
writer.newLine();
}
}
if (StrUtils.isNotBlank(options.getPrecalledCommand())) {
writer.write(options.getPrecalledCommand());
writer.newLine();
}
writer.write(StrUtils.makeCommand(str));
writer.close();
if (!f.setExecutable(true)) {
HMCLog.warn("Failed to give launcher permission.");
MessageBox.Show(C.i18n("launch.failed_sh_permission"));
}
HMCLog.log("Command: " + StrUtils.parseParams("", str, " "));
return f;
}
}
@@ -0,0 +1,225 @@
/*
* 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.launch;
import java.io.File;
import org.jackhuang.hellominecraft.launcher.core.version.GameDirType;
import org.jackhuang.hellominecraft.util.StrUtils;
import org.jackhuang.hellominecraft.util.system.JdkVersion;
/**
*
* @author huangyuhui
*/
public class LaunchOptions {
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;
private JdkVersion java;
private File gameDir;
private GameDirType gameDirType;
public String getVersionName() {
return versionName;
}
public void setVersionName(String versionName) {
this.versionName = versionName;
}
public File getGameDir() {
return gameDir;
}
public void setGameDir(File gameDir) {
this.gameDir = gameDir;
}
public void setJavaDir(String javaDir) {
this.javaDir = javaDir;
}
public String getJavaDir() {
return javaDir;
}
public JdkVersion getJava() {
return java;
}
public void setJava(JdkVersion java) {
this.java = java;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getJavaArgs() {
return javaArgs;
}
public void setJavaArgs(String javaArgs) {
this.javaArgs = javaArgs;
}
public boolean hasJavaArgs() {
return StrUtils.isNotBlank(getJavaArgs().trim());
}
public String getMaxMemory() {
return maxMemory;
}
public void setMaxMemory(String maxMemory) {
this.maxMemory = maxMemory;
}
public String getWrapper() {
return wrapper;
}
public void setWrapper(String wrapper) {
this.wrapper = wrapper;
}
public String getWidth() {
return width;
}
public void setWidth(String width) {
this.width = width;
}
public String getHeight() {
return height;
}
public void setHeight(String height) {
this.height = height;
}
public boolean isFullscreen() {
return fullscreen;
}
public void setFullscreen(boolean fullscreen) {
this.fullscreen = fullscreen;
}
public GameDirType getGameDirType() {
return gameDirType;
}
public void setGameDirType(GameDirType gameDirType) {
this.gameDirType = gameDirType;
}
public String getPermSize() {
return permSize;
}
public void setPermSize(String permSize) {
this.permSize = permSize;
}
public boolean isNoJVMArgs() {
return noJVMArgs;
}
public void setNoJVMArgs(boolean noJVMArgs) {
this.noJVMArgs = noJVMArgs;
}
public String getMinecraftArgs() {
return minecraftArgs;
}
public void setMinecraftArgs(String minecraftArgs) {
this.minecraftArgs = minecraftArgs;
}
public String getServerIp() {
return serverIp;
}
public void setServerIp(String serverIp) {
this.serverIp = serverIp;
}
public String getProxyHost() {
return proxyHost;
}
public void setProxyHost(String proxyHost) {
this.proxyHost = proxyHost;
}
public String getProxyPort() {
return proxyPort;
}
public void setProxyPort(String proxyPort) {
this.proxyPort = proxyPort;
}
public String getProxyUser() {
return proxyUser;
}
public void setProxyUser(String proxyUser) {
this.proxyUser = proxyUser;
}
public String getProxyPass() {
return proxyPass;
}
public void setProxyPass(String proxyPass) {
this.proxyPass = proxyPass;
}
public String getPrecalledCommand() {
return precalledCommand;
}
public void setPrecalledCommand(String precalledCommand) {
this.precalledCommand = precalledCommand;
}
public String getLaunchVersion() {
return launchVersion;
}
public void setLaunchVersion(String launchVersion) {
this.launchVersion = launchVersion;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
}
@@ -0,0 +1,29 @@
/*
* 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.launch;
/**
*
* @author huangyuhui
*/
public enum LaunchingState {
LoggingIn,
GeneratingLaunchingCodes,
DownloadingLibraries,
DecompressingNatives
}
@@ -0,0 +1,66 @@
/*
* 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.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.path);
}
void download(URL url, File filePath) throws Throwable {
this.url = url;
this.filePath = filePath;
super.executeTask();
}
@Override
public String getInfo() {
return C.i18n("download") + ": " + job.lib.name;
}
}
@@ -0,0 +1,111 @@
/*
* 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.List;
import org.jackhuang.hellominecraft.util.StrUtils;
import org.jackhuang.hellominecraft.util.func.Function;
import org.jackhuang.hellominecraft.util.logging.HMCLog;
import org.jackhuang.hellominecraft.util.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;
/**
*
* @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("");
for (MinecraftLibrary l : version.libraries)
if (l.allow() && !l.isRequiredToUnzip())
library.append(l.getFilePath(gameDir).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);
String[] splitted = StrUtils.tokenize(version.minecraftArguments);
String game_assets = assetProvider.apply(version);
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 Function<MinecraftVersion, String> DEFAULT_ASSET_PROVIDER = t -> {
return new File(service.baseDirectory(), "assets").getAbsolutePath();
};
private Function<MinecraftVersion, String> assetProvider = DEFAULT_ASSET_PROVIDER;
public void setAssetProvider(Function<MinecraftVersion, String> assetProvider) {
if (assetProvider == null)
this.assetProvider = DEFAULT_ASSET_PROVIDER;
else
this.assetProvider = assetProvider;
}
}
@@ -0,0 +1,117 @@
/*
* 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.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
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.util.code.DigestUtils;
import org.jackhuang.hellominecraft.util.system.FileUtils;
/**
*
* @author huangyuhui
*/
public class MinecraftModService extends IMinecraftModService {
Map<String, List<ModInfo>> modCache = Collections.synchronizedMap(new HashMap<>());
public MinecraftModService(IMinecraftService service) {
super(service);
}
@Override
public List<ModInfo> getMods(String id) {
if (modCache.containsKey(id))
return modCache.get(id);
else
return recacheMods(id);
}
@Override
public List<ModInfo> recacheMods(String id) {
File modsFolder = service.version().getRunDirectory(id, "mods");
ArrayList<ModInfo> mods = new ArrayList<>();
File[] fs = modsFolder.listFiles();
if (fs != null)
for (File f : fs)
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))
mods.add(ModInfo.readModInfo(ff));
}
Collections.sort(mods);
modCache.put(id, mods);
return mods;
}
@Override
public boolean addMod(String id, File f) {
try {
if (!ModInfo.isFileMod(f))
return false;
if (!modCache.containsKey(id))
recacheMods(id);
File modsFolder = service.version().getRunDirectory(id, "mods");
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);
modCache.get(id).add(i);
return true;
} catch (IOException ex) {
HMCLog.warn("Failed to copy mod", ex);
return false;
}
}
@Override
public void removeMod(String id, Object[] rows) {
if (rows.length == 0)
return;
for (Object r : rows)
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);
}
public String[] checkMd5s(String id) throws IOException {
String[] res = new String[getMods(id).size()];
for (int i = 0; i < res.length; i++)
res[i] = DigestUtils.md5Hex(new FileInputStream(getMods(id).get(i).location));
return res;
}
}
@@ -0,0 +1,147 @@
/*
* 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 com.google.gson.JsonSyntaxException;
import com.google.gson.reflect.TypeToken;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.lang.reflect.Type;
import java.util.List;
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.util.StrUtils;
import org.jackhuang.hellominecraft.util.system.FileUtils;
/**
*
* @author huangyuhui
*/
public class ModInfo implements Comparable<ModInfo> {
public File location;
public String modid, name, description, author, version, mcversion, url, updateUrl, credits;
public String[] authorList;
public boolean isActive() {
return !location.getName().endsWith(".disabled");
}
public void reverseModState() {
File f = location, newf;
if (f.getName().endsWith(".disabled"))
newf = new File(f.getParentFile(), f.getName().substring(0, f.getName().length() - ".disabled".length()));
else
newf = new File(f.getParentFile(), f.getName() + ".disabled");
if (f.renameTo(newf))
location = newf;
}
@Override
public int compareTo(ModInfo o) {
return getFileName().compareToIgnoreCase(o.getFileName());
}
public String getName() {
return name == null ? FileUtils.removeExtension(location.getName()) : name;
}
public String getAuthor() {
if (authorList != null && authorList.length > 0)
return StrUtils.parseParams("", authorList, ", ");
else if (StrUtils.isNotBlank(author))
return author;
else
return "Unknown";
}
@Override
public boolean equals(Object obj) {
return obj != null && obj instanceof ModInfo && (((ModInfo) obj).location == location || ((ModInfo) obj).location.equals(location));
}
@Override
public int hashCode() {
return location.hashCode();
}
@Override
public String toString() {
return getFileName();
}
public String getFileName() {
String n = location.getName();
return FileUtils.removeExtension(isActive() ? n : n.substring(0, n.length() - ".disabled".length()));
}
public static boolean isFileMod(File file) {
if (file == null)
return false;
String name = file.getName();
boolean disabled = name.endsWith(".disabled");
if (disabled)
name = name.substring(0, name.length() - ".disabled".length());
return name.endsWith(".zip") || name.endsWith(".jar") || name.endsWith("litemod");
}
private static final Type TYPE = new TypeToken<List<ModInfo>>() {
}.getType();
private static ModInfo getForgeModInfo(File f, ZipFile jar, ZipEntry entry) throws IOException {
ModInfo i = new ModInfo();
i.location = f;
List<ModInfo> m = C.GSON.fromJson(new InputStreamReader(jar.getInputStream(entry), "UTF-8"), TYPE);
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), "UTF-8"), ModInfo.class);
if (m == null)
m = new ModInfo();
m.location = f;
return m;
}
public static ModInfo readModInfo(File f) {
ModInfo i = new ModInfo();
i.location = f;
try {
try (ZipFile jar = new ZipFile(f)) {
ZipEntry entry = jar.getEntry("mcmod.info");
if (entry != null)
return getForgeModInfo(f, jar, entry);
entry = jar.getEntry("litemod.json");
if (entry != null)
return getLiteLoaderModInfo(f, jar, entry);
return i;
}
} catch (IOException ex) {
HMCLog.warn("File " + f + " is not a jar.", ex);
} catch (JsonSyntaxException ignore) {
}
return i;
}
}
@@ -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.readFileToString(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.writeStringToFile(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();
}
}
}
@@ -0,0 +1,53 @@
/*
* 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.service;
import java.io.File;
import java.io.IOException;
import org.jackhuang.hellominecraft.launcher.core.version.AssetIndexDownloadInfo;
import org.jackhuang.hellominecraft.util.tasks.Task;
/**
*
* @author huangyuhui
*/
public abstract class IMinecraftAssetService extends IMinecraftBasicService {
public IMinecraftAssetService(IMinecraftService service) {
super(service);
}
public abstract Task downloadAssets(String mcVersion);
public abstract File getAssets();
/**
* Redownload the Asset index json of the given version.
*
* @param a the given version name
*
* @return Is the action successful?
*/
public abstract boolean refreshAssetsIndex(String a);
public abstract boolean downloadMinecraftAssetsIndexAsync(AssetIndexDownloadInfo assetsId);
public abstract Task downloadMinecraftAssetsIndex(AssetIndexDownloadInfo assetsId);
public abstract File getAssetObject(String assetVersion, String name) throws IOException;
}
@@ -0,0 +1,32 @@
/*
* 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.service;
/**
*
* @author huangyuhui
*/
public abstract class IMinecraftBasicService {
public IMinecraftService service;
public IMinecraftBasicService(IMinecraftService service) {
this.service = service;
}
}
@@ -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.service;
import java.io.File;
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.util.tasks.Task;
/**
*
* @author huangyuhui
*/
public abstract class IMinecraftDownloadService extends IMinecraftBasicService {
public IMinecraftDownloadService(IMinecraftService service) {
super(service);
}
public abstract Task downloadMinecraft(String id);
public abstract Task downloadMinecraftJar(MinecraftVersion mv, File f);
public abstract Task downloadMinecraftVersionJson(String id);
/**
* Get the libraries that need to download.
*
* @return the library collection
*/
public abstract List<DownloadLibraryJob> getDownloadLibraries(MinecraftVersion mv) throws GameException;
}
@@ -0,0 +1,42 @@
/*
* 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.service;
import org.jackhuang.hellominecraft.launcher.core.install.InstallerType;
import org.jackhuang.hellominecraft.launcher.core.install.InstallerVersionList;
import org.jackhuang.hellominecraft.util.tasks.Task;
/**
*
* @author huangyuhui
*/
public abstract class IMinecraftInstallerService extends IMinecraftBasicService {
public IMinecraftInstallerService(IMinecraftService service) {
super(service);
}
public abstract Task download(String installId, InstallerVersionList.InstallerVersion v, InstallerType type);
public abstract Task downloadForge(String installId, InstallerVersionList.InstallerVersion v);
public abstract Task downloadOptiFine(String installId, InstallerVersionList.InstallerVersion v);
public abstract Task downloadLiteLoader(String installId, InstallerVersionList.InstallerVersion v);
}
@@ -0,0 +1,33 @@
/*
* 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.service;
import java.util.List;
import org.jackhuang.hellominecraft.launcher.core.GameException;
import org.jackhuang.hellominecraft.launcher.core.version.MinecraftVersion;
/**
*
* @author huangyuhui
*/
public interface IMinecraftLoader {
MinecraftVersion getMinecraftVersion();
List<String> makeLaunchingCommand() throws GameException;
}
@@ -0,0 +1,41 @@
/*
* 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.service;
import java.io.File;
import java.util.List;
import org.jackhuang.hellominecraft.launcher.core.mod.ModInfo;
/**
*
* @author huangyuhui
*/
public abstract class IMinecraftModService extends IMinecraftBasicService {
public IMinecraftModService(IMinecraftService service) {
super(service);
}
public abstract List<ModInfo> getMods(String id);
public abstract List<ModInfo> recacheMods(String id);
public abstract boolean addMod(String id, File f);
public abstract void removeMod(String id, Object[] mods);
}
@@ -0,0 +1,173 @@
/*
* 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.service;
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.MinecraftVersion;
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.
*
* @see
* org.jackhuang.hellominecraft.launcher.core.version.MinecraftVersionManager
* @author huangyuhui
*/
public abstract class IMinecraftProvider {
protected IMinecraftService service;
public IMinecraftProvider(IMinecraftService service) {
this.service = service;
}
/**
* To download mod packs.
*/
public abstract void initializeMiencraft();
/**
* Get the run directory of given version.
*
* @param id the given version name
*
* @return the run directory
*/
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);
}
public abstract void open(String version, String folder);
/**
* Install a new version to this profile.
*
* @param version the new version name
*
* @return Is the action successful?
*/
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
*
* @return libraries of resolved minecraft version v.
*/
public abstract DecompressLibraryJob getDecompressLibraries(MinecraftVersion v) throws GameException;
public abstract File getDecompressNativesToLocation(MinecraftVersion v);
/**
* @return the Minecraft jar of selected version.
*/
public abstract File getMinecraftJar(String id);
/**
* Rename version
*
* @param from The old name
* @param to The new name
*
* @return Is the action successful?
*/
public abstract boolean renameVersion(String from, String to);
/**
* Remove the given version from disk.
*
* @param a the version name
*
* @return Is the action successful?
*/
public abstract boolean removeVersionFromDisk(String a);
/**
* Choose a version randomly.
*
* @return the version
*/
public abstract MinecraftVersion getOneVersion(Predicate<MinecraftVersion> p);
/**
* All Minecraft version in this profile.
*
* @return the collection of all Minecraft version
*/
public abstract Collection<MinecraftVersion> getVersions();
/**
* Get the Minecraft json instance of given version.
*
* @param id the given version name
*
* @return the Minecraft json instance
*/
public abstract MinecraftVersion getVersionById(String id);
/**
* getVersions().size()
*
* @return getVersions().size()
*/
public abstract int getVersionCount();
/**
* 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.
*/
public abstract void cleanFolder();
/**
* When GameLauncher launches the game, this function will be called.
*
* @return if false, will break the launch process.
*/
public abstract boolean onLaunch();
public File baseDirectory() {
return service.baseDirectory();
}
}
@@ -0,0 +1,60 @@
/*
* 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.service;
import java.io.File;
import org.jackhuang.hellominecraft.launcher.core.GameException;
import org.jackhuang.hellominecraft.launcher.core.auth.UserProfileProvider;
import org.jackhuang.hellominecraft.launcher.core.download.DownloadType;
import org.jackhuang.hellominecraft.launcher.core.launch.LaunchOptions;
/**
*
* @author huangyuhui
*/
public abstract class IMinecraftService {
public abstract File baseDirectory();
public DownloadType getDownloadType() {
return DownloadType.getSuggestedDownloadType();
}
public abstract IMinecraftAssetService asset();
public abstract IMinecraftDownloadService download();
public abstract IMinecraftModService mod();
public abstract IMinecraftProvider version();
public abstract IMinecraftInstallerService install();
/**
* Provide the Minecraft Loader to generate the launching command.
*
* @see org.jackhuang.hellominecraft.launcher.core.service.IMinecraftLoader
* @param p player informations, including username & auth_token
*
* @return what you want
*
* @throws GameException circular denpendency versions
*/
public abstract IMinecraftLoader launch(LaunchOptions options, UserProfileProvider p) throws GameException;
}
@@ -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;
}
}
@@ -0,0 +1,46 @@
/*
* 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 java.io.File;
/**
*
* @author huangyuhui
*/
public class DecompressLibraryJob {
public File[] decompressFiles;
public Extract[] extractRules;
private File decompressTo;
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,46 @@
/*
* 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 java.util.ArrayList;
import java.util.List;
import org.jackhuang.hellominecraft.util.StrUtils;
/**
*
* @author huangyuhui
*/
public class Extract implements Cloneable {
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,28 @@
/*
* 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;
/**
*
* @author huangyuhui
*/
public enum GameDirType {
ROOT_FOLDER,
VERSION_FOLDER;
}
@@ -0,0 +1,75 @@
/*
* 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 GameDownloadInfo implements Cloneable {
public String sha1;
public int size;
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);
}
}
}
@@ -0,0 +1,67 @@
/*
* 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 java.io.File;
/**
*
* @author huangyuhui
*/
public abstract class IMinecraftLibrary implements Cloneable {
public String name;
public IMinecraftLibrary(String name) {
this.name = name;
}
public abstract boolean isRequiredToUnzip();
public abstract Extract getDecompressExtractRules();
public abstract LibraryDownloadInfo getDownloadInfo();
public abstract boolean allow();
public abstract File getFilePath(File gameDir);
@Override
public boolean equals(Object obj) {
if (obj instanceof MinecraftLibrary)
return ((MinecraftLibrary) obj).name.equals(name);
return false;
}
@Override
public int hashCode() {
int hash = 3;
hash = 89 * hash + (this.name != null ? this.name.hashCode() : 0);
return hash;
}
@Override
@SuppressWarnings("CloneDeclaresCloneNotSupported")
public Object clone() {
try {
return super.clone();
} catch (CloneNotSupportedException ex) {
throw new InternalError(ex);
}
}
}
@@ -0,0 +1,30 @@
/*
* 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 java.util.Map;
/**
*
* @author huangyuhui
*/
public class LibrariesDownloadInfo {
Map<String, LibraryDownloadInfo> classifiers;
LibraryDownloadInfo artifact;
}
@@ -0,0 +1,44 @@
/*
* 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;
import org.jackhuang.hellominecraft.util.StrUtils;
/**
*
* @author huangyuhui
*/
public class LibraryDownloadInfo extends GameDownloadInfo {
public String path;
public String forgeURL;
@Override
public String getUrl(DownloadType dt, boolean allowSelf) {
String myURL = (forgeURL == null ? dt.getProvider().getLibraryDownloadURL() : forgeURL);
if (StrUtils.isNotBlank(url) && allowSelf)
myURL = url;
if (!myURL.endsWith(".jar"))
if (path == null)
return null;
else
myURL += path.replace('\\', '/');
return myURL;
}
}
Loaded 100 of 718 files, more files were not shown because too many files have changed in this diff. Show more