Skip to content
Open
Show file tree
Hide file tree
Changes from 7 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 -> {
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;
}

}
}
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 thread
ToobLac marked this conversation as resolved.
Outdated
Comment thread
ToobLac marked this conversation as resolved.
Outdated

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