mirror of
https://github.com/plexusorg/Plex-FAWE.git
synced 2025-07-12 04:28:34 +00:00
Copy paste/merge FAWE classes to this WorldEdit fork
- so certain people can look at the diff and complain about my sloppy code :( Signed-off-by: Jesse Boyd <jessepaleg@gmail.com>
This commit is contained in:
@ -1,24 +1,6 @@
|
||||
/*
|
||||
* WorldEdit, a Minecraft world manipulation toolkit
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldEdit team and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser 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 Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.jnbt;
|
||||
|
||||
import com.sk89q.worldedit.function.entity.ExtentEntityCopy;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
@ -30,7 +12,6 @@ import java.util.Map;
|
||||
public final class CompoundTag extends Tag {
|
||||
|
||||
private final Map<String, Tag> value;
|
||||
|
||||
/**
|
||||
* Creates the tag with an empty name.
|
||||
*
|
||||
@ -38,7 +19,16 @@ public final class CompoundTag extends Tag {
|
||||
*/
|
||||
public CompoundTag(Map<String, Tag> value) {
|
||||
super();
|
||||
this.value = Collections.unmodifiableMap(value);
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Object> getRaw() {
|
||||
HashMap<String, Object> raw = new HashMap<>();
|
||||
for (Map.Entry<String, Tag> entry : value.entrySet()) {
|
||||
raw.put(entry.getKey(), entry.getValue().getRaw());
|
||||
}
|
||||
return raw;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -72,7 +62,7 @@ public final class CompoundTag extends Tag {
|
||||
* @return the builder
|
||||
*/
|
||||
public CompoundTagBuilder createBuilder() {
|
||||
return new CompoundTagBuilder(new HashMap<>(value));
|
||||
return new CompoundTagBuilder(new HashMap<String, Tag>(value));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -435,4 +425,7 @@ public final class CompoundTag extends Tag {
|
||||
return bldr.toString();
|
||||
}
|
||||
|
||||
}
|
||||
public static Class<?> inject() {
|
||||
return CompoundTag.class;
|
||||
}
|
||||
}
|
@ -19,11 +19,11 @@
|
||||
|
||||
package com.sk89q.jnbt;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
/**
|
||||
* Helps create compound tags.
|
||||
*/
|
||||
@ -34,8 +34,8 @@ public class CompoundTagBuilder {
|
||||
/**
|
||||
* Create a new instance.
|
||||
*/
|
||||
CompoundTagBuilder() {
|
||||
this.entries = new HashMap<>();
|
||||
public CompoundTagBuilder() {
|
||||
this.entries = new HashMap<String, Tag>();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -43,7 +43,7 @@ public class CompoundTagBuilder {
|
||||
*
|
||||
* @param value the value
|
||||
*/
|
||||
CompoundTagBuilder(Map<String, Tag> value) {
|
||||
public CompoundTagBuilder(Map<String, Tag> value) {
|
||||
checkNotNull(value);
|
||||
this.entries = value;
|
||||
}
|
||||
@ -133,18 +133,6 @@ public class CompoundTagBuilder {
|
||||
return put(key, new IntTag(value));
|
||||
}
|
||||
|
||||
/**
|
||||
* Put the given key and value into the compound tag as a
|
||||
* {@code LongArrayTag}.
|
||||
*
|
||||
* @param key they key
|
||||
* @param value the value
|
||||
* @return this object
|
||||
*/
|
||||
public CompoundTagBuilder putLongArray(String key, long[] value) {
|
||||
return put(key, new LongArrayTag(value));
|
||||
}
|
||||
|
||||
/**
|
||||
* Put the given key and value into the compound tag as a
|
||||
* {@code LongTag}.
|
||||
@ -201,7 +189,7 @@ public class CompoundTagBuilder {
|
||||
* @return the new compound tag
|
||||
*/
|
||||
public CompoundTag build() {
|
||||
return new CompoundTag(new HashMap<>(entries));
|
||||
return new CompoundTag(new HashMap<String, Tag>(entries));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -213,4 +201,7 @@ public class CompoundTagBuilder {
|
||||
return new CompoundTagBuilder();
|
||||
}
|
||||
|
||||
}
|
||||
public static Class<?> inject() {
|
||||
return CompoundTagBuilder.class;
|
||||
}
|
||||
}
|
@ -1,38 +1,20 @@
|
||||
/*
|
||||
* WorldEdit, a Minecraft world manipulation toolkit
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldEdit team and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser 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 Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.jnbt;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.NoSuchElementException;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
/**
|
||||
* The {@code TAG_List} tag.
|
||||
*/
|
||||
public final class ListTag extends Tag {
|
||||
public final class ListTag<T extends Tag> extends Tag {
|
||||
|
||||
private final Class<? extends Tag> type;
|
||||
private final List<Tag> value;
|
||||
private final Class<T> type;
|
||||
private final List<T> value;
|
||||
|
||||
/**
|
||||
* Creates the tag with an empty name.
|
||||
@ -40,11 +22,20 @@ public final class ListTag extends Tag {
|
||||
* @param type the type of tag
|
||||
* @param value the value of the tag
|
||||
*/
|
||||
public ListTag(Class<? extends Tag> type, List<? extends Tag> value) {
|
||||
public ListTag(Class<T> type, List<T> value) {
|
||||
super();
|
||||
checkNotNull(value);
|
||||
this.type = type;
|
||||
this.value = Collections.unmodifiableList(value);
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Object> getRaw() {
|
||||
ArrayList<Object> raw = new ArrayList<>();
|
||||
for (Tag t : value) {
|
||||
raw.add(t.getRaw());
|
||||
}
|
||||
return raw;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -52,12 +43,12 @@ public final class ListTag extends Tag {
|
||||
*
|
||||
* @return The type of item in this list.
|
||||
*/
|
||||
public Class<? extends Tag> getType() {
|
||||
public Class<T> getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Tag> getValue() {
|
||||
public List<T> getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
@ -73,16 +64,17 @@ public final class ListTag extends Tag {
|
||||
|
||||
/**
|
||||
* Get the tag if it exists at the given index.
|
||||
*
|
||||
*
|
||||
* @param index the index
|
||||
* @return the tag or null
|
||||
*/
|
||||
@Nullable
|
||||
public Tag getIfExists(int index) {
|
||||
if (index >= value.size()) {
|
||||
try {
|
||||
return value.get(index);
|
||||
} catch (NoSuchElementException e) {
|
||||
return null;
|
||||
}
|
||||
return value.get(index);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -427,4 +419,8 @@ public final class ListTag extends Tag {
|
||||
return bldr.toString();
|
||||
}
|
||||
|
||||
}
|
||||
public static Class<?> inject() {
|
||||
return ListTag.class;
|
||||
}
|
||||
|
||||
}
|
@ -19,13 +19,13 @@
|
||||
|
||||
package com.sk89q.jnbt;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
/**
|
||||
* Helps create list tags.
|
||||
*/
|
||||
|
@ -16,18 +16,13 @@
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.jnbt;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
/**
|
||||
* The {@code TAG_Long_Array} tag.
|
||||
*/
|
||||
public class LongArrayTag extends Tag {
|
||||
|
||||
private final long[] value;
|
||||
|
||||
/**
|
||||
* Creates the tag with an empty name.
|
||||
*
|
||||
@ -38,12 +33,10 @@ public class LongArrayTag extends Tag {
|
||||
checkNotNull(value);
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long[] getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder hex = new StringBuilder();
|
||||
@ -56,5 +49,4 @@ public class LongArrayTag extends Tag {
|
||||
}
|
||||
return "TAG_Long_Array(" + hex + ")";
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@ -19,7 +19,10 @@
|
||||
|
||||
package com.sk89q.jnbt;
|
||||
|
||||
import com.boydti.fawe.jnbt.NBTStreamer;
|
||||
import com.boydti.fawe.object.RunnableVal2;
|
||||
import java.io.Closeable;
|
||||
import java.io.DataInput;
|
||||
import java.io.DataInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
@ -27,24 +30,26 @@ import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.function.Function;
|
||||
|
||||
/**
|
||||
* This class reads <strong>NBT</strong>, or <strong>Named Binary Tag</strong>
|
||||
* streams, and produces an object graph of subclasses of the {@code Tag}
|
||||
* object.
|
||||
*
|
||||
* <p>
|
||||
* <p>The NBT format was created by Markus Persson, and the specification may be
|
||||
* found at <a href="http://www.minecraft.net/docs/NBT.txt">
|
||||
* http://www.minecraft.net/docs/NBT.txt</a>.</p>
|
||||
*/
|
||||
public final class NBTInputStream implements Closeable {
|
||||
|
||||
private final DataInputStream is;
|
||||
private final DataInput is;
|
||||
|
||||
/**
|
||||
* Creates a new {@code NBTInputStream}, which will source its data
|
||||
* from the specified input stream.
|
||||
*
|
||||
*
|
||||
* @param is the input stream
|
||||
* @throws IOException if an I/O error occurs
|
||||
*/
|
||||
@ -52,9 +57,17 @@ public final class NBTInputStream implements Closeable {
|
||||
this.is = new DataInputStream(is);
|
||||
}
|
||||
|
||||
public NBTInputStream(DataInputStream dis) {
|
||||
this.is = dis;
|
||||
}
|
||||
|
||||
public NBTInputStream(DataInput di) {
|
||||
this.is = di;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads an NBT tag from the stream.
|
||||
*
|
||||
*
|
||||
* @return The tag that was read.
|
||||
* @throws IOException if an I/O error occurs.
|
||||
*/
|
||||
@ -62,117 +75,543 @@ public final class NBTInputStream implements Closeable {
|
||||
return readNamedTag(0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads an NBT map from the stream.
|
||||
*
|
||||
* @return The map that was read.
|
||||
* @throws IOException if an I/O error occurs.
|
||||
*/
|
||||
public NamedData readNamedData() throws IOException {
|
||||
return readNamedData(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 NamedTag readNamedTag(int depth) throws IOException {
|
||||
int type = is.readByte() & 0xFF;
|
||||
return new NamedTag(readNamedTagName(type), readTagPayload(type, depth));
|
||||
}
|
||||
|
||||
private NamedData readNamedData(int depth) throws IOException {
|
||||
int type = is.readByte();
|
||||
return new NamedData(readNamedTagName(type), readDataPayload(type, depth));
|
||||
}
|
||||
|
||||
public Tag readTag() throws IOException {
|
||||
int type = is.readByte();
|
||||
return readTagPayload(type, 0);
|
||||
}
|
||||
|
||||
public Object readData() throws IOException {
|
||||
int type = is.readByte();
|
||||
return readDataPayload(type, 0);
|
||||
}
|
||||
|
||||
public void readNamedTagLazy(Function<String, BiConsumer> getReader) throws IOException {
|
||||
int type = is.readByte();
|
||||
String name = readNamedTagName(type);
|
||||
BiConsumer reader = getReader.apply(name);
|
||||
if (reader != null) {
|
||||
reader.accept(0, readTagPaylodRaw(type, 0));
|
||||
return;
|
||||
}
|
||||
readTagPaylodLazy(type, 0, name, getReader);
|
||||
}
|
||||
|
||||
public String readNamedTagName(int type) throws IOException {
|
||||
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);
|
||||
return new String(nameBytes, NBTConstants.CHARSET);
|
||||
} else {
|
||||
name = "";
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
return new NamedTag(name, readTagPayload(type, depth));
|
||||
private byte[] buf;
|
||||
|
||||
public void readTagPaylodLazy(int type, int depth, String node, Function<String, BiConsumer> getReader) throws IOException {
|
||||
switch (type) {
|
||||
case NBTConstants.TYPE_END:
|
||||
return;
|
||||
case NBTConstants.TYPE_BYTE:
|
||||
is.skipBytes(1);
|
||||
return;
|
||||
case NBTConstants.TYPE_SHORT:
|
||||
is.skipBytes(2);
|
||||
return;
|
||||
case NBTConstants.TYPE_INT:
|
||||
is.skipBytes(4);
|
||||
return;
|
||||
case NBTConstants.TYPE_LONG:
|
||||
is.skipBytes(8);
|
||||
return;
|
||||
case NBTConstants.TYPE_FLOAT:
|
||||
is.skipBytes(4);
|
||||
return;
|
||||
case NBTConstants.TYPE_DOUBLE:
|
||||
is.skipBytes(8);
|
||||
return;
|
||||
case NBTConstants.TYPE_STRING:
|
||||
int length = is.readShort();
|
||||
is.skipBytes(length);
|
||||
return;
|
||||
case NBTConstants.TYPE_BYTE_ARRAY:
|
||||
BiConsumer reader = getReader.apply(node + ".?");
|
||||
length = is.readInt();
|
||||
if (reader != null) {
|
||||
reader.accept(length, NBTConstants.TYPE_BYTE);
|
||||
}
|
||||
reader = getReader.apply(node + ".#");
|
||||
if (reader == null) {
|
||||
is.skipBytes(length);
|
||||
return;
|
||||
}
|
||||
if (reader instanceof NBTStreamer.ByteReader) {
|
||||
NBTStreamer.ByteReader byteReader = (NBTStreamer.ByteReader) reader;
|
||||
int i = 0;
|
||||
if (is instanceof InputStream) {
|
||||
DataInputStream dis = (DataInputStream) is;
|
||||
if (length > 1024) {
|
||||
if (buf == null) {
|
||||
buf = new byte[1024];
|
||||
}
|
||||
int left = length;
|
||||
for (; left > 1024; left -= 1024) {
|
||||
dis.readFully(buf);
|
||||
for (byte b : buf) {
|
||||
byteReader.run(i++, b & 0xFF);
|
||||
}
|
||||
}
|
||||
}
|
||||
for (; i < length; i++) {
|
||||
byteReader.run(i, dis.read());
|
||||
}
|
||||
} else {
|
||||
if (length > 1024) {
|
||||
if (buf == null) {
|
||||
buf = new byte[1024];
|
||||
}
|
||||
int left = length;
|
||||
for (; left > 1024; left -= 1024) {
|
||||
is.readFully(buf);
|
||||
for (byte b : buf) {
|
||||
byteReader.run(i++, b & 0xFF);
|
||||
}
|
||||
}
|
||||
}
|
||||
for (; i < length; i++) {
|
||||
byteReader.run(i, is.readByte() & 0xFF);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (int i = 0; i < length; i++) {
|
||||
reader.accept(i, is.readByte());
|
||||
}
|
||||
}
|
||||
return;
|
||||
case NBTConstants.TYPE_LIST:
|
||||
int childType = is.readByte();
|
||||
if (childType == NBTConstants.TYPE_LIST) {
|
||||
childType = NBTConstants.TYPE_COMPOUND;
|
||||
}
|
||||
length = is.readInt();
|
||||
reader = getReader.apply(node + ".?");
|
||||
if (reader != null) {
|
||||
reader.accept(length, childType);
|
||||
}
|
||||
node += ".#";
|
||||
reader = getReader.apply(node);
|
||||
depth++;
|
||||
if (reader == null) {
|
||||
for (int i = 0; i < length; ++i) {
|
||||
readTagPaylodLazy(childType, depth, node, getReader);
|
||||
}
|
||||
return;
|
||||
}
|
||||
for (int i = 0; i < length; ++i) {
|
||||
reader.accept(i, readTagPayload(childType, depth));
|
||||
}
|
||||
return;
|
||||
case NBTConstants.TYPE_COMPOUND:
|
||||
depth++;
|
||||
// 3
|
||||
for (int i = 0; ; i++) {
|
||||
childType = is.readByte();
|
||||
if (childType == NBTConstants.TYPE_END) {
|
||||
return;
|
||||
}
|
||||
String name = readNamedTagName(childType);
|
||||
String childNode = node + "." + name;
|
||||
reader = getReader.apply(childNode);
|
||||
if (reader == null) {
|
||||
readTagPaylodLazy(childType, depth, childNode, getReader);
|
||||
continue;
|
||||
}
|
||||
reader.accept(i, readTagPaylodRaw(childType, depth));
|
||||
}
|
||||
case NBTConstants.TYPE_INT_ARRAY: {
|
||||
length = is.readInt();
|
||||
reader = getReader.apply(node + ".?");
|
||||
if (reader != null) {
|
||||
reader.accept(length, NBTConstants.TYPE_INT);
|
||||
}
|
||||
reader = getReader.apply(node + ".#");
|
||||
if (reader == null) {
|
||||
is.skipBytes(length << 2);
|
||||
return;
|
||||
}
|
||||
if (reader instanceof NBTStreamer.ByteReader) {
|
||||
NBTStreamer.ByteReader byteReader = (NBTStreamer.ByteReader) reader;
|
||||
for (int i = 0; i < length; i++) {
|
||||
byteReader.run(i, is.readInt());
|
||||
}
|
||||
} else {
|
||||
for (int i = 0; i < length; i++) {
|
||||
reader.accept(i, is.readInt());
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
case NBTConstants.TYPE_LONG_ARRAY: {
|
||||
length = is.readInt();
|
||||
reader = getReader.apply(node + ".?");
|
||||
if (reader != null) {
|
||||
reader.accept(length, NBTConstants.TYPE_LONG);
|
||||
}
|
||||
reader = getReader.apply(node + ".#");
|
||||
if (reader == null) {
|
||||
is.skipBytes(length << 3);
|
||||
return;
|
||||
}
|
||||
if (reader instanceof NBTStreamer.LongReader) {
|
||||
NBTStreamer.LongReader longReader = (NBTStreamer.LongReader) reader;
|
||||
for (int i = 0; i < length; i++) {
|
||||
longReader.run(i, is.readLong());
|
||||
}
|
||||
} else {
|
||||
for (int i = 0; i < length; i++) {
|
||||
reader.accept(i, is.readLong());
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
default:
|
||||
throw new IOException("Invalid tag type: " + type + ".");
|
||||
}
|
||||
}
|
||||
|
||||
public static int getSize(int type) {
|
||||
switch (type) {
|
||||
default:
|
||||
case NBTConstants.TYPE_END:
|
||||
case NBTConstants.TYPE_BYTE:
|
||||
return 1;
|
||||
case NBTConstants.TYPE_BYTE_ARRAY:
|
||||
case NBTConstants.TYPE_STRING:
|
||||
case NBTConstants.TYPE_LIST:
|
||||
case NBTConstants.TYPE_COMPOUND:
|
||||
case NBTConstants.TYPE_INT_ARRAY:
|
||||
case NBTConstants.TYPE_LONG_ARRAY:
|
||||
case NBTConstants.TYPE_SHORT:
|
||||
return 2;
|
||||
case NBTConstants.TYPE_FLOAT:
|
||||
case NBTConstants.TYPE_INT:
|
||||
return 4;
|
||||
case NBTConstants.TYPE_DOUBLE:
|
||||
case NBTConstants.TYPE_LONG:
|
||||
return 8;
|
||||
}
|
||||
}
|
||||
|
||||
private Object readTagPaylodRaw(int type, 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 null;
|
||||
}
|
||||
case NBTConstants.TYPE_BYTE:
|
||||
return (is.readByte());
|
||||
case NBTConstants.TYPE_SHORT:
|
||||
return (is.readShort());
|
||||
case NBTConstants.TYPE_INT:
|
||||
return (is.readInt());
|
||||
case NBTConstants.TYPE_LONG:
|
||||
return (is.readLong());
|
||||
case NBTConstants.TYPE_FLOAT:
|
||||
return (is.readFloat());
|
||||
case NBTConstants.TYPE_DOUBLE:
|
||||
return (is.readDouble());
|
||||
case NBTConstants.TYPE_BYTE_ARRAY:
|
||||
int length = is.readInt();
|
||||
byte[] bytes = new byte[length];
|
||||
is.readFully(bytes);
|
||||
return (bytes);
|
||||
case NBTConstants.TYPE_STRING:
|
||||
length = is.readShort();
|
||||
bytes = new byte[length];
|
||||
is.readFully(bytes);
|
||||
return (new String(bytes, NBTConstants.CHARSET));
|
||||
case NBTConstants.TYPE_LIST:
|
||||
int childType = is.readByte();
|
||||
if (childType == NBTConstants.TYPE_LIST) {
|
||||
childType = NBTConstants.TYPE_COMPOUND;
|
||||
}
|
||||
length = is.readInt();
|
||||
List<Tag> tagList = new ArrayList<Tag>();
|
||||
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 (tagList);
|
||||
case NBTConstants.TYPE_COMPOUND:
|
||||
Map<String, Tag> tagMap = new HashMap<String, Tag>();
|
||||
while (true) {
|
||||
NamedTag namedTag = readNamedTag(depth + 1);
|
||||
Tag tag = namedTag.getTag();
|
||||
if (tag instanceof EndTag) {
|
||||
break;
|
||||
} else {
|
||||
tagMap.put(namedTag.getName(), tag);
|
||||
}
|
||||
}
|
||||
return (tagMap);
|
||||
case NBTConstants.TYPE_INT_ARRAY: {
|
||||
length = is.readInt();
|
||||
int[] data = new int[length];
|
||||
if (buf == null) {
|
||||
buf = new byte[1024];
|
||||
}
|
||||
int index = 0;
|
||||
while (length > 0) {
|
||||
int toRead = Math.min(length << 2, buf.length);
|
||||
is.readFully(buf, 0, toRead);
|
||||
for (int i = 0; i < toRead; i += 4, index++) {
|
||||
data[index] = ((buf[i] << 24) + (buf[i + 1] << 16) + (buf[i + 2] << 8) + (buf[i + 3]));
|
||||
}
|
||||
length -= toRead;
|
||||
}
|
||||
return (data);
|
||||
}
|
||||
case NBTConstants.TYPE_LONG_ARRAY: {
|
||||
length = is.readInt();
|
||||
long[] data = new long[length];
|
||||
if (buf == null) {
|
||||
buf = new byte[1024];
|
||||
}
|
||||
int index = 0;
|
||||
while (length > 0) {
|
||||
int toRead = Math.min(length << 3, buf.length);
|
||||
is.readFully(buf, 0, toRead);
|
||||
for (int i = 0; i < toRead; i += 8, index++) {
|
||||
data[index] = (((long) buf[i] << 56) | ((long) buf[i + 1] << 48) | ((long) buf[i + 2] << 40) | ((long) buf[i + 3] << 32) | (buf[i + 4] << 24) | (buf[i + 5] << 16) | (buf[i + 6] << 8) | (buf[i + 7]));
|
||||
}
|
||||
length -= toRead;
|
||||
}
|
||||
return (data);
|
||||
}
|
||||
default:
|
||||
throw new IOException("Invalid tag type: " + type + ".");
|
||||
}
|
||||
}
|
||||
|
||||
public Object readDataPayload(int type, 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 null;
|
||||
}
|
||||
case NBTConstants.TYPE_BYTE:
|
||||
return is.readByte();
|
||||
case NBTConstants.TYPE_SHORT:
|
||||
return is.readShort();
|
||||
case NBTConstants.TYPE_INT:
|
||||
return is.readInt();
|
||||
case NBTConstants.TYPE_LONG:
|
||||
return is.readLong();
|
||||
case NBTConstants.TYPE_FLOAT:
|
||||
return is.readFloat();
|
||||
case NBTConstants.TYPE_DOUBLE:
|
||||
return is.readDouble();
|
||||
case NBTConstants.TYPE_BYTE_ARRAY:
|
||||
int length = is.readInt();
|
||||
byte[] bytes = new byte[length];
|
||||
is.readFully(bytes);
|
||||
return bytes;
|
||||
case NBTConstants.TYPE_STRING:
|
||||
length = is.readShort();
|
||||
bytes = new byte[length];
|
||||
is.readFully(bytes);
|
||||
return new String(bytes, NBTConstants.CHARSET);
|
||||
case NBTConstants.TYPE_LIST:
|
||||
int childType = is.readByte();
|
||||
if (childType == NBTConstants.TYPE_LIST) {
|
||||
childType = NBTConstants.TYPE_COMPOUND;
|
||||
}
|
||||
length = is.readInt();
|
||||
ArrayList<Object> list = new ArrayList<>();
|
||||
for (int i = 0; i < length; ++i) {
|
||||
Object obj = readDataPayload(childType, depth + 1);
|
||||
if (obj == null) {
|
||||
throw new IOException("TAG_End not permitted in a list.");
|
||||
}
|
||||
list.add(obj);
|
||||
}
|
||||
|
||||
return list;
|
||||
case NBTConstants.TYPE_COMPOUND:
|
||||
Map<String, Object> map = new HashMap<>();
|
||||
while (true) {
|
||||
int newType = is.readByte();
|
||||
String name = readNamedTagName(newType);
|
||||
Object data = readDataPayload(newType, depth + 1);
|
||||
if (data == null) {
|
||||
break;
|
||||
} else {
|
||||
map.put(name, data);
|
||||
}
|
||||
}
|
||||
|
||||
return map;
|
||||
case NBTConstants.TYPE_INT_ARRAY: {
|
||||
length = is.readInt();
|
||||
int[] data = new int[length];
|
||||
for (int i = 0; i < length; i++) {
|
||||
data[i] = is.readInt();
|
||||
}
|
||||
return data;
|
||||
}
|
||||
case NBTConstants.TYPE_LONG_ARRAY: {
|
||||
length = is.readInt();
|
||||
long[] data = new long[length];
|
||||
for (int i = 0; i < length; i++) {
|
||||
data[i] = is.readLong();
|
||||
}
|
||||
return data;
|
||||
}
|
||||
default:
|
||||
throw new IOException("Invalid tag type: " + type + ".");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads the payload of a tag given the type.
|
||||
*
|
||||
* @param type the type
|
||||
*
|
||||
* @param type the type
|
||||
* @param depth the depth
|
||||
* @return the tag
|
||||
* @throws IOException if an I/O error occurs.
|
||||
*/
|
||||
private Tag readTagPayload(int type, int depth) throws IOException {
|
||||
public Tag readTagPayload(int type, 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(is.readByte());
|
||||
case NBTConstants.TYPE_SHORT:
|
||||
return new ShortTag(is.readShort());
|
||||
case NBTConstants.TYPE_INT:
|
||||
return new IntTag(is.readInt());
|
||||
case NBTConstants.TYPE_LONG:
|
||||
return new LongTag(is.readLong());
|
||||
case NBTConstants.TYPE_FLOAT:
|
||||
return new FloatTag(is.readFloat());
|
||||
case NBTConstants.TYPE_DOUBLE:
|
||||
return new DoubleTag(is.readDouble());
|
||||
case NBTConstants.TYPE_BYTE_ARRAY:
|
||||
int length = is.readInt();
|
||||
byte[] bytes = new byte[length];
|
||||
is.readFully(bytes);
|
||||
return new ByteArrayTag(bytes);
|
||||
case NBTConstants.TYPE_STRING:
|
||||
length = is.readShort();
|
||||
bytes = new byte[length];
|
||||
is.readFully(bytes);
|
||||
return new StringTag(new String(bytes, NBTConstants.CHARSET));
|
||||
case NBTConstants.TYPE_LIST:
|
||||
int childType = is.readByte();
|
||||
length = is.readInt();
|
||||
|
||||
List<Tag> 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(NBTUtils.getTypeClass(childType), tagList);
|
||||
case NBTConstants.TYPE_COMPOUND:
|
||||
Map<String, Tag> tagMap = new HashMap<>();
|
||||
while (true) {
|
||||
NamedTag namedTag = readNamedTag(depth + 1);
|
||||
Tag tag = namedTag.getTag();
|
||||
if (tag instanceof EndTag) {
|
||||
break;
|
||||
case NBTConstants.TYPE_END:
|
||||
if (depth == 0) {
|
||||
throw new IOException(
|
||||
"TAG_End found without a TAG_Compound/TAG_List tag preceding it.");
|
||||
} else {
|
||||
tagMap.put(namedTag.getName(), tag);
|
||||
return new EndTag();
|
||||
}
|
||||
case NBTConstants.TYPE_BYTE:
|
||||
return new ByteTag(is.readByte());
|
||||
case NBTConstants.TYPE_SHORT:
|
||||
return new ShortTag(is.readShort());
|
||||
case NBTConstants.TYPE_INT:
|
||||
return new IntTag(is.readInt());
|
||||
case NBTConstants.TYPE_LONG:
|
||||
return new LongTag(is.readLong());
|
||||
case NBTConstants.TYPE_FLOAT:
|
||||
return new FloatTag(is.readFloat());
|
||||
case NBTConstants.TYPE_DOUBLE:
|
||||
return new DoubleTag(is.readDouble());
|
||||
case NBTConstants.TYPE_BYTE_ARRAY:
|
||||
int length = is.readInt();
|
||||
byte[] bytes = new byte[length];
|
||||
is.readFully(bytes);
|
||||
return new ByteArrayTag(bytes);
|
||||
case NBTConstants.TYPE_STRING:
|
||||
length = is.readShort();
|
||||
bytes = new byte[length];
|
||||
is.readFully(bytes);
|
||||
return new StringTag(new String(bytes, NBTConstants.CHARSET));
|
||||
case NBTConstants.TYPE_LIST:
|
||||
int childType = is.readByte();
|
||||
if (childType == NBTConstants.TYPE_LIST) {
|
||||
childType = NBTConstants.TYPE_COMPOUND;
|
||||
}
|
||||
length = is.readInt();
|
||||
List<Tag> tagList = new ArrayList<Tag>();
|
||||
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 CompoundTag(tagMap);
|
||||
case NBTConstants.TYPE_INT_ARRAY:
|
||||
length = is.readInt();
|
||||
int[] data = new int[length];
|
||||
for (int i = 0; i < length; i++) {
|
||||
data[i] = is.readInt();
|
||||
return new ListTag(NBTUtils.getTypeClass(childType), tagList);
|
||||
case NBTConstants.TYPE_COMPOUND:
|
||||
Map<String, Tag> tagMap = new HashMap<String, Tag>();
|
||||
while (true) {
|
||||
NamedTag namedTag = readNamedTag(depth + 1);
|
||||
Tag tag = namedTag.getTag();
|
||||
if (tag instanceof EndTag) {
|
||||
break;
|
||||
} else {
|
||||
tagMap.put(namedTag.getName(), tag);
|
||||
}
|
||||
}
|
||||
|
||||
return new CompoundTag(tagMap);
|
||||
case NBTConstants.TYPE_INT_ARRAY: {
|
||||
length = is.readInt();
|
||||
int[] data = new int[length];
|
||||
for (int i = 0; i < length; i++) {
|
||||
data[i] = is.readInt();
|
||||
}
|
||||
return new IntArrayTag(data);
|
||||
}
|
||||
return new IntArrayTag(data);
|
||||
case NBTConstants.TYPE_LONG_ARRAY:
|
||||
length = is.readInt();
|
||||
long[] longData = new long[length];
|
||||
for (int i = 0; i < length; i++) {
|
||||
longData[i] = is.readLong();
|
||||
case NBTConstants.TYPE_LONG_ARRAY: {
|
||||
length = is.readInt();
|
||||
long[] data = new long[length];
|
||||
for (int i = 0; i < length; i++) {
|
||||
data[i] = is.readLong();
|
||||
}
|
||||
return new LongArrayTag(data);
|
||||
}
|
||||
return new LongArrayTag(longData);
|
||||
default:
|
||||
throw new IOException("Invalid tag type: " + type + ".");
|
||||
default:
|
||||
throw new IOException("Invalid tag type: " + type + ".");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() throws IOException {
|
||||
is.close();
|
||||
if (is instanceof AutoCloseable) {
|
||||
try {
|
||||
((AutoCloseable) is).close();
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static Class<?> inject() {
|
||||
return NBTInputStream.class;
|
||||
}
|
||||
}
|
||||
|
@ -19,19 +19,23 @@
|
||||
|
||||
package com.sk89q.jnbt;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
import com.boydti.fawe.object.io.LittleEndianOutputStream;
|
||||
import java.io.Closeable;
|
||||
import java.io.DataOutput;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.Flushable;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
/**
|
||||
* This class writes <strong>NBT</strong>, or <strong>Named Binary Tag</strong>
|
||||
* {@code Tag} objects to an underlying {@code OutputStream}.
|
||||
*
|
||||
* <p>
|
||||
* <p>The NBT format was created by Markus Persson, and the specification may be
|
||||
* found at <a href="http://www.minecraft.net/docs/NBT.txt">
|
||||
* http://www.minecraft.net/docs/NBT.txt</a>.</p>
|
||||
@ -41,109 +45,214 @@ public final class NBTOutputStream implements Closeable {
|
||||
/**
|
||||
* The output stream.
|
||||
*/
|
||||
private final DataOutputStream os;
|
||||
private DataOutput os;
|
||||
|
||||
/**
|
||||
* Creates a new {@code NBTOutputStream}, which will write data to the
|
||||
* specified underlying output stream.
|
||||
*
|
||||
* @param os
|
||||
* The output stream.
|
||||
* @throws IOException
|
||||
* if an I/O error occurs.
|
||||
*
|
||||
* @param os The output stream.
|
||||
* @throws IOException if an I/O error occurs.
|
||||
*/
|
||||
public NBTOutputStream(OutputStream os) throws IOException {
|
||||
this.os = new DataOutputStream(os);
|
||||
}
|
||||
|
||||
public NBTOutputStream(DataOutput os) throws IOException {
|
||||
this.os = os;
|
||||
}
|
||||
|
||||
public DataOutput getOutputStream() {
|
||||
return os;
|
||||
}
|
||||
|
||||
public void setLittleEndian() {
|
||||
if (!(os instanceof LittleEndianOutputStream)) {
|
||||
this.os = new LittleEndianOutputStream((OutputStream) os);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes a tag.
|
||||
*
|
||||
* @param tag
|
||||
* The tag to write.
|
||||
* @throws IOException
|
||||
* if an I/O error occurs.
|
||||
*
|
||||
* @param tag The tag to write.
|
||||
* @throws IOException if an I/O error occurs.
|
||||
*/
|
||||
public void writeNamedTag(String name, Tag tag) throws IOException {
|
||||
checkNotNull(name);
|
||||
checkNotNull(tag);
|
||||
|
||||
int type = NBTUtils.getTypeCode(tag.getClass());
|
||||
byte[] nameBytes = name.getBytes(NBTConstants.CHARSET);
|
||||
|
||||
os.writeByte(type);
|
||||
os.writeShort(nameBytes.length);
|
||||
os.write(nameBytes);
|
||||
|
||||
writeNamedTagName(name, type);
|
||||
if (type == NBTConstants.TYPE_END) {
|
||||
throw new IOException("Named TAG_End not permitted.");
|
||||
}
|
||||
|
||||
writeTagPayload(tag);
|
||||
}
|
||||
|
||||
public void writeNamedTag(String name, String value) throws IOException {
|
||||
checkNotNull(name);
|
||||
checkNotNull(value);
|
||||
int type = NBTConstants.TYPE_STRING;
|
||||
writeNamedTagName(name, type);
|
||||
byte[] bytes = value.getBytes(NBTConstants.CHARSET);
|
||||
os.writeShort(bytes.length);
|
||||
os.write(bytes);
|
||||
}
|
||||
|
||||
public void writeNamedTag(String name, int value) throws IOException {
|
||||
checkNotNull(name);
|
||||
int type = NBTConstants.TYPE_INT;
|
||||
writeNamedTagName(name, type);
|
||||
os.writeInt(value);
|
||||
}
|
||||
|
||||
public void writeNamedTag(String name, byte value) throws IOException {
|
||||
checkNotNull(name);
|
||||
int type = NBTConstants.TYPE_BYTE;
|
||||
writeNamedTagName(name, type);
|
||||
os.writeByte(value);
|
||||
}
|
||||
|
||||
public void writeNamedTag(String name, short value) throws IOException {
|
||||
checkNotNull(name);
|
||||
int type = NBTConstants.TYPE_SHORT;
|
||||
writeNamedTagName(name, type);
|
||||
os.writeShort(value);
|
||||
}
|
||||
|
||||
public void writeNamedTag(String name, long value) throws IOException {
|
||||
checkNotNull(name);
|
||||
int type = NBTConstants.TYPE_LONG;
|
||||
writeNamedTagName(name, type);
|
||||
os.writeLong(value);
|
||||
}
|
||||
|
||||
public void writeNamedTag(String name, byte[] bytes) throws IOException {
|
||||
checkNotNull(name);
|
||||
int type = NBTConstants.TYPE_BYTE_ARRAY;
|
||||
writeNamedTagName(name, type);
|
||||
os.writeInt(bytes.length);
|
||||
os.write(bytes);
|
||||
}
|
||||
|
||||
public void writeNamedTag(String name, int[] data) throws IOException {
|
||||
checkNotNull(name);
|
||||
int type = NBTConstants.TYPE_INT_ARRAY;
|
||||
writeNamedTagName(name, type);
|
||||
os.writeInt(data.length);
|
||||
for (int aData : data) {
|
||||
os.writeInt(aData);
|
||||
}
|
||||
}
|
||||
|
||||
public void writeNamedTag(String name, long[] data) throws IOException {
|
||||
checkNotNull(name);
|
||||
int type = NBTConstants.TYPE_LONG_ARRAY;
|
||||
writeNamedTagName(name, type);
|
||||
os.writeInt(data.length);
|
||||
for (long aData : data) {
|
||||
os.writeLong(aData);
|
||||
}
|
||||
}
|
||||
|
||||
public void writeNamedEmptyList(String name) throws IOException {
|
||||
writeNamedEmptyList(name, NBTConstants.TYPE_COMPOUND);
|
||||
}
|
||||
|
||||
public void writeNamedEmptyList(String name, int type) throws IOException {
|
||||
writeNamedTagName(name, NBTConstants.TYPE_LIST);
|
||||
os.writeByte(type);
|
||||
os.writeInt(0);
|
||||
}
|
||||
|
||||
public void writeNamedTagName(String name, int type) throws IOException {
|
||||
byte[] nameBytes = name.getBytes(NBTConstants.CHARSET);
|
||||
os.writeByte(type);
|
||||
os.writeShort(nameBytes.length);
|
||||
os.write(nameBytes);
|
||||
}
|
||||
|
||||
public void writeLazyCompoundTag(String name, LazyWrite next) throws IOException {
|
||||
byte[] nameBytes = name.getBytes(NBTConstants.CHARSET);
|
||||
os.writeByte(NBTConstants.TYPE_COMPOUND);
|
||||
os.writeShort(nameBytes.length);
|
||||
os.write(nameBytes);
|
||||
next.write(this);
|
||||
os.writeByte(NBTConstants.TYPE_END);
|
||||
}
|
||||
|
||||
public interface LazyWrite {
|
||||
void write(NBTOutputStream out) throws IOException;
|
||||
}
|
||||
|
||||
public void writeTag(Tag tag) throws IOException {
|
||||
int type = NBTUtils.getTypeCode(tag.getClass());
|
||||
os.writeByte(type);
|
||||
writeTagPayload(tag);
|
||||
}
|
||||
|
||||
public void writeEndTag() throws IOException {
|
||||
os.writeByte(NBTConstants.TYPE_END);
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes tag payload.
|
||||
*
|
||||
* @param tag
|
||||
* The tag.
|
||||
* @throws IOException
|
||||
* if an I/O error occurs.
|
||||
*
|
||||
* @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);
|
||||
break;
|
||||
case NBTConstants.TYPE_BYTE:
|
||||
writeByteTagPayload((ByteTag) tag);
|
||||
break;
|
||||
case NBTConstants.TYPE_SHORT:
|
||||
writeShortTagPayload((ShortTag) tag);
|
||||
break;
|
||||
case NBTConstants.TYPE_INT:
|
||||
writeIntTagPayload((IntTag) tag);
|
||||
break;
|
||||
case NBTConstants.TYPE_LONG:
|
||||
writeLongTagPayload((LongTag) tag);
|
||||
break;
|
||||
case NBTConstants.TYPE_FLOAT:
|
||||
writeFloatTagPayload((FloatTag) tag);
|
||||
break;
|
||||
case NBTConstants.TYPE_DOUBLE:
|
||||
writeDoubleTagPayload((DoubleTag) tag);
|
||||
break;
|
||||
case NBTConstants.TYPE_BYTE_ARRAY:
|
||||
writeByteArrayTagPayload((ByteArrayTag) tag);
|
||||
break;
|
||||
case NBTConstants.TYPE_STRING:
|
||||
writeStringTagPayload((StringTag) tag);
|
||||
break;
|
||||
case NBTConstants.TYPE_LIST:
|
||||
writeListTagPayload((ListTag) tag);
|
||||
break;
|
||||
case NBTConstants.TYPE_COMPOUND:
|
||||
writeCompoundTagPayload((CompoundTag) tag);
|
||||
break;
|
||||
case NBTConstants.TYPE_INT_ARRAY:
|
||||
writeIntArrayTagPayload((IntArrayTag) tag);
|
||||
break;
|
||||
case NBTConstants.TYPE_LONG_ARRAY:
|
||||
writeLongArrayTagPayload((LongArrayTag) tag);
|
||||
break;
|
||||
default:
|
||||
throw new IOException("Invalid tag type: " + type + ".");
|
||||
case NBTConstants.TYPE_END:
|
||||
writeEndTagPayload((EndTag) tag);
|
||||
break;
|
||||
case NBTConstants.TYPE_BYTE:
|
||||
writeByteTagPayload((ByteTag) tag);
|
||||
break;
|
||||
case NBTConstants.TYPE_SHORT:
|
||||
writeShortTagPayload((ShortTag) tag);
|
||||
break;
|
||||
case NBTConstants.TYPE_INT:
|
||||
writeIntTagPayload((IntTag) tag);
|
||||
break;
|
||||
case NBTConstants.TYPE_LONG:
|
||||
writeLongTagPayload((LongTag) tag);
|
||||
break;
|
||||
case NBTConstants.TYPE_FLOAT:
|
||||
writeFloatTagPayload((FloatTag) tag);
|
||||
break;
|
||||
case NBTConstants.TYPE_DOUBLE:
|
||||
writeDoubleTagPayload((DoubleTag) tag);
|
||||
break;
|
||||
case NBTConstants.TYPE_BYTE_ARRAY:
|
||||
writeByteArrayTagPayload((ByteArrayTag) tag);
|
||||
break;
|
||||
case NBTConstants.TYPE_STRING:
|
||||
writeStringTagPayload((StringTag) tag);
|
||||
break;
|
||||
case NBTConstants.TYPE_LIST:
|
||||
writeListTagPayload((ListTag) tag);
|
||||
break;
|
||||
case NBTConstants.TYPE_COMPOUND:
|
||||
writeCompoundTagPayload((CompoundTag) tag);
|
||||
break;
|
||||
case NBTConstants.TYPE_INT_ARRAY:
|
||||
writeIntArrayTagPayload((IntArrayTag) tag);
|
||||
break;
|
||||
case NBTConstants.TYPE_LONG_ARRAY:
|
||||
writeLongArrayTagPayload((LongArrayTag) tag);
|
||||
break;
|
||||
default:
|
||||
throw new IOException("Invalid tag type: " + type + ".");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes a {@code TAG_Byte} tag.
|
||||
*
|
||||
* @param tag
|
||||
* The tag.
|
||||
* @throws IOException
|
||||
* if an I/O error occurs.
|
||||
*
|
||||
* @param tag The tag.
|
||||
* @throws IOException if an I/O error occurs.
|
||||
*/
|
||||
private void writeByteTagPayload(ByteTag tag) throws IOException {
|
||||
os.writeByte(tag.getValue());
|
||||
@ -151,11 +260,9 @@ public final class NBTOutputStream implements Closeable {
|
||||
|
||||
/**
|
||||
* Writes a {@code TAG_Byte_Array} tag.
|
||||
*
|
||||
* @param tag
|
||||
* The tag.
|
||||
* @throws IOException
|
||||
* if an I/O error occurs.
|
||||
*
|
||||
* @param tag The tag.
|
||||
* @throws IOException if an I/O error occurs.
|
||||
*/
|
||||
private void writeByteArrayTagPayload(ByteArrayTag tag) throws IOException {
|
||||
byte[] bytes = tag.getValue();
|
||||
@ -165,33 +272,36 @@ public final class NBTOutputStream implements Closeable {
|
||||
|
||||
/**
|
||||
* Writes a {@code TAG_Compound} tag.
|
||||
*
|
||||
* @param tag
|
||||
* The tag.
|
||||
* @throws IOException
|
||||
* if an I/O error occurs.
|
||||
*
|
||||
* @param tag The tag.
|
||||
* @throws IOException if an I/O error occurs.
|
||||
*/
|
||||
private void writeCompoundTagPayload(CompoundTag tag) throws IOException {
|
||||
for (Map.Entry<String, Tag> entry : tag.getValue().entrySet()) {
|
||||
writeNamedTag(entry.getKey(), entry.getValue());
|
||||
}
|
||||
os.writeByte((byte) 0); // end tag - better way?
|
||||
os.writeByte(NBTConstants.TYPE_END); // end tag - better way?
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes a {@code TAG_List} tag.
|
||||
*
|
||||
* @param tag
|
||||
* The tag.
|
||||
* @throws IOException
|
||||
* if an I/O error occurs.
|
||||
*
|
||||
* @param tag The tag.
|
||||
* @throws IOException if an I/O error occurs.
|
||||
*/
|
||||
private void writeListTagPayload(ListTag tag) throws IOException {
|
||||
Class<? extends Tag> clazz = tag.getType();
|
||||
if (clazz == null) {
|
||||
clazz = CompoundTag.class;
|
||||
}
|
||||
List<Tag> tags = tag.getValue();
|
||||
int size = tags.size();
|
||||
|
||||
os.writeByte(NBTUtils.getTypeCode(clazz));
|
||||
if (!tags.isEmpty()) {
|
||||
Tag tag0 = tags.get(0);
|
||||
os.writeByte(NBTUtils.getTypeCode(tag0.getClass()));
|
||||
} else {
|
||||
os.writeByte(NBTUtils.getTypeCode(clazz));
|
||||
}
|
||||
os.writeInt(size);
|
||||
for (Tag tag1 : tags) {
|
||||
writeTagPayload(tag1);
|
||||
@ -200,11 +310,9 @@ public final class NBTOutputStream implements Closeable {
|
||||
|
||||
/**
|
||||
* Writes a {@code TAG_String} tag.
|
||||
*
|
||||
* @param tag
|
||||
* The tag.
|
||||
* @throws IOException
|
||||
* if an I/O error occurs.
|
||||
*
|
||||
* @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);
|
||||
@ -214,11 +322,9 @@ public final class NBTOutputStream implements Closeable {
|
||||
|
||||
/**
|
||||
* Writes a {@code TAG_Double} tag.
|
||||
*
|
||||
* @param tag
|
||||
* The tag.
|
||||
* @throws IOException
|
||||
* if an I/O error occurs.
|
||||
*
|
||||
* @param tag The tag.
|
||||
* @throws IOException if an I/O error occurs.
|
||||
*/
|
||||
private void writeDoubleTagPayload(DoubleTag tag) throws IOException {
|
||||
os.writeDouble(tag.getValue());
|
||||
@ -226,11 +332,9 @@ public final class NBTOutputStream implements Closeable {
|
||||
|
||||
/**
|
||||
* Writes a {@code TAG_Float} tag.
|
||||
*
|
||||
* @param tag
|
||||
* The tag.
|
||||
* @throws IOException
|
||||
* if an I/O error occurs.
|
||||
*
|
||||
* @param tag The tag.
|
||||
* @throws IOException if an I/O error occurs.
|
||||
*/
|
||||
private void writeFloatTagPayload(FloatTag tag) throws IOException {
|
||||
os.writeFloat(tag.getValue());
|
||||
@ -238,11 +342,9 @@ public final class NBTOutputStream implements Closeable {
|
||||
|
||||
/**
|
||||
* Writes a {@code TAG_Long} tag.
|
||||
*
|
||||
* @param tag
|
||||
* The tag.
|
||||
* @throws IOException
|
||||
* if an I/O error occurs.
|
||||
*
|
||||
* @param tag The tag.
|
||||
* @throws IOException if an I/O error occurs.
|
||||
*/
|
||||
private void writeLongTagPayload(LongTag tag) throws IOException {
|
||||
os.writeLong(tag.getValue());
|
||||
@ -250,11 +352,9 @@ public final class NBTOutputStream implements Closeable {
|
||||
|
||||
/**
|
||||
* Writes a {@code TAG_Int} tag.
|
||||
*
|
||||
* @param tag
|
||||
* The tag.
|
||||
* @throws IOException
|
||||
* if an I/O error occurs.
|
||||
*
|
||||
* @param tag The tag.
|
||||
* @throws IOException if an I/O error occurs.
|
||||
*/
|
||||
private void writeIntTagPayload(IntTag tag) throws IOException {
|
||||
os.writeInt(tag.getValue());
|
||||
@ -262,11 +362,9 @@ public final class NBTOutputStream implements Closeable {
|
||||
|
||||
/**
|
||||
* Writes a {@code TAG_Short} tag.
|
||||
*
|
||||
* @param tag
|
||||
* The tag.
|
||||
* @throws IOException
|
||||
* if an I/O error occurs.
|
||||
*
|
||||
* @param tag The tag.
|
||||
* @throws IOException if an I/O error occurs.
|
||||
*/
|
||||
private void writeShortTagPayload(ShortTag tag) throws IOException {
|
||||
os.writeShort(tag.getValue());
|
||||
@ -274,19 +372,19 @@ public final class NBTOutputStream implements Closeable {
|
||||
|
||||
/**
|
||||
* Writes a {@code TAG_Empty} tag.
|
||||
*
|
||||
*
|
||||
* @param tag the tag
|
||||
*/
|
||||
private void writeEndTagPayload(EndTag tag) {
|
||||
/* empty */
|
||||
}
|
||||
|
||||
|
||||
private void writeIntArrayTagPayload(IntArrayTag tag) throws IOException {
|
||||
int[] data = tag.getValue();
|
||||
os.writeInt(data.length);
|
||||
for (int aData : data) {
|
||||
os.writeInt(aData);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void writeLongArrayTagPayload(LongArrayTag tag) throws IOException {
|
||||
@ -299,7 +397,19 @@ public final class NBTOutputStream implements Closeable {
|
||||
|
||||
@Override
|
||||
public void close() throws IOException {
|
||||
os.close();
|
||||
if (os instanceof Closeable) ((Closeable) os).close();
|
||||
}
|
||||
|
||||
}
|
||||
/**
|
||||
* Flush output.
|
||||
*
|
||||
* @throws IOException
|
||||
*/
|
||||
public void flush() throws IOException {
|
||||
if (os instanceof Flushable) ((Flushable) os).flush();
|
||||
}
|
||||
|
||||
public static Class<?> inject() {
|
||||
return NBTOutputStream.class;
|
||||
}
|
||||
}
|
@ -19,13 +19,13 @@
|
||||
|
||||
package com.sk89q.jnbt;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
import com.sk89q.worldedit.Vector;
|
||||
import com.sk89q.worldedit.world.storage.InvalidFormatException;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
/**
|
||||
* A class which contains NBT-related utility methods.
|
||||
*
|
||||
@ -69,8 +69,6 @@ public final class NBTUtils {
|
||||
return "TAG_String";
|
||||
} else if (clazz.equals(IntArrayTag.class)) {
|
||||
return "TAG_Int_Array";
|
||||
} else if (clazz.equals(LongArrayTag.class)) {
|
||||
return "TAG_Long_Array";
|
||||
} else {
|
||||
throw new IllegalArgumentException("Invalid tag classs ("
|
||||
+ clazz.getName() + ").");
|
||||
|
41
worldedit-core/src/main/java/com/sk89q/jnbt/NamedData.java
Normal file
41
worldedit-core/src/main/java/com/sk89q/jnbt/NamedData.java
Normal file
@ -0,0 +1,41 @@
|
||||
package com.sk89q.jnbt;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
/**
|
||||
* Some data with a name
|
||||
*/
|
||||
public class NamedData<T> {
|
||||
private final String name;
|
||||
private final T data;
|
||||
|
||||
/**
|
||||
* Create a new named tag.
|
||||
*
|
||||
* @param name the name
|
||||
* @param data the data
|
||||
*/
|
||||
public NamedData(String name, T data) {
|
||||
checkNotNull(name);
|
||||
this.name = name;
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the name of the tag.
|
||||
*
|
||||
* @return the name
|
||||
*/
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the tag.
|
||||
*
|
||||
* @return the tag
|
||||
*/
|
||||
public T getValue() {
|
||||
return data;
|
||||
}
|
||||
}
|
@ -26,9 +26,18 @@ public abstract class Tag {
|
||||
|
||||
/**
|
||||
* Gets the value of this tag.
|
||||
*
|
||||
*
|
||||
* @return the value
|
||||
*/
|
||||
public abstract Object getValue();
|
||||
|
||||
}
|
||||
public Object getRaw() {
|
||||
return getValue();
|
||||
}
|
||||
|
||||
public static Class<?> inject() {
|
||||
return Tag.class;
|
||||
}
|
||||
|
||||
|
||||
}
|
Reference in New Issue
Block a user