minecraft-src/net/minecraft/data/structures/NbtToSnbt.java
2025-07-04 01:41:11 +03:00

156 lines
4.6 KiB
Java

package net.minecraft.data.structures;
import com.google.common.hash.Hashing;
import com.google.common.hash.HashingOutputStream;
import com.mojang.logging.LogUtils;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Collection;
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.NbtAccounter;
import net.minecraft.nbt.NbtIo;
import net.minecraft.nbt.NbtUtils;
import net.minecraft.util.FastBufferedInputStream;
import org.jetbrains.annotations.Nullable;
import org.slf4j.Logger;
public class NbtToSnbt implements DataProvider {
private static final Logger LOGGER = LogUtils.getLogger();
private final Iterable<Path> inputFolders;
private final PackOutput output;
public NbtToSnbt(PackOutput output, Collection<Path> inputFolders) {
this.inputFolders = inputFolders;
this.output = output;
}
@Override
public CompletableFuture<?> run(CachedOutput output) {
Path path = this.output.getOutputFolder();
List<CompletableFuture<?>> list = new ArrayList();
for (Path path2 : this.inputFolders) {
list.add(
CompletableFuture.supplyAsync(
() -> {
try {
Stream<Path> stream = Files.walk(path2);
CompletableFuture var4;
try {
var4 = CompletableFuture.allOf(
(CompletableFuture[])stream.filter(pathxx -> pathxx.toString().endsWith(".nbt"))
.map(path3 -> CompletableFuture.runAsync(() -> convertStructure(output, path3, getName(path2, path3), path), Util.ioPool()))
.toArray(CompletableFuture[]::new)
);
} catch (Throwable var7) {
if (stream != null) {
try {
stream.close();
} catch (Throwable var6) {
var7.addSuppressed(var6);
}
}
throw var7;
}
if (stream != null) {
stream.close();
}
return var4;
} catch (IOException var8) {
LOGGER.error("Failed to read structure input directory", (Throwable)var8);
return CompletableFuture.completedFuture(null);
}
},
Util.backgroundExecutor()
)
.thenCompose(completableFuture -> completableFuture)
);
}
return CompletableFuture.allOf((CompletableFuture[])list.toArray(CompletableFuture[]::new));
}
@Override
public final String getName() {
return "NBT -> SNBT";
}
/**
* Gets the name of the given NBT file, based on its path and the input directory. The result does not have the ".nbt" extension.
*/
private static String getName(Path inputFolder, Path nbtPath) {
String string = inputFolder.relativize(nbtPath).toString().replaceAll("\\\\", "/");
return string.substring(0, string.length() - ".nbt".length());
}
@Nullable
public static Path convertStructure(CachedOutput output, Path nbtPath, String name, Path directoryPath) {
try {
InputStream inputStream = Files.newInputStream(nbtPath);
Path var7;
try {
InputStream inputStream2 = new FastBufferedInputStream(inputStream);
try {
Path path = directoryPath.resolve(name + ".snbt");
writeSnbt(output, path, NbtUtils.structureToSnbt(NbtIo.readCompressed(inputStream2, NbtAccounter.unlimitedHeap())));
LOGGER.info("Converted {} from NBT to SNBT", name);
var7 = path;
} catch (Throwable var10) {
try {
inputStream2.close();
} catch (Throwable var9) {
var10.addSuppressed(var9);
}
throw var10;
}
inputStream2.close();
} catch (Throwable var11) {
if (inputStream != null) {
try {
inputStream.close();
} catch (Throwable var8) {
var11.addSuppressed(var8);
}
}
throw var11;
}
if (inputStream != null) {
inputStream.close();
}
return var7;
} catch (IOException var12) {
LOGGER.error("Couldn't convert {} from NBT to SNBT at {}", name, nbtPath, var12);
return null;
}
}
public static void writeSnbt(CachedOutput output, Path path, String contents) throws IOException {
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
HashingOutputStream hashingOutputStream = new HashingOutputStream(Hashing.sha1(), byteArrayOutputStream);
hashingOutputStream.write(contents.getBytes(StandardCharsets.UTF_8));
hashingOutputStream.write(10);
output.writeIfNeeded(path, byteArrayOutputStream.toByteArray(), hashingOutputStream.hash());
}
}