Reland: create modpack with launcher packed in

This commit is contained in:
huanghongxun 2021-04-22 08:40:11 +08:00
parent 07d4df312d
commit e36105d937
6 changed files with 122 additions and 38 deletions

View File

@ -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;

View File

@ -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<String, Object> settings) {
@SuppressWarnings("unchecked")
List<String> whitelist = (List<String>) 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<File> launcherJar = Launcher.getCurrentJarFiles();
boolean packWithLauncher = exportInfo.isPackWithLauncher() && launcherJar != null;
return new Task<Object>() {
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<Task<?>> 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<Void>() {
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<Void>() {
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<Void>() {
Task<?> dependency;
@Override
public void execute() {
dependency = new ServerModpackExportTask(profile.getRepository(), version, exportInfo);
dependency = new ServerModpackExportTask(profile.getRepository(), version, exportInfo, modpackFile);
}
@Override

View File

@ -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<ModpackInfoPage> {
@ -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);
}
}
{

View File

@ -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<McbbsModpackManifest.Origin> 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<McbbsModpackManifest.Origin> 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;
}

View File

@ -45,14 +45,16 @@ public class McbbsModpackExportTask extends Task<Void> {
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<Void> {
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<McbbsModpackManifest.File> files = new ArrayList<>();
zip.putDirectory(runDirectory, "overrides", path -> {

View File

@ -45,14 +45,16 @@ public class ServerModpackExportTask extends Task<Void> {
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<Void> {
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<ModpackConfiguration.FileInformation> files = new ArrayList<>();
zip.putDirectory(runDirectory, "overrides", path -> {