diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/game/HMCLModpackExportTask.java b/HMCL/src/main/java/org/jackhuang/hmcl/game/HMCLModpackExportTask.java index c12593034..5b99aa60c 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/game/HMCLModpackExportTask.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/game/HMCLModpackExportTask.java @@ -17,6 +17,7 @@ */ package org.jackhuang.hmcl.game; +import org.jackhuang.hmcl.mod.ModAdviser; import org.jackhuang.hmcl.mod.Modpack; import org.jackhuang.hmcl.task.Task; import org.jackhuang.hmcl.util.Logging; @@ -55,7 +56,7 @@ public class HMCLModpackExportTask extends Task { @Override public void execute() throws Exception { - ArrayList blackList = new ArrayList<>(HMCLModpackManager.MODPACK_BLACK_LIST); + ArrayList blackList = new ArrayList<>(ModAdviser.MODPACK_BLACK_LIST); blackList.add(version + ".jar"); blackList.add(version + ".json"); Logging.LOG.info("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"); diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/game/HMCLModpackManager.java b/HMCL/src/main/java/org/jackhuang/hmcl/game/HMCLModpackManager.java index 9dc08f51f..3d3aff754 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/game/HMCLModpackManager.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/game/HMCLModpackManager.java @@ -19,7 +19,6 @@ package org.jackhuang.hmcl.game; import com.google.gson.JsonParseException; import org.jackhuang.hmcl.mod.Modpack; -import org.jackhuang.hmcl.util.Lang; import org.jackhuang.hmcl.util.StringUtils; import org.jackhuang.hmcl.util.gson.JsonUtils; import org.jackhuang.hmcl.util.io.CompressingUtils; @@ -27,51 +26,12 @@ import org.jackhuang.hmcl.util.io.CompressingUtils; import java.io.IOException; import java.nio.charset.Charset; import java.nio.file.Path; -import java.util.List; /** * @author huangyuhui */ public final class HMCLModpackManager { - public static final List MODPACK_BLACK_LIST = Lang.immutableListOf( - "usernamecache.json", "usercache.json", // Minecraft - "launcher_profiles.json", "launcher.pack.lzma", // Minecraft Launcher - "pack.json", "launcher.jar", "hmclmc.log", "cache", // HMCL - "manifest.json", "minecraftinstance.json", ".curseclient", // Curse - "minetweaker.log", // Mods - "jars", "logs", "versions", "assets", "libraries", "crash-reports", "NVIDIA", "AMD", "screenshots", "natives", "native", "$native", "server-resource-packs", // Minecraft - "downloads", // Curse - "asm", "backups", "TCNodeTracker", "CustomDISkins", "data" // Mods - ); - public static final List MODPACK_SUGGESTED_BLACK_LIST = Lang.immutableListOf( - "fonts", // BetterFonts - "saves", "servers.dat", "options.txt", // Minecraft - "blueprints" /* BuildCraft */, - "optionsof.txt" /* OptiFine */, - "journeymap" /* JourneyMap */, - "optionsshaders.txt", - "mods/VoxelMods"); - - public static ModAdviser.ModSuggestion suggestMod(String fileName, boolean isDirectory) { - if (match(MODPACK_BLACK_LIST, fileName, isDirectory)) - return ModAdviser.ModSuggestion.HIDDEN; - if (match(MODPACK_SUGGESTED_BLACK_LIST, fileName, isDirectory)) - return ModAdviser.ModSuggestion.NORMAL; - else - return ModAdviser.ModSuggestion.SUGGESTED; - } - - private static boolean match(List l, String fileName, boolean isDirectory) { - for (String s : l) - if (isDirectory) { - if (fileName.startsWith(s + "/")) - return true; - } else if (fileName.equals(s)) - return true; - return false; - } - /** * Read the manifest in a HMCL modpack. * diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/game/ModAdviser.java b/HMCL/src/main/java/org/jackhuang/hmcl/game/ModAdviser.java deleted file mode 100644 index a38086181..000000000 --- a/HMCL/src/main/java/org/jackhuang/hmcl/game/ModAdviser.java +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Hello Minecraft! Launcher - * Copyright (C) 2019 huangyuhui and contributors - * - * 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 . - */ -package org.jackhuang.hmcl.game; - -/** - * @author huangyuhui - */ -public interface ModAdviser { - ModSuggestion advise(String fileName, boolean isDirectory); - - enum ModSuggestion { - SUGGESTED, - NORMAL, - HIDDEN - } -} diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/export/ExportWizardProvider.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/export/ExportWizardProvider.java index f5fb14b8b..fb24fa508 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/export/ExportWizardProvider.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/export/ExportWizardProvider.java @@ -20,14 +20,18 @@ package org.jackhuang.hmcl.ui.export; import javafx.scene.Node; import org.jackhuang.hmcl.Launcher; import org.jackhuang.hmcl.game.HMCLModpackExportTask; -import org.jackhuang.hmcl.game.HMCLModpackManager; +import org.jackhuang.hmcl.mod.ModAdviser; import org.jackhuang.hmcl.mod.Modpack; +import org.jackhuang.hmcl.mod.MultiMCInstanceConfiguration; +import org.jackhuang.hmcl.mod.MultiMCModpackExportTask; import org.jackhuang.hmcl.setting.Config; import org.jackhuang.hmcl.setting.ConfigHolder; import org.jackhuang.hmcl.setting.Profile; +import org.jackhuang.hmcl.setting.VersionSetting; import org.jackhuang.hmcl.task.Task; import org.jackhuang.hmcl.ui.wizard.WizardController; import org.jackhuang.hmcl.ui.wizard.WizardProvider; +import org.jackhuang.hmcl.util.Lang; import org.jackhuang.hmcl.util.io.Zipper; import java.io.File; @@ -57,27 +61,37 @@ public final class ExportWizardProvider implements WizardProvider { public Object finish(Map settings) { @SuppressWarnings("unchecked") List whitelist = (List) settings.get(ModpackFileSelectionPage.MODPACK_FILE_SELECTION); + File modpackFile = (File) settings.get(ModpackInfoPage.MODPACK_FILE); + String modpackName = (String) settings.get(ModpackInfoPage.MODPACK_NAME); + String modpackAuthor = (String) settings.get(ModpackInfoPage.MODPACK_AUTHOR); + String modpackVersion = (String) settings.get(ModpackInfoPage.MODPACK_VERSION); + String modpackDescription = (String) settings.get(ModpackInfoPage.MODPACK_DESCRIPTION); + String modpackType = (String) settings.get(ModpackTypeSelectionPage.MODPACK_TYPE); + boolean includeLauncher = (Boolean) settings.get(ModpackInfoPage.MODPACK_INCLUDE_LAUNCHER); + + switch (modpackType) { + case ModpackTypeSelectionPage.MODPACK_TYPE_HMCL: + return exportAsHMCL(whitelist, modpackFile, modpackName, modpackAuthor, modpackVersion, modpackDescription, includeLauncher); + case ModpackTypeSelectionPage.MODPACK_TYPE_MULTIMC: + return exportAsMultiMC(whitelist, modpackFile, modpackName, modpackAuthor, modpackVersion, modpackDescription); + default: + throw new IllegalStateException("Unrecognized modpack type " + modpackType); + } + } + + private Task exportAsHMCL(List whitelist, File modpackFile, String modpackName, String modpackAuthor, String modpackVersion, String modpackDescription, boolean includeLauncherRaw) { List launcherJar = Launcher.getCurrentJarFiles(); - boolean includeLauncher = (Boolean) settings.get(ModpackInfoPage.MODPACK_INCLUDE_LAUNCHER) && launcherJar != null; + boolean includeLauncher = includeLauncherRaw && launcherJar != null; return new Task() { Task dependency = null; @Override public void execute() throws Exception { - File modpackFile = (File) settings.get(ModpackInfoPage.MODPACK_FILE); File tempModpack = includeLauncher ? Files.createTempFile("hmcl", ".zip").toFile() : modpackFile; dependency = new HMCLModpackExportTask(profile.getRepository(), version, whitelist, - new Modpack( - (String) settings.get(ModpackInfoPage.MODPACK_NAME), - (String) settings.get(ModpackInfoPage.MODPACK_AUTHOR), - (String) settings.get(ModpackInfoPage.MODPACK_VERSION), - null, - (String) settings.get(ModpackInfoPage.MODPACK_DESCRIPTION), - StandardCharsets.UTF_8, - null - ), tempModpack); + new Modpack(modpackName, modpackAuthor, modpackVersion, null, modpackDescription, StandardCharsets.UTF_8, null), tempModpack); if (includeLauncher) { dependency = dependency.thenRunAsync(() -> { @@ -120,11 +134,55 @@ public final class ExportWizardProvider implements WizardProvider { }; } + private Task exportAsMultiMC(List whitelist, File modpackFile, String modpackName, String modpackAuthor, String modpackVersion, String modpackDescription) { + return new Task() { + Task dependency; + + @Override + public void execute() { + VersionSetting vs = profile.getVersionSetting(version); + dependency = new MultiMCModpackExportTask(profile.getRepository(), version, whitelist, + new MultiMCInstanceConfiguration( + "OneSix", + modpackName + "-" + modpackVersion, + null, + Lang.toIntOrNull(vs.getPermSize()), + vs.getWrapper(), + vs.getPreLaunchCommand(), + null, + modpackDescription, + null, + vs.getJavaArgs(), + vs.isFullscreen(), + vs.getWidth(), + vs.getHeight(), + vs.getMaxMemory(), + vs.getMinMemory(), + vs.isShowLogs(), + /* showConsoleOnError */ true, + /* autoCloseConsole */ false, + /* overrideMemory */ true, + /* overrideJavaLocation */ false, + /* overrideJavaArgs */ true, + /* overrideConsole */ true, + /* overrideCommands */ true, + /* overrideWindow */ true + ), modpackFile); + } + + @Override + public Collection> getDependencies() { + return Collections.singleton(dependency); + } + }; + } + @Override public Node createPage(WizardController controller, int step, Map settings) { switch (step) { case 0: return new ModpackInfoPage(controller, version); - case 1: return new ModpackFileSelectionPage(controller, profile, version, HMCLModpackManager::suggestMod); + case 1: return new ModpackFileSelectionPage(controller, profile, version, ModAdviser::suggestMod); + case 2: return new ModpackTypeSelectionPage(controller); default: throw new IllegalArgumentException("step"); } } diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/export/ModpackFileSelectionPage.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/export/ModpackFileSelectionPage.java index c3f29f135..77c738706 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/export/ModpackFileSelectionPage.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/export/ModpackFileSelectionPage.java @@ -25,7 +25,7 @@ import javafx.scene.control.Label; import javafx.scene.control.TreeItem; import javafx.scene.layout.HBox; import javafx.scene.layout.StackPane; -import org.jackhuang.hmcl.game.ModAdviser; +import org.jackhuang.hmcl.mod.ModAdviser; import org.jackhuang.hmcl.setting.Profile; import org.jackhuang.hmcl.ui.FXUtils; import org.jackhuang.hmcl.ui.construct.NoneMultipleSelectionModel; @@ -146,7 +146,7 @@ public final class ModpackFileSelectionPage extends StackPane implements WizardP LinkedList list = new LinkedList<>(); getFilesNeeded(rootNode, "minecraft", list); controller.getSettings().put(MODPACK_FILE_SELECTION, list); - controller.onFinish(); + controller.onNext(); } @Override diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/export/ModpackTypeSelectionPage.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/export/ModpackTypeSelectionPage.java new file mode 100644 index 000000000..8884d3e05 --- /dev/null +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/export/ModpackTypeSelectionPage.java @@ -0,0 +1,66 @@ +/* + * Hello Minecraft! Launcher + * Copyright (C) 2019 huangyuhui and contributors + * + * 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 . + */ +package org.jackhuang.hmcl.ui.export; + +import com.jfoenix.controls.JFXButton; +import javafx.fxml.FXML; +import javafx.scene.layout.StackPane; +import org.jackhuang.hmcl.ui.FXUtils; +import org.jackhuang.hmcl.ui.wizard.WizardController; +import org.jackhuang.hmcl.ui.wizard.WizardPage; + +import java.util.Map; + +import static org.jackhuang.hmcl.util.i18n.I18n.i18n; + +public final class ModpackTypeSelectionPage extends StackPane implements WizardPage { + private final WizardController controller; + @FXML + private JFXButton btnHMCL; + @FXML + private JFXButton btnMultiMC; + + public ModpackTypeSelectionPage(WizardController controller) { + this.controller = controller; + FXUtils.loadFXML(this, "/assets/fxml/modpack/type.fxml"); + + JFXButton[] buttons = new JFXButton[]{btnHMCL, btnMultiMC}; + String[] types = new String[]{MODPACK_TYPE_HMCL, MODPACK_TYPE_MULTIMC}; + for (int i = 0; i < types.length; ++i) { + String type = types[i]; + buttons[i].setOnMouseClicked(e -> { + controller.getSettings().put(MODPACK_TYPE, type); + controller.onFinish(); + }); + } + } + + @Override + public void cleanup(Map settings) { + } + + @Override + public String getTitle() { + return i18n("modpack.wizard.step.3.title"); + } + + public static final String MODPACK_TYPE = "modpack.type"; + + public static final String MODPACK_TYPE_MULTIMC = "multimc"; + public static final String MODPACK_TYPE_HMCL = "hmcl"; +} diff --git a/HMCL/src/main/resources/assets/fxml/modpack/selection.fxml b/HMCL/src/main/resources/assets/fxml/modpack/selection.fxml index 3f3dde7ff..5d3746797 100644 --- a/HMCL/src/main/resources/assets/fxml/modpack/selection.fxml +++ b/HMCL/src/main/resources/assets/fxml/modpack/selection.fxml @@ -17,7 +17,7 @@ + text="%wizard.next" styleClass="jfx-button-raised"/> diff --git a/HMCL/src/main/resources/assets/fxml/modpack/type.fxml b/HMCL/src/main/resources/assets/fxml/modpack/type.fxml new file mode 100644 index 000000000..ee84c8f24 --- /dev/null +++ b/HMCL/src/main/resources/assets/fxml/modpack/type.fxml @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + diff --git a/HMCL/src/main/resources/assets/lang/I18N.properties b/HMCL/src/main/resources/assets/lang/I18N.properties index 4302ab0eb..4e750e6d5 100644 --- a/HMCL/src/main/resources/assets/lang/I18N.properties +++ b/HMCL/src/main/resources/assets/lang/I18N.properties @@ -219,6 +219,7 @@ modpack.choose=Choose a modpack zip file which you want to install. modpack.desc=Describe your modpack, including precautions, changlog, supporting Markdown(also supporting online pictures). modpack.enter_name=Enter your desired name for this game. modpack.export=Export Modpack +modpack.export.as=Export Modpack As... modpack.files.blueprints=BuildCraft blueprints modpack.files.config=Mod configs modpack.files.dumps=NEI debug output @@ -248,7 +249,9 @@ modpack.type.curse.tolerable_error=But we cannot complete downloading all files modpack.type.curse.error=Unable to complete this Curse modpack. Please retry. modpack.type.curse.not_found=Some of required resources are deleted and cannot be downloaded. Please consider the latest version or other modpacks. modpack.type.hmcl=HMCL +modpack.type.hmcl.export=Can be imported by Hello Minecraft! Launcher modpack.type.multimc=MultiMC +modpack.type.multimc.export=Can be imported by Hello Minecraft! Launcher and MultiMC modpack.unsupported=Unsupported modpack, only HMCL, MultiMC, Curse modpacks are supported. modpack.update=Upgrading game modpack.wizard=Exporting the modpack wizard @@ -256,7 +259,8 @@ modpack.wizard.step.1=Basic options modpack.wizard.step.1.title=Set the basic options to the modpack. modpack.wizard.step.2=Files selection modpack.wizard.step.2.title=Choose the files you want to put into the modpack. -modpack.wizard.step.3=Description +modpack.wizard.step.3=Modpack Type +modpack.wizard.step.3.title=Choose the format of the modpack. modpack.wizard.step.initialization.exported_version=The exported game version modpack.wizard.step.initialization.include_launcher=Include the launcher modpack.wizard.step.initialization.save=Choose a path to export the game files to diff --git a/HMCL/src/main/resources/assets/lang/I18N_zh.properties b/HMCL/src/main/resources/assets/lang/I18N_zh.properties index 80a73be11..359a83d7d 100644 --- a/HMCL/src/main/resources/assets/lang/I18N_zh.properties +++ b/HMCL/src/main/resources/assets/lang/I18N_zh.properties @@ -217,6 +217,7 @@ modpack.choose=選擇要安裝的遊戲整合包檔案 modpack.desc=描述你要製作的整合包,比如整合包注意事項和更新記錄,支援 Markdown(圖片請上傳至網路)。 modpack.enter_name=給遊戲取個你喜歡的名字 modpack.export=匯出整合包 +modpack.export.as=請選擇整合包類型。若你無法決定,請選擇 HMCL 類型。 modpack.files.blueprints=BuildCraft 藍圖 modpack.files.config=Mod 模組設定檔案 modpack.files.dumps=NEI 調校輸出 @@ -246,7 +247,9 @@ modpack.type.curse.tolerable_error=但未能完成 Curse 整合包文件的下 modpack.type.curse.error=無法完成 Curse 整合包的下載,請多次重試或設定代理 modpack.type.curse.not_found=部分必需檔案已經從網路中被刪除並且再也無法下載,請嘗試該整合包的最新版本或者安裝其他整合包。 modpack.type.hmcl=HMCL +modpack.type.hmcl.export=可以被 Hello Minecraft! Launcher (HMCL) 導入 modpack.type.multimc=MultiMC +modpack.type.multimc.export=可以被 Hello Minecraft! Launcher (HMCL) 和 MultiMC 導入 modpack.unsupported=不支援該整合包。僅 HMCL、MultiMC、Curse 整合包受支援。 modpack.update=正在升級整合包 modpack.wizard=匯出整合包引導 @@ -254,7 +257,8 @@ modpack.wizard.step.1=基本設定 modpack.wizard.step.1.title=設定整合包的主要訊息 modpack.wizard.step.2=檔案選擇 modpack.wizard.step.2.title=選中你想加到整合包中的檔案或資料夾 -modpack.wizard.step.3=整合包描述 +modpack.wizard.step.3=整合包類型 +modpack.wizard.step.3.title=選擇整合包導出類型 modpack.wizard.step.initialization.exported_version=要匯出的遊戲版本 modpack.wizard.step.initialization.include_launcher=包含啟動器 modpack.wizard.step.initialization.save=選擇要匯出到的遊戲整合包位置 diff --git a/HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties b/HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties index c97665ce6..ca9f87cee 100644 --- a/HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties +++ b/HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties @@ -218,6 +218,7 @@ modpack.choose=选择要安装的游戏整合包文件 modpack.desc=描述你要制作的整合包,比如整合包注意事项和更新记录,支持 Markdown(图片请用网络图)。 modpack.enter_name=给游戏起个你喜欢的名字 modpack.export=导出整合包 +modpack.export.as=请选择整合包类型。若你无法决定,请选择 HMCL 类型。 modpack.files.blueprints=BuildCraft 蓝图 modpack.files.config=Mod 配置文件 modpack.files.dumps=NEI 调试输出 @@ -247,7 +248,9 @@ modpack.type.curse.tolerable_error=但未能完成 Curse 整合包文件的下 modpack.type.curse.error=未能完成 Curse 整合包的下载,请多次重试或设置代理 modpack.type.curse.not_found=部分必需文件已经在网络中被删除并且再也无法下载,请尝试该整合包的最新版本或者安装其他整合包。 modpack.type.hmcl=HMCL +modpack.type.hmcl.export=可以被 Hello Minecraft! Launcher (HMCL) 导入 modpack.type.multimc=MultiMC +modpack.type.multimc.export=可以被 Hello Minecraft! Launcher (HMCL) 和 MultiMC 导入 modpack.unsupported=该整合包不被支持。仅 HMCL、MultiMC、Curse 整合包受支持。 modpack.update=正在升级整合包 modpack.wizard=导出整合包向导 @@ -255,7 +258,8 @@ modpack.wizard.step.1=基本设置 modpack.wizard.step.1.title=设置整合包的主要信息 modpack.wizard.step.2=文件选择 modpack.wizard.step.2.title=选中你想加到整合包中的文件或文件夹 -modpack.wizard.step.3=整合包描述 +modpack.wizard.step.3=整合包类型 +modpack.wizard.step.3.title=选择整合包导出类型 modpack.wizard.step.initialization.exported_version=要导出的游戏版本 modpack.wizard.step.initialization.include_launcher=包含启动器 modpack.wizard.step.initialization.save=选择要导出到的游戏整合包位置 diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/ModAdviser.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/ModAdviser.java new file mode 100644 index 000000000..91e5bd37f --- /dev/null +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/ModAdviser.java @@ -0,0 +1,75 @@ +/* + * Hello Minecraft! Launcher + * Copyright (C) 2019 huangyuhui and contributors + * + * 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 . + */ +package org.jackhuang.hmcl.mod; + +import org.jackhuang.hmcl.util.Lang; + +import java.util.List; + +/** + * @author huangyuhui + */ +public interface ModAdviser { + ModSuggestion advise(String fileName, boolean isDirectory); + + enum ModSuggestion { + SUGGESTED, + NORMAL, + HIDDEN + } + + List MODPACK_BLACK_LIST = Lang.immutableListOf( + "usernamecache.json", "usercache.json", // Minecraft + "launcher_profiles.json", "launcher.pack.lzma", // Minecraft Launcher + "pack.json", "launcher.jar", "hmclmc.log", "cache", // HMCL + "manifest.json", "minecraftinstance.json", ".curseclient", // Curse + "minetweaker.log", // Mods + ".fabric", ".mixin.out", // Fabric + "jars", "logs", "versions", "assets", "libraries", "crash-reports", "NVIDIA", "AMD", "screenshots", "natives", "native", "$native", "server-resource-packs", // Minecraft + "downloads", // Curse + "asm", "backups", "TCNodeTracker", "CustomDISkins", "data" // Mods + ); + + List MODPACK_SUGGESTED_BLACK_LIST = Lang.immutableListOf( + "fonts", // BetterFonts + "saves", "servers.dat", "options.txt", // Minecraft + "blueprints" /* BuildCraft */, + "optionsof.txt" /* OptiFine */, + "journeymap" /* JourneyMap */, + "optionsshaders.txt", + "mods/VoxelMods"); + + static ModAdviser.ModSuggestion suggestMod(String fileName, boolean isDirectory) { + if (match(MODPACK_BLACK_LIST, fileName, isDirectory)) + return ModAdviser.ModSuggestion.HIDDEN; + if (match(MODPACK_SUGGESTED_BLACK_LIST, fileName, isDirectory)) + return ModAdviser.ModSuggestion.NORMAL; + else + return ModAdviser.ModSuggestion.SUGGESTED; + } + + static boolean match(List l, String fileName, boolean isDirectory) { + for (String s : l) + if (isDirectory) { + if (fileName.startsWith(s + "/")) + return true; + } else if (fileName.equals(s)) + return true; + return false; + } +} diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/MultiMCInstanceConfiguration.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/MultiMCInstanceConfiguration.java index bf4598dca..137ce6131 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/MultiMCInstanceConfiguration.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/MultiMCInstanceConfiguration.java @@ -36,6 +36,7 @@ import java.util.Properties; */ public final class MultiMCInstanceConfiguration { + private final String instanceType; // InstanceType private final String name; // name private final String gameVersion; // IntendedVersion private final Integer permGen; // PermGen @@ -68,6 +69,7 @@ public final class MultiMCInstanceConfiguration { this.mmcPack = mmcPack; + instanceType = p.getProperty("InstanceType"); autoCloseConsole = Boolean.parseBoolean(p.getProperty("AutoCloseConsole")); gameVersion = mmcPack != null ? mmcPack.getComponents().stream().filter(e -> "net.minecraft".equals(e.getUid())).findAny() .orElseThrow(() -> new IOException("Malformed mmc-pack.json")).getVersion() : p.getProperty("IntendedVersion"); @@ -94,6 +96,38 @@ public final class MultiMCInstanceConfiguration { notes = Optional.ofNullable(p.getProperty("notes")).orElse(""); } + public MultiMCInstanceConfiguration(String instanceType, String name, String gameVersion, Integer permGen, String wrapperCommand, String preLaunchCommand, String postExitCommand, String notes, String javaPath, String jvmArgs, boolean fullscreen, Integer width, Integer height, Integer maxMemory, Integer minMemory, boolean showConsole, boolean showConsoleOnError, boolean autoCloseConsole, boolean overrideMemory, boolean overrideJavaLocation, boolean overrideJavaArgs, boolean overrideConsole, boolean overrideCommands, boolean overrideWindow) { + this.instanceType = instanceType; + this.name = name; + this.gameVersion = gameVersion; + this.permGen = permGen; + this.wrapperCommand = wrapperCommand; + this.preLaunchCommand = preLaunchCommand; + this.postExitCommand = postExitCommand; + this.notes = notes; + this.javaPath = javaPath; + this.jvmArgs = jvmArgs; + this.fullscreen = fullscreen; + this.width = width; + this.height = height; + this.maxMemory = maxMemory; + this.minMemory = minMemory; + this.showConsole = showConsole; + this.showConsoleOnError = showConsoleOnError; + this.autoCloseConsole = autoCloseConsole; + this.overrideMemory = overrideMemory; + this.overrideJavaLocation = overrideJavaLocation; + this.overrideJavaArgs = overrideJavaArgs; + this.overrideConsole = overrideConsole; + this.overrideCommands = overrideCommands; + this.overrideWindow = overrideWindow; + this.mmcPack = null; + } + + public String getInstanceType() { + return instanceType; + } + /** * The instance's name. */ @@ -260,6 +294,35 @@ public final class MultiMCInstanceConfiguration { return overrideWindow; } + public Properties toProperties() { + Properties p = new Properties(); + if (instanceType != null) p.setProperty("InstanceType", instanceType); + p.setProperty("AutoCloseConsole", Boolean.toString(autoCloseConsole)); + if (gameVersion != null) p.setProperty("IntendedVersion", gameVersion); + if (javaPath != null) p.setProperty("JavaPath", javaPath); + if (jvmArgs != null) p.setProperty("JvmArgs", jvmArgs); + p.setProperty("LaunchMaximized", Boolean.toString(fullscreen)); + if (maxMemory != null) p.setProperty("MaxMemAlloc", Integer.toString(maxMemory)); + if (minMemory != null) p.setProperty("MinMemAlloc", Integer.toString(minMemory)); + if (height != null) p.setProperty("MinecraftWinHeight", Integer.toString(height)); + if (width != null) p.setProperty("MinecraftWinWidth", Integer.toString(width)); + p.setProperty("OverrideCommands", Boolean.toString(overrideCommands)); + p.setProperty("OverrideConsole", Boolean.toString(overrideConsole)); + p.setProperty("OverrideJavaArgs", Boolean.toString(overrideJavaArgs)); + p.setProperty("OverrideJavaLocation", Boolean.toString(overrideJavaLocation)); + p.setProperty("OverrideMemory", Boolean.toString(overrideMemory)); + p.setProperty("OverrideWindow", Boolean.toString(overrideWindow)); + if (permGen != null) p.setProperty("PermGen", Integer.toString(permGen)); + if (postExitCommand != null) p.setProperty("PostExitCommand", postExitCommand); + if (preLaunchCommand != null) p.setProperty("PreLaunchCommand", preLaunchCommand); + p.setProperty("ShowConsole", Boolean.toString(showConsole)); + p.setProperty("ShowConsoleOnError", Boolean.toString(showConsoleOnError)); + if (wrapperCommand != null) p.setProperty("WrapperCommand", wrapperCommand); + if (name != null) p.setProperty("name", name); + if (notes != null) p.setProperty("notes", notes); + return p; + } + public MultiMCManifest getMmcPack() { return mmcPack; } diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/MultiMCManifest.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/MultiMCManifest.java index 52899163f..c1daf3704 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/MultiMCManifest.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/MultiMCManifest.java @@ -113,17 +113,25 @@ public final class MultiMCManifest { @SerializedName("important") private final boolean important; + @SerializedName("dependencyOnly") + private final boolean dependencyOnly; + @SerializedName("uid") private final String uid; @SerializedName("version") private final String version; - public MultiMCManifestComponent(String cachedName, List cachedRequires, String cachedVersion, boolean important, String uid, String version) { + public MultiMCManifestComponent(boolean important, boolean dependencyOnly, String uid, String version) { + this(null, null, null, important, dependencyOnly, uid, version); + } + + public MultiMCManifestComponent(String cachedName, List cachedRequires, String cachedVersion, boolean important, boolean dependencyOnly, String uid, String version) { this.cachedName = cachedName; this.cachedRequires = cachedRequires; this.cachedVersion = cachedVersion; this.important = important; + this.dependencyOnly = dependencyOnly; this.uid = uid; this.version = version; } @@ -144,6 +152,10 @@ public final class MultiMCManifest { return important; } + public boolean isDependencyOnly() { + return dependencyOnly; + } + public String getUid() { return uid; } diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/MultiMCModpackExportTask.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/MultiMCModpackExportTask.java new file mode 100644 index 000000000..98fa00d41 --- /dev/null +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/MultiMCModpackExportTask.java @@ -0,0 +1,101 @@ +/* + * Hello Minecraft! Launcher + * Copyright (C) 2019 huangyuhui and contributors + * + * 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 . + */ +package org.jackhuang.hmcl.mod; + +import org.jackhuang.hmcl.download.LibraryAnalyzer; +import org.jackhuang.hmcl.game.DefaultGameRepository; +import org.jackhuang.hmcl.game.GameVersion; +import org.jackhuang.hmcl.task.Task; +import org.jackhuang.hmcl.util.Logging; +import org.jackhuang.hmcl.util.gson.JsonUtils; +import org.jackhuang.hmcl.util.io.Zipper; + +import java.io.File; +import java.io.StringWriter; +import java.util.ArrayList; +import java.util.List; + +import static org.jackhuang.hmcl.download.LibraryAnalyzer.LibraryType.*; + +/** + * Export the game to a mod pack file. + */ +public class MultiMCModpackExportTask extends Task { + private final DefaultGameRepository repository; + private final String versionId; + private final List whitelist; + private final MultiMCInstanceConfiguration configuration; + private final File output; + + /** + * @param output mod pack file. + * @param versionId to locate version.json + */ + public MultiMCModpackExportTask(DefaultGameRepository repository, String versionId, List whitelist, MultiMCInstanceConfiguration configuration, File output) { + this.repository = repository; + this.versionId = versionId; + this.whitelist = whitelist; + this.configuration = configuration; + this.output = output; + + onDone().register(event -> { + if (event.isFailed()) output.delete(); + }); + } + + @Override + public void execute() throws Exception { + ArrayList blackList = new ArrayList<>(ModAdviser.MODPACK_BLACK_LIST); + blackList.add(versionId + ".jar"); + blackList.add(versionId + ".json"); + Logging.LOG.info("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"); + try (Zipper zip = new Zipper(output.toPath())) { + zip.putDirectory(repository.getRunDirectory(versionId).toPath(), ".minecraft", path -> { + if (path.isEmpty()) + return true; + for (String s : blackList) + if (path.equals(s)) + return false; + for (String s : whitelist) + if (path.equals(s)) + return true; + return false; + }); + + LibraryAnalyzer analyzer = LibraryAnalyzer.analyze(repository.getResolvedVersion(versionId)); + String gameVersion = GameVersion.minecraftVersion(repository.getVersionJar(versionId)) + .orElseThrow(() -> new IllegalStateException("Cannot parse the version of " + versionId)); + List components = new ArrayList<>(); + components.add(new MultiMCManifest.MultiMCManifestComponent(true, false, "net.minecraft", gameVersion)); + analyzer.getVersion(FORGE).ifPresent(forgeVersion -> + components.add(new MultiMCManifest.MultiMCManifestComponent(false, false, "net.minecraftforge", forgeVersion))); + analyzer.getVersion(LITELOADER).ifPresent(liteLoaderVersion -> + components.add(new MultiMCManifest.MultiMCManifestComponent(false, false, "com.mumfrey.liteloader", liteLoaderVersion))); + analyzer.getVersion(FABRIC).ifPresent(fabricVersion -> + components.add(new MultiMCManifest.MultiMCManifestComponent(false, false, "net.fabricmc.fabric-loader", fabricVersion))); + MultiMCManifest mmcPack = new MultiMCManifest(1, components); + zip.putTextFile(JsonUtils.GSON.toJson(mmcPack), "mmc-pack.json"); + + StringWriter writer = new StringWriter(); + configuration.toProperties().store(writer, "Auto generated by Hello Minecraft! Launcher"); + zip.putTextFile(writer.toString(), "instance.cfg"); + + zip.putTextFile("", ".packignore"); + } + } +}