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 FileUtils.getName(p1.key()).compareToIgnoreCase(FileUtils.getName(p2.key()));
return p1.value() ? -1 : 1;
}).map(Pair::key).forEach(it -> {
Comment thread
ToobLac marked this conversation as resolved.
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;
}

}
}
25 changes: 4 additions & 21 deletions HMCLCore/src/main/java/org/jackhuang/hmcl/mod/ModAdviser.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@
package org.jackhuang.hmcl.mod;

import org.jackhuang.hmcl.util.Lang;
import org.jackhuang.hmcl.util.io.FileUtils;

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

/**
Expand Down Expand Up @@ -74,31 +74,14 @@ 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))
if (FileUtils.match(MODPACK_BLACK_LIST, fileName, isDirectory))
return ModAdviser.ModSuggestion.HIDDEN;
if (match(MODPACK_SUGGESTED_BLACK_LIST, fileName, isDirectory))
if (FileUtils.match(MODPACK_SUGGESTED_BLACK_LIST, fileName, isDirectory))
return ModAdviser.ModSuggestion.NORMAL;
else
return ModAdviser.ModSuggestion.SUGGESTED;
}

static boolean match(List<String> l, String fileName, boolean isDirectory) {
for (String s : l)
if (isDirectory) {
if (fileName.startsWith(s + File.separator))
return true;
} else {
if (s.startsWith("regex:")) {
if (fileName.matches(s.substring("regex:".length())))
return true;
} else {
if (fileName.equals(s))
return true;
}
}
return false;
}
}
3 changes: 2 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 @@ -19,6 +19,7 @@

import org.jackhuang.hmcl.download.DefaultDependencyManager;
import org.jackhuang.hmcl.task.Task;
import org.jackhuang.hmcl.util.io.FileUtils;

import java.nio.charset.Charset;
import java.nio.file.Path;
Expand Down Expand Up @@ -124,7 +125,7 @@ public Modpack setManifest(ModpackManifest manifest) {
public static boolean acceptFile(String path, List<String> blackList, List<String> whiteList) {
if (path.isEmpty())
return true;
if (ModAdviser.match(blackList, path, false))
if (FileUtils.match(blackList, path, false))
return false;
if (whiteList == null || whiteList.isEmpty())
return true;
Expand Down
18 changes: 18 additions & 0 deletions HMCLCore/src/main/java/org/jackhuang/hmcl/util/io/FileUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -563,4 +563,22 @@ public static EnumSet<PosixFilePermission> parsePosixFilePermission(int unixMode

return permissions;
}

/// @param fileName must be "fileName/" for directories or "fileName" for files, regardless of the operating system
public static boolean match(List<String> l, String fileName, boolean isDirectory) {
for (String s : l)
if (isDirectory) {
if (fileName.startsWith(s + '/'))
return true;
} else {
if (s.startsWith("regex:")) {
if (fileName.matches(s.substring("regex:".length())))
return true;
} else {
if (fileName.equals(s))
return true;
}
}
return false;
}
}