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 inputFolders; private final PackOutput output; public NbtToSnbt(PackOutput output, Collection inputFolders) { this.inputFolders = inputFolders; this.output = output; } @Override public CompletableFuture run(CachedOutput output) { Path path = this.output.getOutputFolder(); List> list = new ArrayList(); for (Path path2 : this.inputFolders) { list.add( CompletableFuture.supplyAsync( () -> { try { Stream 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()); } }