mirror of
https://github.com/HMCL-dev/HMCL.git
synced 2025-08-03 11:26:38 -04:00
Modpack updates UI
This commit is contained in:
parent
e8316de160
commit
1a572be52e
@ -0,0 +1,47 @@
|
||||
/*
|
||||
* Hello Minecraft! Launcher.
|
||||
* Copyright (C) 2017 huangyuhui <huanghongxun2008@126.com>
|
||||
*
|
||||
* 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 {http://www.gnu.org/licenses/}.
|
||||
*/
|
||||
package org.jackhuang.hmcl.game;
|
||||
|
||||
import org.jackhuang.hmcl.download.DefaultDependencyManager;
|
||||
import org.jackhuang.hmcl.download.DownloadProvider;
|
||||
import org.jackhuang.hmcl.download.GameBuilder;
|
||||
import org.jackhuang.hmcl.setting.Profile;
|
||||
|
||||
import java.net.Proxy;
|
||||
|
||||
/**
|
||||
* @author huangyuhui
|
||||
*/
|
||||
public class HMCLDependencyManager extends DefaultDependencyManager {
|
||||
private final Profile profile;
|
||||
|
||||
public HMCLDependencyManager(Profile profile, DownloadProvider downloadProvider) {
|
||||
this(profile, downloadProvider, Proxy.NO_PROXY);
|
||||
}
|
||||
|
||||
public HMCLDependencyManager(Profile profile, DownloadProvider downloadProvider, Proxy proxy) {
|
||||
super(profile.getRepository(), downloadProvider, proxy);
|
||||
|
||||
this.profile = profile;
|
||||
}
|
||||
|
||||
@Override
|
||||
public GameBuilder gameBuilder() {
|
||||
return new HMCLGameBuilder(profile);
|
||||
}
|
||||
}
|
@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Hello Minecraft! Launcher.
|
||||
* Copyright (C) 2017 huangyuhui <huanghongxun2008@126.com>
|
||||
*
|
||||
* 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 {http://www.gnu.org/licenses/}.
|
||||
*/
|
||||
package org.jackhuang.hmcl.game;
|
||||
|
||||
import org.jackhuang.hmcl.download.DefaultDependencyManager;
|
||||
import org.jackhuang.hmcl.download.DefaultGameBuilder;
|
||||
import org.jackhuang.hmcl.setting.Profile;
|
||||
import org.jackhuang.hmcl.task.Task;
|
||||
|
||||
/**
|
||||
* @author huangyuhui
|
||||
*/
|
||||
public class HMCLGameBuilder extends DefaultGameBuilder {
|
||||
private final Profile profile;
|
||||
|
||||
public HMCLGameBuilder(Profile profile) {
|
||||
super(profile.getDependency());
|
||||
|
||||
this.profile = profile;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Task downloadGameAsync(String gameVersion, Version version) {
|
||||
return new HMCLGameDownloadTask(profile, gameVersion, version);
|
||||
}
|
||||
}
|
@ -0,0 +1,78 @@
|
||||
/*
|
||||
* Hello Minecraft! Launcher.
|
||||
* Copyright (C) 2017 huangyuhui <huanghongxun2008@126.com>
|
||||
*
|
||||
* 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 {http://www.gnu.org/licenses/}.
|
||||
*/
|
||||
package org.jackhuang.hmcl.game;
|
||||
|
||||
import org.jackhuang.hmcl.download.DefaultDependencyManager;
|
||||
import org.jackhuang.hmcl.setting.Profile;
|
||||
import org.jackhuang.hmcl.setting.Settings;
|
||||
import org.jackhuang.hmcl.task.FileDownloadTask;
|
||||
import org.jackhuang.hmcl.task.Task;
|
||||
import org.jackhuang.hmcl.util.FileUtils;
|
||||
import org.jackhuang.hmcl.util.Logging;
|
||||
import org.jackhuang.hmcl.util.NetworkUtils;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.logging.Level;
|
||||
|
||||
/**
|
||||
* @author huangyuhui
|
||||
*/
|
||||
public class HMCLGameDownloadTask extends Task {
|
||||
private final Profile profile;
|
||||
private final String gameVersion;
|
||||
private final Version version;
|
||||
private final List<Task> dependencies = new LinkedList<>();
|
||||
|
||||
public HMCLGameDownloadTask(Profile profile, String gameVersion, Version version) {
|
||||
this.profile = profile;
|
||||
this.gameVersion = gameVersion;
|
||||
this.version = version;
|
||||
|
||||
setSignificance(TaskSignificance.MINOR);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Task> getDependencies() {
|
||||
return dependencies;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute() throws IOException {
|
||||
File jar = profile.getRepository().getVersionJar(version);
|
||||
|
||||
File cache = new File(Settings.INSTANCE.getCommonPath(), "jars/" + gameVersion + ".jar");
|
||||
if (cache.exists())
|
||||
try {
|
||||
FileUtils.copyFile(cache, jar);
|
||||
return;
|
||||
} catch (IOException e) {
|
||||
Logging.LOG.log(Level.SEVERE, "Unable to copy cached Minecraft jar from " + cache + " to " + jar, e);
|
||||
}
|
||||
|
||||
dependencies.add(new FileDownloadTask(
|
||||
NetworkUtils.toURL(profile.getDependency().getDownloadProvider().injectURL(version.getDownloadInfo().getUrl())),
|
||||
jar,
|
||||
profile.getDependency().getProxy(),
|
||||
version.getDownloadInfo().getSha1()
|
||||
));
|
||||
}
|
||||
|
||||
}
|
@ -33,10 +33,7 @@ import org.jackhuang.hmcl.util.Logging;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.*;
|
||||
import java.util.logging.Level;
|
||||
|
||||
public class HMCLGameRepository extends DefaultGameRepository {
|
||||
@ -192,6 +189,15 @@ public class HMCLGameRepository extends DefaultGameRepository {
|
||||
Lang.invoke(() -> FileUtils.writeText(getVersionSettingFile(id), GSON.toJson(versionSettings.get(id))));
|
||||
}
|
||||
|
||||
public boolean forbidsVersion(String id) {
|
||||
return FORBIDDEN.contains(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public File getModpackConfiguration(String version) {
|
||||
return new File(getRunDirectory(version), "modpack.cfg");
|
||||
}
|
||||
|
||||
public void markVersionAsModpack(String id) {
|
||||
beingModpackVersions.add(id);
|
||||
}
|
||||
@ -204,5 +210,7 @@ public class HMCLGameRepository extends DefaultGameRepository {
|
||||
.registerTypeAdapter(VersionSetting.class, VersionSetting.Serializer.INSTANCE)
|
||||
.create();
|
||||
|
||||
private static final HashSet<String> FORBIDDEN = new HashSet<>(Arrays.asList("modpack", "minecraftinstance", "manifest"));
|
||||
|
||||
private static final String PROFILE = "{\"selectedProfile\": \"(Default)\",\"profiles\": {\"(Default)\": {\"name\": \"(Default)\"}},\"clientToken\": \"88888888-8888-8888-8888-888888888888\"}";
|
||||
}
|
||||
|
@ -52,7 +52,7 @@ public final class HMCLModpackInstallTask extends Task {
|
||||
this.modpack = modpack;
|
||||
this.run = repository.getRunDirectory(name);
|
||||
|
||||
File json = new File(run, "modpack.json");
|
||||
File json = repository.getModpackConfiguration(name);
|
||||
if (repository.hasVersion(name) && !json.exists())
|
||||
throw new IllegalArgumentException("Version " + name + " already exists");
|
||||
|
||||
@ -64,8 +64,13 @@ public final class HMCLModpackInstallTask extends Task {
|
||||
|
||||
ModpackConfiguration<Modpack> config = null;
|
||||
try {
|
||||
if (json.exists())
|
||||
config = Constants.GSON.fromJson(FileUtils.readText(json), new TypeToken<ModpackConfiguration<Modpack>>(){}.getType());
|
||||
if (json.exists()) {
|
||||
config = Constants.GSON.fromJson(FileUtils.readText(json), new TypeToken<ModpackConfiguration<Modpack>>() {
|
||||
}.getType());
|
||||
|
||||
if (!MODPACK_TYPE.equals(config.getType()))
|
||||
throw new IllegalArgumentException("Version " + name + " is not a HMCL modpack. Cannot update this version.");
|
||||
}
|
||||
} catch (JsonParseException | IOException ignore) {
|
||||
}
|
||||
dependents.add(new ModpackInstallTask<>(zipFile, run, "minecraft/", it -> !Objects.equals(it, "minecraft/pack.json"), config));
|
||||
@ -86,6 +91,8 @@ public final class HMCLModpackInstallTask extends Task {
|
||||
String json = CompressingUtils.readTextZipEntry(zipFile, "minecraft/pack.json");
|
||||
Version version = Constants.GSON.fromJson(json, Version.class).setJar(null);
|
||||
dependencies.add(new VersionJsonSaveTask(repository, version));
|
||||
dependencies.add(new MinecraftInstanceTask<>(zipFile, "minecraft/", modpack, new File(run, "modpack.json")));
|
||||
dependencies.add(new MinecraftInstanceTask<>(zipFile, "minecraft/", modpack, MODPACK_TYPE, repository.getModpackConfiguration(name)));
|
||||
}
|
||||
|
||||
public static final String MODPACK_TYPE = "HMCL";
|
||||
}
|
||||
|
@ -17,20 +17,26 @@
|
||||
*/
|
||||
package org.jackhuang.hmcl.game;
|
||||
|
||||
import org.jackhuang.hmcl.mod.CurseManifest;
|
||||
import org.jackhuang.hmcl.mod.Modpack;
|
||||
import org.jackhuang.hmcl.mod.MultiMCInstanceConfiguration;
|
||||
import com.google.gson.JsonParseException;
|
||||
import com.google.gson.reflect.TypeToken;
|
||||
import org.jackhuang.hmcl.mod.*;
|
||||
import org.jackhuang.hmcl.setting.EnumGameDirectory;
|
||||
import org.jackhuang.hmcl.setting.Profile;
|
||||
import org.jackhuang.hmcl.setting.VersionSetting;
|
||||
import org.jackhuang.hmcl.task.Task;
|
||||
import org.jackhuang.hmcl.util.Constants;
|
||||
import org.jackhuang.hmcl.util.FileUtils;
|
||||
import org.jackhuang.hmcl.util.Lang;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.util.Optional;
|
||||
|
||||
public final class ModpackHelper {
|
||||
private ModpackHelper() {}
|
||||
|
||||
public static Modpack readModpackManifest(File file) {
|
||||
public static Modpack readModpackManifest(File file) throws UnsupportedModpackException {
|
||||
try {
|
||||
return CurseManifest.readCurseForgeModpackManifest(file);
|
||||
} catch (Exception e) {
|
||||
@ -49,7 +55,54 @@ public final class ModpackHelper {
|
||||
// ignore it, not a valid MultiMC modpack.
|
||||
}
|
||||
|
||||
throw new IllegalArgumentException("Modpack file " + file + " is not supported.");
|
||||
throw new UnsupportedModpackException(file.toString());
|
||||
}
|
||||
|
||||
public static <T> ModpackConfiguration<T> readModpackConfiguration(File file) throws IOException {
|
||||
if (!file.exists())
|
||||
throw new FileNotFoundException(file.getPath());
|
||||
else
|
||||
try {
|
||||
return Constants.GSON.fromJson(FileUtils.readText(file), new TypeToken<ModpackConfiguration<T>>() {
|
||||
}.getType());
|
||||
} catch (JsonParseException e) {
|
||||
throw new IOException("Malformed modpack configuration");
|
||||
}
|
||||
}
|
||||
|
||||
private static String getManifestType(Object manifest) throws UnsupportedModpackException {
|
||||
if (manifest instanceof HMCLModpackManifest)
|
||||
return HMCLModpackInstallTask.MODPACK_TYPE;
|
||||
else if (manifest instanceof MultiMCInstanceConfiguration)
|
||||
return MultiMCModpackInstallTask.MODPACK_TYPE;
|
||||
else if (manifest instanceof CurseManifest)
|
||||
return CurseInstallTask.MODPACK_TYPE;
|
||||
else
|
||||
throw new UnsupportedModpackException();
|
||||
}
|
||||
|
||||
public static Task getUpdateTask(Profile profile, File zipFile, String name, ModpackConfiguration configuration) throws UnsupportedModpackException, MismatchedModpackTypeException, IOException {
|
||||
Modpack modpack = ModpackHelper.readModpackManifest(zipFile);
|
||||
|
||||
switch (configuration.getType()) {
|
||||
case CurseInstallTask.MODPACK_TYPE:
|
||||
if (!(modpack.getManifest() instanceof CurseManifest))
|
||||
throw new MismatchedModpackTypeException(CurseInstallTask.MODPACK_TYPE, getManifestType(modpack.getManifest()));
|
||||
|
||||
return new CurseInstallTask(profile.getDependency(), zipFile, (CurseManifest) modpack.getManifest(), name);
|
||||
case MultiMCModpackInstallTask.MODPACK_TYPE:
|
||||
if (!(modpack.getManifest() instanceof MultiMCInstanceConfiguration))
|
||||
throw new MismatchedModpackTypeException(MultiMCModpackInstallTask.MODPACK_TYPE, getManifestType(modpack.getManifest()));
|
||||
|
||||
return new MultiMCModpackInstallTask(profile.getDependency(), zipFile, (MultiMCInstanceConfiguration) modpack.getManifest(), name);
|
||||
case HMCLModpackInstallTask.MODPACK_TYPE:
|
||||
if (!(modpack.getManifest() instanceof HMCLModpackManifest))
|
||||
throw new MismatchedModpackTypeException(HMCLModpackInstallTask.MODPACK_TYPE, getManifestType(modpack.getManifest()));
|
||||
|
||||
return new HMCLModpackInstallTask(profile, zipFile, modpack, name);
|
||||
default:
|
||||
throw new UnsupportedModpackException();
|
||||
}
|
||||
}
|
||||
|
||||
public static void toVersionSetting(MultiMCInstanceConfiguration c, VersionSetting vs) {
|
||||
@ -88,4 +141,6 @@ public final class ModpackHelper {
|
||||
vs.setHeight(c.getHeight());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@ -24,6 +24,8 @@ import org.jackhuang.hmcl.task.Scheduler;
|
||||
import org.jackhuang.hmcl.task.Schedulers;
|
||||
import org.jackhuang.hmcl.task.Task;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
public final class MultiMCInstallVersionSettingTask extends Task {
|
||||
private final Profile profile;
|
||||
private final MultiMCInstanceConfiguration manifest;
|
||||
@ -42,7 +44,8 @@ public final class MultiMCInstallVersionSettingTask extends Task {
|
||||
|
||||
@Override
|
||||
public void execute() {
|
||||
VersionSetting vs = profile.specializeVersionSetting(version);
|
||||
profile.getRepository().refreshVersions();
|
||||
VersionSetting vs = Objects.requireNonNull(profile.specializeVersionSetting(version));
|
||||
ModpackHelper.toVersionSetting(manifest, vs);
|
||||
}
|
||||
}
|
||||
|
@ -20,6 +20,7 @@ package org.jackhuang.hmcl.setting;
|
||||
import com.google.gson.*;
|
||||
import javafx.beans.InvalidationListener;
|
||||
import org.jackhuang.hmcl.download.DefaultDependencyManager;
|
||||
import org.jackhuang.hmcl.game.HMCLDependencyManager;
|
||||
import org.jackhuang.hmcl.game.HMCLGameRepository;
|
||||
import org.jackhuang.hmcl.mod.ModManager;
|
||||
import org.jackhuang.hmcl.util.ImmediateObjectProperty;
|
||||
@ -105,8 +106,8 @@ public final class Profile {
|
||||
return modManager;
|
||||
}
|
||||
|
||||
public DefaultDependencyManager getDependency() {
|
||||
return new DefaultDependencyManager(repository, Settings.INSTANCE.getDownloadProvider(), Settings.INSTANCE.getProxy());
|
||||
public HMCLDependencyManager getDependency() {
|
||||
return new HMCLDependencyManager(this, Settings.INSTANCE.getDownloadProvider(), Settings.INSTANCE.getProxy());
|
||||
}
|
||||
|
||||
public VersionSetting getVersionSetting(String id) {
|
||||
|
@ -27,6 +27,7 @@ import org.jackhuang.hmcl.Main;
|
||||
import org.jackhuang.hmcl.setting.Settings;
|
||||
import org.jackhuang.hmcl.task.Task;
|
||||
import org.jackhuang.hmcl.ui.construct.InputDialogPane;
|
||||
import org.jackhuang.hmcl.ui.construct.MessageBox;
|
||||
import org.jackhuang.hmcl.ui.construct.MessageDialogPane;
|
||||
import org.jackhuang.hmcl.util.JavaVersion;
|
||||
|
||||
@ -112,11 +113,19 @@ public final class Controllers {
|
||||
}
|
||||
|
||||
public static void dialog(String text, String title) {
|
||||
dialog(text, title, null);
|
||||
dialog(text, title, MessageBox.INFORMATION_MESSAGE);
|
||||
}
|
||||
|
||||
public static void dialog(String text, String title, Runnable onAccept) {
|
||||
dialog(new MessageDialogPane(text, title, decorator.getDialog(), onAccept));
|
||||
public static void dialog(String text, String title, int type) {
|
||||
dialog(text, title, type, null);
|
||||
}
|
||||
|
||||
public static void dialog(String text, String title, int type, Runnable onAccept) {
|
||||
dialog(new MessageDialogPane(text, title, decorator.getDialog(), MessageBox.INFORMATION_MESSAGE, onAccept));
|
||||
}
|
||||
|
||||
public static void confirmDialog(String text, String title, Runnable onAccept, Runnable onCacnel) {
|
||||
dialog(new MessageDialogPane(text, title, decorator.getDialog(), onAccept, onCacnel));
|
||||
}
|
||||
|
||||
public static void inputDialog(String text, Consumer<String> onResult) {
|
||||
|
@ -35,15 +35,25 @@ import org.jackhuang.hmcl.event.ProfileLoadingEvent;
|
||||
import org.jackhuang.hmcl.event.RefreshedVersionsEvent;
|
||||
import org.jackhuang.hmcl.game.GameVersion;
|
||||
import org.jackhuang.hmcl.game.LauncherHelper;
|
||||
import org.jackhuang.hmcl.game.ModpackHelper;
|
||||
import org.jackhuang.hmcl.game.Version;
|
||||
import org.jackhuang.hmcl.mod.MismatchedModpackTypeException;
|
||||
import org.jackhuang.hmcl.mod.UnsupportedModpackException;
|
||||
import org.jackhuang.hmcl.setting.Profile;
|
||||
import org.jackhuang.hmcl.setting.Settings;
|
||||
import org.jackhuang.hmcl.task.Schedulers;
|
||||
import org.jackhuang.hmcl.task.Task;
|
||||
import org.jackhuang.hmcl.task.TaskExecutor;
|
||||
import org.jackhuang.hmcl.ui.construct.MessageBox;
|
||||
import org.jackhuang.hmcl.ui.construct.MessageDialogPane;
|
||||
import org.jackhuang.hmcl.ui.construct.TaskExecutorDialogPane;
|
||||
import org.jackhuang.hmcl.ui.download.DownloadWizardProvider;
|
||||
import org.jackhuang.hmcl.ui.wizard.DecoratorPage;
|
||||
import org.jackhuang.hmcl.util.Lang;
|
||||
import org.jackhuang.hmcl.util.OperatingSystem;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
@ -75,6 +85,7 @@ public final class MainPage extends StackPane implements DecoratorPage {
|
||||
|
||||
private Node buildNode(Profile profile, String version, String game) {
|
||||
VersionItem item = new VersionItem();
|
||||
item.setUpdate(profile.getRepository().isModpack(version));
|
||||
item.setGameVersion(game);
|
||||
item.setVersionName(version);
|
||||
item.setOnLaunchButtonClicked(e -> {
|
||||
@ -102,6 +113,29 @@ public final class MainPage extends StackPane implements DecoratorPage {
|
||||
Controllers.getDecorator().showPage(Controllers.getVersionPage());
|
||||
Controllers.getVersionPage().load(version, profile);
|
||||
});
|
||||
item.setOnUpdateButtonClicked(event -> {
|
||||
FileChooser chooser = new FileChooser();
|
||||
chooser.setTitle(Main.i18n("modpack.choose"));
|
||||
chooser.getExtensionFilters().add(new FileChooser.ExtensionFilter(Main.i18n("modpack"), "*.zip"));
|
||||
File selectedFile = chooser.showOpenDialog(Controllers.getStage());
|
||||
if (selectedFile != null) {
|
||||
TaskExecutorDialogPane pane = new TaskExecutorDialogPane(null);
|
||||
try {
|
||||
TaskExecutor executor = ModpackHelper.getUpdateTask(profile, selectedFile, version, ModpackHelper.readModpackConfiguration(profile.getRepository().getModpackConfiguration(version)))
|
||||
.then(Task.of(Schedulers.javafx(), Controllers::closeDialog)).executor();
|
||||
pane.setExecutor(executor);
|
||||
pane.setCurrentState(Main.i18n("modpack.update"));
|
||||
executor.start();
|
||||
Controllers.dialog(pane);
|
||||
} catch (UnsupportedModpackException e) {
|
||||
Controllers.dialog(Main.i18n("modpack.unsupported"), Main.i18n("message.error"), MessageBox.ERROR_MESSAGE);
|
||||
} catch (MismatchedModpackTypeException e) {
|
||||
Controllers.dialog(Main.i18n("modpack.mismatched_type"), Main.i18n("message.error"), MessageBox.ERROR_MESSAGE);
|
||||
} catch (IOException e) {
|
||||
Controllers.dialog(Main.i18n("modpack.invalid"), Main.i18n("message.error"), MessageBox.ERROR_MESSAGE);
|
||||
}
|
||||
}
|
||||
});
|
||||
File iconFile = profile.getRepository().getVersionIcon(version);
|
||||
if (iconFile.exists())
|
||||
item.setImage(new Image("file:" + iconFile.getAbsolutePath()));
|
||||
|
@ -97,4 +97,28 @@ public final class SVG {
|
||||
return createSVGPath("M19,20H4C2.89,20 2,19.1 2,18V6C2,4.89 2.89,4 4,4H10L12,6H19A2,2 0 0,1 21,8H21L4,8V18L6.14,10H23.21L20.93,18.5C20.7,19.37 19.92,20 19,20Z", fill, width, height);
|
||||
}
|
||||
|
||||
public static Node update(String fill, double width, double height) {
|
||||
return createSVGPath("M21,10.12H14.22L16.96,7.3C14.23,4.6 9.81,4.5 7.08,7.2C4.35,9.91 4.35,14.28 7.08,17C9.81,19.7 14.23,19.7 16.96,17C18.32,15.65 19,14.08 19,12.1H21C21,14.08 20.12,16.65 18.36,18.39C14.85,21.87 9.15,21.87 5.64,18.39C2.14,14.92 2.11,9.28 5.62,5.81C9.13,2.34 14.76,2.34 18.27,5.81L21,3V10.12M12.5,8V12.25L16,14.33L15.28,15.54L11,13V8H12.5Z", fill, width, height);
|
||||
}
|
||||
|
||||
public static Node close_circle(String fill, double width, double height) {
|
||||
return createSVGPath("M12,2C17.53,2 22,6.47 22,12C22,17.53 17.53,22 12,22C6.47,22 2,17.53 2,12C2,6.47 6.47,2 12,2M15.59,7L12,10.59L8.41,7L7,8.41L10.59,12L7,15.59L8.41,17L12,13.41L15.59,17L17,15.59L13.41,12L17,8.41L15.59,7Z", fill, width, height);
|
||||
}
|
||||
|
||||
public static Node check_circle(String fill, double width, double height) {
|
||||
return createSVGPath("M12,2A10,10 0 0,1 22,12A10,10 0 0,1 12,22A10,10 0 0,1 2,12A10,10 0 0,1 12,2M11,16.5L18,9.5L16.59,8.09L11,13.67L7.91,10.59L6.5,12L11,16.5Z", fill, width, height);
|
||||
}
|
||||
|
||||
public static Node info_circle(String fill, double width, double height) {
|
||||
return createSVGPath("M13,9H11V7H13M13,17H11V11H13M12,2A10,10 0 0,0 2,12A10,10 0 0,0 12,22A10,10 0 0,0 22,12A10,10 0 0,0 12,2Z", fill, width, height);
|
||||
}
|
||||
|
||||
public static Node help_circle(String fill, double width, double height) {
|
||||
return createSVGPath("M15.07,11.25L14.17,12.17C13.45,12.89 13,13.5 13,15H11V14.5C11,13.39 11.45,12.39 12.17,11.67L13.41,10.41C13.78,10.05 14,9.55 14,9C14,7.89 13.1,7 12,7A2,2 0 0,0 10,9H8A4,4 0 0,1 12,5A4,4 0 0,1 16,9C16,9.88 15.64,10.67 15.07,11.25M13,19H11V17H13M12,2A10,10 0 0,0 2,12A10,10 0 0,0 12,22A10,10 0 0,0 22,12C22,6.47 17.5,2 12,2Z", fill, width, height);
|
||||
}
|
||||
|
||||
public static Node alert(String fill, double width, double height) {
|
||||
return createSVGPath("M13,14H11V10H13M13,18H11V16H13M1,21H23L12,2L1,21Z", fill, width, height);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -49,6 +49,8 @@ public final class VersionItem extends StackPane {
|
||||
@FXML
|
||||
private JFXButton btnSettings;
|
||||
@FXML
|
||||
private JFXButton btnUpdate;
|
||||
@FXML
|
||||
private JFXButton btnLaunch;
|
||||
@FXML
|
||||
private JFXButton btnScript;
|
||||
@ -67,10 +69,12 @@ public final class VersionItem extends StackPane {
|
||||
FXUtils.limitHeight(this, 156);
|
||||
setEffect(new DropShadow(BlurType.GAUSSIAN, Color.rgb(0, 0, 0, 0.26), 5.0, 0.12, -1.0, 1.0));
|
||||
btnSettings.setGraphic(SVG.gear("black", 15, 15));
|
||||
btnUpdate.setGraphic(SVG.update("black", 15, 15));
|
||||
btnLaunch.setGraphic(SVG.launch("black", 15, 15));
|
||||
btnScript.setGraphic(SVG.script("black", 15, 15));
|
||||
|
||||
FXUtils.installTooltip(btnSettings, 0, 5000, 0, new Tooltip(Main.i18n("version.manage.settings")));
|
||||
FXUtils.installTooltip(btnSettings, 0, 5000, 0, new Tooltip(Main.i18n("version.settings")));
|
||||
FXUtils.installTooltip(btnUpdate, 0, 5000, 0, new Tooltip(Main.i18n("version.update")));
|
||||
FXUtils.installTooltip(btnLaunch, 0, 5000, 0, new Tooltip(Main.i18n("version.launch")));
|
||||
FXUtils.installTooltip(btnScript, 0, 5000, 0, new Tooltip(Main.i18n("version.launch_script")));
|
||||
|
||||
@ -84,6 +88,10 @@ public final class VersionItem extends StackPane {
|
||||
});
|
||||
}
|
||||
|
||||
public void setUpdate(boolean update) {
|
||||
btnUpdate.setVisible(update);
|
||||
}
|
||||
|
||||
public void setVersionName(String versionName) {
|
||||
lblVersionName.setText(versionName);
|
||||
}
|
||||
@ -108,4 +116,8 @@ public final class VersionItem extends StackPane {
|
||||
launchClickedHandler = handler;
|
||||
btnLaunch.setOnMouseClicked(handler);
|
||||
}
|
||||
|
||||
public void setOnUpdateButtonClicked(EventHandler<? super MouseEvent> handler) {
|
||||
btnUpdate.setOnMouseClicked(handler);
|
||||
}
|
||||
}
|
||||
|
@ -112,12 +112,12 @@ public final class VersionPage extends StackPane implements DecoratorPage {
|
||||
}
|
||||
|
||||
public void onDelete() {
|
||||
if (FXUtils.alert(Alert.AlertType.CONFIRMATION, "Confirm", Main.i18n("version.manage.remove.confirm") + version)) {
|
||||
Controllers.confirmDialog(Main.i18n("version.manage.remove.confirm", version), Main.i18n("message.confirm"), () -> {
|
||||
if (profile.getRepository().removeVersionFromDisk(version)) {
|
||||
profile.getRepository().refreshVersionsAsync().start();
|
||||
Controllers.navigate(null);
|
||||
}
|
||||
}
|
||||
}, null);
|
||||
}
|
||||
|
||||
public void onExport() {
|
||||
|
@ -85,6 +85,10 @@ public final class MessageBox {
|
||||
* Message Box Type: Question
|
||||
*/
|
||||
public static final int QUESTION_MESSAGE = 3;
|
||||
/**
|
||||
* Message Box Type: Fine
|
||||
*/
|
||||
public static final int FINE_MESSAGE = 4;
|
||||
/**
|
||||
* Message Box Type: Plain
|
||||
*/
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Hello Minecraft! Launcher.
|
||||
* Copyright (C) 2017 huangyuhui <huanghongxun2008@126.com>
|
||||
* Copyright (C) 4017 huangyuhui <huanghongxun4008@126.com>
|
||||
*
|
||||
* 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
|
||||
@ -21,8 +21,11 @@ import com.jfoenix.controls.JFXButton;
|
||||
import com.jfoenix.controls.JFXDialog;
|
||||
import javafx.fxml.FXML;
|
||||
import javafx.scene.control.Label;
|
||||
import javafx.scene.layout.HBox;
|
||||
import javafx.scene.layout.StackPane;
|
||||
import org.jackhuang.hmcl.Main;
|
||||
import org.jackhuang.hmcl.ui.FXUtils;
|
||||
import org.jackhuang.hmcl.ui.SVG;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
@ -33,11 +36,17 @@ public final class MessageDialogPane extends StackPane {
|
||||
@FXML
|
||||
private JFXButton acceptButton;
|
||||
@FXML
|
||||
private JFXButton cancelButton;
|
||||
@FXML
|
||||
private Label content;
|
||||
@FXML
|
||||
private Label graphic;
|
||||
@FXML
|
||||
private Label title;
|
||||
@FXML
|
||||
private HBox actions;
|
||||
|
||||
public MessageDialogPane(String text, String title, JFXDialog dialog, Runnable onAccept) {
|
||||
public MessageDialogPane(String text, String title, JFXDialog dialog, int type, Runnable onAccept) {
|
||||
this.text = text;
|
||||
this.dialog = dialog;
|
||||
|
||||
@ -51,5 +60,39 @@ public final class MessageDialogPane extends StackPane {
|
||||
dialog.close();
|
||||
Optional.ofNullable(onAccept).ifPresent(Runnable::run);
|
||||
});
|
||||
|
||||
actions.getChildren().remove(cancelButton);
|
||||
|
||||
switch (type) {
|
||||
case MessageBox.INFORMATION_MESSAGE:
|
||||
graphic.setGraphic(SVG.info_circle("black", 40, 40));
|
||||
break;
|
||||
case MessageBox.ERROR_MESSAGE:
|
||||
graphic.setGraphic(SVG.close_circle("black", 40, 40));
|
||||
break;
|
||||
case MessageBox.FINE_MESSAGE:
|
||||
graphic.setGraphic(SVG.check_circle("black", 40, 40));
|
||||
break;
|
||||
case MessageBox.WARNING_MESSAGE:
|
||||
graphic.setGraphic(SVG.alert("black", 40, 40));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public MessageDialogPane(String text, String title, JFXDialog dialog, Runnable onAccept, Runnable onCancel) {
|
||||
this(text, title, dialog, -1, onAccept);
|
||||
|
||||
cancelButton.setVisible(true);
|
||||
cancelButton.setOnMouseClicked(e -> {
|
||||
dialog.close();
|
||||
Optional.ofNullable(onCancel).ifPresent(Runnable::run);
|
||||
});
|
||||
|
||||
acceptButton.setText(Main.i18n("button.yes"));
|
||||
cancelButton.setText(Main.i18n("button.no"));
|
||||
|
||||
actions.getChildren().add(cancelButton);
|
||||
|
||||
graphic.setGraphic(SVG.help_circle("black", 40, 40));
|
||||
}
|
||||
}
|
||||
|
@ -50,6 +50,9 @@ public class TaskExecutorDialogPane extends StackPane {
|
||||
FXUtils.limitHeight(this, 200);
|
||||
FXUtils.limitWidth(this, 400);
|
||||
|
||||
if (cancel == null)
|
||||
btnCancel.setDisable(true);
|
||||
|
||||
btnCancel.setOnMouseClicked(e -> {
|
||||
Optional.ofNullable(executor).ifPresent(TaskExecutor::cancel);
|
||||
cancel.run();
|
||||
|
@ -62,18 +62,18 @@ public interface TaskExecutorDialogWizardDisplayer extends AbstractWizardDisplay
|
||||
@Override
|
||||
public void onSucceed() {
|
||||
if (settings.containsKey("success_message") && settings.get("success_message") instanceof String)
|
||||
JFXUtilities.runInFX(() -> Controllers.dialog((String) settings.get("success_message"), null, () -> Controllers.navigate(null)));
|
||||
JFXUtilities.runInFX(() -> Controllers.dialog((String) settings.get("success_message"), null, MessageBox.FINE_MESSAGE, () -> Controllers.navigate(null)));
|
||||
else if (!settings.containsKey("forbid_success_message"))
|
||||
JFXUtilities.runInFX(() -> Controllers.dialog(Main.i18n("message.success"), null, () -> Controllers.navigate(null)));
|
||||
JFXUtilities.runInFX(() -> Controllers.dialog(Main.i18n("message.success"), null, MessageBox.FINE_MESSAGE, () -> Controllers.navigate(null)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTerminate() {
|
||||
String appendix = StringUtils.getStackTrace(e.getLastException());
|
||||
if (settings.containsKey("failure_message") && settings.get("failure_message") instanceof String)
|
||||
JFXUtilities.runInFX(() -> Controllers.dialog(appendix, (String) settings.get("failure_message"), () -> Controllers.navigate(null)));
|
||||
JFXUtilities.runInFX(() -> Controllers.dialog(appendix, (String) settings.get("failure_message"), MessageBox.ERROR_MESSAGE, () -> Controllers.navigate(null)));
|
||||
else if (!settings.containsKey("forbid_failure_message"))
|
||||
JFXUtilities.runInFX(() -> Controllers.dialog(appendix, Main.i18n("wizard.failed"), () -> Controllers.navigate(null)));
|
||||
JFXUtilities.runInFX(() -> Controllers.dialog(appendix, Main.i18n("wizard.failed"), MessageBox.ERROR_MESSAGE, () -> Controllers.navigate(null)));
|
||||
}
|
||||
});
|
||||
pane.setExecutor(executor);
|
||||
|
@ -83,9 +83,9 @@ public final class TaskListPane extends StackPane {
|
||||
} else if (task instanceof CurseInstallTask) {
|
||||
task.setName(Main.i18n("modpack.install", Main.i18n("modpack.type.curse")));
|
||||
} else if (task instanceof MultiMCModpackInstallTask) {
|
||||
task.setName(Main.i18n("modpack.install", Main.i18n("modpack.type.curse")));
|
||||
task.setName(Main.i18n("modpack.install", Main.i18n("modpack.type.multimc")));
|
||||
} else if (task instanceof HMCLModpackInstallTask) {
|
||||
task.setName(Main.i18n("modpack.install", Main.i18n("modpack.type.curse")));
|
||||
task.setName(Main.i18n("modpack.install", Main.i18n("modpack.type.hmcl")));
|
||||
} else if (task instanceof HMCLModpackExportTask) {
|
||||
task.setName(Main.i18n("modpack.export"));
|
||||
} else if (task instanceof MinecraftInstanceTask) {
|
||||
|
@ -82,7 +82,10 @@ public final class ModpackPage extends StackPane implements WizardPage {
|
||||
// TODO: original HMCL modpack support.
|
||||
controller.getSettings().put(MODPACK_FILE, selectedFile);
|
||||
lblModpackLocation.setText(selectedFile.getAbsolutePath());
|
||||
txtModpackName.getValidators().add(new Validator(Main.i18n("version.already_exists"), str -> !profile.getRepository().hasVersion(str) && StringUtils.isNotBlank(str)));
|
||||
txtModpackName.getValidators().addAll(
|
||||
new Validator(Main.i18n("install.new_game.already_exists"), str -> !profile.getRepository().hasVersion(str) && StringUtils.isNotBlank(str)),
|
||||
new Validator(Main.i18n("version.forbidden_name"), str -> !profile.getRepository().forbidsVersion(str))
|
||||
);
|
||||
txtModpackName.textProperty().addListener(e -> btnInstall.setDisable(!txtModpackName.validate()));
|
||||
|
||||
try {
|
||||
|
@ -19,6 +19,7 @@ package org.jackhuang.hmcl.ui.export;
|
||||
|
||||
import javafx.scene.Node;
|
||||
import org.jackhuang.hmcl.game.HMCLModpackExportTask;
|
||||
import org.jackhuang.hmcl.game.HMCLModpackManager;
|
||||
import org.jackhuang.hmcl.mod.Modpack;
|
||||
import org.jackhuang.hmcl.setting.Profile;
|
||||
import org.jackhuang.hmcl.ui.wizard.WizardController;
|
||||
@ -28,8 +29,6 @@ import java.io.File;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static org.jackhuang.hmcl.game.HMCLModpackManager.MODPACK_PREDICATE;
|
||||
|
||||
public final class ExportWizardProvider implements WizardProvider {
|
||||
private final Profile profile;
|
||||
private final String version;
|
||||
@ -60,7 +59,7 @@ public final class ExportWizardProvider implements WizardProvider {
|
||||
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, MODPACK_PREDICATE);
|
||||
case 1: return new ModpackFileSelectionPage(controller, profile, version, HMCLModpackManager::suggestMod);
|
||||
default: throw new IllegalArgumentException("step");
|
||||
}
|
||||
}
|
||||
|
@ -19,7 +19,7 @@
|
||||
<JFXTextField fx:id="txtModpackName" labelFloat="true" promptText="%modpack.enter_name" StackPane.margin="$insets" />
|
||||
<BorderPane><left><Label text="%modpack.name"/></left><right><Label fx:id="lblName" /></right></BorderPane>
|
||||
<BorderPane><left><Label text="%archive.version"/></left><right><Label fx:id="lblVersion" /></right></BorderPane>
|
||||
<BorderPane><left><Label text="Author"/></left><right><Label fx:id="lblAuthor" /></right></BorderPane>
|
||||
<BorderPane><left><Label text="%archive.author"/></left><right><Label fx:id="lblAuthor" /></right></BorderPane>
|
||||
<BorderPane>
|
||||
<left><JFXButton fx:id="btnDescription" onMouseClicked="#onDescribe" text="%modpack.wizard.step.3" styleClass="jfx-button" /></left>
|
||||
<right><JFXButton buttonType="RAISED" fx:id="btnInstall" onMouseClicked="#onInstall" text="%button.install" styleClass="jfx-button-raised" /></right>
|
||||
|
@ -4,18 +4,25 @@
|
||||
<?import com.jfoenix.controls.JFXDialogLayout?>
|
||||
<?import javafx.scene.control.Label?>
|
||||
<?import javafx.scene.layout.StackPane?>
|
||||
<?import javafx.scene.layout.HBox?>
|
||||
<fx:root xmlns="http://javafx.com/javafx"
|
||||
xmlns:fx="http://javafx.com/fxml"
|
||||
type="StackPane">
|
||||
<JFXDialogLayout>
|
||||
<heading>
|
||||
<Label fx:id="title" text="%message.info" />
|
||||
</heading>
|
||||
<body>
|
||||
<Label fx:id="content" textAlignment="JUSTIFY" wrapText="true" />
|
||||
</body>
|
||||
<actions>
|
||||
<JFXButton fx:id="acceptButton" styleClass="dialog-accept" text="%button.ok" />
|
||||
</actions>
|
||||
</JFXDialogLayout>
|
||||
<HBox spacing="8">
|
||||
<Label fx:id="graphic" translateX="34" translateY="34" minWidth="40" maxWidth="40" minHeight="40" maxHeight="40" />
|
||||
<JFXDialogLayout>
|
||||
<heading>
|
||||
<Label fx:id="title" text="%message.info" />
|
||||
</heading>
|
||||
<body>
|
||||
<Label fx:id="content" wrapText="true" />
|
||||
</body>
|
||||
<actions>
|
||||
<HBox fx:id="actions">
|
||||
<JFXButton fx:id="acceptButton" styleClass="dialog-accept" text="%button.ok" />
|
||||
<JFXButton fx:id="cancelButton" visible="false" styleClass="dialog-cancel" text="%button.cancel" />
|
||||
</HBox>
|
||||
</actions>
|
||||
</JFXDialogLayout>
|
||||
</HBox>
|
||||
</fx:root>
|
||||
|
@ -30,6 +30,7 @@
|
||||
<left>
|
||||
<HBox spacing="8">
|
||||
<JFXButton fx:id="btnSettings" styleClass="toggle-icon4" maxWidth="30" maxHeight="30" minWidth="30" minHeight="30" prefWidth="30" prefHeight="30" />
|
||||
<JFXButton fx:id="btnUpdate" styleClass="toggle-icon4" maxWidth="30" maxHeight="30" minWidth="30" minHeight="30" prefWidth="30" prefHeight="30" />
|
||||
</HBox>
|
||||
</left>
|
||||
<right>
|
||||
|
@ -110,7 +110,7 @@ profile.new=New Config
|
||||
|
||||
button.refresh=Refresh
|
||||
version.launch=Play
|
||||
version.manage.settings=Settings
|
||||
version.settings=Settings
|
||||
button.about=About
|
||||
button.others=Others
|
||||
button.download=Download
|
||||
@ -211,7 +211,7 @@ modpack.wizard.step.1=Basic options
|
||||
modpack.wizard.step.1.title=Set the basic options to the modpack.
|
||||
modpack.wizard.step.initialization.include_launcher=Include the launcher
|
||||
modpack.wizard.step.initialization.exported_version=The exported game version
|
||||
modpack.wizard.step.initialization.save=Choose a location to export the game files to
|
||||
modpack.wizard.step.initialization.save=Choose a path to export the game files to
|
||||
modpack.wizard.step.initialization.warning=Before making modpack, you should ensure that your game can launch successfully,\nand that your Minecraft is release, not snapshot.\nand that it is not allowed to add mods which is not allowed to distribute to the modpack.
|
||||
modpack.wizard.step.2=Files selection
|
||||
modpack.wizard.step.2.title=Choose the files you want to put into the modpack.
|
||||
@ -219,10 +219,8 @@ modpack.wizard.step.3=Description
|
||||
modpack.wizard.step.3.title=Describe your modpack.
|
||||
|
||||
modpack.desc=Describe your modpack, including precautions, changlog, supporting Markdown(also supporting online pictures).
|
||||
modpack.incorrect_format.no_json=The format of the modpack is incorrect, pack.json is missing.
|
||||
modpack.incorrect_format.no_jar=The format of the modpack is incorrect, pack.json does not have attribute 'jar'
|
||||
modpack.cannot_read_version=Failed to gather the game version
|
||||
modpack.not_a_valid_location=Not a valid modpack location
|
||||
modpack.not_a_valid_location=Not a valid modpack path
|
||||
modpack.name=Modpack Name
|
||||
modpack.not_a_valid_name=Not a valid modpack name
|
||||
|
||||
@ -308,7 +306,7 @@ version.game.old_alpha=Old Alpha
|
||||
version.manage.rename=Rename this version
|
||||
version.manage.rename.message=Please enter the new name
|
||||
version.manage.remove=Delete this version
|
||||
version.manage.remove.confirm=Sure to remove the version
|
||||
version.manage.remove.confirm=Sure to remove version %s?
|
||||
version.manage.redownload_json=Redownload Minecraft Configuration(minecraft.json)
|
||||
version.manage.redownload_assets_index=Redownload Assets Index
|
||||
version.manage.remove_libraries=Delete library files
|
||||
@ -413,3 +411,10 @@ extension.png=Image file
|
||||
message.success=Tasks succeeded
|
||||
message.doing=Please wait
|
||||
modpack.scan=Scanning this modpack
|
||||
version.update=Update
|
||||
modpack.unsupported=Unsupported modpack, only HMCL, MultiMC, Curse modpacks are supported.
|
||||
modpack.mismatched_type=Mismatched modpack type, your current game is %s modpack, but your update file is %s modpack.
|
||||
modpack.invalid=Invalid modpack file.
|
||||
modpack.update=Upgrading game
|
||||
message.confirm=Confirm
|
||||
version.forbidden_name=Forbidden name, do not use this.
|
||||
|
@ -110,7 +110,7 @@ profile.new=新建配置
|
||||
|
||||
button.refresh=刷新
|
||||
version.launch=启动游戏
|
||||
version.manage.settings=游戏设置
|
||||
version.settings=游戏设置
|
||||
button.about=关于
|
||||
button.others=其他
|
||||
button.download=下载
|
||||
@ -219,8 +219,6 @@ modpack.wizard.step.3=整合包描述
|
||||
modpack.wizard.step.3.title=描述你要制作的整合包
|
||||
|
||||
modpack.desc=描述你要制作的整合包,比如整合包注意事项和更新记录,支持Markdown(图片请用网络图片)。
|
||||
modpack.incorrect_format.no_json=整合包格式错误,pack.json丢失
|
||||
modpack.incorrect_format.no_jar=整合包格式错误,pack.json丢失jar字段
|
||||
modpack.cannot_read_version=读取游戏版本失败
|
||||
modpack.not_a_valid_location=不是一个有效整合包位置
|
||||
modpack.name=整合包名称
|
||||
@ -308,7 +306,7 @@ version.game.old_alpha=远古版
|
||||
version.manage.rename=重命名该版本
|
||||
version.manage.rename.message=请输入要改成的名字
|
||||
version.manage.remove=删除该版本
|
||||
version.manage.remove.confirm=真的要删除版本
|
||||
version.manage.remove.confirm=真的要删除版本 %s 吗?
|
||||
version.manage.redownload_json=重新下载版本配置(minecraft.json)
|
||||
version.manage.redownload_assets_index=重新下载资源配置(assets_index.json)
|
||||
version.manage.remove_libraries=删除所有库文件
|
||||
@ -413,3 +411,10 @@ extension.png=图片文件
|
||||
message.success=已完成
|
||||
message.doing=请耐心等待
|
||||
modpack.scan=解析整合包
|
||||
version.update=更新
|
||||
modpack.unsupported=该整合包不被支持。仅HMCL、MultiMC、Curse整合包受支持。
|
||||
modpack.mismatched_type=整合包类型不匹配,当前游戏是 %s 整合包,但是提供的整合包更新文件是 %s 整合包。
|
||||
modpack.invalid=无效的整合包升级文件,可能是下载时出现问题。
|
||||
modpack.update=正在升级整合包
|
||||
message.confirm=提示
|
||||
version.forbidden_name=此版本名称不受支持,请换一个名字
|
||||
|
4
HMCLCore/gradlew
vendored
4
HMCLCore/gradlew
vendored
@ -78,14 +78,14 @@ if [ -n "$JAVA_HOME" ] ; then
|
||||
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
|
||||
|
||||
Please set the JAVA_HOME variable in your environment to match the
|
||||
location of your Java installation."
|
||||
path of your Java installation."
|
||||
fi
|
||||
else
|
||||
JAVACMD="java"
|
||||
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||
|
||||
Please set the JAVA_HOME variable in your environment to match the
|
||||
location of your Java installation."
|
||||
path of your Java installation."
|
||||
fi
|
||||
|
||||
# Increase the maximum file descriptors if we can.
|
||||
|
4
HMCLCore/gradlew.bat
vendored
4
HMCLCore/gradlew.bat
vendored
@ -27,7 +27,7 @@ echo.
|
||||
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||
echo.
|
||||
echo Please set the JAVA_HOME variable in your environment to match the
|
||||
echo location of your Java installation.
|
||||
echo path of your Java installation.
|
||||
|
||||
goto fail
|
||||
|
||||
@ -41,7 +41,7 @@ echo.
|
||||
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
|
||||
echo.
|
||||
echo Please set the JAVA_HOME variable in your environment to match the
|
||||
echo location of your Java installation.
|
||||
echo path of your Java installation.
|
||||
|
||||
goto fail
|
||||
|
||||
|
@ -41,6 +41,14 @@ public class DefaultGameBuilder extends GameBuilder {
|
||||
this.downloadProvider = dependencyManager.getDownloadProvider();
|
||||
}
|
||||
|
||||
public DefaultDependencyManager getDependencyManager() {
|
||||
return dependencyManager;
|
||||
}
|
||||
|
||||
public DownloadProvider getDownloadProvider() {
|
||||
return downloadProvider;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Task buildAsync() {
|
||||
return new VersionJsonDownloadTask(gameVersion, dependencyManager).then(variables -> {
|
||||
@ -50,7 +58,7 @@ public class DefaultGameBuilder extends GameBuilder {
|
||||
Task result = new ParallelTask(
|
||||
new GameAssetDownloadTask(dependencyManager, version),
|
||||
new GameLoggingDownloadTask(dependencyManager, version),
|
||||
new GameDownloadTask(dependencyManager, version),
|
||||
downloadGameAsync(gameVersion, version),
|
||||
new GameLibrariesTask(dependencyManager, version) // Game libraries will be downloaded for multiple times partly, this time is for vanilla libraries.
|
||||
).with(new VersionJsonSaveTask(dependencyManager.getGameRepository(), version)); // using [with] because download failure here are tolerant.
|
||||
|
||||
@ -68,4 +76,8 @@ public class DefaultGameBuilder extends GameBuilder {
|
||||
return variables -> dependencyManager.installLibraryAsync(gameVersion, variables.get("version"), libraryId, toolVersions.get(libraryId));
|
||||
}
|
||||
|
||||
protected Task downloadGameAsync(String gameVersion, Version version) {
|
||||
return new GameDownloadTask(dependencyManager, version);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -310,4 +310,12 @@ public class DefaultGameRepository implements GameRepository {
|
||||
return loaded;
|
||||
}
|
||||
|
||||
public File getModpackConfiguration(String version) {
|
||||
return new File(getRunDirectory(version), "modpack.json");
|
||||
}
|
||||
|
||||
public boolean isModpack(String version) {
|
||||
return getModpackConfiguration(version).exists();
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -23,7 +23,6 @@ import org.jackhuang.hmcl.download.DefaultDependencyManager;
|
||||
import org.jackhuang.hmcl.download.GameBuilder;
|
||||
import org.jackhuang.hmcl.game.DefaultGameRepository;
|
||||
import org.jackhuang.hmcl.task.Task;
|
||||
import org.jackhuang.hmcl.util.CompressingUtils;
|
||||
import org.jackhuang.hmcl.util.Constants;
|
||||
import org.jackhuang.hmcl.util.FileUtils;
|
||||
|
||||
@ -32,7 +31,6 @@ import java.io.IOException;
|
||||
import java.util.Collection;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
/**
|
||||
* Install a downloaded CurseForge modpack.
|
||||
@ -68,7 +66,7 @@ public final class CurseInstallTask extends Task {
|
||||
this.repository = dependencyManager.getGameRepository();
|
||||
this.run = repository.getRunDirectory(name);
|
||||
|
||||
File json = new File(run, "modpack.json");
|
||||
File json = repository.getModpackConfiguration(name);
|
||||
if (repository.hasVersion(name) && !json.exists())
|
||||
throw new IllegalArgumentException("Version " + name + " already exists.");
|
||||
|
||||
@ -80,8 +78,13 @@ public final class CurseInstallTask extends Task {
|
||||
|
||||
ModpackConfiguration<CurseManifest> config = null;
|
||||
try {
|
||||
if (json.exists())
|
||||
config = Constants.GSON.fromJson(FileUtils.readText(json), new TypeToken<ModpackConfiguration<CurseManifest>>(){}.getType());
|
||||
if (json.exists()) {
|
||||
config = Constants.GSON.fromJson(FileUtils.readText(json), new TypeToken<ModpackConfiguration<CurseManifest>>() {
|
||||
}.getType());
|
||||
|
||||
if (!MODPACK_TYPE.equals(config.getType()))
|
||||
throw new IllegalArgumentException("Version " + name + " is not a Curse modpack. Cannot update this version.");
|
||||
}
|
||||
} catch (JsonParseException | IOException ignore) {
|
||||
}
|
||||
this.config = config;
|
||||
@ -110,7 +113,8 @@ public final class CurseInstallTask extends Task {
|
||||
}
|
||||
|
||||
dependencies.add(new CurseCompletionTask(dependencyManager, name));
|
||||
dependencies.add(new MinecraftInstanceTask<>(zipFile, manifest.getOverrides(), false, manifest, new File(run, "modpack.json")));
|
||||
dependencies.add(new MinecraftInstanceTask<>(zipFile, manifest.getOverrides(), manifest, MODPACK_TYPE, repository.getModpackConfiguration(name)));
|
||||
}
|
||||
|
||||
public static final String MODPACK_TYPE = "Curse";
|
||||
}
|
||||
|
@ -23,11 +23,12 @@ import org.jackhuang.hmcl.task.Task;
|
||||
import org.jackhuang.hmcl.util.Constants;
|
||||
import org.jackhuang.hmcl.util.DigestUtils;
|
||||
import org.jackhuang.hmcl.util.FileUtils;
|
||||
import org.jackhuang.hmcl.util.IOUtils;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public final class MinecraftInstanceTask<T> extends Task {
|
||||
@ -36,12 +37,14 @@ public final class MinecraftInstanceTask<T> extends Task {
|
||||
private final String subDirectory;
|
||||
private final File jsonFile;
|
||||
private final T manifest;
|
||||
private final String type;
|
||||
|
||||
public MinecraftInstanceTask(File zipFile, String subDirectory, T manifest, File jsonFile) {
|
||||
public MinecraftInstanceTask(File zipFile, String subDirectory, T manifest, String type, File jsonFile) {
|
||||
this.zipFile = zipFile;
|
||||
this.subDirectory = subDirectory;
|
||||
this.manifest = manifest;
|
||||
this.jsonFile = jsonFile;
|
||||
this.type = type;
|
||||
|
||||
if (!zipFile.exists())
|
||||
throw new IllegalArgumentException("File " + zipFile + " does not exist. Cannot parse this modpack.");
|
||||
@ -49,9 +52,8 @@ public final class MinecraftInstanceTask<T> extends Task {
|
||||
|
||||
@Override
|
||||
public void execute() throws Exception {
|
||||
Map<String, ModpackConfiguration.FileInformation> overrides = new HashMap<>();
|
||||
List<ModpackConfiguration.FileInformation> overrides = new LinkedList<>();
|
||||
|
||||
byte[] buf = new byte[IOUtils.DEFAULT_BUFFER_SIZE];
|
||||
try (ZipArchiveInputStream zip = new ZipArchiveInputStream(new FileInputStream(zipFile), null, true, true)) {
|
||||
ArchiveEntry entry;
|
||||
while ((entry = zip.getNextEntry()) != null) {
|
||||
@ -62,12 +64,10 @@ public final class MinecraftInstanceTask<T> extends Task {
|
||||
if (path.startsWith("/") || path.startsWith("\\"))
|
||||
path = path.substring(1);
|
||||
|
||||
overrides.put(path, new ModpackConfiguration.FileInformation(
|
||||
path, DigestUtils.sha1Hex(zip)
|
||||
));
|
||||
overrides.add(new ModpackConfiguration.FileInformation(path, DigestUtils.sha1Hex(zip)));
|
||||
}
|
||||
}
|
||||
|
||||
FileUtils.writeText(jsonFile, Constants.GSON.toJson(new ModpackConfiguration<>(manifest, overrides)));
|
||||
FileUtils.writeText(jsonFile, Constants.GSON.toJson(new ModpackConfiguration<>(manifest, type, overrides)));
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,30 @@
|
||||
/*
|
||||
* Hello Minecraft! Launcher.
|
||||
* Copyright (C) 2017 huangyuhui <huanghongxun2008@126.com>
|
||||
*
|
||||
* 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 {http://www.gnu.org/licenses/}.
|
||||
*/
|
||||
package org.jackhuang.hmcl.mod;
|
||||
|
||||
public class MismatchedModpackTypeException extends Exception {
|
||||
private final String required;
|
||||
private final String found;
|
||||
|
||||
public MismatchedModpackTypeException(String required, String found) {
|
||||
super("Required " + required + ", but found " + found);
|
||||
|
||||
this.required = required;
|
||||
this.found = found;
|
||||
}
|
||||
}
|
@ -21,50 +21,56 @@ import com.google.gson.JsonParseException;
|
||||
import org.jackhuang.hmcl.util.Immutable;
|
||||
import org.jackhuang.hmcl.util.Validation;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
import java.util.*;
|
||||
|
||||
@Immutable
|
||||
public final class ModpackConfiguration<T> implements Validation {
|
||||
|
||||
private final T manifest;
|
||||
|
||||
private final Map<String, FileInformation> overrides;
|
||||
private final String type;
|
||||
private final List<FileInformation> overrides;
|
||||
|
||||
public ModpackConfiguration() {
|
||||
this(null, Collections.emptyMap());
|
||||
this(null, null, Collections.emptyList());
|
||||
}
|
||||
|
||||
public ModpackConfiguration(T manifest, Map<String, FileInformation> overrides) {
|
||||
public ModpackConfiguration(T manifest, String type, List<FileInformation> overrides) {
|
||||
this.manifest = manifest;
|
||||
this.overrides = overrides;
|
||||
this.type = type;
|
||||
this.overrides = new ArrayList<>(overrides);
|
||||
}
|
||||
|
||||
public T getManifest() {
|
||||
return manifest;
|
||||
}
|
||||
|
||||
public String getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public ModpackConfiguration<T> setManifest(T manifest) {
|
||||
return new ModpackConfiguration<>(manifest, overrides);
|
||||
return new ModpackConfiguration<>(manifest, type, overrides);
|
||||
}
|
||||
|
||||
public ModpackConfiguration<T> setOverrides(Map<String, FileInformation> overrides) {
|
||||
return new ModpackConfiguration<>(manifest, overrides);
|
||||
public ModpackConfiguration<T> setOverrides(List<FileInformation> overrides) {
|
||||
return new ModpackConfiguration<>(manifest, type, overrides);
|
||||
}
|
||||
|
||||
public Map<String, FileInformation> getOverrides() {
|
||||
return Collections.unmodifiableMap(overrides);
|
||||
public List<FileInformation> getOverrides() {
|
||||
return Collections.unmodifiableList(overrides);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void validate() throws JsonParseException {
|
||||
if (manifest == null)
|
||||
throw new JsonParseException("MinecraftInstanceConfiguration missing `manifest`");
|
||||
if (type == null)
|
||||
throw new JsonParseException("MinecraftInstanceConfiguration missing `type`");
|
||||
}
|
||||
|
||||
@Immutable
|
||||
public static class FileInformation implements Validation {
|
||||
private final String location; // relative
|
||||
private final String path; // relative
|
||||
private final String hash;
|
||||
private final String downloadURL;
|
||||
|
||||
@ -72,18 +78,22 @@ public final class ModpackConfiguration<T> implements Validation {
|
||||
this(null, null);
|
||||
}
|
||||
|
||||
public FileInformation(String location, String hash) {
|
||||
this(location, hash, null);
|
||||
public FileInformation(String path, String hash) {
|
||||
this(path, hash, null);
|
||||
}
|
||||
|
||||
public FileInformation(String location, String hash, String downloadURL) {
|
||||
this.location = location;
|
||||
public FileInformation(String path, String hash, String downloadURL) {
|
||||
this.path = path;
|
||||
this.hash = hash;
|
||||
this.downloadURL = downloadURL;
|
||||
}
|
||||
|
||||
public String getLocation() {
|
||||
return location;
|
||||
/**
|
||||
* The relative path to Minecraft run directory
|
||||
* @return
|
||||
*/
|
||||
public String getPath() {
|
||||
return path;
|
||||
}
|
||||
|
||||
public String getDownloadURL() {
|
||||
@ -96,8 +106,8 @@ public final class ModpackConfiguration<T> implements Validation {
|
||||
|
||||
@Override
|
||||
public void validate() throws JsonParseException {
|
||||
if (location == null)
|
||||
throw new JsonParseException("FileInformation missing `location`.");
|
||||
if (path == null)
|
||||
throw new JsonParseException("FileInformation missing `path`.");
|
||||
if (hash == null)
|
||||
throw new JsonParseException("FileInformation missing file hash code.");
|
||||
}
|
||||
|
@ -25,10 +25,7 @@ import org.jackhuang.hmcl.util.FileUtils;
|
||||
import org.jackhuang.hmcl.util.IOUtils;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.*;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
public class ModpackInstallTask<T> extends Task {
|
||||
@ -36,7 +33,7 @@ public class ModpackInstallTask<T> extends Task {
|
||||
private final File modpackFile;
|
||||
private final File dest;
|
||||
private final String subDirectory;
|
||||
private final Map<String, ModpackConfiguration.FileInformation> overrides;
|
||||
private final List<ModpackConfiguration.FileInformation> overrides;
|
||||
private final Predicate<String> callback;
|
||||
|
||||
public ModpackInstallTask(File modpackFile, File dest, String subDirectory, Predicate<String> callback, ModpackConfiguration<T> oldConfiguration) {
|
||||
@ -46,7 +43,7 @@ public class ModpackInstallTask<T> extends Task {
|
||||
this.callback = callback;
|
||||
|
||||
if (oldConfiguration == null)
|
||||
overrides = Collections.emptyMap();
|
||||
overrides = Collections.emptyList();
|
||||
else
|
||||
overrides = oldConfiguration.getOverrides();
|
||||
}
|
||||
@ -57,6 +54,11 @@ public class ModpackInstallTask<T> extends Task {
|
||||
byte[] buf = new byte[IOUtils.DEFAULT_BUFFER_SIZE];
|
||||
if (!FileUtils.makeDirectory(dest))
|
||||
throw new IOException("Unable to make directory " + dest);
|
||||
|
||||
HashSet<String> files = new HashSet<>();
|
||||
for (ModpackConfiguration.FileInformation file : overrides)
|
||||
files.add(file.getPath());
|
||||
|
||||
try (ZipArchiveInputStream zipStream = new ZipArchiveInputStream(new FileInputStream(modpackFile), null, true, true)) {
|
||||
ArchiveEntry entry;
|
||||
while ((entry = zipStream.getNextEntry()) != null) {
|
||||
@ -86,7 +88,7 @@ public class ModpackInstallTask<T> extends Task {
|
||||
IOUtils.copyTo(zipStream, os, buf);
|
||||
byte[] data = os.toByteArray();
|
||||
|
||||
if (!overrides.containsKey(path) || entryFile.exists()) {
|
||||
if (files.contains(path) && entryFile.exists()) {
|
||||
String oldHash = DigestUtils.sha1Hex(new FileInputStream(entryFile));
|
||||
String newHash = DigestUtils.sha1Hex(new ByteArrayInputStream(data));
|
||||
if (!oldHash.equals(newHash)) {
|
||||
@ -94,15 +96,19 @@ public class ModpackInstallTask<T> extends Task {
|
||||
IOUtils.copyTo(new ByteArrayInputStream(data), fos, buf);
|
||||
}
|
||||
}
|
||||
} else if (!files.contains(path)) {
|
||||
try (FileOutputStream fos = new FileOutputStream(entryFile)) {
|
||||
IOUtils.copyTo(new ByteArrayInputStream(data), fos, buf);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (String path : overrides.keySet()) {
|
||||
File original = new File(dest, path);
|
||||
if (original.exists() && !entries.contains(path))
|
||||
for (ModpackConfiguration.FileInformation file : overrides) {
|
||||
File original = new File(dest, file.getPath());
|
||||
if (original.exists() && !entries.contains(file.getPath()))
|
||||
original.delete();
|
||||
}
|
||||
}
|
||||
|
@ -58,7 +58,7 @@ public final class MultiMCModpackInstallTask extends Task {
|
||||
this.repository = dependencyManager.getGameRepository();
|
||||
this.run = repository.getRunDirectory(name);
|
||||
|
||||
File json = new File(run, "modpack.json");
|
||||
File json = repository.getModpackConfiguration(name);
|
||||
if (repository.hasVersion(name) && !json.exists())
|
||||
throw new IllegalArgumentException("Version " + name + " already exists.");
|
||||
dependents.add(dependencyManager.gameBuilder().name(name).gameVersion(manifest.getGameVersion()).buildAsync());
|
||||
@ -69,8 +69,13 @@ public final class MultiMCModpackInstallTask extends Task {
|
||||
|
||||
ModpackConfiguration<MultiMCInstanceConfiguration> config = null;
|
||||
try {
|
||||
if (json.exists())
|
||||
config = Constants.GSON.fromJson(FileUtils.readText(json), new TypeToken<ModpackConfiguration<MultiMCInstanceConfiguration>>(){}.getType());
|
||||
if (json.exists()) {
|
||||
config = Constants.GSON.fromJson(FileUtils.readText(json), new TypeToken<ModpackConfiguration<MultiMCInstanceConfiguration>>() {
|
||||
}.getType());
|
||||
|
||||
if (!MODPACK_TYPE.equals(config.getType()))
|
||||
throw new IllegalArgumentException("Version " + name + " is not a MultiMC modpack. Cannot update this version.");
|
||||
}
|
||||
} catch (JsonParseException | IOException ignore) {
|
||||
}
|
||||
|
||||
@ -110,7 +115,8 @@ public final class MultiMCModpackInstallTask extends Task {
|
||||
}
|
||||
|
||||
dependencies.add(new VersionJsonSaveTask(repository, version));
|
||||
dependencies.add(new MinecraftInstanceTask<>(zipFile, manifest.getName() + "/minecraft/", manifest, new File(run, "modpack.json")));
|
||||
dependencies.add(new MinecraftInstanceTask<>(zipFile, manifest.getName() + "/minecraft/", manifest, MODPACK_TYPE, repository.getModpackConfiguration(name)));
|
||||
}
|
||||
|
||||
|
||||
public static final String MODPACK_TYPE = "MultiMC";
|
||||
}
|
||||
|
@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Hello Minecraft! Launcher.
|
||||
* Copyright (C) 2017 huangyuhui <huanghongxun2008@126.com>
|
||||
*
|
||||
* 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 {http://www.gnu.org/licenses/}.
|
||||
*/
|
||||
package org.jackhuang.hmcl.mod;
|
||||
|
||||
public class UnsupportedModpackException extends Exception {
|
||||
public UnsupportedModpackException() {
|
||||
}
|
||||
|
||||
public UnsupportedModpackException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public UnsupportedModpackException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
|
||||
public UnsupportedModpackException(Throwable cause) {
|
||||
super(cause);
|
||||
}
|
||||
}
|
@ -114,7 +114,7 @@ public class FileDownloadTask extends Task {
|
||||
@Override
|
||||
public void execute() throws Exception {
|
||||
URL currentURL = url;
|
||||
Logging.LOG.log(Level.FINER, "Downloading {0}, to {1}", new Object[] { currentURL, file });
|
||||
Logging.LOG.log(Level.FINER, "Downloading {0} to {1}", new Object[] { currentURL, file });
|
||||
Exception exception = null;
|
||||
|
||||
for (int repeat = 0; repeat < retry; repeat++) {
|
||||
@ -193,7 +193,7 @@ public class FileDownloadTask extends Task {
|
||||
Thread.currentThread().interrupt();
|
||||
break;
|
||||
} else {
|
||||
if (file.exists() || !file.delete())
|
||||
if (file.exists() && !file.delete())
|
||||
throw new IOException("Unable to delete existent file " + file);
|
||||
if (!FileUtils.makeDirectory(file.getAbsoluteFile().getParentFile()))
|
||||
throw new IOException("Unable to make parent directory " + file);
|
||||
|
4
gradlew
vendored
4
gradlew
vendored
@ -78,14 +78,14 @@ if [ -n "$JAVA_HOME" ] ; then
|
||||
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
|
||||
|
||||
Please set the JAVA_HOME variable in your environment to match the
|
||||
location of your Java installation."
|
||||
path of your Java installation."
|
||||
fi
|
||||
else
|
||||
JAVACMD="java"
|
||||
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||
|
||||
Please set the JAVA_HOME variable in your environment to match the
|
||||
location of your Java installation."
|
||||
path of your Java installation."
|
||||
fi
|
||||
|
||||
# Increase the maximum file descriptors if we can.
|
||||
|
4
gradlew.bat
vendored
4
gradlew.bat
vendored
@ -27,7 +27,7 @@ echo.
|
||||
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||
echo.
|
||||
echo Please set the JAVA_HOME variable in your environment to match the
|
||||
echo location of your Java installation.
|
||||
echo path of your Java installation.
|
||||
|
||||
goto fail
|
||||
|
||||
@ -41,7 +41,7 @@ echo.
|
||||
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
|
||||
echo.
|
||||
echo Please set the JAVA_HOME variable in your environment to match the
|
||||
echo location of your Java installation.
|
||||
echo path of your Java installation.
|
||||
|
||||
goto fail
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user