From 14af19873c9d6269b49b05c21b22f3e34ed6bd7f Mon Sep 17 00:00:00 2001 From: Daniel Mills Date: Wed, 4 Aug 2021 22:00:51 -0400 Subject: [PATCH] Fix nbt --- .../volmit/iris/util/oldnbt/ByteArrayTag.java | 67 +++++ .../com/volmit/iris/util/oldnbt/ByteTag.java | 59 ++++ .../volmit/iris/util/oldnbt/CompoundTag.java | 67 +++++ .../volmit/iris/util/oldnbt/DoubleTag.java | 59 ++++ .../com/volmit/iris/util/oldnbt/EndTag.java | 45 +++ .../com/volmit/iris/util/oldnbt/FloatTag.java | 59 ++++ .../volmit/iris/util/oldnbt/IntArrayTag.java | 61 ++++ .../com/volmit/iris/util/oldnbt/IntTag.java | 59 ++++ .../com/volmit/iris/util/oldnbt/ListTag.java | 84 ++++++ .../com/volmit/iris/util/oldnbt/LongTag.java | 59 ++++ .../volmit/iris/util/oldnbt/NBTConstants.java | 63 +++++ .../iris/util/oldnbt/NBTInputStream.java | 189 +++++++++++++ .../iris/util/oldnbt/NBTOutputStream.java | 262 ++++++++++++++++++ .../com/volmit/iris/util/oldnbt/NBTUtils.java | 137 +++++++++ .../com/volmit/iris/util/oldnbt/ShortTag.java | 59 ++++ .../volmit/iris/util/oldnbt/StringTag.java | 59 ++++ .../java/com/volmit/iris/util/oldnbt/Tag.java | 58 ++++ 17 files changed, 1446 insertions(+) create mode 100644 src/main/java/com/volmit/iris/util/oldnbt/ByteArrayTag.java create mode 100644 src/main/java/com/volmit/iris/util/oldnbt/ByteTag.java create mode 100644 src/main/java/com/volmit/iris/util/oldnbt/CompoundTag.java create mode 100644 src/main/java/com/volmit/iris/util/oldnbt/DoubleTag.java create mode 100644 src/main/java/com/volmit/iris/util/oldnbt/EndTag.java create mode 100644 src/main/java/com/volmit/iris/util/oldnbt/FloatTag.java create mode 100644 src/main/java/com/volmit/iris/util/oldnbt/IntArrayTag.java create mode 100644 src/main/java/com/volmit/iris/util/oldnbt/IntTag.java create mode 100644 src/main/java/com/volmit/iris/util/oldnbt/ListTag.java create mode 100644 src/main/java/com/volmit/iris/util/oldnbt/LongTag.java create mode 100644 src/main/java/com/volmit/iris/util/oldnbt/NBTConstants.java create mode 100644 src/main/java/com/volmit/iris/util/oldnbt/NBTInputStream.java create mode 100644 src/main/java/com/volmit/iris/util/oldnbt/NBTOutputStream.java create mode 100644 src/main/java/com/volmit/iris/util/oldnbt/NBTUtils.java create mode 100644 src/main/java/com/volmit/iris/util/oldnbt/ShortTag.java create mode 100644 src/main/java/com/volmit/iris/util/oldnbt/StringTag.java create mode 100644 src/main/java/com/volmit/iris/util/oldnbt/Tag.java diff --git a/src/main/java/com/volmit/iris/util/oldnbt/ByteArrayTag.java b/src/main/java/com/volmit/iris/util/oldnbt/ByteArrayTag.java new file mode 100644 index 000000000..38ef3ff90 --- /dev/null +++ b/src/main/java/com/volmit/iris/util/oldnbt/ByteArrayTag.java @@ -0,0 +1,67 @@ +/* + * Iris is a World Generator for Minecraft Bukkit Servers + * Copyright (c) 2021 Arcane Arts (Volmit Software) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.volmit.iris.util.oldnbt; + +/** + * The TAG_Byte_Array tag. + * + * @author Graham Edgecombe + */ +public final class ByteArrayTag extends Tag { + + /** + * The value. + */ + private final byte[] value; + + /** + * Creates the tag. + * + * @param name The name. + * @param value The value. + */ + public ByteArrayTag(String name, byte[] value) { + super(name); + this.value = value; + } + + @Override + public byte[] getValue() { + return value; + } + + @Override + public String toString() { + StringBuilder hex = new StringBuilder(); + for (byte b : value) { + String hexDigits = Integer.toHexString(b).toUpperCase(); + if (hexDigits.length() == 1) { + hex.append("0"); + } + hex.append(hexDigits).append(" "); + } + String name = getName(); + String append = ""; + if (name != null && !name.equals("")) { + append = "(\"" + this.getName() + "\")"; + } + return "TAG_Byte_Array" + append + ": " + hex; + } + +} diff --git a/src/main/java/com/volmit/iris/util/oldnbt/ByteTag.java b/src/main/java/com/volmit/iris/util/oldnbt/ByteTag.java new file mode 100644 index 000000000..edb4bf2b6 --- /dev/null +++ b/src/main/java/com/volmit/iris/util/oldnbt/ByteTag.java @@ -0,0 +1,59 @@ +/* + * Iris is a World Generator for Minecraft Bukkit Servers + * Copyright (c) 2021 Arcane Arts (Volmit Software) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.volmit.iris.util.oldnbt; + +/** + * The TAG_Byte tag. + * + * @author Graham Edgecombe + */ +public final class ByteTag extends Tag { + + /** + * The value. + */ + private final byte value; + + /** + * Creates the tag. + * + * @param name The name. + * @param value The value. + */ + public ByteTag(String name, byte value) { + super(name); + this.value = value; + } + + @Override + public Byte getValue() { + return value; + } + + @Override + public String toString() { + String name = getName(); + String append = ""; + if (name != null && !name.equals("")) { + append = "(\"" + this.getName() + "\")"; + } + return "TAG_Byte" + append + ": " + value; + } + +} diff --git a/src/main/java/com/volmit/iris/util/oldnbt/CompoundTag.java b/src/main/java/com/volmit/iris/util/oldnbt/CompoundTag.java new file mode 100644 index 000000000..61d61d606 --- /dev/null +++ b/src/main/java/com/volmit/iris/util/oldnbt/CompoundTag.java @@ -0,0 +1,67 @@ +/* + * Iris is a World Generator for Minecraft Bukkit Servers + * Copyright (c) 2021 Arcane Arts (Volmit Software) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.volmit.iris.util.oldnbt; + +import java.util.Map; + +/** + * The TAG_Compound tag. + * + * @author Graham Edgecombe + */ +public final class CompoundTag extends Tag { + + /** + * The value. + */ + private final Map value; + + /** + * Creates the tag. + * + * @param name The name. + * @param value The value. + */ + public CompoundTag(String name, Map value) { + super(name); + this.value = value; + } + + @Override + public Map getValue() { + return value; + } + + @Override + public String toString() { + String name = getName(); + String append = ""; + if (name != null && !name.equals("")) { + append = "(\"" + this.getName() + "\")"; + } + StringBuilder bldr = new StringBuilder(); + bldr.append("TAG_Compound").append(append).append(": ").append(value.size()).append(" entries\r\n{\r\n"); + for (Map.Entry entry : value.entrySet()) { + bldr.append(" ").append(entry.getValue().toString().replaceAll("\r\n", "\r\n ")).append("\r\n"); + } + bldr.append("}"); + return bldr.toString(); + } + +} diff --git a/src/main/java/com/volmit/iris/util/oldnbt/DoubleTag.java b/src/main/java/com/volmit/iris/util/oldnbt/DoubleTag.java new file mode 100644 index 000000000..c7d0eaa7b --- /dev/null +++ b/src/main/java/com/volmit/iris/util/oldnbt/DoubleTag.java @@ -0,0 +1,59 @@ +/* + * Iris is a World Generator for Minecraft Bukkit Servers + * Copyright (c) 2021 Arcane Arts (Volmit Software) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.volmit.iris.util.oldnbt; + +/** + * The TAG_Double tag. + * + * @author Graham Edgecombe + */ +public final class DoubleTag extends Tag { + + /** + * The value. + */ + private final double value; + + /** + * Creates the tag. + * + * @param name The name. + * @param value The value. + */ + public DoubleTag(String name, double value) { + super(name); + this.value = value; + } + + @Override + public Double getValue() { + return value; + } + + @Override + public String toString() { + String name = getName(); + String append = ""; + if (name != null && !name.equals("")) { + append = "(\"" + this.getName() + "\")"; + } + return "TAG_Double" + append + ": " + value; + } + +} diff --git a/src/main/java/com/volmit/iris/util/oldnbt/EndTag.java b/src/main/java/com/volmit/iris/util/oldnbt/EndTag.java new file mode 100644 index 000000000..4488e18ec --- /dev/null +++ b/src/main/java/com/volmit/iris/util/oldnbt/EndTag.java @@ -0,0 +1,45 @@ +/* + * Iris is a World Generator for Minecraft Bukkit Servers + * Copyright (c) 2021 Arcane Arts (Volmit Software) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.volmit.iris.util.oldnbt; + +/** + * The TAG_End tag. + * + * @author Graham Edgecombe + */ +public final class EndTag extends Tag { + + /** + * Creates the tag. + */ + public EndTag() { + super(""); + } + + @Override + public Object getValue() { + return null; + } + + @Override + public String toString() { + return "TAG_End"; + } + +} diff --git a/src/main/java/com/volmit/iris/util/oldnbt/FloatTag.java b/src/main/java/com/volmit/iris/util/oldnbt/FloatTag.java new file mode 100644 index 000000000..17833b557 --- /dev/null +++ b/src/main/java/com/volmit/iris/util/oldnbt/FloatTag.java @@ -0,0 +1,59 @@ +/* + * Iris is a World Generator for Minecraft Bukkit Servers + * Copyright (c) 2021 Arcane Arts (Volmit Software) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.volmit.iris.util.oldnbt; + +/** + * The TAG_Float tag. + * + * @author Graham Edgecombe + */ +public final class FloatTag extends Tag { + + /** + * The value. + */ + private final float value; + + /** + * Creates the tag. + * + * @param name The name. + * @param value The value. + */ + public FloatTag(String name, float value) { + super(name); + this.value = value; + } + + @Override + public Float getValue() { + return value; + } + + @Override + public String toString() { + String name = getName(); + String append = ""; + if (name != null && !name.equals("")) { + append = "(\"" + this.getName() + "\")"; + } + return "TAG_Float" + append + ": " + value; + } + +} diff --git a/src/main/java/com/volmit/iris/util/oldnbt/IntArrayTag.java b/src/main/java/com/volmit/iris/util/oldnbt/IntArrayTag.java new file mode 100644 index 000000000..a2e9ebef4 --- /dev/null +++ b/src/main/java/com/volmit/iris/util/oldnbt/IntArrayTag.java @@ -0,0 +1,61 @@ +/* + * Iris is a World Generator for Minecraft Bukkit Servers + * Copyright (c) 2021 Arcane Arts (Volmit Software) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.volmit.iris.util.oldnbt; + +import java.util.Arrays; + +/** + * The TAG_Int_Array tag. + * + * @author Neil Wightman + */ +public final class IntArrayTag extends Tag { + + /** + * The value. + */ + private final int[] value; + + /** + * Creates the tag. + * + * @param name The name. + * @param value The value. + */ + public IntArrayTag(String name, int[] value) { + super(name); + this.value = value; + } + + @Override + public int[] getValue() { + return value; + } + + @Override + public String toString() { + String name = getName(); + String append = ""; + if (name != null && !name.equals("")) { + append = "(\"" + this.getName() + "\")"; + } + return "TAG_Int_Array" + append + ": " + Arrays.toString(value); + } + +} diff --git a/src/main/java/com/volmit/iris/util/oldnbt/IntTag.java b/src/main/java/com/volmit/iris/util/oldnbt/IntTag.java new file mode 100644 index 000000000..7f2537249 --- /dev/null +++ b/src/main/java/com/volmit/iris/util/oldnbt/IntTag.java @@ -0,0 +1,59 @@ +/* + * Iris is a World Generator for Minecraft Bukkit Servers + * Copyright (c) 2021 Arcane Arts (Volmit Software) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.volmit.iris.util.oldnbt; + +/** + * The TAG_Int tag. + * + * @author Graham Edgecombe + */ +public final class IntTag extends Tag { + + /** + * The value. + */ + private final int value; + + /** + * Creates the tag. + * + * @param name The name. + * @param value The value. + */ + public IntTag(String name, int value) { + super(name); + this.value = value; + } + + @Override + public Integer getValue() { + return value; + } + + @Override + public String toString() { + String name = getName(); + String append = ""; + if (name != null && !name.equals("")) { + append = "(\"" + this.getName() + "\")"; + } + return "TAG_Int" + append + ": " + value; + } + +} diff --git a/src/main/java/com/volmit/iris/util/oldnbt/ListTag.java b/src/main/java/com/volmit/iris/util/oldnbt/ListTag.java new file mode 100644 index 000000000..71d144d75 --- /dev/null +++ b/src/main/java/com/volmit/iris/util/oldnbt/ListTag.java @@ -0,0 +1,84 @@ +/* + * Iris is a World Generator for Minecraft Bukkit Servers + * Copyright (c) 2021 Arcane Arts (Volmit Software) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.volmit.iris.util.oldnbt; + +import java.util.Collections; +import java.util.List; + +/** + * The TAG_List tag. + * + * @author Graham Edgecombe + */ +public final class ListTag extends Tag { + + /** + * The type. + */ + private final Class type; + + /** + * The value. + */ + private final List value; + + /** + * Creates the tag. + * + * @param name The name. + * @param type The type of item in the list. + * @param value The value. + */ + public ListTag(String name, Class type, List value) { + super(name); + this.type = type; + this.value = Collections.unmodifiableList(value); + } + + /** + * Gets the type of item in this list. + * + * @return The type of item in this list. + */ + public Class getType() { + return type; + } + + @Override + public List getValue() { + return value; + } + + @Override + public String toString() { + String name = getName(); + String append = ""; + if (name != null && !name.equals("")) { + append = "(\"" + this.getName() + "\")"; + } + StringBuilder bldr = new StringBuilder(); + bldr.append("TAG_List").append(append).append(": ").append(value.size()).append(" entries of type ").append(NBTUtils.getTypeName(type)).append("\r\n{\r\n"); + for (Tag t : value) { + bldr.append(" ").append(t.toString().replaceAll("\r\n", "\r\n ")).append("\r\n"); + } + bldr.append("}"); + return bldr.toString(); + } + +} diff --git a/src/main/java/com/volmit/iris/util/oldnbt/LongTag.java b/src/main/java/com/volmit/iris/util/oldnbt/LongTag.java new file mode 100644 index 000000000..59671da6d --- /dev/null +++ b/src/main/java/com/volmit/iris/util/oldnbt/LongTag.java @@ -0,0 +1,59 @@ +/* + * Iris is a World Generator for Minecraft Bukkit Servers + * Copyright (c) 2021 Arcane Arts (Volmit Software) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.volmit.iris.util.oldnbt; + +/** + * The TAG_Long tag. + * + * @author Graham Edgecombe + */ +public final class LongTag extends Tag { + + /** + * The value. + */ + private final long value; + + /** + * Creates the tag. + * + * @param name The name. + * @param value The value. + */ + public LongTag(String name, long value) { + super(name); + this.value = value; + } + + @Override + public Long getValue() { + return value; + } + + @Override + public String toString() { + String name = getName(); + String append = ""; + if (name != null && !name.equals("")) { + append = "(\"" + this.getName() + "\")"; + } + return "TAG_Long" + append + ": " + value; + } + +} diff --git a/src/main/java/com/volmit/iris/util/oldnbt/NBTConstants.java b/src/main/java/com/volmit/iris/util/oldnbt/NBTConstants.java new file mode 100644 index 000000000..690bf1514 --- /dev/null +++ b/src/main/java/com/volmit/iris/util/oldnbt/NBTConstants.java @@ -0,0 +1,63 @@ +/* + * Iris is a World Generator for Minecraft Bukkit Servers + * Copyright (c) 2021 Arcane Arts (Volmit Software) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.volmit.iris.util.oldnbt; + +import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; + +/* + Changes : Neil Wightman - Support 19133 Tag_Int_Array tag + */ + +/** + * A class which holds constant values. + * + * @author Graham Edgecombe + */ +public final class NBTConstants { + + /** + * The character set used by NBT (UTF-8). + */ + public static final Charset CHARSET = StandardCharsets.UTF_8; + + /** + * Tag type constants. + */ + public static final int TYPE_END = 0, + TYPE_BYTE = 1, + TYPE_SHORT = 2, + TYPE_INT = 3, + TYPE_LONG = 4, + TYPE_FLOAT = 5, + TYPE_DOUBLE = 6, + TYPE_BYTE_ARRAY = 7, + TYPE_STRING = 8, + TYPE_LIST = 9, + TYPE_COMPOUND = 10, + TYPE_INT_ARRAY = 11; + + /** + * Default private constructor. + */ + private NBTConstants() { + + } + +} diff --git a/src/main/java/com/volmit/iris/util/oldnbt/NBTInputStream.java b/src/main/java/com/volmit/iris/util/oldnbt/NBTInputStream.java new file mode 100644 index 000000000..55d6b35f1 --- /dev/null +++ b/src/main/java/com/volmit/iris/util/oldnbt/NBTInputStream.java @@ -0,0 +1,189 @@ +/* + * Iris is a World Generator for Minecraft Bukkit Servers + * Copyright (c) 2021 Arcane Arts (Volmit Software) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.volmit.iris.util.oldnbt; + +import java.io.Closeable; +import java.io.DataInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.zip.GZIPInputStream; + +/* + Changes : + Neil Wightman - Support 19133 Tag_Int_Array tag + */ + +/** + *

+ * This class reads NBT, or + * Named Binary Tag streams, and produces an object graph of subclasses of the Tag object.

+ * + *

+ * The NBT format was created by Markus Persson, and the specification may be found at + * http://www.minecraft.net/docs/NBT.txt.

+ * + * @author Graham Edgecombe + */ +public final class NBTInputStream implements Closeable { + + /** + * The data input stream. + */ + private final DataInputStream is; + + /** + * Create a new NBTInputStream, which will source its data from the specified input stream. + * + * @param is The output stream + */ + public NBTInputStream(DataInputStream is) { + this.is = is; + } + + /** + * Creates a new NBTInputStream, which will source its data from the specified input stream. + * The stream will be decompressed using GZIP. + * + * @param is The input stream. + * @throws IOException if an I/O error occurs. + */ + public NBTInputStream(InputStream is) throws IOException { + this.is = new DataInputStream(new GZIPInputStream(is)); + } + + /** + * Reads an NBT tag from the stream. + * + * @return The tag that was read. + * @throws IOException if an I/O error occurs. + */ + public Tag readTag() throws IOException { + return readTag(0); + } + + /** + * Reads an NBT from the stream. + * + * @param depth The depth of this tag. + * @return The tag that was read. + * @throws IOException if an I/O error occurs. + */ + private Tag readTag(int depth) throws IOException { + int type = is.readByte() & 0xFF; + + String name; + if (type != NBTConstants.TYPE_END) { + int nameLength = is.readShort() & 0xFFFF; + byte[] nameBytes = new byte[nameLength]; + is.readFully(nameBytes); + name = new String(nameBytes, NBTConstants.CHARSET); + } else { + name = ""; + } + + return readTagPayload(type, name, depth); + } + + /** + * Reads the payload of a tag, given the name and type. + * + * @param type The type. + * @param name The name. + * @param depth The depth. + * @return The tag. + * @throws IOException if an I/O error occurs. + */ + private Tag readTagPayload(int type, String name, int depth) throws IOException { + switch (type) { + case NBTConstants.TYPE_END: + if (depth == 0) { + throw new IOException("TAG_End found without a TAG_Compound/TAG_List tag preceding it."); + } else { + return new EndTag(); + } + case NBTConstants.TYPE_BYTE: + return new ByteTag(name, is.readByte()); + case NBTConstants.TYPE_SHORT: + return new ShortTag(name, is.readShort()); + case NBTConstants.TYPE_INT: + return new IntTag(name, is.readInt()); + case NBTConstants.TYPE_LONG: + return new LongTag(name, is.readLong()); + case NBTConstants.TYPE_FLOAT: + return new FloatTag(name, is.readFloat()); + case NBTConstants.TYPE_DOUBLE: + return new DoubleTag(name, is.readDouble()); + case NBTConstants.TYPE_BYTE_ARRAY: + int length = is.readInt(); + byte[] bytes = new byte[length]; + is.readFully(bytes); + return new ByteArrayTag(name, bytes); + case NBTConstants.TYPE_STRING: + length = is.readShort(); + bytes = new byte[length]; + is.readFully(bytes); + return new StringTag(name, new String(bytes, NBTConstants.CHARSET)); + case NBTConstants.TYPE_LIST: + int childType = is.readByte(); + length = is.readInt(); + + List tagList = new ArrayList<>(); + for (int i = 0; i < length; i++) { + Tag tag = readTagPayload(childType, "", depth + 1); + if (tag instanceof EndTag) { + throw new IOException("TAG_End not permitted in a list."); + } + tagList.add(tag); + } + + return new ListTag(name, NBTUtils.getTypeClass(childType), tagList); + case NBTConstants.TYPE_COMPOUND: + Map tagMap = new HashMap<>(); + while (true) { + Tag tag = readTag(depth + 1); + if (tag instanceof EndTag) { + break; + } else { + tagMap.put(tag.getName(), tag); + } + } + + return new CompoundTag(name, tagMap); + case NBTConstants.TYPE_INT_ARRAY: + length = is.readInt(); + int[] value = new int[length]; + for (int i = 0; i < length; i++) { + value[i] = is.readInt(); + } + return new IntArrayTag(name, value); + default: + throw new IOException("Invalid tag type: " + type + "."); + } + } + + @Override + public void close() throws IOException { + is.close(); + } + +} diff --git a/src/main/java/com/volmit/iris/util/oldnbt/NBTOutputStream.java b/src/main/java/com/volmit/iris/util/oldnbt/NBTOutputStream.java new file mode 100644 index 000000000..d2f05da65 --- /dev/null +++ b/src/main/java/com/volmit/iris/util/oldnbt/NBTOutputStream.java @@ -0,0 +1,262 @@ +/* + * Iris is a World Generator for Minecraft Bukkit Servers + * Copyright (c) 2021 Arcane Arts (Volmit Software) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.volmit.iris.util.oldnbt; + +import java.io.Closeable; +import java.io.DataOutputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.util.List; +import java.util.zip.GZIPOutputStream; +/* + Changes : Neil Wightman - Support 19133 Tag_Int_Array tag + */ + +/** + *

+ * This class writes NBT, or + * Named Binary Tag Tag objects to an underlying OutputStream.

+ * + *

+ * The NBT format was created by Markus Persson, and the specification may be found at + * http://www.minecraft.net/docs/NBT.txt.

+ * + * @author Graham Edgecombe + */ +@SuppressWarnings({"EmptyMethod", "JavaDoc"}) +public final class NBTOutputStream implements Closeable { + + /** + * The output stream. + */ + private final DataOutputStream os; + + /** + * Create a new NBTOutputStream, which will write data to the specified underlying output stream. + * + * @param os The output stream + */ + public NBTOutputStream(DataOutputStream os) { + this.os = os; + } + + /** + * Creates a new NBTOutputStream, which will write data to the specified underlying output stream. + * the stream will be compressed using GZIP. + * + * @param os The output stream. + * @throws IOException if an I/O error occurs. + */ + public NBTOutputStream(OutputStream os) throws IOException { + this.os = new DataOutputStream(new GZIPOutputStream(os)); + } + + /** + * Writes a tag. + * + * @param tag The tag to write. + * @throws IOException if an I/O error occurs. + */ + public void writeTag(Tag tag) throws IOException { + int type = NBTUtils.getTypeCode(tag.getClass()); + String name = tag.getName(); + byte[] nameBytes = name.getBytes(NBTConstants.CHARSET); + + os.writeByte(type); + os.writeShort(nameBytes.length); + os.write(nameBytes); + + if (type == NBTConstants.TYPE_END) { + throw new IOException("Named TAG_End not permitted."); + } + + writeTagPayload(tag); + } + + /** + * Writes tag payload. + * + * @param tag The tag. + * @throws IOException if an I/O error occurs. + */ + private void writeTagPayload(Tag tag) throws IOException { + int type = NBTUtils.getTypeCode(tag.getClass()); + switch (type) { + case NBTConstants.TYPE_END -> writeEndTagPayload((EndTag) tag); + case NBTConstants.TYPE_BYTE -> writeByteTagPayload((ByteTag) tag); + case NBTConstants.TYPE_SHORT -> writeShortTagPayload((ShortTag) tag); + case NBTConstants.TYPE_INT -> writeIntTagPayload((IntTag) tag); + case NBTConstants.TYPE_LONG -> writeLongTagPayload((LongTag) tag); + case NBTConstants.TYPE_FLOAT -> writeFloatTagPayload((FloatTag) tag); + case NBTConstants.TYPE_DOUBLE -> writeDoubleTagPayload((DoubleTag) tag); + case NBTConstants.TYPE_BYTE_ARRAY -> writeByteArrayTagPayload((ByteArrayTag) tag); + case NBTConstants.TYPE_STRING -> writeStringTagPayload((StringTag) tag); + case NBTConstants.TYPE_LIST -> writeListTagPayload((ListTag) tag); + case NBTConstants.TYPE_COMPOUND -> writeCompoundTagPayload((CompoundTag) tag); + case NBTConstants.TYPE_INT_ARRAY -> writeIntArrayTagPayload((IntArrayTag) tag); + default -> throw new IOException("Invalid tag type: " + type + "."); + } + } + + /** + * Writes a TAG_Byte tag. + * + * @param tag The tag. + * @throws IOException if an I/O error occurs. + */ + private void writeByteTagPayload(ByteTag tag) throws IOException { + os.writeByte(tag.getValue()); + } + + /** + * Writes a TAG_Byte_Array tag. + * + * @param tag The tag. + * @throws IOException if an I/O error occurs. + */ + private void writeByteArrayTagPayload(ByteArrayTag tag) throws IOException { + byte[] bytes = tag.getValue(); + os.writeInt(bytes.length); + os.write(bytes); + } + + + /** + * Writes a TAG_Compound tag. + * + * @param tag The tag. + * @throws IOException if an I/O error occurs. + */ + private void writeCompoundTagPayload(CompoundTag tag) throws IOException { + for (Tag childTag : tag.getValue().values()) { + writeTag(childTag); + } + os.writeByte((byte) 0); // end tag - better way? + } + + /** + * Writes a TAG_List tag. + * + * @param tag The tag. + * @throws IOException if an I/O error occurs. + */ + private void writeListTagPayload(ListTag tag) throws IOException { + Class clazz = tag.getType(); + List tags = tag.getValue(); + int size = tags.size(); + + os.writeByte(NBTUtils.getTypeCode(clazz)); + os.writeInt(size); + for (Tag value : tags) { + writeTagPayload(value); + } + } + + /** + * Writes a TAG_String tag. + * + * @param tag The tag. + * @throws IOException if an I/O error occurs. + */ + private void writeStringTagPayload(StringTag tag) throws IOException { + byte[] bytes = tag.getValue().getBytes(NBTConstants.CHARSET); + os.writeShort(bytes.length); + os.write(bytes); + } + + /** + * Writes a TAG_Double tag. + * + * @param tag The tag. + * @throws IOException if an I/O error occurs. + */ + private void writeDoubleTagPayload(DoubleTag tag) throws IOException { + os.writeDouble(tag.getValue()); + } + + /** + * Writes a TAG_Float tag. + * + * @param tag The tag. + * @throws IOException if an I/O error occurs. + */ + private void writeFloatTagPayload(FloatTag tag) throws IOException { + os.writeFloat(tag.getValue()); + } + + /** + * Writes a TAG_Long tag. + * + * @param tag The tag. + * @throws IOException if an I/O error occurs. + */ + private void writeLongTagPayload(LongTag tag) throws IOException { + os.writeLong(tag.getValue()); + } + + /** + * Writes a TAG_Int tag. + * + * @param tag The tag. + * @throws IOException if an I/O error occurs. + */ + private void writeIntTagPayload(IntTag tag) throws IOException { + os.writeInt(tag.getValue()); + } + + /** + * Writes a TAG_Short tag. + * + * @param tag The tag. + * @throws IOException if an I/O error occurs. + */ + private void writeShortTagPayload(ShortTag tag) throws IOException { + os.writeShort(tag.getValue()); + } + + /** + * Writes a TAG_Empty tag. + * + * @param tag The tag. + * @throws IOException if an I/O error occurs. + */ + private void writeEndTagPayload(EndTag tag) { + /* empty */ + } + + /** + * Writes a TAG_Int_Array tag. + * + * @param tag The tag. + * @throws IOException if an I/O error occurs. + */ + private void writeIntArrayTagPayload(IntArrayTag tag) throws IOException { + final int[] values = tag.getValue(); + os.writeInt(values.length); + for (final int value : values) { + os.writeInt(value); + } + } + + @Override + public void close() throws IOException { + os.close(); + } + +} diff --git a/src/main/java/com/volmit/iris/util/oldnbt/NBTUtils.java b/src/main/java/com/volmit/iris/util/oldnbt/NBTUtils.java new file mode 100644 index 000000000..3062584a7 --- /dev/null +++ b/src/main/java/com/volmit/iris/util/oldnbt/NBTUtils.java @@ -0,0 +1,137 @@ +/* + * Iris is a World Generator for Minecraft Bukkit Servers + * Copyright (c) 2021 Arcane Arts (Volmit Software) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.volmit.iris.util.oldnbt; + +/* + Changes : Neil Wightman - Support 19133 Tag_Int_Array tag + */ + +/** + * A class which contains NBT-related utility methods. This currently supports reading 19133 but only writing 19132. + * + * @author Graham Edgecombe + */ +public final class NBTUtils { + + /** + * Gets the type name of a tag. + * + * @param clazz The tag class. + * @return The type name. + */ + public static String getTypeName(Class clazz) { + if (clazz.equals(ByteArrayTag.class)) { + return "TAG_Byte_Array"; + } else if (clazz.equals(ByteTag.class)) { + return "TAG_Byte"; + } else if (clazz.equals(CompoundTag.class)) { + return "TAG_Compound"; + } else if (clazz.equals(DoubleTag.class)) { + return "TAG_Double"; + } else if (clazz.equals(EndTag.class)) { + return "TAG_End"; + } else if (clazz.equals(FloatTag.class)) { + return "TAG_Float"; + } else if (clazz.equals(IntTag.class)) { + return "TAG_Int"; + } else if (clazz.equals(ListTag.class)) { + return "TAG_List"; + } else if (clazz.equals(LongTag.class)) { + return "TAG_Long"; + } else if (clazz.equals(ShortTag.class)) { + return "TAG_Short"; + } else if (clazz.equals(StringTag.class)) { + return "TAG_String"; + } else if (clazz.equals(IntArrayTag.class)) { + return "TAG_Int_Array"; + } else { + throw new IllegalArgumentException("Invalid tag classs (" + clazz.getName() + ")."); + } + } + + /** + * Gets the type code of a tag class. + * + * @param clazz The tag class. + * @return The type code. + * @throws IllegalArgumentException if the tag class is invalid. + */ + public static int getTypeCode(Class clazz) { + if (clazz.equals(ByteArrayTag.class)) { + return NBTConstants.TYPE_BYTE_ARRAY; + } else if (clazz.equals(ByteTag.class)) { + return NBTConstants.TYPE_BYTE; + } else if (clazz.equals(CompoundTag.class)) { + return NBTConstants.TYPE_COMPOUND; + } else if (clazz.equals(DoubleTag.class)) { + return NBTConstants.TYPE_DOUBLE; + } else if (clazz.equals(EndTag.class)) { + return NBTConstants.TYPE_END; + } else if (clazz.equals(FloatTag.class)) { + return NBTConstants.TYPE_FLOAT; + } else if (clazz.equals(IntTag.class)) { + return NBTConstants.TYPE_INT; + } else if (clazz.equals(ListTag.class)) { + return NBTConstants.TYPE_LIST; + } else if (clazz.equals(LongTag.class)) { + return NBTConstants.TYPE_LONG; + } else if (clazz.equals(ShortTag.class)) { + return NBTConstants.TYPE_SHORT; + } else if (clazz.equals(StringTag.class)) { + return NBTConstants.TYPE_STRING; + } else if (clazz.equals(IntArrayTag.class)) { + return NBTConstants.TYPE_INT_ARRAY; + } else { + throw new IllegalArgumentException("Invalid tag classs (" + clazz.getName() + ")."); + } + } + + /** + * Gets the class of a type of tag. + * + * @param type The type. + * @return The class. + * @throws IllegalArgumentException if the tag type is invalid. + */ + public static Class getTypeClass(int type) { + return switch (type) { + case NBTConstants.TYPE_END -> EndTag.class; + case NBTConstants.TYPE_BYTE -> ByteTag.class; + case NBTConstants.TYPE_SHORT -> ShortTag.class; + case NBTConstants.TYPE_INT -> IntTag.class; + case NBTConstants.TYPE_LONG -> LongTag.class; + case NBTConstants.TYPE_FLOAT -> FloatTag.class; + case NBTConstants.TYPE_DOUBLE -> DoubleTag.class; + case NBTConstants.TYPE_BYTE_ARRAY -> ByteArrayTag.class; + case NBTConstants.TYPE_STRING -> StringTag.class; + case NBTConstants.TYPE_LIST -> ListTag.class; + case NBTConstants.TYPE_COMPOUND -> CompoundTag.class; + case NBTConstants.TYPE_INT_ARRAY -> IntArrayTag.class; + default -> throw new IllegalArgumentException("Invalid tag type : " + type + "."); + }; + } + + /** + * Default private constructor. + */ + private NBTUtils() { + + } + +} diff --git a/src/main/java/com/volmit/iris/util/oldnbt/ShortTag.java b/src/main/java/com/volmit/iris/util/oldnbt/ShortTag.java new file mode 100644 index 000000000..e1239e016 --- /dev/null +++ b/src/main/java/com/volmit/iris/util/oldnbt/ShortTag.java @@ -0,0 +1,59 @@ +/* + * Iris is a World Generator for Minecraft Bukkit Servers + * Copyright (c) 2021 Arcane Arts (Volmit Software) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.volmit.iris.util.oldnbt; + +/** + * The TAG_Short tag. + * + * @author Graham Edgecombe + */ +public final class ShortTag extends Tag { + + /** + * The value. + */ + private final short value; + + /** + * Creates the tag. + * + * @param name The name. + * @param value The value. + */ + public ShortTag(String name, short value) { + super(name); + this.value = value; + } + + @Override + public Short getValue() { + return value; + } + + @Override + public String toString() { + String name = getName(); + String append = ""; + if (name != null && !name.equals("")) { + append = "(\"" + this.getName() + "\")"; + } + return "TAG_Short" + append + ": " + value; + } + +} diff --git a/src/main/java/com/volmit/iris/util/oldnbt/StringTag.java b/src/main/java/com/volmit/iris/util/oldnbt/StringTag.java new file mode 100644 index 000000000..54ddce7da --- /dev/null +++ b/src/main/java/com/volmit/iris/util/oldnbt/StringTag.java @@ -0,0 +1,59 @@ +/* + * Iris is a World Generator for Minecraft Bukkit Servers + * Copyright (c) 2021 Arcane Arts (Volmit Software) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.volmit.iris.util.oldnbt; + +/** + * The TAG_String tag. + * + * @author Graham Edgecombe + */ +public final class StringTag extends Tag { + + /** + * The value. + */ + private final String value; + + /** + * Creates the tag. + * + * @param name The name. + * @param value The value. + */ + public StringTag(String name, String value) { + super(name); + this.value = value; + } + + @Override + public String getValue() { + return value; + } + + @Override + public String toString() { + String name = getName(); + String append = ""; + if (name != null && !name.equals("")) { + append = "(\"" + this.getName() + "\")"; + } + return "TAG_String" + append + ": " + value; + } + +} diff --git a/src/main/java/com/volmit/iris/util/oldnbt/Tag.java b/src/main/java/com/volmit/iris/util/oldnbt/Tag.java new file mode 100644 index 000000000..d5fdac4ab --- /dev/null +++ b/src/main/java/com/volmit/iris/util/oldnbt/Tag.java @@ -0,0 +1,58 @@ +/* + * Iris is a World Generator for Minecraft Bukkit Servers + * Copyright (c) 2021 Arcane Arts (Volmit Software) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.volmit.iris.util.oldnbt; + +/** + * Represents a single NBT tag. + * + * @author Graham Edgecombe + */ +public abstract class Tag { + + /** + * The name of this tag. + */ + private final String name; + + /** + * Creates the tag with the specified name. + * + * @param name The name. + */ + public Tag(String name) { + this.name = name; + } + + /** + * Gets the name of this tag. + * + * @return The name of this tag. + */ + public final String getName() { + return name; + } + + /** + * Gets the value of this tag. + * + * @return The value of this tag. + */ + public abstract Object getValue(); + +}