mirror of
https://github.com/HMCL-dev/HMCL.git
synced 2025-09-18 08:16:58 -04:00
Support exporting multimc modpack
This commit is contained in:
parent
86bf3d473a
commit
880b8cb072
@ -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<Void> {
|
||||
|
||||
@Override
|
||||
public void execute() throws Exception {
|
||||
ArrayList<String> blackList = new ArrayList<>(HMCLModpackManager.MODPACK_BLACK_LIST);
|
||||
ArrayList<String> 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");
|
||||
|
@ -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<String> 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<String> 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<String> 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.
|
||||
*
|
||||
|
@ -1,31 +0,0 @@
|
||||
/*
|
||||
* Hello Minecraft! Launcher
|
||||
* Copyright (C) 2019 huangyuhui <huanghongxun2008@126.com> 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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package org.jackhuang.hmcl.game;
|
||||
|
||||
/**
|
||||
* @author huangyuhui
|
||||
*/
|
||||
public interface ModAdviser {
|
||||
ModSuggestion advise(String fileName, boolean isDirectory);
|
||||
|
||||
enum ModSuggestion {
|
||||
SUGGESTED,
|
||||
NORMAL,
|
||||
HIDDEN
|
||||
}
|
||||
}
|
@ -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<String, Object> settings) {
|
||||
@SuppressWarnings("unchecked")
|
||||
List<String> whitelist = (List<String>) 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<String> whitelist, File modpackFile, String modpackName, String modpackAuthor, String modpackVersion, String modpackDescription, boolean includeLauncherRaw) {
|
||||
List<File> launcherJar = Launcher.getCurrentJarFiles();
|
||||
boolean includeLauncher = (Boolean) settings.get(ModpackInfoPage.MODPACK_INCLUDE_LAUNCHER) && launcherJar != null;
|
||||
boolean includeLauncher = includeLauncherRaw && launcherJar != null;
|
||||
|
||||
return new Task<Void>() {
|
||||
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<String> whitelist, File modpackFile, String modpackName, String modpackAuthor, String modpackVersion, String modpackDescription) {
|
||||
return new Task<Void>() {
|
||||
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<Task<?>> getDependencies() {
|
||||
return Collections.singleton(dependency);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public Node createPage(WizardController controller, int step, Map<String, Object> 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");
|
||||
}
|
||||
}
|
||||
|
@ -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<String> list = new LinkedList<>();
|
||||
getFilesNeeded(rootNode, "minecraft", list);
|
||||
controller.getSettings().put(MODPACK_FILE_SELECTION, list);
|
||||
controller.onFinish();
|
||||
controller.onNext();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -0,0 +1,66 @@
|
||||
/*
|
||||
* Hello Minecraft! Launcher
|
||||
* Copyright (C) 2019 huangyuhui <huanghongxun2008@126.com> 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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
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<String, Object> 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";
|
||||
}
|
@ -17,7 +17,7 @@
|
||||
<bottom>
|
||||
<HBox alignment="CENTER_RIGHT" style="-fx-padding: 16 16 16 0;">
|
||||
<JFXButton fx:id="btnNext" onMouseClicked="#onNext" prefWidth="100" prefHeight="40" buttonType="RAISED"
|
||||
text="%wizard.finish" styleClass="jfx-button-raised"/>
|
||||
text="%wizard.next" styleClass="jfx-button-raised"/>
|
||||
</HBox>
|
||||
</bottom>
|
||||
</BorderPane>
|
||||
|
41
HMCL/src/main/resources/assets/fxml/modpack/type.fxml
Normal file
41
HMCL/src/main/resources/assets/fxml/modpack/type.fxml
Normal file
@ -0,0 +1,41 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<?import com.jfoenix.controls.*?>
|
||||
<?import javafx.geometry.Insets?>
|
||||
<?import javafx.scene.control.*?>
|
||||
<?import javafx.scene.layout.*?>
|
||||
<?import org.jackhuang.hmcl.ui.construct.TwoLineListItem?>
|
||||
<fx:root xmlns="http://javafx.com/javafx"
|
||||
xmlns:fx="http://javafx.com/fxml"
|
||||
type="StackPane">
|
||||
<fx:define>
|
||||
<Insets fx:id="insets" topRightBottomLeft="8" />
|
||||
</fx:define>
|
||||
<VBox fx:id="list" styleClass="jfx-list-view" maxHeight="150" maxWidth="300">
|
||||
<Label padding="${insets}" text="%modpack.export.as" />
|
||||
<JFXButton fx:id="btnHMCL" prefWidth="${list.width}">
|
||||
<graphic>
|
||||
<BorderPane mouseTransparent="true">
|
||||
<left>
|
||||
<TwoLineListItem title="%modpack.type.hmcl" subtitle="%modpack.type.hmcl.export" />
|
||||
</left>
|
||||
<right>
|
||||
<fx:include BorderPane.alignment="CENTER" source="/assets/svg/arrow-right.fxml"/>
|
||||
</right>
|
||||
</BorderPane>
|
||||
</graphic>
|
||||
</JFXButton>
|
||||
<JFXButton fx:id="btnMultiMC" prefWidth="${list.width}">
|
||||
<graphic>
|
||||
<BorderPane mouseTransparent="true">
|
||||
<left>
|
||||
<TwoLineListItem title="%modpack.type.multimc" subtitle="%modpack.type.multimc.export" />
|
||||
</left>
|
||||
<right>
|
||||
<fx:include BorderPane.alignment="CENTER" source="/assets/svg/arrow-right.fxml"/>
|
||||
</right>
|
||||
</BorderPane>
|
||||
</graphic>
|
||||
</JFXButton>
|
||||
</VBox>
|
||||
</fx:root>
|
@ -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
|
||||
|
@ -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=選擇要匯出到的遊戲整合包位置
|
||||
|
@ -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=选择要导出到的游戏整合包位置
|
||||
|
@ -0,0 +1,75 @@
|
||||
/*
|
||||
* Hello Minecraft! Launcher
|
||||
* Copyright (C) 2019 huangyuhui <huanghongxun2008@126.com> 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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
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<String> 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<String> 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<String> 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;
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
|
@ -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<MultiMCManifestCachedRequires> 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<MultiMCManifestCachedRequires> 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;
|
||||
}
|
||||
|
@ -0,0 +1,101 @@
|
||||
/*
|
||||
* Hello Minecraft! Launcher
|
||||
* Copyright (C) 2019 huangyuhui <huanghongxun2008@126.com> 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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
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<Void> {
|
||||
private final DefaultGameRepository repository;
|
||||
private final String versionId;
|
||||
private final List<String> 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<String> 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<String> 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<MultiMCManifest.MultiMCManifestComponent> 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");
|
||||
}
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user