2
0
mirror of https://github.com/HMCL-dev/HMCL.git synced 2025-04-12 18:30:26 +08:00

feat: display new version of updated modpack. Closes .

This commit is contained in:
yuhuihuang 2020-07-19 15:19:53 +08:00
parent d6859d1956
commit 4ce0a83845
15 changed files with 119 additions and 17 deletions

@ -77,7 +77,7 @@ public final class HMCLModpackInstallTask extends Task<Void> {
} catch (JsonParseException | IOException ignore) {
}
dependents.add(new ModpackInstallTask<>(zipFile, run, modpack.getEncoding(), "/minecraft", it -> !"pack.json".equals(it), config));
dependents.add(new MinecraftInstanceTask<>(zipFile, modpack.getEncoding(), "/minecraft", modpack, MODPACK_TYPE, repository.getModpackConfiguration(name)).withStage("hmcl.modpack"));
dependents.add(new MinecraftInstanceTask<>(zipFile, modpack.getEncoding(), "/minecraft", modpack, MODPACK_TYPE, modpack.getName(), modpack.getVersion(), repository.getModpackConfiguration(name)).withStage("hmcl.modpack"));
}
@Override

@ -17,15 +17,19 @@
*/
package org.jackhuang.hmcl.ui.construct;
import javafx.beans.binding.Bindings;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.scene.control.Label;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import org.jackhuang.hmcl.util.StringUtils;
public class TwoLineListItem extends VBox {
private static final String DEFAULT_STYLE_CLASS = "two-line-list-item";
private final StringProperty title = new SimpleStringProperty(this, "title");
private final StringProperty tag = new SimpleStringProperty(this, "tag");
private final StringProperty subtitle = new SimpleStringProperty(this, "subtitle");
public TwoLineListItem(String titleString, String subtitleString) {
@ -37,15 +41,28 @@ public class TwoLineListItem extends VBox {
public TwoLineListItem() {
setMouseTransparent(true);
HBox firstLine = new HBox();
Label lblTitle = new Label();
lblTitle.getStyleClass().add("title");
lblTitle.textProperty().bind(title);
Label lblTag = new Label();
lblTag.getStyleClass().add("tag");
lblTag.textProperty().bind(tag);
lblTag.visibleProperty().bind(Bindings.createBooleanBinding(
() -> StringUtils.isNotBlank(tag.getValue()),
tag));
firstLine.getChildren().addAll(lblTitle, lblTag);
Label lblSubtitle = new Label();
lblSubtitle.getStyleClass().add("subtitle");
lblSubtitle.textProperty().bind(subtitle);
getChildren().setAll(lblTitle, lblSubtitle);
getChildren().setAll(firstLine, lblSubtitle);
getStyleClass().add(DEFAULT_STYLE_CLASS);
}
@ -73,6 +90,18 @@ public class TwoLineListItem extends VBox {
this.subtitle.set(subtitle);
}
public String getTag() {
return tag.get();
}
public StringProperty tagProperty() {
return tag;
}
public void setTag(String tag) {
this.tag.set(tag);
}
@Override
public String toString() {
return getTitle();

@ -121,7 +121,7 @@ public final class LocalModpackPage extends StackPane implements WizardPage {
lblModpackLocation.setText(selectedFile.getAbsolutePath());
if (!name.isPresent()) {
txtModpackName.setText(manifest.getName() + (StringUtils.isBlank(manifest.getVersion()) ? "" : "-" + manifest.getVersion()));
txtModpackName.setText(manifest.getName());
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))

@ -101,7 +101,7 @@ public class RemoteModpackPage extends StackPane implements WizardPage {
lblAuthor.setText(manifest.getAuthor());
if (!name.isPresent()) {
txtModpackName.setText(manifest.getName() + (StringUtils.isBlank(manifest.getVersion()) ? "" : "-" + manifest.getVersion()));
txtModpackName.setText(manifest.getName());
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))

@ -27,16 +27,20 @@ import javafx.scene.control.Skin;
import javafx.scene.image.Image;
import org.jackhuang.hmcl.download.LibraryAnalyzer;
import org.jackhuang.hmcl.game.GameVersion;
import org.jackhuang.hmcl.mod.ModpackConfiguration;
import org.jackhuang.hmcl.setting.Profile;
import org.jackhuang.hmcl.util.i18n.I18n;
import java.io.IOException;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.logging.Level;
import static org.jackhuang.hmcl.download.LibraryAnalyzer.LibraryType.MINECRAFT;
import static org.jackhuang.hmcl.util.Lang.handleUncaught;
import static org.jackhuang.hmcl.util.Lang.threadPool;
import static org.jackhuang.hmcl.util.Logging.LOG;
import static org.jackhuang.hmcl.util.StringUtils.removePrefix;
import static org.jackhuang.hmcl.util.StringUtils.removeSuffix;
import static org.jackhuang.hmcl.util.i18n.I18n.i18n;
@ -48,6 +52,7 @@ public class GameItem extends Control {
private final Profile profile;
private final String version;
private final StringProperty title = new SimpleStringProperty();
private final StringProperty tag = new SimpleStringProperty();
private final StringProperty subtitle = new SimpleStringProperty();
private final ObjectProperty<Image> image = new SimpleObjectProperty<>();
@ -75,6 +80,17 @@ public class GameItem extends Control {
}, Platform::runLater)
.exceptionally(handleUncaught);
CompletableFuture.runAsync(() -> {
try {
ModpackConfiguration<Void> config = profile.getRepository().readModpackConfiguration(version);
if (config == null) return;
tag.set(config.getVersion());
} catch (IOException e) {
LOG.log(Level.WARNING, "Failed to read modpack configuration from ", e);
}
}, Platform::runLater)
.exceptionally(handleUncaught);
title.set(id);
image.set(profile.getRepository().getVersionIconImage(version));
}
@ -96,6 +112,10 @@ public class GameItem extends Control {
return title;
}
public StringProperty tagProperty() {
return tag;
}
public StringProperty subtitleProperty() {
return subtitle;
}

@ -45,6 +45,7 @@ public class GameItemSkin extends SkinBase<GameItem> {
TwoLineListItem item = new TwoLineListItem();
item.titleProperty().bind(skinnable.titleProperty());
item.tagProperty().bind(skinnable.tagProperty());
item.subtitleProperty().bind(skinnable.subtitleProperty());
BorderPane.setAlignment(item, Pos.CENTER);
center.getChildren().setAll(imageView, item);

@ -114,15 +114,26 @@
-fx-padding: 4 0 4 0;
}
.two-line-list-item > .title {
.two-line-list-item HBox {
-fx-spacing: 8;
-fx-alignment: center-left;
}
.two-line-list-item .title {
-fx-text-fill: #292929;
-fx-font-size: 15px;
}
.two-line-list-item > .subtitle {
.two-line-list-item .subtitle {
-fx-text-fill: rgba(0, 0, 0, 0.5);
}
.two-line-list-item .tag {
-fx-text-fill: -fx-base-color;
-fx-background-color: -fx-base-rippler-color;
-fx-padding: 2;
}
.bubble {
-fx-background-color: rgba(0, 0, 0, 0.5);
-fx-background-radius: 2px;

@ -18,6 +18,7 @@
package org.jackhuang.hmcl.game;
import com.google.gson.JsonParseException;
import com.google.gson.reflect.TypeToken;
import org.jackhuang.hmcl.download.MaintainTask;
import org.jackhuang.hmcl.download.game.VersionJsonSaveTask;
import org.jackhuang.hmcl.event.Event;
@ -29,11 +30,13 @@ import org.jackhuang.hmcl.event.RefreshingVersionsEvent;
import org.jackhuang.hmcl.event.RemoveVersionEvent;
import org.jackhuang.hmcl.event.RenameVersionEvent;
import org.jackhuang.hmcl.mod.ModManager;
import org.jackhuang.hmcl.mod.ModpackConfiguration;
import org.jackhuang.hmcl.task.Task;
import org.jackhuang.hmcl.util.Lang;
import org.jackhuang.hmcl.util.ToStringBuilder;
import org.jackhuang.hmcl.util.gson.JsonUtils;
import org.jackhuang.hmcl.util.io.FileUtils;
import org.jetbrains.annotations.Nullable;
import java.io.File;
import java.io.IOException;
@ -437,6 +440,22 @@ public class DefaultGameRepository implements GameRepository {
return new File(getVersionRoot(version), "modpack.json");
}
/**
* read modpack configuration for a version.
* @param version version installed as modpack
* @param <M> manifest type of ModpackConfiguration
* @return modpack configuration object, or null if this version is not a modpack.
* @throws VersionNotFoundException if version does not exist.
* @throws IOException if an i/o error occurs.
*/
@Nullable
public <M> ModpackConfiguration<M> readModpackConfiguration(String version) throws IOException, VersionNotFoundException {
if (!hasVersion(version)) throw new VersionNotFoundException(version);
File file = getModpackConfiguration(version);
if (!file.exists()) return null;
return JsonUtils.GSON.fromJson(FileUtils.readText(file), new TypeToken<ModpackConfiguration<M>>(){}.getType());
}
public boolean isModpack(String version) {
return getModpackConfiguration(version).exists();
}

@ -41,14 +41,18 @@ public final class MinecraftInstanceTask<T> extends Task<Void> {
private final File jsonFile;
private final T manifest;
private final String type;
private final String name;
private final String version;
public MinecraftInstanceTask(File zipFile, Charset encoding, String subDirectory, T manifest, String type, File jsonFile) {
public MinecraftInstanceTask(File zipFile, Charset encoding, String subDirectory, T manifest, String type, String name, String version, File jsonFile) {
this.zipFile = zipFile;
this.encoding = encoding;
this.subDirectory = FileUtils.normalizePath(subDirectory);
this.manifest = manifest;
this.jsonFile = jsonFile;
this.type = type;
this.name = name;
this.version = version;
}
@Override
@ -69,6 +73,6 @@ public final class MinecraftInstanceTask<T> extends Task<Void> {
});
}
FileUtils.writeText(jsonFile, JsonUtils.GSON.toJson(new ModpackConfiguration<>(manifest, type, overrides)));
FileUtils.writeText(jsonFile, JsonUtils.GSON.toJson(new ModpackConfiguration<>(manifest, type, name, version, overrides)));
}
}

@ -20,6 +20,7 @@ package org.jackhuang.hmcl.mod;
import com.google.gson.JsonParseException;
import org.jackhuang.hmcl.util.Immutable;
import org.jackhuang.hmcl.util.gson.Validation;
import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.Collections;
@ -30,15 +31,19 @@ public final class ModpackConfiguration<T> implements Validation {
private final T manifest;
private final String type;
private final String name;
private final String version;
private final List<FileInformation> overrides;
public ModpackConfiguration() {
this(null, null, Collections.emptyList());
this(null, null, "", null, Collections.emptyList());
}
public ModpackConfiguration(T manifest, String type, List<FileInformation> overrides) {
public ModpackConfiguration(T manifest, String type, String name, String version, List<FileInformation> overrides) {
this.manifest = manifest;
this.type = type;
this.name = name;
this.version = version;
this.overrides = new ArrayList<>(overrides);
}
@ -50,12 +55,25 @@ public final class ModpackConfiguration<T> implements Validation {
return type;
}
public String getName() {
return name;
}
@Nullable
public String getVersion() {
return version;
}
public ModpackConfiguration<T> setManifest(T manifest) {
return new ModpackConfiguration<>(manifest, type, overrides);
return new ModpackConfiguration<>(manifest, type, name, version, overrides);
}
public ModpackConfiguration<T> setOverrides(List<FileInformation> overrides) {
return new ModpackConfiguration<>(manifest, type, overrides);
return new ModpackConfiguration<>(manifest, type, name, version, overrides);
}
public ModpackConfiguration<T> setVersion(String version) {
return new ModpackConfiguration<>(manifest, type, name, version, overrides);
}
public List<FileInformation> getOverrides() {

@ -107,7 +107,7 @@ public final class CurseInstallTask extends Task<Void> {
}
this.config = config;
dependents.add(new ModpackInstallTask<>(zipFile, run, modpack.getEncoding(), manifest.getOverrides(), any -> true, config).withStage("hmcl.modpack"));
dependents.add(new MinecraftInstanceTask<>(zipFile, modpack.getEncoding(), manifest.getOverrides(), manifest, MODPACK_TYPE, repository.getModpackConfiguration(name)).withStage("hmcl.modpack"));
dependents.add(new MinecraftInstanceTask<>(zipFile, modpack.getEncoding(), manifest.getOverrides(), manifest, MODPACK_TYPE, manifest.getName(), manifest.getVersion(), repository.getModpackConfiguration(name)).withStage("hmcl.modpack"));
dependencies.add(new CurseCompletionTask(dependencyManager, name, manifest).withStage("hmcl.modpack.download"));
}

@ -131,7 +131,7 @@ public final class MultiMCModpackInstallTask extends Task<Void> {
dependents.add(new ModpackInstallTask<>(zipFile, run, modpack.getEncoding(), "/" + manifest.getName() + "/minecraft", any -> true, config).withStage("hmcl.modpack"));
}
dependents.add(new MinecraftInstanceTask<>(zipFile, modpack.getEncoding(), "/" + manifest.getName() + "/minecraft", manifest, MODPACK_TYPE, repository.getModpackConfiguration(name)).withStage("hmcl.modpack"));
dependents.add(new MinecraftInstanceTask<>(zipFile, modpack.getEncoding(), "/" + manifest.getName() + "/minecraft", manifest, MODPACK_TYPE, manifest.getName(), null, repository.getModpackConfiguration(name)).withStage("hmcl.modpack"));
}
@Override

@ -158,6 +158,6 @@ public class ServerModpackCompletionTask extends Task<Void> {
public void postExecute() throws Exception {
if (manifest == null || StringUtils.isBlank(manifest.getManifest().getFileApi())) return;
File manifestFile = repository.getModpackConfiguration(version);
FileUtils.writeText(manifestFile, JsonUtils.GSON.toJson(new ModpackConfiguration<>(remoteManifest, this.manifest.getType(), remoteManifest.getFiles())));
FileUtils.writeText(manifestFile, JsonUtils.GSON.toJson(new ModpackConfiguration<>(remoteManifest, this.manifest.getType(), this.manifest.getName(), this.manifest.getVersion(), remoteManifest.getFiles())));
}
}

@ -82,7 +82,7 @@ public class ServerModpackLocalInstallTask extends Task<Void> {
} catch (JsonParseException | IOException ignore) {
}
dependents.add(new ModpackInstallTask<>(zipFile, run, modpack.getEncoding(), "/overrides", any -> true, config).withStage("hmcl.modpack"));
dependents.add(new MinecraftInstanceTask<>(zipFile, modpack.getEncoding(), "/overrides", manifest, MODPACK_TYPE, repository.getModpackConfiguration(name)).withStage("hmcl.modpack"));
dependents.add(new MinecraftInstanceTask<>(zipFile, modpack.getEncoding(), "/overrides", manifest, MODPACK_TYPE, modpack.getName(), modpack.getVersion(), repository.getModpackConfiguration(name)).withStage("hmcl.modpack"));
}
@Override

@ -88,7 +88,7 @@ public class ServerModpackRemoteInstallTask extends Task<Void> {
@Override
public void execute() throws Exception {
dependencies.add(new ServerModpackCompletionTask(dependency, name, new ModpackConfiguration<>(manifest, MODPACK_TYPE, Collections.emptyList())));
dependencies.add(new ServerModpackCompletionTask(dependency, name, new ModpackConfiguration<>(manifest, MODPACK_TYPE, manifest.getName(), manifest.getVersion(), Collections.emptyList())));
}
public static final String MODPACK_TYPE = "Server";