From e36105d9371fb3b374882a6873bf5b044b2d6c9b Mon Sep 17 00:00:00 2001 From: huanghongxun Date: Thu, 22 Apr 2021 08:40:11 +0800 Subject: [PATCH] Reland: create modpack with launcher packed in --- .../java/org/jackhuang/hmcl/Launcher.java | 6 + .../hmcl/ui/export/ExportWizardProvider.java | 105 +++++++++++++++--- .../hmcl/ui/export/ModpackInfoPage.java | 20 +++- .../jackhuang/hmcl/mod/ModpackExportInfo.java | 13 --- .../mod/mcbbs/McbbsModpackExportTask.java | 8 +- .../mod/server/ServerModpackExportTask.java | 8 +- 6 files changed, 122 insertions(+), 38 deletions(-) diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/Launcher.java b/HMCL/src/main/java/org/jackhuang/hmcl/Launcher.java index 00a6a0e98..8fa9823bd 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/Launcher.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/Launcher.java @@ -30,6 +30,7 @@ import org.jackhuang.hmcl.upgrade.UpdateHandler; import org.jackhuang.hmcl.util.CrashReporter; import org.jackhuang.hmcl.util.Lang; import org.jackhuang.hmcl.util.StringUtils; +import org.jackhuang.hmcl.util.io.FileUtils; import org.jackhuang.hmcl.util.platform.OperatingSystem; import java.awt.*; @@ -158,6 +159,11 @@ public final class Launcher extends Application { } catch (URISyntaxException e) { return null; } + } else { + File jarFile = new File(Launcher.class.getProtectionDomain().getCodeSource().getLocation().getPath()); + String ext = FileUtils.getExtension(jarFile); + if ("jar".equals(ext) || "exe".equals(ext)) + result.add(jarFile); } if (result.isEmpty()) return null; 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 b6058f496..610703955 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 @@ -25,19 +25,25 @@ import org.jackhuang.hmcl.mod.mcbbs.McbbsModpackExportTask; import org.jackhuang.hmcl.mod.multimc.MultiMCInstanceConfiguration; import org.jackhuang.hmcl.mod.multimc.MultiMCModpackExportTask; import org.jackhuang.hmcl.mod.server.ServerModpackExportTask; +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; +import java.nio.file.Files; import java.util.Collection; import java.util.Collections; import java.util.List; import java.util.Map; +import static org.jackhuang.hmcl.setting.ConfigHolder.config; + public final class ExportWizardProvider implements WizardProvider { private final Profile profile; private final String version; @@ -55,31 +61,98 @@ 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); ModpackExportInfo exportInfo = (ModpackExportInfo) settings.get(ModpackInfoPage.MODPACK_INFO); exportInfo.setWhitelist(whitelist); String modpackType = (String) settings.get(ModpackTypeSelectionPage.MODPACK_TYPE); - switch (modpackType) { - case ModpackTypeSelectionPage.MODPACK_TYPE_MCBBS: - return exportAsMcbbs(exportInfo); - case ModpackTypeSelectionPage.MODPACK_TYPE_MULTIMC: - return exportAsMultiMC(exportInfo); - case ModpackTypeSelectionPage.MODPACK_TYPE_SERVER: - return exportAsServer(exportInfo); - default: - throw new IllegalStateException("Unrecognized modpack type " + modpackType); - } + return exportWithLauncher(modpackType, exportInfo, modpackFile); } - private Task exportAsMcbbs(ModpackExportInfo exportInfo) { + private Task exportWithLauncher(String modpackType, ModpackExportInfo exportInfo, File modpackFile) { List launcherJar = Launcher.getCurrentJarFiles(); + boolean packWithLauncher = exportInfo.isPackWithLauncher() && launcherJar != null; + return new Task() { + File tempModpack; + Task exportTask; + @Override + public boolean doPreExecute() { + return true; + } + + @Override + public void preExecute() throws Exception { + File dest; + if (packWithLauncher) { + dest = tempModpack = Files.createTempFile("hmcl", ".zip").toFile(); + } else { + dest = modpackFile; + } + + switch (modpackType) { + case ModpackTypeSelectionPage.MODPACK_TYPE_MCBBS: + exportTask = exportAsMcbbs(exportInfo, dest); + break; + case ModpackTypeSelectionPage.MODPACK_TYPE_MULTIMC: + exportTask = exportAsMultiMC(exportInfo, dest); + break; + case ModpackTypeSelectionPage.MODPACK_TYPE_SERVER: + exportTask = exportAsServer(exportInfo, dest); + break; + default: + throw new IllegalStateException("Unrecognized modpack type " + modpackType); + } + + } + + @Override + public Collection> getDependents() { + return Collections.singleton(exportTask); + } + + @Override + public void execute() throws Exception { + if (!packWithLauncher) return; + try (Zipper zip = new Zipper(modpackFile.toPath())) { + Config exported = new Config(); + + exported.setBackgroundImageType(config().getBackgroundImageType()); + exported.setBackgroundImage(config().getBackgroundImage()); + exported.setTheme(config().getTheme()); + exported.setDownloadType(config().getDownloadType()); + exported.setPreferredLoginType(config().getPreferredLoginType()); + exported.getAuthlibInjectorServers().setAll(config().getAuthlibInjectorServers()); + + zip.putTextFile(exported.toJson(), ConfigHolder.CONFIG_FILENAME); + zip.putFile(tempModpack, "modpack.zip"); + + File bg = new File("bg").getAbsoluteFile(); + if (bg.isDirectory()) + zip.putDirectory(bg.toPath(), "bg"); + + File background_png = new File("background.png").getAbsoluteFile(); + if (background_png.isFile()) + zip.putFile(background_png, "background.png"); + + File background_jpg = new File("background.jpg").getAbsoluteFile(); + if (background_jpg.isFile()) + zip.putFile(background_jpg, "background.jpg"); + + for (File jar : launcherJar) + zip.putFile(jar, jar.getName()); + } + } + }; + } + + private Task exportAsMcbbs(ModpackExportInfo exportInfo, File modpackFile) { return new Task() { Task dependency = null; @Override public void execute() { - dependency = new McbbsModpackExportTask(profile.getRepository(), version, exportInfo); + dependency = new McbbsModpackExportTask(profile.getRepository(), version, exportInfo, modpackFile); } @Override @@ -89,7 +162,7 @@ public final class ExportWizardProvider implements WizardProvider { }; } - private Task exportAsMultiMC(ModpackExportInfo exportInfo) { + private Task exportAsMultiMC(ModpackExportInfo exportInfo, File modpackFile) { return new Task() { Task dependency; @@ -122,7 +195,7 @@ public final class ExportWizardProvider implements WizardProvider { /* overrideConsole */ true, /* overrideCommands */ true, /* overrideWindow */ true - ), exportInfo.getOutput().toFile()); + ), modpackFile); } @Override @@ -132,13 +205,13 @@ public final class ExportWizardProvider implements WizardProvider { }; } - private Task exportAsServer(ModpackExportInfo exportInfo) { + private Task exportAsServer(ModpackExportInfo exportInfo, File modpackFile) { return new Task() { Task dependency; @Override public void execute() { - dependency = new ServerModpackExportTask(profile.getRepository(), version, exportInfo); + dependency = new ServerModpackExportTask(profile.getRepository(), version, exportInfo, modpackFile); } @Override diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/export/ModpackInfoPage.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/export/ModpackInfoPage.java index 08918d0fe..8c049ba0a 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/export/ModpackInfoPage.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/export/ModpackInfoPage.java @@ -121,7 +121,6 @@ public final class ModpackInfoPage extends Control implements WizardPage { exportInfo.setFileApi(fileApi.get()); exportInfo.setVersion(version.get()); exportInfo.setAuthor(author.get()); - exportInfo.setOutput(file.toPath()); exportInfo.setDescription(description.get()); exportInfo.setPackWithLauncher(packWithLauncher.get()); exportInfo.setUrl(url.get()); @@ -139,6 +138,7 @@ public final class ModpackInfoPage extends Control implements WizardPage { } controller.getSettings().put(MODPACK_INFO, exportInfo); + controller.getSettings().put(MODPACK_FILE, file); controller.onNext(); } @@ -158,6 +158,7 @@ public final class ModpackInfoPage extends Control implements WizardPage { } public static final String MODPACK_INFO = "modpack.info"; + public static final String MODPACK_FILE = "modpack.file"; public static final String MODPACK_INFO_OPTION = "modpack.info.option"; public static class ModpackInfoPageSkin extends SkinBase { @@ -288,8 +289,7 @@ public final class ModpackInfoPage extends Control implements WizardPage { list.getContent().add(pane); JFXToggleButton button = new JFXToggleButton(); - button.setDisable(!skinnable.canIncludeLauncher); - button.selectedProperty().bindBidirectional(skinnable.packWithLauncher); + button.selectedProperty().bindBidirectional(skinnable.forceUpdate); button.setSize(8); button.setMinHeight(16); button.setMaxHeight(16); @@ -387,6 +387,20 @@ public final class ModpackInfoPage extends Control implements WizardPage { validatingFields.add(txtMcbbs); } } + + { + BorderPane pane = new BorderPane(); + pane.setLeft(new Label(i18n("modpack.wizard.step.initialization.include_launcher"))); + list.getContent().add(pane); + + JFXToggleButton button = new JFXToggleButton(); + button.setDisable(!skinnable.canIncludeLauncher); + button.selectedProperty().bindBidirectional(skinnable.packWithLauncher); + button.setSize(8); + button.setMinHeight(16); + button.setMaxHeight(16); + pane.setRight(button); + } } { diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/ModpackExportInfo.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/ModpackExportInfo.java index bd889dcab..6c8fd5749 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/ModpackExportInfo.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/ModpackExportInfo.java @@ -3,7 +3,6 @@ package org.jackhuang.hmcl.mod; import org.jackhuang.hmcl.mod.mcbbs.McbbsModpackManifest; import org.jetbrains.annotations.Nullable; -import java.nio.file.Path; import java.util.ArrayList; import java.util.Collections; import java.util.List; @@ -28,7 +27,6 @@ public class ModpackExportInfo { private String authlibInjectorServer; - private Path output; private List origins = new ArrayList<>(); public ModpackExportInfo() {} @@ -178,15 +176,6 @@ public class ModpackExportInfo { return this; } - public Path getOutput() { - return output; - } - - public ModpackExportInfo setOutput(Path output) { - this.output = output; - return this; - } - public List getOrigins() { return Collections.unmodifiableList(origins); } @@ -198,8 +187,6 @@ public class ModpackExportInfo { } public ModpackExportInfo validate() throws NullPointerException { - if (output == null) - throw new NullPointerException("ModpackExportInfo.output cannot be null"); return this; } diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/mcbbs/McbbsModpackExportTask.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/mcbbs/McbbsModpackExportTask.java index 2ce8fdbaf..81f5cbf8d 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/mcbbs/McbbsModpackExportTask.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/mcbbs/McbbsModpackExportTask.java @@ -45,14 +45,16 @@ public class McbbsModpackExportTask extends Task { private final DefaultGameRepository repository; private final String version; private final ModpackExportInfo info; + private final File modpackFile; - public McbbsModpackExportTask(DefaultGameRepository repository, String version, ModpackExportInfo info) { + public McbbsModpackExportTask(DefaultGameRepository repository, String version, ModpackExportInfo info, File modpackFile) { this.repository = repository; this.version = version; this.info = info.validate(); + this.modpackFile = modpackFile; onDone().register(event -> { - if (event.isFailed()) this.info.getOutput().toFile().delete(); + if (event.isFailed()) modpackFile.delete(); }); } @@ -62,7 +64,7 @@ public class McbbsModpackExportTask extends Task { 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"); - try (Zipper zip = new Zipper(info.getOutput())) { + try (Zipper zip = new Zipper(modpackFile.toPath())) { Path runDirectory = repository.getRunDirectory(version).toPath(); List files = new ArrayList<>(); zip.putDirectory(runDirectory, "overrides", path -> { diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/server/ServerModpackExportTask.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/server/ServerModpackExportTask.java index 76e947631..4e0487e14 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/server/ServerModpackExportTask.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/server/ServerModpackExportTask.java @@ -45,14 +45,16 @@ public class ServerModpackExportTask extends Task { private final DefaultGameRepository repository; private final String versionId; private final ModpackExportInfo exportInfo; + private final File modpackFile; - public ServerModpackExportTask(DefaultGameRepository repository, String version, ModpackExportInfo exportInfo) { + public ServerModpackExportTask(DefaultGameRepository repository, String version, ModpackExportInfo exportInfo, File modpackFile) { this.repository = repository; this.versionId = version; this.exportInfo = exportInfo.validate(); + this.modpackFile = modpackFile; onDone().register(event -> { - if (event.isFailed()) exportInfo.getOutput().toFile().delete(); + if (event.isFailed()) modpackFile.delete(); }); } @@ -62,7 +64,7 @@ public class ServerModpackExportTask extends Task { 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(exportInfo.getOutput())) { + try (Zipper zip = new Zipper(modpackFile.toPath())) { Path runDirectory = repository.getRunDirectory(versionId).toPath(); List files = new ArrayList<>(); zip.putDirectory(runDirectory, "overrides", path -> {