make nbt implementation smaller
This commit is contained in:
parent
4849bc9276
commit
721e668d51
20 changed files with 164 additions and 417 deletions
|
@ -1,42 +0,0 @@
|
||||||
package proxy.nbt;
|
|
||||||
|
|
||||||
import java.io.DataInput;
|
|
||||||
import java.io.DataOutput;
|
|
||||||
import java.io.IOException;
|
|
||||||
|
|
||||||
abstract class Nbt {
|
|
||||||
abstract void write(DataOutput output) throws IOException;
|
|
||||||
abstract void read(DataInput input, int depth, Tracker tracker) throws IOException;
|
|
||||||
abstract byte getId();
|
|
||||||
|
|
||||||
static Nbt createTag(byte id) {
|
|
||||||
switch(id) {
|
|
||||||
case 0:
|
|
||||||
return new NbtNull();
|
|
||||||
case 1:
|
|
||||||
return new NbtByte();
|
|
||||||
case 2:
|
|
||||||
return new NbtShort();
|
|
||||||
case 3:
|
|
||||||
return new NbtInt();
|
|
||||||
case 4:
|
|
||||||
return new NbtLong();
|
|
||||||
case 5:
|
|
||||||
return new NbtFloat();
|
|
||||||
case 6:
|
|
||||||
return new NbtDouble();
|
|
||||||
case 7:
|
|
||||||
return new NbtByteArray();
|
|
||||||
case 8:
|
|
||||||
return new NbtString();
|
|
||||||
case 9:
|
|
||||||
return new NbtList();
|
|
||||||
case 10:
|
|
||||||
return new NbtCompound();
|
|
||||||
case 11:
|
|
||||||
return new NbtIntArray();
|
|
||||||
default:
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,22 +0,0 @@
|
||||||
package proxy.nbt;
|
|
||||||
|
|
||||||
import java.io.DataInput;
|
|
||||||
import java.io.DataOutput;
|
|
||||||
import java.io.IOException;
|
|
||||||
|
|
||||||
class NbtByte extends Nbt {
|
|
||||||
private byte data;
|
|
||||||
|
|
||||||
void write(DataOutput output) throws IOException {
|
|
||||||
output.writeByte(this.data);
|
|
||||||
}
|
|
||||||
|
|
||||||
void read(DataInput input, int depth, Tracker tracker) throws IOException {
|
|
||||||
tracker.read(72L);
|
|
||||||
this.data = input.readByte();
|
|
||||||
}
|
|
||||||
|
|
||||||
byte getId() {
|
|
||||||
return (byte)1;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,26 +0,0 @@
|
||||||
package proxy.nbt;
|
|
||||||
|
|
||||||
import java.io.DataInput;
|
|
||||||
import java.io.DataOutput;
|
|
||||||
import java.io.IOException;
|
|
||||||
|
|
||||||
class NbtByteArray extends Nbt {
|
|
||||||
private byte[] data;
|
|
||||||
|
|
||||||
void write(DataOutput output) throws IOException {
|
|
||||||
output.writeInt(this.data.length);
|
|
||||||
output.write(this.data);
|
|
||||||
}
|
|
||||||
|
|
||||||
void read(DataInput input, int depth, Tracker tracker) throws IOException {
|
|
||||||
tracker.read(192L);
|
|
||||||
int len = input.readInt();
|
|
||||||
tracker.read((long)(8 * len));
|
|
||||||
this.data = new byte[len];
|
|
||||||
input.readFully(this.data);
|
|
||||||
}
|
|
||||||
|
|
||||||
byte getId() {
|
|
||||||
return (byte)7;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,68 +0,0 @@
|
||||||
package proxy.nbt;
|
|
||||||
|
|
||||||
import java.io.DataInput;
|
|
||||||
import java.io.DataOutput;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.Map;
|
|
||||||
import com.google.common.collect.Maps;
|
|
||||||
|
|
||||||
public class NbtCompound extends Nbt {
|
|
||||||
private Map<String, Nbt> tags = Maps.newHashMap();
|
|
||||||
|
|
||||||
void write(DataOutput output) throws IOException {
|
|
||||||
for(String key : this.tags.keySet()) {
|
|
||||||
Nbt tag = this.tags.get(key);
|
|
||||||
output.writeByte(tag.getId());
|
|
||||||
if(tag.getId() != 0) {
|
|
||||||
output.writeUTF(key);
|
|
||||||
tag.write(output);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
output.writeByte(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
void read(DataInput input, int depth, Tracker tracker) throws IOException {
|
|
||||||
tracker.read(384L);
|
|
||||||
if(depth > 512)
|
|
||||||
throw new RuntimeException("Tried to read tag tree deeper than 512");
|
|
||||||
this.tags.clear();
|
|
||||||
byte type;
|
|
||||||
while((type = input.readByte()) != 0) {
|
|
||||||
String key = input.readUTF();
|
|
||||||
tracker.read((long)(224 + 16 * key.length()));
|
|
||||||
Nbt tag = Nbt.createTag(type);
|
|
||||||
tag.read(input, depth + 1, tracker);
|
|
||||||
if(this.tags.put(key, tag) != null)
|
|
||||||
tracker.read(288L);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
byte getId() {
|
|
||||||
return (byte)10;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getString(String key) {
|
|
||||||
Nbt tag = this.tags.get(key);
|
|
||||||
return tag instanceof NbtString ? ((NbtString)tag).getData() : null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getStringListLength(String key) {
|
|
||||||
Nbt tag = this.tags.get(key);
|
|
||||||
return tag instanceof NbtList ? ((NbtList)tag).getStringListLength() : -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static NbtCompound readTag(DataInput input) throws IOException {
|
|
||||||
if(input.readByte() != 10)
|
|
||||||
throw new IOException("Root is not a compound");
|
|
||||||
input.readUTF();
|
|
||||||
NbtCompound tag = new NbtCompound();
|
|
||||||
tag.read(input, 0, new Tracker());
|
|
||||||
return tag;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void writeTag(NbtCompound tag, DataOutput output) throws IOException {
|
|
||||||
output.writeByte(tag.getId());
|
|
||||||
output.writeUTF("");
|
|
||||||
tag.write(output);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,22 +0,0 @@
|
||||||
package proxy.nbt;
|
|
||||||
|
|
||||||
import java.io.DataInput;
|
|
||||||
import java.io.DataOutput;
|
|
||||||
import java.io.IOException;
|
|
||||||
|
|
||||||
class NbtDouble extends Nbt {
|
|
||||||
private double data;
|
|
||||||
|
|
||||||
void write(DataOutput output) throws IOException {
|
|
||||||
output.writeDouble(this.data);
|
|
||||||
}
|
|
||||||
|
|
||||||
void read(DataInput input, int depth, Tracker tracker) throws IOException {
|
|
||||||
tracker.read(128L);
|
|
||||||
this.data = input.readDouble();
|
|
||||||
}
|
|
||||||
|
|
||||||
byte getId() {
|
|
||||||
return (byte)6;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,22 +0,0 @@
|
||||||
package proxy.nbt;
|
|
||||||
|
|
||||||
import java.io.DataInput;
|
|
||||||
import java.io.DataOutput;
|
|
||||||
import java.io.IOException;
|
|
||||||
|
|
||||||
class NbtFloat extends Nbt {
|
|
||||||
private float data;
|
|
||||||
|
|
||||||
void write(DataOutput output) throws IOException {
|
|
||||||
output.writeFloat(this.data);
|
|
||||||
}
|
|
||||||
|
|
||||||
void read(DataInput input, int depth, Tracker tracker) throws IOException {
|
|
||||||
tracker.read(96L);
|
|
||||||
this.data = input.readFloat();
|
|
||||||
}
|
|
||||||
|
|
||||||
byte getId() {
|
|
||||||
return (byte)5;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,22 +0,0 @@
|
||||||
package proxy.nbt;
|
|
||||||
|
|
||||||
import java.io.DataInput;
|
|
||||||
import java.io.DataOutput;
|
|
||||||
import java.io.IOException;
|
|
||||||
|
|
||||||
class NbtInt extends Nbt {
|
|
||||||
private int data;
|
|
||||||
|
|
||||||
void write(DataOutput output) throws IOException {
|
|
||||||
output.writeInt(this.data);
|
|
||||||
}
|
|
||||||
|
|
||||||
void read(DataInput input, int depth, Tracker tracker) throws IOException {
|
|
||||||
tracker.read(96L);
|
|
||||||
this.data = input.readInt();
|
|
||||||
}
|
|
||||||
|
|
||||||
byte getId() {
|
|
||||||
return (byte)3;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,30 +0,0 @@
|
||||||
package proxy.nbt;
|
|
||||||
|
|
||||||
import java.io.DataInput;
|
|
||||||
import java.io.DataOutput;
|
|
||||||
import java.io.IOException;
|
|
||||||
|
|
||||||
class NbtIntArray extends Nbt {
|
|
||||||
private int[] data;
|
|
||||||
|
|
||||||
void write(DataOutput output) throws IOException {
|
|
||||||
output.writeInt(this.data.length);
|
|
||||||
for(int z = 0; z < this.data.length; z++) {
|
|
||||||
output.writeInt(this.data[z]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void read(DataInput input, int depth, Tracker tracker) throws IOException {
|
|
||||||
tracker.read(192L);
|
|
||||||
int len = input.readInt();
|
|
||||||
tracker.read((long)(32 * len));
|
|
||||||
this.data = new int[len];
|
|
||||||
for(int z = 0; z < len; z++) {
|
|
||||||
this.data[z] = input.readInt();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
byte getId() {
|
|
||||||
return (byte)11;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,47 +0,0 @@
|
||||||
package proxy.nbt;
|
|
||||||
|
|
||||||
import java.io.DataInput;
|
|
||||||
import java.io.DataOutput;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import com.google.common.collect.Lists;
|
|
||||||
|
|
||||||
class NbtList extends Nbt {
|
|
||||||
private List<Nbt> list = Lists.newArrayList();
|
|
||||||
private byte type = 0;
|
|
||||||
|
|
||||||
void write(DataOutput output) throws IOException {
|
|
||||||
this.type = this.list.isEmpty() ? 0 : this.list.get(0).getId();
|
|
||||||
output.writeByte(this.type);
|
|
||||||
output.writeInt(this.list.size());
|
|
||||||
for(int z = 0; z < this.list.size(); z++) {
|
|
||||||
this.list.get(z).write(output);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void read(DataInput input, int depth, Tracker tracker) throws IOException {
|
|
||||||
tracker.read(296L);
|
|
||||||
if(depth > 512)
|
|
||||||
throw new RuntimeException("Tried to read tag tree deeper than 512");
|
|
||||||
this.type = input.readByte();
|
|
||||||
int len = input.readInt();
|
|
||||||
if(this.type == 0 && len > 0)
|
|
||||||
throw new RuntimeException("Type null on list tag");
|
|
||||||
tracker.read(32L * (long)len);
|
|
||||||
this.list = Lists.newArrayListWithCapacity(len);
|
|
||||||
for(int z = 0; z < len; z++) {
|
|
||||||
Nbt nbtbase = Nbt.createTag(this.type);
|
|
||||||
nbtbase.read(input, depth + 1, tracker);
|
|
||||||
this.list.add(nbtbase);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
byte getId() {
|
|
||||||
return (byte)9;
|
|
||||||
}
|
|
||||||
|
|
||||||
int getStringListLength() {
|
|
||||||
return this.type != 8 && !this.list.isEmpty() ? -1 : this.list.size();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,22 +0,0 @@
|
||||||
package proxy.nbt;
|
|
||||||
|
|
||||||
import java.io.DataInput;
|
|
||||||
import java.io.DataOutput;
|
|
||||||
import java.io.IOException;
|
|
||||||
|
|
||||||
class NbtLong extends Nbt {
|
|
||||||
private long data;
|
|
||||||
|
|
||||||
void write(DataOutput output) throws IOException {
|
|
||||||
output.writeLong(this.data);
|
|
||||||
}
|
|
||||||
|
|
||||||
void read(DataInput input, int depth, Tracker tracker) throws IOException {
|
|
||||||
tracker.read(128L);
|
|
||||||
this.data = input.readLong();
|
|
||||||
}
|
|
||||||
|
|
||||||
byte getId() {
|
|
||||||
return (byte)4;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,18 +0,0 @@
|
||||||
package proxy.nbt;
|
|
||||||
|
|
||||||
import java.io.DataInput;
|
|
||||||
import java.io.DataOutput;
|
|
||||||
import java.io.IOException;
|
|
||||||
|
|
||||||
class NbtNull extends Nbt {
|
|
||||||
void read(DataInput input, int depth, Tracker tracker) throws IOException {
|
|
||||||
tracker.read(64L);
|
|
||||||
}
|
|
||||||
|
|
||||||
void write(DataOutput output) throws IOException {
|
|
||||||
}
|
|
||||||
|
|
||||||
byte getId() {
|
|
||||||
return (byte)0;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,22 +0,0 @@
|
||||||
package proxy.nbt;
|
|
||||||
|
|
||||||
import java.io.DataInput;
|
|
||||||
import java.io.DataOutput;
|
|
||||||
import java.io.IOException;
|
|
||||||
|
|
||||||
class NbtShort extends Nbt {
|
|
||||||
private short data;
|
|
||||||
|
|
||||||
void write(DataOutput output) throws IOException {
|
|
||||||
output.writeShort(this.data);
|
|
||||||
}
|
|
||||||
|
|
||||||
void read(DataInput input, int depth, Tracker tracker) throws IOException {
|
|
||||||
tracker.read(80L);
|
|
||||||
this.data = input.readShort();
|
|
||||||
}
|
|
||||||
|
|
||||||
byte getId() {
|
|
||||||
return (byte)2;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,27 +0,0 @@
|
||||||
package proxy.nbt;
|
|
||||||
|
|
||||||
import java.io.DataInput;
|
|
||||||
import java.io.DataOutput;
|
|
||||||
import java.io.IOException;
|
|
||||||
|
|
||||||
class NbtString extends Nbt {
|
|
||||||
private String data;
|
|
||||||
|
|
||||||
void write(DataOutput output) throws IOException {
|
|
||||||
output.writeUTF(this.data);
|
|
||||||
}
|
|
||||||
|
|
||||||
void read(DataInput input, int depth, Tracker tracker) throws IOException {
|
|
||||||
tracker.read(288L);
|
|
||||||
this.data = input.readUTF();
|
|
||||||
tracker.read((long)(16 * this.data.length()));
|
|
||||||
}
|
|
||||||
|
|
||||||
byte getId() {
|
|
||||||
return (byte)8;
|
|
||||||
}
|
|
||||||
|
|
||||||
String getData() {
|
|
||||||
return this.data;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,11 +0,0 @@
|
||||||
package proxy.nbt;
|
|
||||||
|
|
||||||
class Tracker {
|
|
||||||
private long read;
|
|
||||||
|
|
||||||
void read(long bits) {
|
|
||||||
this.read += bits / 8L;
|
|
||||||
if(this.read > 2097152L)
|
|
||||||
throw new RuntimeException("Tried to read tag that was too big: Read " + this.read + " bytes, maximum 2097152 bytes");
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -16,10 +16,11 @@ import java.nio.ByteOrder;
|
||||||
import java.nio.channels.GatheringByteChannel;
|
import java.nio.channels.GatheringByteChannel;
|
||||||
import java.nio.channels.ScatteringByteChannel;
|
import java.nio.channels.ScatteringByteChannel;
|
||||||
import java.nio.charset.Charset;
|
import java.nio.charset.Charset;
|
||||||
|
import java.util.Map;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
import proxy.nbt.NbtCompound;
|
|
||||||
import proxy.util.Vec3;
|
import proxy.util.Vec3;
|
||||||
|
import proxy.util.Nbt;
|
||||||
import proxy.util.Stack;
|
import proxy.util.Stack;
|
||||||
|
|
||||||
public class PacketBuffer extends ByteBuf
|
public class PacketBuffer extends ByteBuf
|
||||||
|
@ -187,7 +188,7 @@ public class PacketBuffer extends ByteBuf
|
||||||
/**
|
/**
|
||||||
* Writes a compressed NBTTagCompound to this buffer
|
* Writes a compressed NBTTagCompound to this buffer
|
||||||
*/
|
*/
|
||||||
public void writeNBTTagCompoundToBuffer(NbtCompound nbt)
|
public void writeNBTTagCompoundToBuffer(Map<String, Object> nbt)
|
||||||
{
|
{
|
||||||
if (nbt == null)
|
if (nbt == null)
|
||||||
{
|
{
|
||||||
|
@ -197,7 +198,7 @@ public class PacketBuffer extends ByteBuf
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
NbtCompound.writeTag(nbt, new ByteBufOutputStream(this));
|
Nbt.writeTag(nbt, new ByteBufOutputStream(this));
|
||||||
}
|
}
|
||||||
catch (IOException ioexception)
|
catch (IOException ioexception)
|
||||||
{
|
{
|
||||||
|
@ -209,7 +210,7 @@ public class PacketBuffer extends ByteBuf
|
||||||
/**
|
/**
|
||||||
* Reads a compressed NBTTagCompound from this buffer
|
* Reads a compressed NBTTagCompound from this buffer
|
||||||
*/
|
*/
|
||||||
public NbtCompound readNBTTagCompoundFromBuffer() throws IOException
|
public Map<String, Object> readNBTTagCompoundFromBuffer() throws IOException
|
||||||
{
|
{
|
||||||
int i = this.readerIndex();
|
int i = this.readerIndex();
|
||||||
byte b0 = this.readByte();
|
byte b0 = this.readByte();
|
||||||
|
@ -221,7 +222,7 @@ public class PacketBuffer extends ByteBuf
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
this.readerIndex(i);
|
this.readerIndex(i);
|
||||||
return NbtCompound.readTag(new ByteBufInputStream(this));
|
return Nbt.readTag(new ByteBufInputStream(this));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -21,6 +21,7 @@ import proxy.util.Formatter;
|
||||||
import proxy.util.User;
|
import proxy.util.User;
|
||||||
import proxy.util.Stack;
|
import proxy.util.Stack;
|
||||||
import proxy.util.Log;
|
import proxy.util.Log;
|
||||||
|
import proxy.util.Nbt;
|
||||||
|
|
||||||
public class ProxyHandler extends User implements Handler {
|
public class ProxyHandler extends User implements Handler {
|
||||||
public class ProxyLoginHandler implements Handler {
|
public class ProxyLoginHandler implements Handler {
|
||||||
|
@ -539,7 +540,7 @@ public class ProxyHandler extends User implements Handler {
|
||||||
Stack itemstack1 = packetbuffer.readStack();
|
Stack itemstack1 = packetbuffer.readStack();
|
||||||
|
|
||||||
if(itemstack1 != null && itemstack1.getTag() != null) {
|
if(itemstack1 != null && itemstack1.getTag() != null) {
|
||||||
int pages = itemstack1.getTag().getStringListLength("pages");
|
int pages = Nbt.getStringListLength(itemstack1.getTag(), "pages");
|
||||||
if(pages > 50)
|
if(pages > 50)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -559,10 +560,10 @@ public class ProxyHandler extends User implements Handler {
|
||||||
Stack itemstack = packetbuffer.readStack();
|
Stack itemstack = packetbuffer.readStack();
|
||||||
|
|
||||||
if(itemstack != null && itemstack.getTag() != null) {
|
if(itemstack != null && itemstack.getTag() != null) {
|
||||||
String title = itemstack.getTag().getString("title");
|
String title = Nbt.getString(itemstack.getTag(), "title");
|
||||||
if(title != null && (title.length() > 50 || !isValidString(title)))
|
if(title != null && (title.length() > 50 || !isValidString(title)))
|
||||||
return;
|
return;
|
||||||
int pages = itemstack.getTag().getStringListLength("pages");
|
int pages = Nbt.getStringListLength(itemstack.getTag(), "pages");
|
||||||
if(pages > 50)
|
if(pages > 50)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
package proxy.packet;
|
package proxy.packet;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
import proxy.nbt.NbtCompound;
|
|
||||||
import proxy.network.ProxyHandler;
|
import proxy.network.ProxyHandler;
|
||||||
import proxy.network.Packet;
|
import proxy.network.Packet;
|
||||||
import proxy.network.PacketBuffer;
|
import proxy.network.PacketBuffer;
|
||||||
|
@ -12,7 +12,7 @@ public class S35PacketUpdateTileEntity implements Packet<ProxyHandler>
|
||||||
{
|
{
|
||||||
private Vec3 blockPos;
|
private Vec3 blockPos;
|
||||||
private int metadata;
|
private int metadata;
|
||||||
private NbtCompound nbt;
|
private Map<String, Object> nbt;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reads the raw packet data from the data stream.
|
* Reads the raw packet data from the data stream.
|
||||||
|
|
|
@ -1,15 +1,15 @@
|
||||||
package proxy.packet;
|
package proxy.packet;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
import proxy.nbt.NbtCompound;
|
|
||||||
import proxy.network.ProxyHandler;
|
import proxy.network.ProxyHandler;
|
||||||
import proxy.network.Packet;
|
import proxy.network.Packet;
|
||||||
import proxy.network.PacketBuffer;
|
import proxy.network.PacketBuffer;
|
||||||
|
|
||||||
public class S49PacketUpdateEntityNBT extends EntityIdPacketClient implements Packet<ProxyHandler>
|
public class S49PacketUpdateEntityNBT extends EntityIdPacketClient implements Packet<ProxyHandler>
|
||||||
{
|
{
|
||||||
private NbtCompound tagCompound;
|
private Map<String, Object> tagCompound;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reads the raw packet data from the data stream.
|
* Reads the raw packet data from the data stream.
|
||||||
|
|
146
proxy/src/main/java/proxy/util/Nbt.java
Executable file
146
proxy/src/main/java/proxy/util/Nbt.java
Executable file
|
@ -0,0 +1,146 @@
|
||||||
|
package proxy.util;
|
||||||
|
|
||||||
|
import java.io.DataInput;
|
||||||
|
import java.io.DataOutput;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import com.google.common.collect.Lists;
|
||||||
|
import com.google.common.collect.Maps;
|
||||||
|
|
||||||
|
public abstract class Nbt {
|
||||||
|
private static Object read(byte id, DataInput input, int depth) throws IOException {
|
||||||
|
switch(id) {
|
||||||
|
case 0:
|
||||||
|
return null;
|
||||||
|
case 1:
|
||||||
|
return input.readByte();
|
||||||
|
case 2:
|
||||||
|
return input.readShort();
|
||||||
|
case 3:
|
||||||
|
return input.readInt();
|
||||||
|
case 4:
|
||||||
|
return input.readLong();
|
||||||
|
case 5:
|
||||||
|
return input.readFloat();
|
||||||
|
case 6:
|
||||||
|
return input.readDouble();
|
||||||
|
case 7: {
|
||||||
|
int len = input.readInt();
|
||||||
|
byte[] data = new byte[len];
|
||||||
|
input.readFully(data);
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
case 8:
|
||||||
|
return input.readUTF();
|
||||||
|
case 9: {
|
||||||
|
if(depth > 512)
|
||||||
|
throw new RuntimeException("Tried to read tag tree deeper than 512");
|
||||||
|
byte type = input.readByte();
|
||||||
|
int len = input.readInt();
|
||||||
|
if(type == 0 && len > 0)
|
||||||
|
throw new RuntimeException("Type null on list tag");
|
||||||
|
List<Object> list = Lists.newArrayListWithCapacity(len);
|
||||||
|
for(int z = 0; z < len; z++) {
|
||||||
|
list.add(read(type, input, depth + 1));
|
||||||
|
}
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
case 10:
|
||||||
|
if(depth > 512)
|
||||||
|
throw new RuntimeException("Tried to read tag tree deeper than 512");
|
||||||
|
Map<String, Object> tags = Maps.newHashMap();
|
||||||
|
byte type;
|
||||||
|
while((type = input.readByte()) != 0) {
|
||||||
|
String key = input.readUTF();
|
||||||
|
tags.put(key, read(type, input, depth + 1));
|
||||||
|
}
|
||||||
|
return tags;
|
||||||
|
case 11: {
|
||||||
|
int len = input.readInt();
|
||||||
|
int[] data = new int[len];
|
||||||
|
for(int z = 0; z < len; z++) {
|
||||||
|
data[z] = input.readInt();
|
||||||
|
}
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static byte getId(Object obj) {
|
||||||
|
return (byte)(obj instanceof Byte ? 1 : (obj instanceof Short ? 2 : (obj instanceof Integer ? 3 : (obj instanceof Long ? 4 : (obj instanceof Float ? 5 : (obj instanceof Double ? 6 : (obj instanceof byte[] ? 7 : (obj instanceof String ? 8 : (obj instanceof List ? 9 : (obj instanceof Map ? 10 : (obj instanceof int[] ? 11 : 0)))))))))));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void write(Object obj, DataOutput output) throws IOException {
|
||||||
|
if(obj instanceof Byte)
|
||||||
|
output.writeByte((Byte)obj);
|
||||||
|
else if(obj instanceof Short)
|
||||||
|
output.writeShort((Short)obj);
|
||||||
|
else if(obj instanceof Integer)
|
||||||
|
output.writeInt((Integer)obj);
|
||||||
|
else if(obj instanceof Long)
|
||||||
|
output.writeLong((Long)obj);
|
||||||
|
else if(obj instanceof Float)
|
||||||
|
output.writeFloat((Float)obj);
|
||||||
|
else if(obj instanceof Double)
|
||||||
|
output.writeDouble((Double)obj);
|
||||||
|
else if(obj instanceof byte[]) {
|
||||||
|
output.writeInt(((byte[])obj).length);
|
||||||
|
output.write(((byte[])obj));
|
||||||
|
}
|
||||||
|
else if(obj instanceof String)
|
||||||
|
output.writeUTF((String)obj);
|
||||||
|
else if(obj instanceof List) {
|
||||||
|
output.writeByte(((List)obj).isEmpty() ? 0 : getId(((List)obj).get(0)));
|
||||||
|
output.writeInt(((List)obj).size());
|
||||||
|
for(int z = 0; z < ((List)obj).size(); z++) {
|
||||||
|
write(((List)obj).get(z), output);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(obj instanceof Map) {
|
||||||
|
for(String key : ((Map<String, Object>)obj).keySet()) {
|
||||||
|
Object data = ((Map<String, Object>)obj).get(key);
|
||||||
|
output.writeByte(getId(data));
|
||||||
|
if(data != null) {
|
||||||
|
output.writeUTF(key);
|
||||||
|
write(data, output);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
output.writeByte(0);
|
||||||
|
}
|
||||||
|
else if(obj instanceof int[]) {
|
||||||
|
output.writeInt(((int[])obj).length);
|
||||||
|
for(int z = 0; z < ((int[])obj).length; z++) {
|
||||||
|
output.writeInt(((int[])obj)[z]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Map<String, Object> readTag(DataInput input) throws IOException {
|
||||||
|
if(input.readByte() != 10)
|
||||||
|
throw new IOException("Root is not a compound");
|
||||||
|
input.readUTF();
|
||||||
|
return (Map<String, Object>)read((byte)10, input, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void writeTag(Map<String, Object> tag, DataOutput output) throws IOException {
|
||||||
|
output.writeByte(10);
|
||||||
|
output.writeUTF("");
|
||||||
|
write(tag, output);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String getString(Map<String, Object> tags, String key) {
|
||||||
|
Object data = tags.get(key);
|
||||||
|
return data instanceof String ? ((String)data) : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int getStringListLength(Map<String, Object> tags, String key) {
|
||||||
|
Object data = tags.get(key);
|
||||||
|
if(!(data instanceof List))
|
||||||
|
return -1;
|
||||||
|
return ((List)data).isEmpty() ? 0 : (((List)data).get(0) instanceof String ? ((List)data).size() : -1);
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,14 +1,14 @@
|
||||||
package proxy.util;
|
package proxy.util;
|
||||||
|
|
||||||
import proxy.nbt.NbtCompound;
|
import java.util.Map;
|
||||||
|
|
||||||
public final class Stack {
|
public final class Stack {
|
||||||
private final short id;
|
private final short id;
|
||||||
private final byte size;
|
private final byte size;
|
||||||
private final short meta;
|
private final short meta;
|
||||||
private final NbtCompound tag;
|
private final Map<String, Object> tag;
|
||||||
|
|
||||||
public Stack(short id, byte size, short meta, NbtCompound tag) {
|
public Stack(short id, byte size, short meta, Map<String, Object> tag) {
|
||||||
this.id = id;
|
this.id = id;
|
||||||
this.size = size;
|
this.size = size;
|
||||||
this.meta = meta;
|
this.meta = meta;
|
||||||
|
@ -27,7 +27,7 @@ public final class Stack {
|
||||||
return this.meta;
|
return this.meta;
|
||||||
}
|
}
|
||||||
|
|
||||||
public NbtCompound getTag() {
|
public Map<String, Object> getTag() {
|
||||||
return this.tag;
|
return this.tag;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue