diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/Launcher.java b/HMCL/src/main/java/org/jackhuang/hmcl/Launcher.java index 5ad5a770a..83abb02b3 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/Launcher.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/Launcher.java @@ -31,7 +31,13 @@ import org.jackhuang.hmcl.upgrade.UpdateChecker; import org.jackhuang.hmcl.util.*; import java.io.File; +import java.io.IOException; +import java.net.URISyntaxException; +import java.net.URL; +import java.net.URLClassLoader; import java.util.Arrays; +import java.util.LinkedList; +import java.util.List; import java.util.ResourceBundle; import java.util.concurrent.TimeUnit; import java.util.logging.Level; @@ -123,6 +129,25 @@ public final class Launcher extends Application { } } + public static List getCurrentJarFiles() { + List result = new LinkedList<>(); + if (Launcher.class.getClassLoader() instanceof URLClassLoader) { + URL[] urls = ((URLClassLoader) Launcher.class.getClassLoader()).getURLs(); + for (URL u : urls) + try { + File f = new File(u.toURI()); + if (f.isFile() && (f.getName().endsWith(".exe") || f.getName().endsWith(".jar"))) + result.add(f); + } catch (URISyntaxException e) { + return null; + } + } + if (result.isEmpty()) + return null; + else + return result; + } + public static String i18n(String key) { try { return RESOURCE_BUNDLE.getString(key); diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/setting/Config.java b/HMCL/src/main/java/org/jackhuang/hmcl/setting/Config.java index afd722a3c..98e0cbda9 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/setting/Config.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/setting/Config.java @@ -23,7 +23,7 @@ import org.jackhuang.hmcl.util.JavaVersion; import java.util.*; -final class Config { +public final class Config implements Cloneable { @SerializedName("last") private String selectedProfile = ""; @@ -97,7 +97,6 @@ final class Config { public void setSelectedProfile(String selectedProfile) { this.selectedProfile = selectedProfile; - Settings.INSTANCE.save(); } public String getBackgroundImage() { @@ -106,7 +105,6 @@ final class Config { public void setBackgroundImage(String backgroundImage) { this.backgroundImage = backgroundImage; - Settings.INSTANCE.save(); } public int getBackgroundImageType() { @@ -115,7 +113,6 @@ final class Config { public void setBackgroundImageType(int backgroundImageType) { this.backgroundImageType = backgroundImageType; - Settings.INSTANCE.save(); } public String getCommonDirectory() { @@ -124,7 +121,6 @@ final class Config { public void setCommonDirectory(String commonDirectory) { this.commonDirectory = commonDirectory; - Settings.INSTANCE.save(); } public boolean isHasProxy() { @@ -133,7 +129,6 @@ final class Config { public void setHasProxy(boolean hasProxy) { this.hasProxy = hasProxy; - Settings.INSTANCE.save(); } public boolean isHasProxyAuth() { @@ -142,7 +137,6 @@ final class Config { public void setHasProxyAuth(boolean hasProxyAuth) { this.hasProxyAuth = hasProxyAuth; - Settings.INSTANCE.save(); } public int getProxyType() { @@ -151,7 +145,6 @@ final class Config { public void setProxyType(int proxyType) { this.proxyType = proxyType; - Settings.INSTANCE.save(); } public String getProxyHost() { @@ -160,7 +153,6 @@ final class Config { public void setProxyHost(String proxyHost) { this.proxyHost = proxyHost; - Settings.INSTANCE.save(); } public String getProxyPort() { @@ -169,7 +161,6 @@ final class Config { public void setProxyPort(String proxyPort) { this.proxyPort = proxyPort; - Settings.INSTANCE.save(); } public String getProxyUser() { @@ -178,7 +169,6 @@ final class Config { public void setProxyUser(String proxyUser) { this.proxyUser = proxyUser; - Settings.INSTANCE.save(); } public String getProxyPass() { @@ -187,7 +177,6 @@ final class Config { public void setProxyPass(String proxyPass) { this.proxyPass = proxyPass; - Settings.INSTANCE.save(); } public String getTheme() { @@ -196,7 +185,6 @@ final class Config { public void setTheme(String theme) { this.theme = theme; - Settings.INSTANCE.save(); } public List getJava() { @@ -205,7 +193,6 @@ final class Config { public void setJava(List java) { this.java = java; - Settings.INSTANCE.save(); } public String getLocalization() { @@ -214,7 +201,6 @@ final class Config { public void setLocalization(String localization) { this.localization = localization; - Settings.INSTANCE.save(); } public int getDownloadType() { @@ -223,7 +209,6 @@ final class Config { public void setDownloadType(int downloadType) { this.downloadType = downloadType; - Settings.INSTANCE.save(); } public Map getConfigurations() { @@ -232,7 +217,6 @@ final class Config { public void setConfigurations(Map configurations) { this.configurations = configurations; - Settings.INSTANCE.save(); } public List> getAccounts() { @@ -241,7 +225,6 @@ final class Config { public void setAccounts(List> accounts) { this.accounts = accounts; - Settings.INSTANCE.save(); } public String getSelectedAccount() { @@ -250,7 +233,6 @@ final class Config { public void setSelectedAccount(String selectedAccount) { this.selectedAccount = selectedAccount; - Settings.INSTANCE.save(); } public String getFontFamily() { @@ -259,7 +241,6 @@ final class Config { public void setFontFamily(String fontFamily) { this.fontFamily = fontFamily; - Settings.INSTANCE.save(); } public double getFontSize() { @@ -268,7 +249,6 @@ final class Config { public void setFontSize(double fontSize) { this.fontSize = fontSize; - Settings.INSTANCE.save(); } public int getLogLines() { @@ -285,6 +265,9 @@ final class Config { public void setAuthlibInjectorServerURLs(Set authlibInjectorServerURLs) { this.authlibInjectorServerURLs = authlibInjectorServerURLs; - Settings.INSTANCE.save(); + } + + public Config clone() { + return Settings.GSON.fromJson(Settings.GSON.toJson(this), Config.class); } } diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/setting/Settings.java b/HMCL/src/main/java/org/jackhuang/hmcl/setting/Settings.java index 584d2e6a5..afb484687 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/setting/Settings.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/setting/Settings.java @@ -55,7 +55,8 @@ public class Settings { public static final String DEFAULT_PROFILE = "Default"; public static final String HOME_PROFILE = "Home"; - public static final File SETTINGS_FILE = new File("hmcl.json").getAbsoluteFile(); + public static final String SETTINGS_FILE_NAME = "hmcl.json"; + public static final File SETTINGS_FILE = new File(SETTINGS_FILE_NAME).getAbsoluteFile(); public static final Settings INSTANCE = new Settings(); @@ -144,6 +145,7 @@ public class Settings { super.invalidated(); SETTINGS.setCommonDirectory(get()); + save(); } }; @@ -168,6 +170,7 @@ public class Settings { public void setLocale(Locales.SupportedLocale locale) { this.locale = locale; SETTINGS.setLocalization(Locales.getNameByLocale(locale)); + save(); } private Proxy proxy = Proxy.NO_PROXY; @@ -185,6 +188,7 @@ public class Settings { public void setProxyType(Proxy.Type proxyType) { this.proxyType = proxyType; SETTINGS.setProxyType(Proxies.PROXIES.indexOf(proxyType)); + save(); loadProxy(); } @@ -194,6 +198,7 @@ public class Settings { public void setProxyHost(String proxyHost) { SETTINGS.setProxyHost(proxyHost); + save(); } public String getProxyPort() { @@ -202,6 +207,7 @@ public class Settings { public void setProxyPort(String proxyPort) { SETTINGS.setProxyPort(proxyPort); + save(); } public String getProxyUser() { @@ -210,6 +216,7 @@ public class Settings { public void setProxyUser(String proxyUser) { SETTINGS.setProxyUser(proxyUser); + save(); } public String getProxyPass() { @@ -218,15 +225,22 @@ public class Settings { public void setProxyPass(String proxyPass) { SETTINGS.setProxyPass(proxyPass); + save(); } public boolean hasProxy() { return SETTINGS.isHasProxy(); } - public void setHasProxy(boolean hasProxy) { SETTINGS.setHasProxy(hasProxy); } + public void setHasProxy(boolean hasProxy) { + SETTINGS.setHasProxy(hasProxy); + save(); + } public boolean hasProxyAuth() { return SETTINGS.isHasProxyAuth(); } - public void setHasProxyAuth(boolean hasProxyAuth) { SETTINGS.setHasProxyAuth(hasProxyAuth); } + public void setHasProxyAuth(boolean hasProxyAuth) { + SETTINGS.setHasProxyAuth(hasProxyAuth); + save(); + } private void loadProxy() { String host = getProxyHost(); @@ -261,6 +275,7 @@ public class Settings { public void setFont(Font font) { SETTINGS.setFontFamily(font.getFamily()); SETTINGS.setFontSize(font.getSize()); + save(); } public int getLogLines() { @@ -269,6 +284,7 @@ public class Settings { public void setLogLines(int logLines) { SETTINGS.setLogLines(logLines); + save(); } /**************************************** @@ -296,8 +312,10 @@ public class Settings { } private void checkAuthlibInjectorServerURLs() { - if (SETTINGS.getAuthlibInjectorServerURLs() == null) + if (SETTINGS.getAuthlibInjectorServerURLs() == null) { SETTINGS.setAuthlibInjectorServerURLs(new HashSet<>()); + save(); + } } private void checkAuthlibInjectorAccounts() { @@ -323,6 +341,7 @@ public class Settings { if (index == -1) throw new IllegalArgumentException("Unknown download provider: " + downloadProvider); SETTINGS.setDownloadType(index); + save(); } /**************************************** @@ -352,6 +371,7 @@ public class Settings { super.invalidated(); SETTINGS.setSelectedAccount(getValue() == null ? "" : Accounts.getAccountId(getValue())); + save(); } }; @@ -404,6 +424,7 @@ public class Settings { super.invalidated(); SETTINGS.setBackgroundImage(get()); + save(); } }; @@ -425,6 +446,7 @@ public class Settings { super.invalidated(); SETTINGS.setBackgroundImageType(get().ordinal()); + save(); } }; @@ -450,6 +472,7 @@ public class Settings { super.invalidated(); SETTINGS.setTheme(get().getName().toLowerCase()); + save(); } }; @@ -473,7 +496,10 @@ public class Settings { checkProfileMap(); if (!hasProfile(SETTINGS.getSelectedProfile())) { - getProfileMap().keySet().stream().findFirst().ifPresent(SETTINGS::setSelectedProfile); + getProfileMap().keySet().stream().findFirst().ifPresent(selectedProfile -> { + SETTINGS.setSelectedProfile(selectedProfile); + save(); + }); Schedulers.computation().schedule(this::onProfileChanged); } return getProfile(SETTINGS.getSelectedProfile()); @@ -482,6 +508,7 @@ public class Settings { public void setSelectedProfile(Profile selectedProfile) { if (hasProfile(selectedProfile.getName()) && !Objects.equals(selectedProfile.getName(), SETTINGS.getSelectedProfile())) { SETTINGS.setSelectedProfile(selectedProfile.getName()); + save(); Schedulers.computation().schedule(this::onProfileChanged); } } @@ -555,4 +582,8 @@ public class Settings { public void onAccountLoading() { EventBus.EVENT_BUS.fireEvent(new AccountLoadingEvent(this, getAccounts())); } + + public Config getRawConfig() { + return SETTINGS.clone(); + } } 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 791fe235e..2bdb58be7 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 @@ -18,14 +18,23 @@ 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.Modpack; +import org.jackhuang.hmcl.setting.Config; import org.jackhuang.hmcl.setting.Profile; +import org.jackhuang.hmcl.setting.Settings; +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.Constants; +import org.jackhuang.hmcl.util.ZipEngine; 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; @@ -46,16 +55,73 @@ public final class ExportWizardProvider implements WizardProvider { public Object finish(Map settings) { @SuppressWarnings("unchecked") List whitelist = (List) settings.get(ModpackFileSelectionPage.MODPACK_FILE_SELECTION); + List launcherJar = Launcher.getCurrentJarFiles(); + boolean includeLauncher = (Boolean) settings.get(ModpackInfoPage.MODPACK_INCLUDE_LAUNCHER) && launcherJar != null; - return 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), - null - ), (File) settings.get(ModpackInfoPage.MODPACK_FILE)); + 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), + null + ), tempModpack); + + if (includeLauncher) { + dependency = dependency.then(Task.of(() -> { + boolean flag = true; + + try (ZipEngine zip = new ZipEngine(modpackFile)) { + Config config = Settings.INSTANCE.getRawConfig(); + + config.setHasProxy(false); + config.setSelectedProfile(""); + config.setCommonDirectory(null); + config.setFontFamily("Consolas"); + config.setFontSize(12); + config.setJava(null); + config.setLocalization(null); + config.setAccounts(null); + config.setSelectedAccount(""); + config.setLogLines(100); + config.setConfigurations(null); + + zip.putTextFile(Settings.GSON.toJson(config), Settings.SETTINGS_FILE_NAME); + zip.putFile(tempModpack, "modpack.zip"); + + File bg = new File("bg").getAbsoluteFile(); + if (bg.isDirectory()) + zip.putDirectory(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()); + } + })); + } + } + + @Override + public Collection getDependencies() { + return Collections.singleton(dependency); + } + }; } @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 e903d6f5d..5bfa2240b 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 @@ -33,8 +33,10 @@ import org.jackhuang.hmcl.ui.Controllers; import org.jackhuang.hmcl.ui.FXUtils; import org.jackhuang.hmcl.ui.wizard.WizardController; import org.jackhuang.hmcl.ui.wizard.WizardPage; +import org.jackhuang.hmcl.util.FileUtils; import java.io.File; +import java.util.List; import java.util.Map; import java.util.Optional; @@ -45,12 +47,16 @@ public final class ModpackInfoPage extends StackPane implements WizardPage { @FXML private JFXTextField txtModpackName; @FXML - private JFXTextField txtModpackAuthor;@FXML - private JFXTextField txtModpackVersion;@FXML + private JFXTextField txtModpackAuthor; + @FXML + private JFXTextField txtModpackVersion; + @FXML private JFXTextArea txtModpackDescription; @FXML - private JFXToggleButton chkIncludeLauncher;@FXML - private JFXButton btnNext;@FXML + private JFXToggleButton chkIncludeLauncher; + @FXML + private JFXButton btnNext; + @FXML private ScrollPane scroll; public ModpackInfoPage(WizardController controller, String version) { @@ -63,6 +69,10 @@ public final class ModpackInfoPage extends StackPane implements WizardPage { txtModpackVersion.textProperty().addListener(e -> checkValidation()); txtModpackAuthor.setText(Optional.ofNullable(Settings.INSTANCE.getSelectedAccount()).map(Account::getUsername).orElse("")); lblVersionName.setText(version); + + List launcherJar = Launcher.getCurrentJarFiles(); + if (launcherJar == null) + chkIncludeLauncher.setDisable(true); } private void checkValidation() {