177 lines
5.4 KiB
Java
177 lines
5.4 KiB
Java
package net.minecraft.data.structures;
|
|
|
|
import com.google.common.collect.Lists;
|
|
import com.google.common.hash.HashCode;
|
|
import com.google.common.hash.Hashing;
|
|
import com.google.common.hash.HashingOutputStream;
|
|
import com.mojang.logging.LogUtils;
|
|
import java.io.BufferedReader;
|
|
import java.io.ByteArrayOutputStream;
|
|
import java.io.IOException;
|
|
import java.nio.file.Files;
|
|
import java.nio.file.Path;
|
|
import java.util.List;
|
|
import java.util.concurrent.CompletableFuture;
|
|
import java.util.stream.Stream;
|
|
import net.minecraft.Util;
|
|
import net.minecraft.data.CachedOutput;
|
|
import net.minecraft.data.DataProvider;
|
|
import net.minecraft.data.PackOutput;
|
|
import net.minecraft.nbt.CompoundTag;
|
|
import net.minecraft.nbt.NbtIo;
|
|
import net.minecraft.nbt.NbtUtils;
|
|
import org.apache.commons.io.IOUtils;
|
|
import org.slf4j.Logger;
|
|
|
|
public class SnbtToNbt implements DataProvider {
|
|
private static final Logger LOGGER = LogUtils.getLogger();
|
|
private final PackOutput output;
|
|
private final Iterable<Path> inputFolders;
|
|
private final List<SnbtToNbt.Filter> filters = Lists.<SnbtToNbt.Filter>newArrayList();
|
|
|
|
public SnbtToNbt(PackOutput output, Iterable<Path> inputFolders) {
|
|
this.output = output;
|
|
this.inputFolders = inputFolders;
|
|
}
|
|
|
|
public SnbtToNbt addFilter(SnbtToNbt.Filter filter) {
|
|
this.filters.add(filter);
|
|
return this;
|
|
}
|
|
|
|
private CompoundTag applyFilters(String fileName, CompoundTag tag) {
|
|
CompoundTag compoundTag = tag;
|
|
|
|
for (SnbtToNbt.Filter filter : this.filters) {
|
|
compoundTag = filter.apply(fileName, compoundTag);
|
|
}
|
|
|
|
return compoundTag;
|
|
}
|
|
|
|
@Override
|
|
public CompletableFuture<?> run(CachedOutput output) {
|
|
Path path = this.output.getOutputFolder();
|
|
List<CompletableFuture<?>> list = Lists.<CompletableFuture<?>>newArrayList();
|
|
|
|
for (Path path2 : this.inputFolders) {
|
|
list.add(
|
|
CompletableFuture.supplyAsync(
|
|
() -> {
|
|
try {
|
|
Stream<Path> stream = Files.walk(path2);
|
|
|
|
CompletableFuture var5x;
|
|
try {
|
|
var5x = CompletableFuture.allOf(
|
|
(CompletableFuture[])stream.filter(pathxx -> pathxx.toString().endsWith(".snbt")).map(path3 -> CompletableFuture.runAsync(() -> {
|
|
SnbtToNbt.TaskResult taskResult = this.readStructure(path3, this.getName(path2, path3));
|
|
this.storeStructureIfChanged(output, taskResult, path);
|
|
}, Util.backgroundExecutor().forName("SnbtToNbt"))).toArray(CompletableFuture[]::new)
|
|
);
|
|
} catch (Throwable var8) {
|
|
if (stream != null) {
|
|
try {
|
|
stream.close();
|
|
} catch (Throwable var7) {
|
|
var8.addSuppressed(var7);
|
|
}
|
|
}
|
|
|
|
throw var8;
|
|
}
|
|
|
|
if (stream != null) {
|
|
stream.close();
|
|
}
|
|
|
|
return var5x;
|
|
} catch (Exception var9) {
|
|
throw new RuntimeException("Failed to read structure input directory, aborting", var9);
|
|
}
|
|
},
|
|
Util.backgroundExecutor().forName("SnbtToNbt")
|
|
)
|
|
.thenCompose(completableFuture -> completableFuture)
|
|
);
|
|
}
|
|
|
|
return Util.sequenceFailFast(list);
|
|
}
|
|
|
|
@Override
|
|
public final String getName() {
|
|
return "SNBT -> NBT";
|
|
}
|
|
|
|
/**
|
|
* Gets the name of the given SNBT file, based on its path and the input directory. The result does not have the ".snbt" extension.
|
|
*/
|
|
private String getName(Path inputFolder, Path file) {
|
|
String string = inputFolder.relativize(file).toString().replaceAll("\\\\", "/");
|
|
return string.substring(0, string.length() - ".snbt".length());
|
|
}
|
|
|
|
private SnbtToNbt.TaskResult readStructure(Path filePath, String fileName) {
|
|
try {
|
|
BufferedReader bufferedReader = Files.newBufferedReader(filePath);
|
|
|
|
SnbtToNbt.TaskResult var10;
|
|
try {
|
|
String string = IOUtils.toString(bufferedReader);
|
|
CompoundTag compoundTag = this.applyFilters(fileName, NbtUtils.snbtToStructure(string));
|
|
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
|
|
HashingOutputStream hashingOutputStream = new HashingOutputStream(Hashing.sha1(), byteArrayOutputStream);
|
|
NbtIo.writeCompressed(compoundTag, hashingOutputStream);
|
|
byte[] bs = byteArrayOutputStream.toByteArray();
|
|
HashCode hashCode = hashingOutputStream.hash();
|
|
var10 = new SnbtToNbt.TaskResult(fileName, bs, hashCode);
|
|
} catch (Throwable var12) {
|
|
if (bufferedReader != null) {
|
|
try {
|
|
bufferedReader.close();
|
|
} catch (Throwable var11) {
|
|
var12.addSuppressed(var11);
|
|
}
|
|
}
|
|
|
|
throw var12;
|
|
}
|
|
|
|
if (bufferedReader != null) {
|
|
bufferedReader.close();
|
|
}
|
|
|
|
return var10;
|
|
} catch (Throwable var13) {
|
|
throw new SnbtToNbt.StructureConversionException(filePath, var13);
|
|
}
|
|
}
|
|
|
|
private void storeStructureIfChanged(CachedOutput output, SnbtToNbt.TaskResult taskResult, Path directoryPath) {
|
|
Path path = directoryPath.resolve(taskResult.name + ".nbt");
|
|
|
|
try {
|
|
output.writeIfNeeded(path, taskResult.payload, taskResult.hash);
|
|
} catch (IOException var6) {
|
|
LOGGER.error("Couldn't write structure {} at {}", taskResult.name, path, var6);
|
|
}
|
|
}
|
|
|
|
@FunctionalInterface
|
|
public interface Filter {
|
|
CompoundTag apply(String structureLocationPath, CompoundTag tag);
|
|
}
|
|
|
|
/**
|
|
* Wraps exceptions thrown while reading structures to include the path of the structure in the exception message.
|
|
*/
|
|
static class StructureConversionException extends RuntimeException {
|
|
public StructureConversionException(Path path, Throwable cause) {
|
|
super(path.toAbsolutePath().toString(), cause);
|
|
}
|
|
}
|
|
|
|
record TaskResult(String name, byte[] payload, HashCode hash) {
|
|
}
|
|
}
|