package cn.nukkit.nbt; import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.nio.ByteOrder; import java.nio.file.Files; import java.nio.file.StandardCopyOption; import java.util.Collection; import java.util.zip.Deflater; import java.util.zip.DeflaterOutputStream; import java.util.zip.GZIPInputStream; import java.util.zip.GZIPOutputStream; import cn.nukkit.item.Item; import cn.nukkit.nbt.stream.NBTInputStream; import cn.nukkit.nbt.stream.NBTOutputStream; import cn.nukkit.nbt.tag.CompoundTag; import cn.nukkit.nbt.tag.Tag; public class NBTIO { /** * A Named Binary Tag library for Nukkit Project */ public static CompoundTag putItemHelper(Item item) { return putItemHelper(item, null); } public static CompoundTag putItemHelper(Item item, Integer slot) { CompoundTag tag = new CompoundTag(null) .putShort("id", item.getId()) .putByte("Count", item.getCount()) .putShort("Damage", item.getDamage()); if (slot != null) { tag.putByte("Slot", slot); } if (item.hasCompoundTag()) { tag.putCompound("tag", item.getNamedTag()); } return tag; } public static Item getItemHelper(CompoundTag tag) { if (!tag.contains("id") || !tag.contains("Count")) { return Item.get(0); } Item item = Item.get(tag.getShort("id"), !tag.contains("Damage") ? 0 : tag.getShort("Damage"), tag.getByte("Count")); if (tag.contains("tag") && tag.get("tag") instanceof CompoundTag) { CompoundTag nbt = tag.getCompound("tag").clone(); nbt.setName(""); item.setNamedTag(nbt); } return item; } public static CompoundTag read(File file) throws IOException { return read(file, ByteOrder.BIG_ENDIAN); } public static CompoundTag read(File file, ByteOrder endianness) throws IOException { if (!file.exists()) return null; return read(new BufferedInputStream(new FileInputStream(file)), endianness); } public static CompoundTag read(InputStream inputStream) throws IOException { return read(new BufferedInputStream(inputStream), ByteOrder.BIG_ENDIAN); } public static CompoundTag read(InputStream inputStream, ByteOrder endianness) throws IOException { return read(new BufferedInputStream(inputStream), endianness, false); } public static CompoundTag read(InputStream inputStream, ByteOrder endianness, boolean network) throws IOException { try (NBTInputStream stream = new NBTInputStream(inputStream, endianness, network)) { Tag tag = Tag.readNamedTag(stream); if (tag instanceof CompoundTag) { return (CompoundTag) tag; } throw new IOException("Root tag must be a named compound tag"); } } public static CompoundTag read(byte[] data) throws IOException { return read(data, ByteOrder.BIG_ENDIAN); } public static CompoundTag read(byte[] data, ByteOrder endianness) throws IOException { return read(new ByteArrayInputStream(data), endianness); } public static CompoundTag read(byte[] data, ByteOrder endianness, boolean network) throws IOException { return read(new ByteArrayInputStream(data), endianness, network); } public static CompoundTag readCompressed(InputStream inputStream) throws IOException { return readCompressed(inputStream, ByteOrder.BIG_ENDIAN); } public static CompoundTag readCompressed(InputStream inputStream, ByteOrder endianness) throws IOException { return read(new BufferedInputStream(new GZIPInputStream(inputStream)), endianness); } public static CompoundTag readCompressed(byte[] data) throws IOException { return readCompressed(data, ByteOrder.BIG_ENDIAN); } public static CompoundTag readCompressed(byte[] data, ByteOrder endianness) throws IOException { return read(new BufferedInputStream(new GZIPInputStream(new ByteArrayInputStream(data))), endianness, true); } public static CompoundTag readNetworkCompressed(InputStream inputStream) throws IOException { return readNetworkCompressed(inputStream, ByteOrder.BIG_ENDIAN); } public static CompoundTag readNetworkCompressed(InputStream inputStream, ByteOrder endianness) throws IOException { return read(new BufferedInputStream(new GZIPInputStream(inputStream)), endianness); } public static CompoundTag readNetworkCompressed(byte[] data) throws IOException { return readNetworkCompressed(data, ByteOrder.BIG_ENDIAN); } public static CompoundTag readNetworkCompressed(byte[] data, ByteOrder endianness) throws IOException { return read(new BufferedInputStream(new GZIPInputStream(new ByteArrayInputStream(data))), endianness, true); } public static byte[] write(CompoundTag tag) throws IOException { return write(tag, ByteOrder.BIG_ENDIAN); } public static byte[] write(CompoundTag tag, ByteOrder endianness) throws IOException { return write(tag, endianness, false); } public static byte[] write(CompoundTag tag, ByteOrder endianness, boolean network) throws IOException { ByteArrayOutputStream baos = new ByteArrayOutputStream(); try (NBTOutputStream stream = new NBTOutputStream(baos, endianness, network)) { Tag.writeNamedTag(tag, stream); return baos.toByteArray(); } } public static byte[] write(Collection<CompoundTag> tags) throws IOException { return write(tags, ByteOrder.BIG_ENDIAN); } public static byte[] write(Collection<CompoundTag> tags, ByteOrder endianness) throws IOException { return write(tags, endianness, false); } public static byte[] write(Collection<CompoundTag> tags, ByteOrder endianness, boolean network) throws IOException { ByteArrayOutputStream baos = new ByteArrayOutputStream(); try (NBTOutputStream stream = new NBTOutputStream(baos, endianness, network)) { for (CompoundTag tag : tags) { Tag.writeNamedTag(tag, stream); } return baos.toByteArray(); } } public static void write(CompoundTag tag, File file) throws IOException { write(tag, file, ByteOrder.BIG_ENDIAN); } public static void write(CompoundTag tag, File file, ByteOrder endianness) throws IOException { write(tag, new BufferedOutputStream(new FileOutputStream(file)), endianness); } public static void write(CompoundTag tag, OutputStream outputStream) throws IOException { write(tag, outputStream, ByteOrder.BIG_ENDIAN); } public static void write(CompoundTag tag, OutputStream outputStream, ByteOrder endianness) throws IOException { write(tag, outputStream, endianness, false); } public static void write(CompoundTag tag, OutputStream outputStream, ByteOrder endianness, boolean network) throws IOException { try (NBTOutputStream stream = new NBTOutputStream(outputStream, endianness, network)) { Tag.writeNamedTag(tag, stream); } } public static byte[] writeGZIPCompressed(CompoundTag tag) throws IOException { return writeGZIPCompressed(tag, ByteOrder.BIG_ENDIAN); } public static byte[] writeGZIPCompressed(CompoundTag tag, ByteOrder endianness) throws IOException { ByteArrayOutputStream baos = new ByteArrayOutputStream(); writeGZIPCompressed(tag, baos, endianness); return baos.toByteArray(); } public static void writeGZIPCompressed(CompoundTag tag, OutputStream outputStream) throws IOException { writeGZIPCompressed(tag, outputStream, ByteOrder.BIG_ENDIAN); } public static void writeGZIPCompressed(CompoundTag tag, OutputStream outputStream, ByteOrder endianness) throws IOException { write(tag, new GZIPOutputStream(outputStream), endianness); } public static byte[] writeNetworkGZIPCompressed(CompoundTag tag) throws IOException { return writeNetworkGZIPCompressed(tag, ByteOrder.BIG_ENDIAN); } public static byte[] writeNetworkGZIPCompressed(CompoundTag tag, ByteOrder endianness) throws IOException { ByteArrayOutputStream baos = new ByteArrayOutputStream(); writeNetworkGZIPCompressed(tag, baos, endianness); return baos.toByteArray(); } public static void writeNetworkGZIPCompressed(CompoundTag tag, OutputStream outputStream) throws IOException { writeNetworkGZIPCompressed(tag, outputStream, ByteOrder.BIG_ENDIAN); } public static void writeNetworkGZIPCompressed(CompoundTag tag, OutputStream outputStream, ByteOrder endianness) throws IOException { write(tag, new GZIPOutputStream(outputStream), endianness, true); } public static void writeZLIBCompressed(CompoundTag tag, OutputStream outputStream) throws IOException { writeZLIBCompressed(tag, outputStream, ByteOrder.BIG_ENDIAN); } public static void writeZLIBCompressed(CompoundTag tag, OutputStream outputStream, ByteOrder endianness) throws IOException { writeZLIBCompressed(tag, outputStream, Deflater.DEFAULT_COMPRESSION, endianness); } public static void writeZLIBCompressed(CompoundTag tag, OutputStream outputStream, int level) throws IOException { writeZLIBCompressed(tag, outputStream, level, ByteOrder.BIG_ENDIAN); } public static void writeZLIBCompressed(CompoundTag tag, OutputStream outputStream, int level, ByteOrder endianness) throws IOException { write(tag, new DeflaterOutputStream(outputStream, new Deflater(level)), endianness); } public static void safeWrite(CompoundTag tag, File file) throws IOException { File tmpFile = new File(file.getAbsolutePath() + "_tmp"); if (tmpFile.exists()) { tmpFile.delete(); } write(tag, tmpFile); Files.move(tmpFile.toPath(), file.toPath(), StandardCopyOption.REPLACE_EXISTING, StandardCopyOption.ATOMIC_MOVE); } }