mirror of
https://github.com/HMCL-dev/HMCL.git
synced 2025-09-16 15:26:27 -04:00
Fix #632
This commit is contained in:
parent
61abed04f3
commit
71131dadb7
@ -25,8 +25,9 @@ import org.jackhuang.hmcl.mod.curse.CurseInstallTask;
|
|||||||
import org.jackhuang.hmcl.mod.curse.CurseManifest;
|
import org.jackhuang.hmcl.mod.curse.CurseManifest;
|
||||||
import org.jackhuang.hmcl.mod.multimc.MultiMCInstanceConfiguration;
|
import org.jackhuang.hmcl.mod.multimc.MultiMCInstanceConfiguration;
|
||||||
import org.jackhuang.hmcl.mod.multimc.MultiMCModpackInstallTask;
|
import org.jackhuang.hmcl.mod.multimc.MultiMCModpackInstallTask;
|
||||||
import org.jackhuang.hmcl.mod.server.ServerModpackInstallTask;
|
import org.jackhuang.hmcl.mod.server.ServerModpackLocalInstallTask;
|
||||||
import org.jackhuang.hmcl.mod.server.ServerModpackManifest;
|
import org.jackhuang.hmcl.mod.server.ServerModpackManifest;
|
||||||
|
import org.jackhuang.hmcl.mod.server.ServerModpackRemoteInstallTask;
|
||||||
import org.jackhuang.hmcl.setting.EnumGameDirectory;
|
import org.jackhuang.hmcl.setting.EnumGameDirectory;
|
||||||
import org.jackhuang.hmcl.setting.Profile;
|
import org.jackhuang.hmcl.setting.Profile;
|
||||||
import org.jackhuang.hmcl.setting.VersionSetting;
|
import org.jackhuang.hmcl.setting.VersionSetting;
|
||||||
@ -99,6 +100,29 @@ public final class ModpackHelper {
|
|||||||
throw new UnsupportedModpackException();
|
throw new UnsupportedModpackException();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static Task<Void> getInstallTask(Profile profile, ServerModpackManifest manifest, String name, Modpack modpack) {
|
||||||
|
profile.getRepository().markVersionAsModpack(name);
|
||||||
|
|
||||||
|
ExceptionalRunnable<?> success = () -> {
|
||||||
|
HMCLGameRepository repository = profile.getRepository();
|
||||||
|
repository.refreshVersions();
|
||||||
|
VersionSetting vs = repository.specializeVersionSetting(name);
|
||||||
|
repository.undoMark(name);
|
||||||
|
if (vs != null)
|
||||||
|
vs.setGameDirType(EnumGameDirectory.VERSION_FOLDER);
|
||||||
|
};
|
||||||
|
|
||||||
|
ExceptionalConsumer<Exception, ?> failure = ex -> {
|
||||||
|
if (ex instanceof CurseCompletionException && !(ex.getCause() instanceof FileNotFoundException)) {
|
||||||
|
success.run();
|
||||||
|
// This is tolerable and we will not delete the game
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return new ServerModpackRemoteInstallTask(profile.getDependency(), manifest, name)
|
||||||
|
.whenComplete(Schedulers.defaultScheduler(), success, failure);
|
||||||
|
}
|
||||||
|
|
||||||
public static Task<Void> getInstallTask(Profile profile, File zipFile, String name, Modpack modpack) {
|
public static Task<Void> getInstallTask(Profile profile, File zipFile, String name, Modpack modpack) {
|
||||||
profile.getRepository().markVersionAsModpack(name);
|
profile.getRepository().markVersionAsModpack(name);
|
||||||
|
|
||||||
@ -129,7 +153,7 @@ public final class ModpackHelper {
|
|||||||
.whenComplete(Schedulers.defaultScheduler(), success, failure)
|
.whenComplete(Schedulers.defaultScheduler(), success, failure)
|
||||||
.thenComposeAsync(new MultiMCInstallVersionSettingTask(profile, ((MultiMCInstanceConfiguration) modpack.getManifest()), name));
|
.thenComposeAsync(new MultiMCInstallVersionSettingTask(profile, ((MultiMCInstanceConfiguration) modpack.getManifest()), name));
|
||||||
else if (modpack.getManifest() instanceof ServerModpackManifest)
|
else if (modpack.getManifest() instanceof ServerModpackManifest)
|
||||||
return new ServerModpackInstallTask(profile.getDependency(), zipFile, modpack, ((ServerModpackManifest) modpack.getManifest()), name)
|
return new ServerModpackLocalInstallTask(profile.getDependency(), zipFile, modpack, ((ServerModpackManifest) modpack.getManifest()), name)
|
||||||
.whenComplete(Schedulers.defaultScheduler(), success, failure);
|
.whenComplete(Schedulers.defaultScheduler(), success, failure);
|
||||||
else throw new IllegalArgumentException("Unrecognized modpack: " + modpack.getManifest());
|
else throw new IllegalArgumentException("Unrecognized modpack: " + modpack.getManifest());
|
||||||
}
|
}
|
||||||
|
@ -48,7 +48,7 @@ import java.util.Optional;
|
|||||||
import static org.jackhuang.hmcl.util.Lang.tryCast;
|
import static org.jackhuang.hmcl.util.Lang.tryCast;
|
||||||
import static org.jackhuang.hmcl.util.i18n.I18n.i18n;
|
import static org.jackhuang.hmcl.util.i18n.I18n.i18n;
|
||||||
|
|
||||||
public final class ModpackPage extends StackPane implements WizardPage {
|
public final class LocalModpackPage extends StackPane implements WizardPage {
|
||||||
private final WizardController controller;
|
private final WizardController controller;
|
||||||
|
|
||||||
private Modpack manifest = null;
|
private Modpack manifest = null;
|
||||||
@ -77,7 +77,7 @@ public final class ModpackPage extends StackPane implements WizardPage {
|
|||||||
@FXML
|
@FXML
|
||||||
private SpinnerPane spinnerPane;
|
private SpinnerPane spinnerPane;
|
||||||
|
|
||||||
public ModpackPage(WizardController controller) {
|
public LocalModpackPage(WizardController controller) {
|
||||||
this.controller = controller;
|
this.controller = controller;
|
||||||
|
|
||||||
FXUtils.loadFXML(this, "/assets/fxml/download/modpack.fxml");
|
FXUtils.loadFXML(this, "/assets/fxml/download/modpack.fxml");
|
@ -23,6 +23,7 @@ import org.jackhuang.hmcl.mod.curse.CurseCompletionException;
|
|||||||
import org.jackhuang.hmcl.mod.MismatchedModpackTypeException;
|
import org.jackhuang.hmcl.mod.MismatchedModpackTypeException;
|
||||||
import org.jackhuang.hmcl.mod.Modpack;
|
import org.jackhuang.hmcl.mod.Modpack;
|
||||||
import org.jackhuang.hmcl.mod.UnsupportedModpackException;
|
import org.jackhuang.hmcl.mod.UnsupportedModpackException;
|
||||||
|
import org.jackhuang.hmcl.mod.server.ServerModpackManifest;
|
||||||
import org.jackhuang.hmcl.setting.Profile;
|
import org.jackhuang.hmcl.setting.Profile;
|
||||||
import org.jackhuang.hmcl.task.Schedulers;
|
import org.jackhuang.hmcl.task.Schedulers;
|
||||||
import org.jackhuang.hmcl.task.Task;
|
import org.jackhuang.hmcl.task.Task;
|
||||||
@ -65,22 +66,24 @@ public class ModpackInstallWizardProvider implements WizardProvider {
|
|||||||
@Override
|
@Override
|
||||||
public void start(Map<String, Object> settings) {
|
public void start(Map<String, Object> settings) {
|
||||||
if (file != null)
|
if (file != null)
|
||||||
settings.put(ModpackPage.MODPACK_FILE, file);
|
settings.put(LocalModpackPage.MODPACK_FILE, file);
|
||||||
if (updateVersion != null)
|
if (updateVersion != null)
|
||||||
settings.put(ModpackPage.MODPACK_NAME, updateVersion);
|
settings.put(LocalModpackPage.MODPACK_NAME, updateVersion);
|
||||||
settings.put(PROFILE, profile);
|
settings.put(PROFILE, profile);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Task<Void> finishModpackInstallingAsync(Map<String, Object> settings) {
|
private Task<Void> finishModpackInstallingAsync(Map<String, Object> settings) {
|
||||||
if (!settings.containsKey(ModpackPage.MODPACK_FILE))
|
File selected = tryCast(settings.get(LocalModpackPage.MODPACK_FILE), File.class).orElse(null);
|
||||||
return null;
|
ServerModpackManifest serverModpackManifest = tryCast(settings.get(RemoteModpackPage.MODPACK_SERVER_MANIFEST), ServerModpackManifest.class).orElse(null);
|
||||||
|
Modpack modpack = tryCast(settings.get(LocalModpackPage.MODPACK_MANIFEST), Modpack.class).orElse(null);
|
||||||
File selected = tryCast(settings.get(ModpackPage.MODPACK_FILE), File.class).orElse(null);
|
String name = tryCast(settings.get(LocalModpackPage.MODPACK_NAME), String.class).orElse(null);
|
||||||
Modpack modpack = tryCast(settings.get(ModpackPage.MODPACK_MANIFEST), Modpack.class).orElse(null);
|
if ((selected == null && serverModpackManifest == null) || modpack == null || name == null) return null;
|
||||||
String name = tryCast(settings.get(ModpackPage.MODPACK_NAME), String.class).orElse(null);
|
|
||||||
if (selected == null || modpack == null || name == null) return null;
|
|
||||||
|
|
||||||
if (updateVersion != null) {
|
if (updateVersion != null) {
|
||||||
|
if (selected == null) {
|
||||||
|
Controllers.dialog(i18n("modpack.unsupported"), i18n("message.error"), MessageType.ERROR);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
try {
|
try {
|
||||||
return ModpackHelper.getUpdateTask(profile, selected, modpack.getEncoding(), name, ModpackHelper.readModpackConfiguration(profile.getRepository().getModpackConfiguration(name)));
|
return ModpackHelper.getUpdateTask(profile, selected, modpack.getEncoding(), name, ModpackHelper.readModpackConfiguration(profile.getRepository().getModpackConfiguration(name)));
|
||||||
} catch (UnsupportedModpackException e) {
|
} catch (UnsupportedModpackException e) {
|
||||||
@ -92,8 +95,13 @@ public class ModpackInstallWizardProvider implements WizardProvider {
|
|||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
} else {
|
} else {
|
||||||
return ModpackHelper.getInstallTask(profile, selected, name, modpack)
|
if (serverModpackManifest != null) {
|
||||||
.thenRunAsync(Schedulers.javafx(), () -> profile.setSelectedVersion(name));
|
return ModpackHelper.getInstallTask(profile, serverModpackManifest, name, modpack)
|
||||||
|
.thenRunAsync(Schedulers.javafx(), () -> profile.setSelectedVersion(name));
|
||||||
|
} else {
|
||||||
|
return ModpackHelper.getInstallTask(profile, selected, name, modpack)
|
||||||
|
.thenRunAsync(Schedulers.javafx(), () -> profile.setSelectedVersion(name));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -124,7 +132,12 @@ public class ModpackInstallWizardProvider implements WizardProvider {
|
|||||||
case 0:
|
case 0:
|
||||||
return new ModpackSelectionPage(controller);
|
return new ModpackSelectionPage(controller);
|
||||||
case 1:
|
case 1:
|
||||||
return new ModpackPage(controller);
|
if (controller.getSettings().containsKey(LocalModpackPage.MODPACK_FILE))
|
||||||
|
return new LocalModpackPage(controller);
|
||||||
|
else if (controller.getSettings().containsKey(RemoteModpackPage.MODPACK_SERVER_MANIFEST))
|
||||||
|
return new RemoteModpackPage(controller);
|
||||||
|
else
|
||||||
|
throw new IllegalArgumentException();
|
||||||
default:
|
default:
|
||||||
throw new IllegalStateException("error step " + step + ", settings: " + settings + ", pages: " + controller.getPages());
|
throw new IllegalStateException("error step " + step + ", settings: " + settings + ", pages: " + controller.getPages());
|
||||||
}
|
}
|
||||||
|
@ -22,12 +22,15 @@ import javafx.application.Platform;
|
|||||||
import javafx.fxml.FXML;
|
import javafx.fxml.FXML;
|
||||||
import javafx.scene.layout.StackPane;
|
import javafx.scene.layout.StackPane;
|
||||||
import javafx.stage.FileChooser;
|
import javafx.stage.FileChooser;
|
||||||
|
import org.jackhuang.hmcl.mod.server.ServerModpackManifest;
|
||||||
import org.jackhuang.hmcl.task.FileDownloadTask;
|
import org.jackhuang.hmcl.task.FileDownloadTask;
|
||||||
|
import org.jackhuang.hmcl.task.GetTask;
|
||||||
import org.jackhuang.hmcl.task.Schedulers;
|
import org.jackhuang.hmcl.task.Schedulers;
|
||||||
import org.jackhuang.hmcl.ui.Controllers;
|
import org.jackhuang.hmcl.ui.Controllers;
|
||||||
import org.jackhuang.hmcl.ui.FXUtils;
|
import org.jackhuang.hmcl.ui.FXUtils;
|
||||||
import org.jackhuang.hmcl.ui.wizard.WizardController;
|
import org.jackhuang.hmcl.ui.wizard.WizardController;
|
||||||
import org.jackhuang.hmcl.ui.wizard.WizardPage;
|
import org.jackhuang.hmcl.ui.wizard.WizardPage;
|
||||||
|
import org.jackhuang.hmcl.util.gson.JsonUtils;
|
||||||
import org.jackhuang.hmcl.util.io.FileUtils;
|
import org.jackhuang.hmcl.util.io.FileUtils;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
@ -38,7 +41,8 @@ import java.nio.file.Path;
|
|||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
|
||||||
import static org.jackhuang.hmcl.ui.download.ModpackPage.MODPACK_FILE;
|
import static org.jackhuang.hmcl.ui.download.LocalModpackPage.*;
|
||||||
|
import static org.jackhuang.hmcl.ui.download.RemoteModpackPage.MODPACK_SERVER_MANIFEST;
|
||||||
import static org.jackhuang.hmcl.util.Lang.tryCast;
|
import static org.jackhuang.hmcl.util.Lang.tryCast;
|
||||||
import static org.jackhuang.hmcl.util.i18n.I18n.i18n;
|
import static org.jackhuang.hmcl.util.i18n.I18n.i18n;
|
||||||
|
|
||||||
@ -85,22 +89,40 @@ public final class ModpackSelectionPage extends StackPane implements WizardPage
|
|||||||
Controllers.inputDialog(i18n("modpack.choose.remote.tooltip"), (urlString, resolve, reject) -> {
|
Controllers.inputDialog(i18n("modpack.choose.remote.tooltip"), (urlString, resolve, reject) -> {
|
||||||
try {
|
try {
|
||||||
URL url = new URL(urlString);
|
URL url = new URL(urlString);
|
||||||
Path modpack = Files.createTempFile("forge-installer", ".jar");
|
if (urlString.endsWith("server-manifest.json")) {
|
||||||
resolve.run();
|
// if urlString ends with .json, we assume that the url is server-manifest.json
|
||||||
|
Controllers.taskDialog(new GetTask(url).whenComplete(Schedulers.javafx(), (result, e) -> {
|
||||||
|
ServerModpackManifest manifest = JsonUtils.fromMaybeMalformedJson(result, ServerModpackManifest.class);
|
||||||
|
if (manifest == null) {
|
||||||
|
reject.accept(i18n("modpack.type.server.malformed"));
|
||||||
|
} else if (e == null) {
|
||||||
|
resolve.run();
|
||||||
|
controller.getSettings().put(MODPACK_SERVER_MANIFEST, manifest);
|
||||||
|
controller.onNext();
|
||||||
|
} else {
|
||||||
|
reject.accept(e.getMessage());
|
||||||
|
}
|
||||||
|
}).executor(true), i18n("message.downloading"));
|
||||||
|
} else {
|
||||||
|
// otherwise we still consider the file as modpack zip file
|
||||||
|
// since casually the url may not ends with ".zip"
|
||||||
|
Path modpack = Files.createTempFile("modpack", ".zip");
|
||||||
|
resolve.run();
|
||||||
|
|
||||||
Controllers.taskDialog(
|
Controllers.taskDialog(
|
||||||
new FileDownloadTask(url, modpack.toFile(), null)
|
new FileDownloadTask(url, modpack.toFile(), null)
|
||||||
.whenComplete(Schedulers.javafx(), e -> {
|
.whenComplete(Schedulers.javafx(), e -> {
|
||||||
if (e == null) {
|
if (e == null) {
|
||||||
resolve.run();
|
resolve.run();
|
||||||
controller.getSettings().put(MODPACK_FILE, modpack.toFile());
|
controller.getSettings().put(MODPACK_FILE, modpack.toFile());
|
||||||
controller.onNext();
|
controller.onNext();
|
||||||
} else {
|
} else {
|
||||||
reject.accept(e.getMessage());
|
reject.accept(e.getMessage());
|
||||||
}
|
}
|
||||||
}).executor(true),
|
}).executor(true),
|
||||||
i18n("message.downloading")
|
i18n("message.downloading")
|
||||||
);
|
);
|
||||||
|
}
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
reject.accept(e.getMessage());
|
reject.accept(e.getMessage());
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,150 @@
|
|||||||
|
/*
|
||||||
|
* Hello Minecraft! Launcher
|
||||||
|
* Copyright (C) 2019 huangyuhui <huanghongxun2008@126.com> and contributors
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package org.jackhuang.hmcl.ui.download;
|
||||||
|
|
||||||
|
import com.jfoenix.controls.JFXButton;
|
||||||
|
import com.jfoenix.controls.JFXTextField;
|
||||||
|
import javafx.application.Platform;
|
||||||
|
import javafx.fxml.FXML;
|
||||||
|
import javafx.scene.control.Label;
|
||||||
|
import javafx.scene.layout.Region;
|
||||||
|
import javafx.scene.layout.StackPane;
|
||||||
|
import javafx.stage.FileChooser;
|
||||||
|
import org.jackhuang.hmcl.game.ModpackHelper;
|
||||||
|
import org.jackhuang.hmcl.mod.Modpack;
|
||||||
|
import org.jackhuang.hmcl.mod.server.ServerModpackManifest;
|
||||||
|
import org.jackhuang.hmcl.setting.Profile;
|
||||||
|
import org.jackhuang.hmcl.task.Schedulers;
|
||||||
|
import org.jackhuang.hmcl.task.Task;
|
||||||
|
import org.jackhuang.hmcl.ui.Controllers;
|
||||||
|
import org.jackhuang.hmcl.ui.FXUtils;
|
||||||
|
import org.jackhuang.hmcl.ui.WebStage;
|
||||||
|
import org.jackhuang.hmcl.ui.construct.MessageDialogPane;
|
||||||
|
import org.jackhuang.hmcl.ui.construct.SpinnerPane;
|
||||||
|
import org.jackhuang.hmcl.ui.construct.Validator;
|
||||||
|
import org.jackhuang.hmcl.ui.wizard.WizardController;
|
||||||
|
import org.jackhuang.hmcl.ui.wizard.WizardPage;
|
||||||
|
import org.jackhuang.hmcl.util.StringUtils;
|
||||||
|
import org.jackhuang.hmcl.util.gson.JsonUtils;
|
||||||
|
import org.jackhuang.hmcl.util.io.CompressingUtils;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
|
import static org.jackhuang.hmcl.util.Lang.tryCast;
|
||||||
|
import static org.jackhuang.hmcl.util.i18n.I18n.i18n;
|
||||||
|
|
||||||
|
public class RemoteModpackPage extends StackPane implements WizardPage {
|
||||||
|
private final WizardController controller;
|
||||||
|
|
||||||
|
private final ServerModpackManifest manifest;
|
||||||
|
|
||||||
|
@FXML
|
||||||
|
private Region borderPane;
|
||||||
|
|
||||||
|
@FXML
|
||||||
|
private Label lblName;
|
||||||
|
|
||||||
|
@FXML
|
||||||
|
private Label lblVersion;
|
||||||
|
|
||||||
|
@FXML
|
||||||
|
private Label lblAuthor;
|
||||||
|
|
||||||
|
@FXML
|
||||||
|
private Label lblModpackLocation;
|
||||||
|
|
||||||
|
@FXML
|
||||||
|
private JFXTextField txtModpackName;
|
||||||
|
|
||||||
|
@FXML
|
||||||
|
private JFXButton btnInstall;
|
||||||
|
|
||||||
|
@FXML
|
||||||
|
private SpinnerPane spinnerPane;
|
||||||
|
|
||||||
|
public RemoteModpackPage(WizardController controller) {
|
||||||
|
this.controller = controller;
|
||||||
|
|
||||||
|
FXUtils.loadFXML(this, "/assets/fxml/download/modpack.fxml");
|
||||||
|
|
||||||
|
Profile profile = (Profile) controller.getSettings().get("PROFILE");
|
||||||
|
|
||||||
|
Optional<String> name = tryCast(controller.getSettings().get(MODPACK_NAME), String.class);
|
||||||
|
if (name.isPresent()) {
|
||||||
|
txtModpackName.setText(name.get());
|
||||||
|
txtModpackName.setDisable(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
manifest = tryCast(controller.getSettings().get(MODPACK_SERVER_MANIFEST), ServerModpackManifest.class)
|
||||||
|
.orElseThrow(() -> new IllegalStateException("MODPACK_SERVER_MANIFEST should exist"));
|
||||||
|
lblModpackLocation.setText(manifest.getFileApi());
|
||||||
|
|
||||||
|
try {
|
||||||
|
controller.getSettings().put(MODPACK_MANIFEST, manifest.toModpack(null));
|
||||||
|
} catch (IOException e) {
|
||||||
|
Controllers.dialog(i18n("modpack.type.server.malformed"), i18n("message.error"), MessageDialogPane.MessageType.ERROR);
|
||||||
|
Platform.runLater(controller::onEnd);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
lblName.setText(manifest.getName());
|
||||||
|
lblVersion.setText(manifest.getVersion());
|
||||||
|
lblAuthor.setText(manifest.getAuthor());
|
||||||
|
|
||||||
|
if (!name.isPresent()) {
|
||||||
|
txtModpackName.setText(manifest.getName() + (StringUtils.isBlank(manifest.getVersion()) ? "" : "-" + manifest.getVersion()));
|
||||||
|
txtModpackName.getValidators().addAll(
|
||||||
|
new Validator(i18n("install.new_game.already_exists"), str -> !profile.getRepository().hasVersion(str) && StringUtils.isNotBlank(str)),
|
||||||
|
new Validator(i18n("version.forbidden_name"), str -> !profile.getRepository().forbidsVersion(str))
|
||||||
|
);
|
||||||
|
txtModpackName.textProperty().addListener(e -> btnInstall.setDisable(!txtModpackName.validate()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void cleanup(Map<String, Object> settings) {
|
||||||
|
settings.remove(MODPACK_SERVER_MANIFEST);
|
||||||
|
}
|
||||||
|
|
||||||
|
@FXML
|
||||||
|
private void onInstall() {
|
||||||
|
if (!txtModpackName.validate()) return;
|
||||||
|
controller.getSettings().put(MODPACK_NAME, txtModpackName.getText());
|
||||||
|
controller.onFinish();
|
||||||
|
}
|
||||||
|
|
||||||
|
@FXML
|
||||||
|
private void onDescribe() {
|
||||||
|
WebStage stage = new WebStage();
|
||||||
|
stage.getWebView().getEngine().loadContent(manifest.getDescription());
|
||||||
|
stage.setTitle(i18n("modpack.description"));
|
||||||
|
stage.showAndWait();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getTitle() {
|
||||||
|
return i18n("modpack.task.install");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final String MODPACK_SERVER_MANIFEST = "MODPACK_SERVER_MANIFEST";
|
||||||
|
public static final String MODPACK_NAME = "MODPACK_NAME";
|
||||||
|
public static final String MODPACK_MANIFEST = "MODPACK_MANIFEST";
|
||||||
|
}
|
@ -264,6 +264,7 @@ modpack.type.multimc=MultiMC
|
|||||||
modpack.type.multimc.export=Can be imported by Hello Minecraft! Launcher and MultiMC
|
modpack.type.multimc.export=Can be imported by Hello Minecraft! Launcher and MultiMC
|
||||||
modpack.type.server=Server Auto-Update Modpack
|
modpack.type.server=Server Auto-Update Modpack
|
||||||
modpack.type.server.export=Allow server manager updating game client remotely
|
modpack.type.server.export=Allow server manager updating game client remotely
|
||||||
|
modpack.type.server.malformed=Malformed server modpack manifest
|
||||||
modpack.unsupported=Unsupported modpack, only HMCL, MultiMC, and Curse modpacks are supported.
|
modpack.unsupported=Unsupported modpack, only HMCL, MultiMC, and Curse modpacks are supported.
|
||||||
modpack.update=Game Update
|
modpack.update=Game Update
|
||||||
modpack.wizard=Exporting modpack wizard
|
modpack.wizard=Exporting modpack wizard
|
||||||
|
@ -201,6 +201,7 @@ login.enter_password=請輸入您的密碼
|
|||||||
logwindow.show_lines=顯示行數
|
logwindow.show_lines=顯示行數
|
||||||
logwindow.terminate_game=結束遊戲執行程序
|
logwindow.terminate_game=結束遊戲執行程序
|
||||||
logwindow.title=記錄
|
logwindow.title=記錄
|
||||||
|
logwindow.autoscroll=自動滾動
|
||||||
|
|
||||||
main_page=首頁
|
main_page=首頁
|
||||||
|
|
||||||
@ -261,6 +262,7 @@ modpack.type.multimc=MultiMC
|
|||||||
modpack.type.multimc.export=可以被 Hello Minecraft! Launcher (HMCL) 和 MultiMC 導入
|
modpack.type.multimc.export=可以被 Hello Minecraft! Launcher (HMCL) 和 MultiMC 導入
|
||||||
modpack.type.server=伺服器自動更新整合包
|
modpack.type.server=伺服器自動更新整合包
|
||||||
modpack.type.server.export=允許伺服器管理員遠程更新遊戲用戶端
|
modpack.type.server.export=允許伺服器管理員遠程更新遊戲用戶端
|
||||||
|
modpack.type.server.malformed=伺服器整合包配置格式錯誤,請聯絡伺服器管理員解決此問題
|
||||||
modpack.unsupported=不支援該整合包。僅 HMCL、MultiMC、Curse 整合包受支援。
|
modpack.unsupported=不支援該整合包。僅 HMCL、MultiMC、Curse 整合包受支援。
|
||||||
modpack.update=正在升級整合包
|
modpack.update=正在升級整合包
|
||||||
modpack.wizard=匯出整合包引導
|
modpack.wizard=匯出整合包引導
|
||||||
|
@ -202,6 +202,7 @@ login.enter_password=请输入您的密码
|
|||||||
logwindow.show_lines=显示行数
|
logwindow.show_lines=显示行数
|
||||||
logwindow.terminate_game=结束游戏进程
|
logwindow.terminate_game=结束游戏进程
|
||||||
logwindow.title=日志
|
logwindow.title=日志
|
||||||
|
logwindow.autoscroll=自动滚动
|
||||||
|
|
||||||
main_page=主页
|
main_page=主页
|
||||||
|
|
||||||
@ -262,6 +263,7 @@ modpack.type.multimc=MultiMC
|
|||||||
modpack.type.multimc.export=可以被 Hello Minecraft! Launcher (HMCL) 和 MultiMC 导入
|
modpack.type.multimc.export=可以被 Hello Minecraft! Launcher (HMCL) 和 MultiMC 导入
|
||||||
modpack.type.server=服务器自动更新整合包
|
modpack.type.server=服务器自动更新整合包
|
||||||
modpack.type.server.export=允许服务器管理员远程更新游戏客户端
|
modpack.type.server.export=允许服务器管理员远程更新游戏客户端
|
||||||
|
modpack.type.server.malformed=服务器整合包配置格式错误,请联系服务器管理员解决此问题
|
||||||
modpack.unsupported=该整合包不被支持。仅 HMCL、MultiMC、Curse 整合包受支持。
|
modpack.unsupported=该整合包不被支持。仅 HMCL、MultiMC、Curse 整合包受支持。
|
||||||
modpack.update=正在升级整合包
|
modpack.update=正在升级整合包
|
||||||
modpack.wizard=导出整合包向导
|
modpack.wizard=导出整合包向导
|
||||||
|
@ -29,6 +29,7 @@ import org.jackhuang.hmcl.util.Logging;
|
|||||||
import org.jackhuang.hmcl.util.StringUtils;
|
import org.jackhuang.hmcl.util.StringUtils;
|
||||||
import org.jackhuang.hmcl.util.gson.JsonUtils;
|
import org.jackhuang.hmcl.util.gson.JsonUtils;
|
||||||
import org.jackhuang.hmcl.util.io.FileUtils;
|
import org.jackhuang.hmcl.util.io.FileUtils;
|
||||||
|
import org.jackhuang.hmcl.util.io.NetworkUtils;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
@ -53,16 +54,25 @@ public class ServerModpackCompletionTask extends Task<Void> {
|
|||||||
private final List<Task<?>> dependencies = new LinkedList<>();
|
private final List<Task<?>> dependencies = new LinkedList<>();
|
||||||
|
|
||||||
public ServerModpackCompletionTask(DefaultDependencyManager dependencyManager, String version) {
|
public ServerModpackCompletionTask(DefaultDependencyManager dependencyManager, String version) {
|
||||||
|
this(dependencyManager, version, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ServerModpackCompletionTask(DefaultDependencyManager dependencyManager, String version, ModpackConfiguration<ServerModpackManifest> manifest) {
|
||||||
this.repository = dependencyManager.getGameRepository();
|
this.repository = dependencyManager.getGameRepository();
|
||||||
this.version = version;
|
this.version = version;
|
||||||
|
|
||||||
try {
|
if (manifest == null) {
|
||||||
File manifestFile = repository.getModpackConfiguration(version);
|
try {
|
||||||
if (manifestFile.exists())
|
File manifestFile = repository.getModpackConfiguration(version);
|
||||||
this.manifest = JsonUtils.GSON.fromJson(FileUtils.readText(manifestFile), new TypeToken<ModpackConfiguration<ServerModpackManifest>>() {
|
if (manifestFile.exists()) {
|
||||||
}.getType());
|
this.manifest = JsonUtils.GSON.fromJson(FileUtils.readText(manifestFile), new TypeToken<ModpackConfiguration<ServerModpackManifest>>() {
|
||||||
} catch (Exception e) {
|
}.getType());
|
||||||
Logging.LOG.log(Level.WARNING, "Unable to read CurseForge modpack manifest.json", e);
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
Logging.LOG.log(Level.WARNING, "Unable to read CurseForge modpack manifest.json", e);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
this.manifest = manifest;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -125,7 +135,7 @@ public class ServerModpackCompletionTask extends Task<Void> {
|
|||||||
|
|
||||||
if (download) {
|
if (download) {
|
||||||
dependencies.add(new FileDownloadTask(
|
dependencies.add(new FileDownloadTask(
|
||||||
new URL(remoteManifest.getFileApi() + "/overrides/" + file.getPath()),
|
new URL(remoteManifest.getFileApi() + "/overrides/" + NetworkUtils.encodeLocation(file.getPath())),
|
||||||
actualPath.toFile(),
|
actualPath.toFile(),
|
||||||
new FileDownloadTask.IntegrityCheck("SHA-1", file.getHash())));
|
new FileDownloadTask.IntegrityCheck("SHA-1", file.getHash())));
|
||||||
}
|
}
|
||||||
|
@ -35,7 +35,7 @@ import java.io.IOException;
|
|||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public class ServerModpackInstallTask extends Task<Void> {
|
public class ServerModpackLocalInstallTask extends Task<Void> {
|
||||||
|
|
||||||
private final File zipFile;
|
private final File zipFile;
|
||||||
private final Modpack modpack;
|
private final Modpack modpack;
|
||||||
@ -45,7 +45,7 @@ public class ServerModpackInstallTask extends Task<Void> {
|
|||||||
private final List<Task<?>> dependencies = new LinkedList<>();
|
private final List<Task<?>> dependencies = new LinkedList<>();
|
||||||
private final List<Task<?>> dependents = new LinkedList<>();
|
private final List<Task<?>> dependents = new LinkedList<>();
|
||||||
|
|
||||||
public ServerModpackInstallTask(DefaultDependencyManager dependencyManager, File zipFile, Modpack modpack, ServerModpackManifest manifest, String name) {
|
public ServerModpackLocalInstallTask(DefaultDependencyManager dependencyManager, File zipFile, Modpack modpack, ServerModpackManifest manifest, String name) {
|
||||||
this.zipFile = zipFile;
|
this.zipFile = zipFile;
|
||||||
this.modpack = modpack;
|
this.modpack = modpack;
|
||||||
this.manifest = manifest;
|
this.manifest = manifest;
|
||||||
@ -75,7 +75,7 @@ public class ServerModpackInstallTask extends Task<Void> {
|
|||||||
}.getType());
|
}.getType());
|
||||||
|
|
||||||
if (!MODPACK_TYPE.equals(config.getType()))
|
if (!MODPACK_TYPE.equals(config.getType()))
|
||||||
throw new IllegalArgumentException("Version " + name + " is not a Curse modpack. Cannot update this version.");
|
throw new IllegalArgumentException("Version " + name + " is not a Server modpack. Cannot update this version.");
|
||||||
}
|
}
|
||||||
} catch (JsonParseException | IOException ignore) {
|
} catch (JsonParseException | IOException ignore) {
|
||||||
}
|
}
|
@ -114,6 +114,12 @@ public class ServerModpackManifest implements Validation {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Modpack toModpack(Charset encoding) throws IOException {
|
||||||
|
String gameVersion = addons.stream().filter(x -> MINECRAFT.getPatchId().equals(x.id)).findAny()
|
||||||
|
.orElseThrow(() -> new IOException("Cannot find game version")).getVersion();
|
||||||
|
return new Modpack(name, author, version, gameVersion, description, encoding, this);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param zip the CurseForge modpack file.
|
* @param zip the CurseForge modpack file.
|
||||||
* @throws IOException if the file is not a valid zip file.
|
* @throws IOException if the file is not a valid zip file.
|
||||||
@ -123,7 +129,6 @@ public class ServerModpackManifest implements Validation {
|
|||||||
public static Modpack readManifest(Path zip, Charset encoding) throws IOException, JsonParseException {
|
public static Modpack readManifest(Path zip, Charset encoding) throws IOException, JsonParseException {
|
||||||
String json = CompressingUtils.readTextZipEntry(zip, "server-manifest.json", encoding);
|
String json = CompressingUtils.readTextZipEntry(zip, "server-manifest.json", encoding);
|
||||||
ServerModpackManifest manifest = JsonUtils.fromNonNullJson(json, ServerModpackManifest.class);
|
ServerModpackManifest manifest = JsonUtils.fromNonNullJson(json, ServerModpackManifest.class);
|
||||||
String gameVersion = manifest.getAddons().stream().filter(x -> MINECRAFT.getPatchId().equals(x.getId())).findAny().orElseThrow(() -> new IOException("Cannot find game version")).getVersion();
|
return manifest.toModpack(encoding);
|
||||||
return new Modpack(manifest.getName(), manifest.getAuthor(), manifest.getVersion(), gameVersion, manifest.getDescription(), encoding, manifest);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,98 @@
|
|||||||
|
/*
|
||||||
|
* Hello Minecraft! Launcher
|
||||||
|
* Copyright (C) 2019 huangyuhui <huanghongxun2008@126.com> and contributors
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package org.jackhuang.hmcl.mod.server;
|
||||||
|
|
||||||
|
import com.google.gson.JsonParseException;
|
||||||
|
import com.google.gson.reflect.TypeToken;
|
||||||
|
import org.jackhuang.hmcl.download.DefaultDependencyManager;
|
||||||
|
import org.jackhuang.hmcl.download.GameBuilder;
|
||||||
|
import org.jackhuang.hmcl.game.DefaultGameRepository;
|
||||||
|
import org.jackhuang.hmcl.mod.MinecraftInstanceTask;
|
||||||
|
import org.jackhuang.hmcl.mod.Modpack;
|
||||||
|
import org.jackhuang.hmcl.mod.ModpackConfiguration;
|
||||||
|
import org.jackhuang.hmcl.mod.ModpackInstallTask;
|
||||||
|
import org.jackhuang.hmcl.task.Task;
|
||||||
|
import org.jackhuang.hmcl.util.gson.JsonUtils;
|
||||||
|
import org.jackhuang.hmcl.util.io.FileUtils;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.LinkedList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class ServerModpackRemoteInstallTask extends Task<Void> {
|
||||||
|
|
||||||
|
private final String name;
|
||||||
|
private final DefaultDependencyManager dependency;
|
||||||
|
private final DefaultGameRepository repository;
|
||||||
|
private final List<Task<?>> dependencies = new LinkedList<>();
|
||||||
|
private final List<Task<?>> dependents = new LinkedList<>();
|
||||||
|
private final ServerModpackManifest manifest;
|
||||||
|
|
||||||
|
public ServerModpackRemoteInstallTask(DefaultDependencyManager dependencyManager, ServerModpackManifest manifest, String name) {
|
||||||
|
this.name = name;
|
||||||
|
this.dependency = dependencyManager;
|
||||||
|
this.repository = dependencyManager.getGameRepository();
|
||||||
|
this.manifest = manifest;
|
||||||
|
|
||||||
|
File json = repository.getModpackConfiguration(name);
|
||||||
|
if (repository.hasVersion(name) && !json.exists())
|
||||||
|
throw new IllegalArgumentException("Version " + name + " already exists.");
|
||||||
|
|
||||||
|
GameBuilder builder = dependencyManager.gameBuilder().name(name);
|
||||||
|
for (ServerModpackManifest.Addon addon : manifest.getAddons()) {
|
||||||
|
builder.version(addon.getId(), addon.getVersion());
|
||||||
|
}
|
||||||
|
|
||||||
|
dependents.add(builder.buildAsync());
|
||||||
|
onDone().register(event -> {
|
||||||
|
if (event.isFailed())
|
||||||
|
repository.removeVersionFromDisk(name);
|
||||||
|
});
|
||||||
|
|
||||||
|
ModpackConfiguration<ServerModpackManifest> config = null;
|
||||||
|
try {
|
||||||
|
if (json.exists()) {
|
||||||
|
config = JsonUtils.GSON.fromJson(FileUtils.readText(json), new TypeToken<ModpackConfiguration<ServerModpackManifest>>() {
|
||||||
|
}.getType());
|
||||||
|
|
||||||
|
if (!MODPACK_TYPE.equals(config.getType()))
|
||||||
|
throw new IllegalArgumentException("Version " + name + " is not a Server modpack. Cannot update this version.");
|
||||||
|
}
|
||||||
|
} catch (JsonParseException | IOException ignore) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<Task<?>> getDependents() {
|
||||||
|
return dependents;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<Task<?>> getDependencies() {
|
||||||
|
return dependencies;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void execute() throws Exception {
|
||||||
|
dependencies.add(new ServerModpackCompletionTask(dependency, name, new ModpackConfiguration<>(manifest, MODPACK_TYPE, Collections.emptyList())));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final String MODPACK_TYPE = "Server";
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user