make nbt implementation smaller

This commit is contained in:
Sen 2025-06-05 10:56:05 +02:00
parent 4849bc9276
commit 721e668d51
Signed by: sen
GPG key ID: 3AC50A6F47D1B722
20 changed files with 164 additions and 417 deletions

View file

@ -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;
}
}
}

View file

@ -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;
}
}

View file

@ -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;
}
}

View file

@ -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);
}
}

View file

@ -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;
}
}

View file

@ -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;
}
}

View file

@ -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;
}
}

View file

@ -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;
}
}

View file

@ -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();
}
}

View file

@ -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;
}
}

View file

@ -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;
}
}

View file

@ -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;
}
}

View file

@ -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;
}
}

View file

@ -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");
}
}

View file

@ -16,10 +16,11 @@ import java.nio.ByteOrder;
import java.nio.channels.GatheringByteChannel;
import java.nio.channels.ScatteringByteChannel;
import java.nio.charset.Charset;
import java.util.Map;
import java.util.UUID;
import proxy.nbt.NbtCompound;
import proxy.util.Vec3;
import proxy.util.Nbt;
import proxy.util.Stack;
public class PacketBuffer extends ByteBuf
@ -187,7 +188,7 @@ public class PacketBuffer extends ByteBuf
/**
* Writes a compressed NBTTagCompound to this buffer
*/
public void writeNBTTagCompoundToBuffer(NbtCompound nbt)
public void writeNBTTagCompoundToBuffer(Map<String, Object> nbt)
{
if (nbt == null)
{
@ -197,7 +198,7 @@ public class PacketBuffer extends ByteBuf
{
try
{
NbtCompound.writeTag(nbt, new ByteBufOutputStream(this));
Nbt.writeTag(nbt, new ByteBufOutputStream(this));
}
catch (IOException ioexception)
{
@ -209,7 +210,7 @@ public class PacketBuffer extends ByteBuf
/**
* Reads a compressed NBTTagCompound from this buffer
*/
public NbtCompound readNBTTagCompoundFromBuffer() throws IOException
public Map<String, Object> readNBTTagCompoundFromBuffer() throws IOException
{
int i = this.readerIndex();
byte b0 = this.readByte();
@ -221,7 +222,7 @@ public class PacketBuffer extends ByteBuf
else
{
this.readerIndex(i);
return NbtCompound.readTag(new ByteBufInputStream(this));
return Nbt.readTag(new ByteBufInputStream(this));
}
}

View file

@ -21,6 +21,7 @@ import proxy.util.Formatter;
import proxy.util.User;
import proxy.util.Stack;
import proxy.util.Log;
import proxy.util.Nbt;
public class ProxyHandler extends User implements Handler {
public class ProxyLoginHandler implements Handler {
@ -539,7 +540,7 @@ public class ProxyHandler extends User implements Handler {
Stack itemstack1 = packetbuffer.readStack();
if(itemstack1 != null && itemstack1.getTag() != null) {
int pages = itemstack1.getTag().getStringListLength("pages");
int pages = Nbt.getStringListLength(itemstack1.getTag(), "pages");
if(pages > 50)
return;
}
@ -559,10 +560,10 @@ public class ProxyHandler extends User implements Handler {
Stack itemstack = packetbuffer.readStack();
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)))
return;
int pages = itemstack.getTag().getStringListLength("pages");
int pages = Nbt.getStringListLength(itemstack.getTag(), "pages");
if(pages > 50)
return;
}

View file

@ -1,8 +1,8 @@
package proxy.packet;
import java.io.IOException;
import java.util.Map;
import proxy.nbt.NbtCompound;
import proxy.network.ProxyHandler;
import proxy.network.Packet;
import proxy.network.PacketBuffer;
@ -12,7 +12,7 @@ public class S35PacketUpdateTileEntity implements Packet<ProxyHandler>
{
private Vec3 blockPos;
private int metadata;
private NbtCompound nbt;
private Map<String, Object> nbt;
/**
* Reads the raw packet data from the data stream.

View file

@ -1,15 +1,15 @@
package proxy.packet;
import java.io.IOException;
import java.util.Map;
import proxy.nbt.NbtCompound;
import proxy.network.ProxyHandler;
import proxy.network.Packet;
import proxy.network.PacketBuffer;
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.

View 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);
}
}

View file

@ -1,14 +1,14 @@
package proxy.util;
import proxy.nbt.NbtCompound;
import java.util.Map;
public final class Stack {
private final short id;
private final byte size;
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.size = size;
this.meta = meta;
@ -27,7 +27,7 @@ public final class Stack {
return this.meta;
}
public NbtCompound getTag() {
public Map<String, Object> getTag() {
return this.tag;
}
}