Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
import org.jackhuang.hmcl.ui.construct.NoneMultipleSelectionModel;
import org.jackhuang.hmcl.ui.wizard.WizardController;
import org.jackhuang.hmcl.ui.wizard.WizardPage;
import org.jackhuang.hmcl.util.Pair;
import org.jackhuang.hmcl.util.SettingsMap;
import org.jackhuang.hmcl.util.StringUtils;
import org.jackhuang.hmcl.util.io.FileUtils;
Expand All @@ -57,15 +58,15 @@ public final class ModpackFileSelectionPage extends BorderPane implements Wizard
private final WizardController controller;
private final String version;
private final ModAdviser adviser;
private final CheckBoxTreeItem<String> rootNode;
private final ModpackFileTreeItem rootNode;

public ModpackFileSelectionPage(WizardController controller, Profile profile, String version, ModAdviser adviser) {
this.controller = controller;
this.version = version;
this.adviser = adviser;

JFXTreeView<String> treeView = new JFXTreeView<>();
rootNode = getTreeItem(profile.getRepository().getRunDirectory(version), "minecraft");
rootNode = getTreeItem(profile.getRepository().getRunDirectory(version), "minecraft", 0);
treeView.setRoot(rootNode);
treeView.setSelectionModel(new NoneMultipleSelectionModel<>());
onEscPressed(treeView, () -> controller.onPrev(true));
Expand All @@ -86,7 +87,7 @@ public ModpackFileSelectionPage(WizardController controller, Profile profile, St
this.setBottom(nextPane);
}

private CheckBoxTreeItem<String> getTreeItem(Path file, String basePath) {
private ModpackFileTreeItem getTreeItem(Path file, String basePath, int level) {
if (Files.notExists(file))
return null;

Expand All @@ -110,20 +111,29 @@ private CheckBoxTreeItem<String> getTreeItem(Path file, String basePath) {
state = ModAdviser.ModSuggestion.HIDDEN;
}

if (isDirectory && fileName.equals(version + "-natives")) // Ignore <version>-natives
state = ModAdviser.ModSuggestion.HIDDEN;
if (isDirectory) {
if (fileName.equals(version + "-natives")) { // Ignore <version>-natives
state = ModAdviser.ModSuggestion.HIDDEN;
}
if (level == 1 && fileName.startsWith("natives-")) { // Ignore natives-os-arch
state = ModAdviser.ModSuggestion.HIDDEN;
}
}
if (state == ModAdviser.ModSuggestion.HIDDEN)
return null;
}

CheckBoxTreeItem<String> node = new CheckBoxTreeItem<>(StringUtils.substringAfterLast(basePath, "/"));
ModpackFileTreeItem node = new ModpackFileTreeItem(level == 0 ? version : StringUtils.substringAfterLast(basePath, '/'), basePath);
if (state == ModAdviser.ModSuggestion.SUGGESTED)
node.setSelected(true);

if (isDirectory) {
try (var stream = Files.list(file)) {
stream.forEach(it -> {
CheckBoxTreeItem<String> subNode = getTreeItem(it, basePath + "/" + FileUtils.getName(it));
stream.map(path -> Pair.pair(path, Files.isDirectory(path))).sorted((p1, p2) -> {
if (p1.value() == p2.value()) return p1.key().compareTo(p2.key());
return p1.value() ? -1 : 1;
}).map(Pair::key).forEach(it -> {
ModpackFileTreeItem subNode = getTreeItem(it, basePath + "/" + FileUtils.getName(it), level + 1);
if (subNode != null) {
node.setSelected(subNode.isSelected() || node.isSelected());
if (!subNode.isSelected()) {
Expand All @@ -144,33 +154,17 @@ private CheckBoxTreeItem<String> getTreeItem(Path file, String basePath) {
}
}

HBox graphic = new HBox();
JFXCheckBox checkBox = new JFXCheckBox();
checkBox.selectedProperty().bindBidirectional(node.selectedProperty());
checkBox.indeterminateProperty().bindBidirectional(node.indeterminateProperty());
graphic.getChildren().add(checkBox);

if (TRANSLATION.containsKey(basePath)) {
Label comment = new Label(TRANSLATION.get(basePath));
comment.setStyle("-fx-text-fill: -monet-on-surface-variant;");
comment.setMouseTransparent(true);
graphic.getChildren().add(comment);
}
graphic.setPickOnBounds(false);
node.setExpanded("minecraft".equals(basePath));
node.setGraphic(graphic);

return node;
}

private void getFilesNeeded(CheckBoxTreeItem<String> node, String basePath, List<String> list) {
private void getFilesNeeded(ModpackFileTreeItem node, String basePath, List<String> list) {
if (node == null) return;
if (node.isSelected() || node.isIndeterminate()) {
if (basePath.length() > "minecraft/".length())
list.add(StringUtils.substringAfter(basePath, "minecraft/"));
for (TreeItem<String> child : node.getChildren()) {
if (child instanceof CheckBoxTreeItem) {
getFilesNeeded(((CheckBoxTreeItem<String>) child), basePath + "/" + child.getValue(), list);
if (child instanceof ModpackFileTreeItem mChild) {
getFilesNeeded(mChild, basePath + "/" + mChild.getFileName(), list);
}
}
}
Expand Down Expand Up @@ -210,4 +204,40 @@ public String getTitle() {
pair("minecraft/blueprints", i18n("modpack.files.blueprints")),
pair("minecraft/scripts", i18n("modpack.files.scripts"))
);

private static final class ModpackFileTreeItem extends CheckBoxTreeItem<String> {

private final String fileName;

public ModpackFileTreeItem(String fileName, String basePath) {
this.fileName = fileName;

HBox graphic = new HBox();
JFXCheckBox checkBox = new JFXCheckBox();
checkBox.selectedProperty().bindBidirectional(this.selectedProperty());
checkBox.indeterminateProperty().bindBidirectional(this.indeterminateProperty());
graphic.getChildren().add(checkBox);

{
Label text = new Label(fileName);
text.setMouseTransparent(true);
graphic.getChildren().add(text);
}
if (TRANSLATION.containsKey(basePath)) {
Label comment = new Label(TRANSLATION.get(basePath));
comment.setStyle("-fx-text-fill: -monet-on-surface-variant;");
comment.setMouseTransparent(true);
graphic.getChildren().add(comment);
}
graphic.setPickOnBounds(false);
this.setExpanded("minecraft".equals(basePath));
this.setValue(""); // To disable the default display of text
this.setGraphic(graphic);
}

public String getFileName() {
return fileName;
}

}
}
6 changes: 3 additions & 3 deletions HMCLCore/src/main/java/org/jackhuang/hmcl/mod/ModAdviser.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@

import org.jackhuang.hmcl.util.Lang;

import java.io.File;
import java.util.List;

/**
Expand Down Expand Up @@ -74,7 +73,7 @@ enum ModSuggestion {
"optionsof.txt" /* OptiFine */,
"journeymap" /* JourneyMap */,
"optionsshaders.txt",
"mods" + File.separator + "VoxelMods");
"mods/VoxelMods");

static ModAdviser.ModSuggestion suggestMod(String fileName, boolean isDirectory) {
if (match(MODPACK_BLACK_LIST, fileName, isDirectory))
Expand All @@ -85,10 +84,11 @@ static ModAdviser.ModSuggestion suggestMod(String fileName, boolean isDirectory)
return ModAdviser.ModSuggestion.SUGGESTED;
}

/// @param fileName "fileName/" for directories and "fileName" for files, regardless of the operating system
static boolean match(List<String> l, String fileName, boolean isDirectory) {
for (String s : l)
if (isDirectory) {
if (fileName.startsWith(s + File.separator))
if (fileName.startsWith(s + '/'))
return true;
} else {
if (s.startsWith("regex:")) {
Expand Down
15 changes: 14 additions & 1 deletion HMCLCore/src/main/java/org/jackhuang/hmcl/mod/Modpack.java
Original file line number Diff line number Diff line change
Expand Up @@ -121,10 +121,23 @@ public Modpack setManifest(ModpackManifest manifest) {

public abstract Task<?> getInstallTask(DefaultDependencyManager dependencyManager, Path zipFile, String name, String iconUrl);

private static boolean match(List<String> l, String fileName) {
for (String s : l) {
if (s.startsWith("regex:")) {
if (fileName.matches(s.substring("regex:".length())))
return true;
} else {
if (fileName.equals(s))
return true;
}
}
return false;
}
Comment on lines +124 to +135
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

match 方法与 ModAdviser.match 的逻辑完全重复。既然 Modpack 已经依赖于 ModAdviser,建议删除此冗余方法,并直接调用 ModAdviser.match(blackList, path, false),以提高代码的可维护性。

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

故意拆出来的,防止出问题。本来就应该自己用自己的


public static boolean acceptFile(String path, List<String> blackList, List<String> whiteList) {
if (path.isEmpty())
return true;
if (ModAdviser.match(blackList, path, false))
if (match(blackList, path))
return false;
if (whiteList == null || whiteList.isEmpty())
return true;
Expand Down