Datapack resolving
This commit is contained in:
@@ -0,0 +1,10 @@
|
|||||||
|
package org.jackhuang.hmcl.ui.versions;
|
||||||
|
|
||||||
|
import org.jackhuang.hmcl.ui.ListPage;
|
||||||
|
|
||||||
|
public class DatapackList extends ListPage<DatapackListItem> {
|
||||||
|
@Override
|
||||||
|
public void add() {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,46 @@
|
|||||||
|
package org.jackhuang.hmcl.ui.versions;
|
||||||
|
|
||||||
|
import com.jfoenix.concurrency.JFXUtilities;
|
||||||
|
import com.jfoenix.controls.JFXButton;
|
||||||
|
import com.jfoenix.controls.JFXCheckBox;
|
||||||
|
import com.jfoenix.effects.JFXDepthManager;
|
||||||
|
import javafx.geometry.Pos;
|
||||||
|
import javafx.scene.layout.BorderPane;
|
||||||
|
import org.jackhuang.hmcl.mod.Datapack;
|
||||||
|
import org.jackhuang.hmcl.setting.Theme;
|
||||||
|
import org.jackhuang.hmcl.ui.FXUtils;
|
||||||
|
import org.jackhuang.hmcl.ui.SVG;
|
||||||
|
import org.jackhuang.hmcl.ui.construct.TwoLineListItem;
|
||||||
|
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
|
import static org.jackhuang.hmcl.util.i18n.I18n.i18n;
|
||||||
|
|
||||||
|
public class DatapackListItem extends BorderPane {
|
||||||
|
|
||||||
|
public DatapackListItem(Datapack root, Datapack.Pack info, Consumer<DatapackListItem> deleteCallback) {
|
||||||
|
JFXCheckBox chkEnabled = new JFXCheckBox();
|
||||||
|
BorderPane.setAlignment(chkEnabled, Pos.CENTER);
|
||||||
|
setLeft(chkEnabled);
|
||||||
|
|
||||||
|
TwoLineListItem modItem = new TwoLineListItem();
|
||||||
|
BorderPane.setAlignment(modItem, Pos.CENTER);
|
||||||
|
setCenter(modItem);
|
||||||
|
|
||||||
|
JFXButton btnRemove = new JFXButton();
|
||||||
|
JFXUtilities.runInFX(() -> {
|
||||||
|
FXUtils.installTooltip(btnRemove, i18n("mods.remove"));
|
||||||
|
});
|
||||||
|
btnRemove.setOnMouseClicked(e -> deleteCallback.accept(this));
|
||||||
|
btnRemove.getStyleClass().add("toggle-icon4");
|
||||||
|
BorderPane.setAlignment(btnRemove, Pos.CENTER);
|
||||||
|
btnRemove.setGraphic(SVG.close(Theme.blackFillBinding(), 15, 15));
|
||||||
|
setRight(btnRemove);
|
||||||
|
|
||||||
|
setStyle("-fx-background-radius: 2; -fx-background-color: white; -fx-padding: 8;");
|
||||||
|
JFXDepthManager.setDepth(this, 1);
|
||||||
|
modItem.setTitle(info.getId());
|
||||||
|
modItem.setSubtitle(info.getDescription());
|
||||||
|
chkEnabled.selectedProperty().bindBidirectional(info.activeProperty());
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -15,7 +15,7 @@
|
|||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see {http://www.gnu.org/licenses/}.
|
* along with this program. If not, see {http://www.gnu.org/licenses/}.
|
||||||
*/
|
*/
|
||||||
package org.jackhuang.hmcl.ui;
|
package org.jackhuang.hmcl.ui.versions;
|
||||||
|
|
||||||
import com.jfoenix.concurrency.JFXUtilities;
|
import com.jfoenix.concurrency.JFXUtilities;
|
||||||
import com.jfoenix.controls.JFXButton;
|
import com.jfoenix.controls.JFXButton;
|
||||||
@@ -25,6 +25,8 @@ import javafx.geometry.Pos;
|
|||||||
import javafx.scene.layout.BorderPane;
|
import javafx.scene.layout.BorderPane;
|
||||||
import org.jackhuang.hmcl.mod.ModInfo;
|
import org.jackhuang.hmcl.mod.ModInfo;
|
||||||
import org.jackhuang.hmcl.setting.Theme;
|
import org.jackhuang.hmcl.setting.Theme;
|
||||||
|
import org.jackhuang.hmcl.ui.FXUtils;
|
||||||
|
import org.jackhuang.hmcl.ui.SVG;
|
||||||
import org.jackhuang.hmcl.ui.construct.TwoLineListItem;
|
import org.jackhuang.hmcl.ui.construct.TwoLineListItem;
|
||||||
import org.jackhuang.hmcl.util.StringUtils;
|
import org.jackhuang.hmcl.util.StringUtils;
|
||||||
|
|
||||||
@@ -28,7 +28,6 @@ import org.jackhuang.hmcl.task.Task;
|
|||||||
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.ListPage;
|
import org.jackhuang.hmcl.ui.ListPage;
|
||||||
import org.jackhuang.hmcl.ui.ModItem;
|
|
||||||
import org.jackhuang.hmcl.util.FileUtils;
|
import org.jackhuang.hmcl.util.FileUtils;
|
||||||
import org.jackhuang.hmcl.util.Logging;
|
import org.jackhuang.hmcl.util.Logging;
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,12 @@
|
|||||||
|
package org.jackhuang.hmcl.ui.versions;
|
||||||
|
|
||||||
|
import org.jackhuang.hmcl.ui.ListPage;
|
||||||
|
|
||||||
|
public class WorldList extends ListPage<WorldListItem> {
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void add() {
|
||||||
|
// Not adding world here.
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,56 @@
|
|||||||
|
package org.jackhuang.hmcl.ui.versions;
|
||||||
|
|
||||||
|
import javafx.beans.property.*;
|
||||||
|
import javafx.scene.control.Control;
|
||||||
|
import javafx.scene.control.Skin;
|
||||||
|
import javafx.scene.image.Image;
|
||||||
|
import javafx.stage.FileChooser;
|
||||||
|
import org.jackhuang.hmcl.game.World;
|
||||||
|
import org.jackhuang.hmcl.ui.Controllers;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
|
||||||
|
import static org.jackhuang.hmcl.util.i18n.I18n.i18n;
|
||||||
|
|
||||||
|
public class WorldListItem extends Control {
|
||||||
|
private final StringProperty title = new SimpleStringProperty();
|
||||||
|
private final StringProperty subtitle = new SimpleStringProperty();
|
||||||
|
private final ObjectProperty<Image> image = new SimpleObjectProperty<>();
|
||||||
|
private final World world;
|
||||||
|
|
||||||
|
public WorldListItem(World world) {
|
||||||
|
this.world = world;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Skin<?> createDefaultSkin() {
|
||||||
|
return new WorldListItemSkin(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public StringProperty titleProperty() {
|
||||||
|
return title;
|
||||||
|
}
|
||||||
|
|
||||||
|
public StringProperty subtitleProperty() {
|
||||||
|
return subtitle;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ObjectProperty<Image> imageProperty() {
|
||||||
|
return image;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void export() {
|
||||||
|
FileChooser fileChooser = new FileChooser();
|
||||||
|
fileChooser.setTitle(i18n("world.export.title"));
|
||||||
|
fileChooser.getExtensionFilters().add(new FileChooser.ExtensionFilter(i18n("world"), "*.zip"));
|
||||||
|
File file = fileChooser.showSaveDialog(Controllers.getStage());
|
||||||
|
if (file == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void manageDatapacks() {
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,90 @@
|
|||||||
|
package org.jackhuang.hmcl.ui.versions;
|
||||||
|
|
||||||
|
import com.jfoenix.controls.JFXButton;
|
||||||
|
import com.jfoenix.controls.JFXPopup;
|
||||||
|
import com.jfoenix.effects.JFXDepthManager;
|
||||||
|
import javafx.geometry.Pos;
|
||||||
|
import javafx.scene.Node;
|
||||||
|
import javafx.scene.control.SkinBase;
|
||||||
|
import javafx.scene.image.ImageView;
|
||||||
|
import javafx.scene.layout.BorderPane;
|
||||||
|
import javafx.scene.layout.HBox;
|
||||||
|
import javafx.scene.layout.StackPane;
|
||||||
|
import javafx.scene.layout.VBox;
|
||||||
|
import org.jackhuang.hmcl.setting.Theme;
|
||||||
|
import org.jackhuang.hmcl.ui.FXUtils;
|
||||||
|
import org.jackhuang.hmcl.ui.SVG;
|
||||||
|
import org.jackhuang.hmcl.ui.construct.IconedMenuItem;
|
||||||
|
import org.jackhuang.hmcl.ui.construct.TwoLineListItem;
|
||||||
|
|
||||||
|
import java.util.function.Function;
|
||||||
|
|
||||||
|
import static org.jackhuang.hmcl.util.i18n.I18n.i18n;
|
||||||
|
|
||||||
|
public class WorldListItemSkin extends SkinBase<WorldListItem> {
|
||||||
|
|
||||||
|
public WorldListItemSkin(WorldListItem skinnable) {
|
||||||
|
super(skinnable);
|
||||||
|
|
||||||
|
BorderPane root = new BorderPane();
|
||||||
|
|
||||||
|
|
||||||
|
HBox center = new HBox();
|
||||||
|
center.setSpacing(8);
|
||||||
|
center.setAlignment(Pos.CENTER_LEFT);
|
||||||
|
|
||||||
|
StackPane imageViewContainer = new StackPane();
|
||||||
|
FXUtils.setLimitWidth(imageViewContainer, 32);
|
||||||
|
FXUtils.setLimitHeight(imageViewContainer, 32);
|
||||||
|
|
||||||
|
ImageView imageView = new ImageView();
|
||||||
|
FXUtils.limitSize(imageView, 32, 32);
|
||||||
|
imageView.imageProperty().bind(skinnable.imageProperty());
|
||||||
|
imageViewContainer.getChildren().setAll(imageView);
|
||||||
|
|
||||||
|
TwoLineListItem item = new TwoLineListItem();
|
||||||
|
BorderPane.setAlignment(item, Pos.CENTER);
|
||||||
|
center.getChildren().setAll(imageView, item);
|
||||||
|
root.setCenter(center);
|
||||||
|
|
||||||
|
VBox menu = new VBox();
|
||||||
|
JFXPopup popup = new JFXPopup(menu);
|
||||||
|
|
||||||
|
Function<Runnable, Runnable> wrap = r -> () -> {
|
||||||
|
r.run();
|
||||||
|
popup.hide();
|
||||||
|
};
|
||||||
|
|
||||||
|
Function<Node, Node> limitWidth = node -> {
|
||||||
|
StackPane pane = new StackPane(node);
|
||||||
|
pane.setAlignment(Pos.CENTER);
|
||||||
|
FXUtils.setLimitWidth(pane, 14);
|
||||||
|
FXUtils.setLimitHeight(pane, 14);
|
||||||
|
return pane;
|
||||||
|
};
|
||||||
|
|
||||||
|
menu.getChildren().setAll(
|
||||||
|
new IconedMenuItem(limitWidth.apply(SVG.gear(Theme.blackFillBinding(), 14, 14)), i18n("world.datapack"), wrap.apply(skinnable::manageDatapacks)),
|
||||||
|
new IconedMenuItem(limitWidth.apply(SVG.export(Theme.blackFillBinding(), 14, 14)), i18n("world.export"), wrap.apply(skinnable::export)));
|
||||||
|
|
||||||
|
HBox right = new HBox();
|
||||||
|
right.setAlignment(Pos.CENTER_RIGHT);
|
||||||
|
|
||||||
|
JFXButton btnManage = new JFXButton();
|
||||||
|
btnManage.setOnMouseClicked(e -> {
|
||||||
|
popup.show(root, JFXPopup.PopupVPosition.TOP, JFXPopup.PopupHPosition.RIGHT, 0, root.getHeight());
|
||||||
|
});
|
||||||
|
btnManage.getStyleClass().add("toggle-icon4");
|
||||||
|
BorderPane.setAlignment(btnManage, Pos.CENTER);
|
||||||
|
btnManage.setGraphic(SVG.dotsVertical(Theme.blackFillBinding(), -1, -1));
|
||||||
|
right.getChildren().add(btnManage);
|
||||||
|
root.setRight(right);
|
||||||
|
|
||||||
|
root.setStyle("-fx-background-color: white; -fx-padding: 8 8 8 0;");
|
||||||
|
JFXDepthManager.setDepth(root, 1);
|
||||||
|
item.titleProperty().bind(skinnable.titleProperty());
|
||||||
|
item.subtitleProperty().bind(skinnable.subtitleProperty());
|
||||||
|
|
||||||
|
getChildren().setAll(root);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -240,6 +240,15 @@ mods.add.success=Successfully added mods %s.
|
|||||||
mods.choose_mod=Choose your mods
|
mods.choose_mod=Choose your mods
|
||||||
mods.remove=Remove
|
mods.remove=Remove
|
||||||
|
|
||||||
|
datapack=Data packs
|
||||||
|
datapack.add=Add data pack
|
||||||
|
datapack.remove=Remove
|
||||||
|
|
||||||
|
world=Worlds
|
||||||
|
world.datapack=Manage data packs
|
||||||
|
world.export=Export this world
|
||||||
|
world.export.title=Choose a file location to hold your world
|
||||||
|
|
||||||
profile=Game Directories
|
profile=Game Directories
|
||||||
profile.default=Current directory
|
profile.default=Current directory
|
||||||
profile.home=User home
|
profile.home=User home
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ import org.tukaani.xz.XZInputStream;
|
|||||||
import java.io.*;
|
import java.io.*;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.nio.charset.Charset;
|
import java.nio.charset.Charset;
|
||||||
|
import java.nio.file.Files;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.jar.JarEntry;
|
import java.util.jar.JarEntry;
|
||||||
@@ -75,7 +76,7 @@ public class LibraryDownloadTask extends Task {
|
|||||||
else
|
else
|
||||||
throw new LibraryDownloadException(library, t);
|
throw new LibraryDownloadException(library, t);
|
||||||
} else {
|
} else {
|
||||||
if (xz) unpackLibrary(jar, FileUtils.readBytes(xzFile));
|
if (xz) unpackLibrary(jar, Files.readAllBytes(xzFile.toPath()));
|
||||||
if (!checksumValid(jar, library.getChecksums())) {
|
if (!checksumValid(jar, library.getChecksums())) {
|
||||||
jar.delete();
|
jar.delete();
|
||||||
throw new IOException("Checksum failed for " + library);
|
throw new IOException("Checksum failed for " + library);
|
||||||
@@ -125,7 +126,7 @@ public class LibraryDownloadTask extends Task {
|
|||||||
if (checksums == null || checksums.isEmpty()) {
|
if (checksums == null || checksums.isEmpty()) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
byte[] fileData = FileUtils.readBytes(libPath);
|
byte[] fileData = Files.readAllBytes(libPath.toPath());
|
||||||
boolean valid = checksums.contains(encodeHex(digest("SHA-1", fileData)));
|
boolean valid = checksums.contains(encodeHex(digest("SHA-1", fileData)));
|
||||||
if (!valid && libPath.getName().endsWith(".jar")) {
|
if (!valid && libPath.getName().endsWith(".jar")) {
|
||||||
valid = validateJar(fileData, checksums);
|
valid = validateJar(fileData, checksums);
|
||||||
|
|||||||
@@ -0,0 +1,4 @@
|
|||||||
|
package org.jackhuang.hmcl.game;
|
||||||
|
|
||||||
|
public class World {
|
||||||
|
}
|
||||||
185
HMCLCore/src/main/java/org/jackhuang/hmcl/mod/Datapack.java
Normal file
185
HMCLCore/src/main/java/org/jackhuang/hmcl/mod/Datapack.java
Normal file
@@ -0,0 +1,185 @@
|
|||||||
|
package org.jackhuang.hmcl.mod;
|
||||||
|
|
||||||
|
import com.google.gson.JsonParseException;
|
||||||
|
import com.google.gson.annotations.SerializedName;
|
||||||
|
import javafx.beans.property.BooleanProperty;
|
||||||
|
import javafx.beans.property.SimpleBooleanProperty;
|
||||||
|
import org.jackhuang.hmcl.util.*;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.nio.file.FileSystem;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.nio.file.Path;
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
public class Datapack {
|
||||||
|
private final Path path;
|
||||||
|
private final List<Pack> info;
|
||||||
|
|
||||||
|
private Datapack(Path path, List<Pack> info) {
|
||||||
|
this.path = path;
|
||||||
|
this.info = Collections.unmodifiableList(info);
|
||||||
|
|
||||||
|
for (Pack pack : info) {
|
||||||
|
pack.datapack = this;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Path getPath() {
|
||||||
|
return path;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Pack> getInfo() {
|
||||||
|
return info;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void installTo(Path worldPath) throws IOException {
|
||||||
|
Path datapacks = worldPath.resolve("datapacks");
|
||||||
|
|
||||||
|
Set<String> packs = new HashSet<>();
|
||||||
|
for (Pack pack : info) packs.add(pack.getId());
|
||||||
|
|
||||||
|
for (Path datapack : Files.newDirectoryStream(datapacks)) {
|
||||||
|
if (packs.contains(FileUtils.getName(datapack)))
|
||||||
|
FileUtils.deleteDirectory(datapack.toFile());
|
||||||
|
}
|
||||||
|
|
||||||
|
new Unzipper(path, worldPath).setReplaceExistentFile(true).unzip();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Datapack fromZip(Path path) throws IOException {
|
||||||
|
try (FileSystem fs = CompressingUtils.createReadOnlyZipFileSystem(path)) {
|
||||||
|
Datapack datapack = fromDir(fs.getPath("/datapacks/"));
|
||||||
|
return new Datapack(path, datapack.info);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param dir
|
||||||
|
* @return
|
||||||
|
* @throws IOException
|
||||||
|
*/
|
||||||
|
public static Datapack fromDir(Path dir) throws IOException {
|
||||||
|
List<Pack> info = new LinkedList<>();
|
||||||
|
|
||||||
|
for (Path subDir : Files.newDirectoryStream(dir)) {
|
||||||
|
Path mcmeta = subDir.resolve("pack.mcmeta");
|
||||||
|
|
||||||
|
if (!Files.exists(mcmeta))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
PackMcMeta pack = JsonUtils.fromNonNullJson(FileUtils.readText(mcmeta), PackMcMeta.class);
|
||||||
|
info.add(new Pack(mcmeta, FileUtils.getName(subDir), pack.getPackInfo().getDescription()));
|
||||||
|
}
|
||||||
|
return new Datapack(dir, info);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Pack {
|
||||||
|
private Path packMcMeta;
|
||||||
|
private final BooleanProperty active;
|
||||||
|
private final String id;
|
||||||
|
private final String description;
|
||||||
|
private Datapack datapack;
|
||||||
|
|
||||||
|
public Pack(Path packMcMeta, String id, String description) {
|
||||||
|
this.packMcMeta = packMcMeta;
|
||||||
|
this.id = id;
|
||||||
|
this.description = description;
|
||||||
|
|
||||||
|
active = new SimpleBooleanProperty(this, "active", !DISABLED_EXT.equals(FileUtils.getExtension(packMcMeta))) {
|
||||||
|
@Override
|
||||||
|
protected void invalidated() {
|
||||||
|
Path f = Pack.this.packMcMeta.toAbsolutePath(), newF;
|
||||||
|
if (DISABLED_EXT.equals(FileUtils.getExtension(f)))
|
||||||
|
newF = f.getParent().resolve(FileUtils.getNameWithoutExtension(f));
|
||||||
|
else
|
||||||
|
newF = f.getParent().resolve(FileUtils.getName(f) + DISABLED_EXT);
|
||||||
|
|
||||||
|
try {
|
||||||
|
Files.move(f, newF);
|
||||||
|
Pack.this.packMcMeta = newF;
|
||||||
|
} catch (IOException e) {
|
||||||
|
// Mod file is occupied.
|
||||||
|
Logging.LOG.warning("Unable to rename file " + f + " to " + newF);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDescription() {
|
||||||
|
return description;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Datapack getDatapack() {
|
||||||
|
return datapack;
|
||||||
|
}
|
||||||
|
|
||||||
|
public BooleanProperty activeProperty() {
|
||||||
|
return active;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isActive() {
|
||||||
|
return active.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setActive(boolean active) {
|
||||||
|
this.active.set(active);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class PackMcMeta implements Validation {
|
||||||
|
|
||||||
|
@SerializedName("pack")
|
||||||
|
private final PackInfo pack;
|
||||||
|
|
||||||
|
public PackMcMeta() {
|
||||||
|
this(new PackInfo());
|
||||||
|
}
|
||||||
|
|
||||||
|
public PackMcMeta(PackInfo packInfo) {
|
||||||
|
this.pack = packInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
public PackInfo getPackInfo() {
|
||||||
|
return pack;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void validate() throws JsonParseException {
|
||||||
|
if (pack == null)
|
||||||
|
throw new JsonParseException("pack cannot be null");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class PackInfo {
|
||||||
|
@SerializedName("pack_format")
|
||||||
|
private final int packFormat;
|
||||||
|
|
||||||
|
@SerializedName("description")
|
||||||
|
private final String description;
|
||||||
|
|
||||||
|
public PackInfo() {
|
||||||
|
this(0, "");
|
||||||
|
}
|
||||||
|
|
||||||
|
public PackInfo(int packFormat, String description) {
|
||||||
|
this.packFormat = packFormat;
|
||||||
|
this.description = description;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getPackFormat() {
|
||||||
|
return packFormat;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDescription() {
|
||||||
|
return description;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final String DISABLED_EXT = ".disabled";
|
||||||
|
}
|
||||||
@@ -43,10 +43,18 @@ public final class FileUtils {
|
|||||||
return StringUtils.substringBeforeLast(file.getName(), '.');
|
return StringUtils.substringBeforeLast(file.getName(), '.');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static String getNameWithoutExtension(Path file) {
|
||||||
|
return StringUtils.substringBeforeLast(getName(file), '.');
|
||||||
|
}
|
||||||
|
|
||||||
public static String getExtension(File file) {
|
public static String getExtension(File file) {
|
||||||
return StringUtils.substringAfterLast(file.getName(), '.');
|
return StringUtils.substringAfterLast(file.getName(), '.');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static String getExtension(Path file) {
|
||||||
|
return StringUtils.substringAfterLast(getName(file), '.');
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method is for normalizing ZipPath since Path.normalize of ZipFileSystem does not work properly.
|
* This method is for normalizing ZipPath since Path.normalize of ZipFileSystem does not work properly.
|
||||||
*/
|
*/
|
||||||
@@ -63,11 +71,15 @@ public final class FileUtils {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static String readText(File file, Charset charset) throws IOException {
|
public static String readText(File file, Charset charset) throws IOException {
|
||||||
return new String(readBytes(file), charset);
|
return new String(Files.readAllBytes(file.toPath()), charset);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static byte[] readBytes(File file) throws IOException {
|
public static String readText(Path file) throws IOException {
|
||||||
return Files.readAllBytes(file.toPath());
|
return readText(file, UTF_8);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String readText(Path file, Charset charset) throws IOException {
|
||||||
|
return new String(Files.readAllBytes(file), charset);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void writeText(File file, String text) throws IOException {
|
public static void writeText(File file, String text) throws IOException {
|
||||||
|
|||||||
@@ -45,6 +45,7 @@ subprojects {
|
|||||||
compile group: 'org.tukaani', name: 'xz', version: '1.8'
|
compile group: 'org.tukaani', name: 'xz', version: '1.8'
|
||||||
compile group: 'org.hildan.fxgson', name: 'fx-gson', version: '3.1.0'
|
compile group: 'org.hildan.fxgson', name: 'fx-gson', version: '3.1.0'
|
||||||
compile group: 'org.jenkins-ci', name: 'constant-pool-scanner', version: '1.2'
|
compile group: 'org.jenkins-ci', name: 'constant-pool-scanner', version: '1.2'
|
||||||
|
compile group: 'org.spacehq', name: 'opennbt', version: '1.0'
|
||||||
testCompile group: 'junit', name: 'junit', version: '4.12'
|
testCompile group: 'junit', name: 'junit', version: '4.12'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user