From 9ba14d9dc9f3862f3d8e3010b8d5484d521739fe Mon Sep 17 00:00:00 2001
From: EOT3000 <43685885+EOT3000@users.noreply.github.com>
Date: Thu, 18 Jul 2019 20:11:58 -0400
Subject: [PATCH] attempt crash fix/fix typo/others

---
 .../connector/console/GeyserLogger.java       |   9 +
 .../network/ConnectorServerEventHandler.java  |   4 +-
 .../network/translators/Registry.java         |   3 +-
 .../network/translators/TranslatorsInit.java  |  44 +-
 .../connector/utils/ArraySerializer.java      | 272 --------
 .../geysermc/connector/utils/GeyserUtils.java | 653 ++++++++++++++++++
 .../connector/utils/MiscSerializer.java       | 159 -----
 .../geysermc/connector/utils/NibbleArray.java | 129 ++++
 .../geysermc/connector/utils/PSPEStuff.java   |  52 --
 .../connector/utils/PositionSerializer.java   |  97 ---
 .../org/geysermc/connector/utils/Toolbox.java |  13 +-
 .../connector/utils/VarNumberSerializer.java  | 177 -----
 12 files changed, 833 insertions(+), 779 deletions(-)
 delete mode 100644 connector/src/main/java/org/geysermc/connector/utils/ArraySerializer.java
 create mode 100644 connector/src/main/java/org/geysermc/connector/utils/GeyserUtils.java
 delete mode 100644 connector/src/main/java/org/geysermc/connector/utils/MiscSerializer.java
 create mode 100644 connector/src/main/java/org/geysermc/connector/utils/NibbleArray.java
 delete mode 100644 connector/src/main/java/org/geysermc/connector/utils/PSPEStuff.java
 delete mode 100644 connector/src/main/java/org/geysermc/connector/utils/PositionSerializer.java
 delete mode 100644 connector/src/main/java/org/geysermc/connector/utils/VarNumberSerializer.java

diff --git a/connector/src/main/java/org/geysermc/connector/console/GeyserLogger.java b/connector/src/main/java/org/geysermc/connector/console/GeyserLogger.java
index a57d95538..da76a3086 100644
--- a/connector/src/main/java/org/geysermc/connector/console/GeyserLogger.java
+++ b/connector/src/main/java/org/geysermc/connector/console/GeyserLogger.java
@@ -92,29 +92,38 @@ public class GeyserLogger implements org.geysermc.api.logger.Logger {
 
     @Override
     public void severe(String message) {
+        waitFor();
         System.out.println(printConsole(ChatColor.DARK_RED + message, colored));
     }
 
     @Override
     public void error(String message) {
+        waitFor();
         System.out.println(printConsole(ChatColor.RED + message, colored));
     }
 
     @Override
     public void warning(String message) {
+        waitFor();
         System.out.println(printConsole(ChatColor.YELLOW + message, colored));
     }
 
     @Override
     public void info(String message) {
+        waitFor();
         System.out.println(printConsole(ChatColor.WHITE + message, colored));
     }
 
     @Override
     public void debug(String message) {
+        waitFor();
         System.out.println(printConsole(ChatColor.GRAY + message, colored));
     }
 
+    private synchronized void waitFor() {
+
+    }
+
     public void stop() {
     }
 
diff --git a/connector/src/main/java/org/geysermc/connector/network/ConnectorServerEventHandler.java b/connector/src/main/java/org/geysermc/connector/network/ConnectorServerEventHandler.java
index 0732676eb..ae1b779b6 100644
--- a/connector/src/main/java/org/geysermc/connector/network/ConnectorServerEventHandler.java
+++ b/connector/src/main/java/org/geysermc/connector/network/ConnectorServerEventHandler.java
@@ -47,7 +47,7 @@ public class ConnectorServerEventHandler implements BedrockServerEventHandler {
 
     @Override
     public boolean onConnectionRequest(InetSocketAddress inetSocketAddress) {
-        System.out.println(inetSocketAddress + " tried to connect!");
+        GeyserLogger.DEFAULT.info(inetSocketAddress + " tried to connect!");
         return true;
     }
 
@@ -74,7 +74,7 @@ public class ConnectorServerEventHandler implements BedrockServerEventHandler {
     public void onSessionCreation(BedrockServerSession bedrockServerSession) {
         bedrockServerSession.setLogging(true);
         bedrockServerSession.setPacketHandler(new UpstreamPacketHandler(connector, new GeyserSession(connector, bedrockServerSession)));
-        bedrockServerSession.addDisconnectHandler((x) -> GeyserLogger.DEFAULT.warning("Bedrock user with ip: " + bedrockServerSession.getAddress().getAddress() + " has disconected for reason " + x));
+        bedrockServerSession.addDisconnectHandler((x) -> GeyserLogger.DEFAULT.warning("Bedrock user with ip: " + bedrockServerSession.getAddress().getAddress() + " has disconnected for reason " + x));
         bedrockServerSession.setPacketCodec(Bedrock_v361.V361_CODEC);
     }
 
diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/Registry.java b/connector/src/main/java/org/geysermc/connector/network/translators/Registry.java
index de10204aa..ffb80afaa 100644
--- a/connector/src/main/java/org/geysermc/connector/network/translators/Registry.java
+++ b/connector/src/main/java/org/geysermc/connector/network/translators/Registry.java
@@ -2,6 +2,7 @@ package org.geysermc.connector.network.translators;
 
 import com.github.steveice10.packetlib.packet.Packet;
 import org.geysermc.api.Geyser;
+import org.geysermc.connector.console.GeyserLogger;
 import org.geysermc.connector.network.session.GeyserSession;
 
 import java.util.HashMap;
@@ -22,7 +23,7 @@ public class Registry<T> {
         try {
             ((BiConsumer<P, GeyserSession>) JAVA.MAP.get(clazz)).accept(p, s);
         } catch (NullPointerException e) {
-            System.err.println("could not translate packet" + p.getClass().getSimpleName());
+            GeyserLogger.DEFAULT.warning("could not translate packet " + p.getClass().getSimpleName());
         }
     }
 
diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/TranslatorsInit.java b/connector/src/main/java/org/geysermc/connector/network/translators/TranslatorsInit.java
index 623c56bff..6ab1224ed 100644
--- a/connector/src/main/java/org/geysermc/connector/network/translators/TranslatorsInit.java
+++ b/connector/src/main/java/org/geysermc/connector/network/translators/TranslatorsInit.java
@@ -5,7 +5,6 @@ import com.flowpowered.math.vector.Vector2i;
 import com.flowpowered.math.vector.Vector3f;
 import com.flowpowered.math.vector.Vector3i;
 import com.github.steveice10.mc.protocol.packet.ingame.server.ServerJoinGamePacket;
-import com.github.steveice10.mc.protocol.packet.ingame.server.entity.player.ServerPlayerAbilitiesPacket;
 import com.nukkitx.nbt.NbtUtils;
 import com.nukkitx.nbt.stream.NBTOutputStream;
 import com.nukkitx.nbt.tag.CompoundTag;
@@ -13,13 +12,9 @@ import com.nukkitx.network.VarInts;
 import com.nukkitx.protocol.bedrock.data.GamePublishSetting;
 import com.nukkitx.protocol.bedrock.data.GameRule;
 import com.nukkitx.protocol.bedrock.packet.*;
-import com.nukkitx.protocol.bedrock.v340.serializer.FullChunkDataSerializer_v340;
-import com.nukkitx.protocol.bedrock.v340.serializer.ResourcePackChunkDataSerializer_v340;
-import com.nukkitx.protocol.bedrock.v340.serializer.SetSpawnPositionSerializer_v340;
 import io.netty.buffer.ByteBuf;
 import io.netty.buffer.Unpooled;
-import org.geysermc.connector.console.GeyserLogger;
-import org.geysermc.connector.utils.PositionSerializer;
+import org.geysermc.connector.utils.GeyserUtils;
 import org.geysermc.connector.utils.Toolbox;
 
 import java.io.ByteArrayOutputStream;
@@ -32,9 +27,6 @@ public class TranslatorsInit {
 
     private static void addLoginPackets() {
         Registry.add(ServerJoinGamePacket.class, (packet, session) -> {
-            for(byte b : Toolbox.EMPTY_CHUNK) {
-                GeyserLogger.DEFAULT.warning("" + b);
-            }
             AdventureSettingsPacket bedrockPacket = new AdventureSettingsPacket();
 
             bedrockPacket.setUniqueEntityId(packet.getEntityId());
@@ -104,7 +96,37 @@ public class TranslatorsInit {
                     data.setChunkX(chunkX + x);
                     data.setChunkZ(chunkZ + z);
 
-                    data.setData(Toolbox.EMPTY_CHUNK);
+                    ByteBuf buf = Unpooled.buffer();
+
+                    data.setSubChunksLength(1);
+
+                    for(int i = 0; i < 1; i++) {
+                        GeyserUtils.writeEmptySubChunk(buf);
+                    }
+
+                    for(int i  = 0; i < 256; i++) {
+                        buf.writeByte(0);
+                    }
+
+                    buf.writeZero(1);
+
+                    VarInts.writeInt(buf, 0);
+
+                    ByteArrayOutputStream s = new ByteArrayOutputStream();
+
+                    NBTOutputStream stream = NbtUtils.createNetworkWriter(s);
+
+                    try {
+                        stream.write(new CompoundTag("", new HashMap<>()));
+                        s.close();
+                        stream.close();
+                    } catch (Exception e) {
+                        e.printStackTrace();
+                    }
+
+                    buf.writeBytes(s.toByteArray());
+
+                    data.setData(new byte[0]);
 
                     session.getUpstream().sendPacketImmediately(data);
 
@@ -123,7 +145,7 @@ public class TranslatorsInit {
     private static byte[] empty(byte[] b, Vector2i pos) {
         ByteBuf by = Unpooled.buffer();
 
-        PositionSerializer.writePEChunkCoord(by, pos);
+        GeyserUtils.writePEChunkCoord(by, pos);
 
         return by.array();
     }
diff --git a/connector/src/main/java/org/geysermc/connector/utils/ArraySerializer.java b/connector/src/main/java/org/geysermc/connector/utils/ArraySerializer.java
deleted file mode 100644
index c8b0ceabc..000000000
--- a/connector/src/main/java/org/geysermc/connector/utils/ArraySerializer.java
+++ /dev/null
@@ -1,272 +0,0 @@
-package org.geysermc.connector.utils;
-
-import java.lang.reflect.Array;
-
-import java.util.List;
-
-import java.util.function.BiConsumer;
-
-import java.util.function.Consumer;
-
-import java.util.function.Function;
-
-import java.util.function.ToIntFunction;
-
-
-
-import io.netty.buffer.ByteBuf;
-
-
-
-public class ArraySerializer {
-
-
-
-    public static ByteBuf readShortByteArraySlice(ByteBuf from, int limit) {
-
-        int length = from.readShort();
-
-        MiscSerializer.checkLimit(length, limit);
-
-        return from.readSlice(length);
-
-    }
-
-
-
-    @SuppressWarnings("unchecked")
-
-    public static <T> T[] readShortTArray(ByteBuf from, Class<T> tclass, Function<ByteBuf, T> elementReader) {
-
-        T[] array = (T[]) Array.newInstance(tclass, from.readShort());
-
-        for (int i = 0; i < array.length; i++) {
-
-            array[i] = elementReader.apply(from);
-
-        }
-
-        return array;
-
-    }
-
-
-
-
-
-    public static byte[] readVarIntByteArray(ByteBuf from) {
-
-        return MiscSerializer.readBytes(from, VarNumberSerializer.readVarInt(from));
-
-    }
-
-
-
-    public static ByteBuf readVarIntByteArraySlice(ByteBuf from, int limit) {
-
-        int length = VarNumberSerializer.readVarInt(from);
-
-        MiscSerializer.checkLimit(length, limit);
-
-        return from.readSlice(length);
-
-    }
-
-
-
-    public static ByteBuf readVarIntByteArraySlice(ByteBuf from) {
-
-        return from.readSlice(VarNumberSerializer.readVarInt(from));
-
-    }
-
-
-
-    @SuppressWarnings("unchecked")
-
-    public static <T> T[] readVarIntTArray(ByteBuf from, Class<T> tclass, Function<ByteBuf, T> elementReader) {
-
-        T[] array = (T[]) Array.newInstance(tclass, VarNumberSerializer.readVarInt(from));
-
-        for (int i = 0; i < array.length; i++) {
-
-            array[i] = elementReader.apply(from);
-
-        }
-
-        return array;
-
-    }
-
-
-
-    public static int[] readVarIntVarIntArray(ByteBuf from) {
-
-        int[] array = new int[VarNumberSerializer.readVarInt(from)];
-
-        for (int i = 0; i < array.length; i++) {
-
-            array[i] = VarNumberSerializer.readVarInt(from);
-
-        }
-
-        return array;
-
-    }
-
-
-
-
-
-    public static void writeShortByteArray(ByteBuf to, ByteBuf data) {
-
-        to.writeShort(data.readableBytes());
-
-        to.writeBytes(data);
-
-    }
-
-
-
-    public static void writeShortByteArray(ByteBuf to, byte[] data) {
-
-        to.writeShort(data.length);
-
-        to.writeBytes(data);
-
-    }
-
-
-
-    public static void writeShortByteArray(ByteBuf to, Consumer<ByteBuf> dataWriter) {
-
-        MiscSerializer.writeLengthPrefixedBytes(to, (lTo, length) -> lTo.writeShort(length), dataWriter);
-
-    }
-
-
-
-    public static <T> void writeShortTArray(ByteBuf to, T[] array, BiConsumer<ByteBuf, T> elementWriter) {
-
-        to.writeShort(array.length);
-
-        for (T element : array) {
-
-            elementWriter.accept(to, element);
-
-        }
-
-    }
-
-
-
-
-
-    public static void writeVarIntByteArray(ByteBuf to, ByteBuf data) {
-
-        VarNumberSerializer.writeVarInt(to, data.readableBytes());
-
-        to.writeBytes(data);
-
-    }
-
-
-
-    public static void writeVarIntByteArray(ByteBuf to, byte[] data) {
-
-        VarNumberSerializer.writeVarInt(to, data.length);
-
-        to.writeBytes(data);
-
-    }
-
-
-
-    public static void writeVarIntByteArray(ByteBuf to, Consumer<ByteBuf> dataWriter) {
-
-        MiscSerializer.writeLengthPrefixedBytes(to, VarNumberSerializer::writeFixedSizeVarInt, dataWriter);
-
-    }
-
-
-
-    public static void writeVarIntTArray(ByteBuf to, ToIntFunction<ByteBuf> arrayWriter) {
-
-        MiscSerializer.writeSizePrefixedData(to, VarNumberSerializer::writeFixedSizeVarInt, arrayWriter);
-
-    }
-
-
-
-    public static <T> void writeVarIntTArray(ByteBuf to, T[] array, BiConsumer<ByteBuf, T> elementWriter) {
-
-        VarNumberSerializer.writeVarInt(to, array.length);
-
-        for (T element : array) {
-
-            elementWriter.accept(to, element);
-
-        }
-
-    }
-
-
-
-    public static <T> void writeVarIntTArray(ByteBuf to, List<T> array, BiConsumer<ByteBuf, T> elementWriter) {
-
-        VarNumberSerializer.writeVarInt(to, array.size());
-
-        for (T element : array) {
-
-            elementWriter.accept(to, element);
-
-        }
-
-    }
-
-
-
-
-    public static void writeVarIntVarIntArray(ByteBuf to, int[] array) {
-
-        VarNumberSerializer.writeVarInt(to, array.length);
-
-        for (int element : array) {
-
-            VarNumberSerializer.writeVarInt(to, element);
-
-        }
-
-    }
-
-
-
-    public static void writeSVarIntSVarIntArray(ByteBuf to, int[] array) {
-
-        VarNumberSerializer.writeSVarInt(to, array.length);
-
-        for (int element : array) {
-
-            VarNumberSerializer.writeSVarInt(to, element);
-
-        }
-
-    }
-
-
-
-    public static void writeVarIntLongArray(ByteBuf to, long[] array) {
-
-        VarNumberSerializer.writeVarInt(to, array.length);
-
-        for (long element : array) {
-
-            to.writeLong(element);
-
-        }
-
-    }
-
-
-
-}
diff --git a/connector/src/main/java/org/geysermc/connector/utils/GeyserUtils.java b/connector/src/main/java/org/geysermc/connector/utils/GeyserUtils.java
new file mode 100644
index 000000000..1e95a3e3f
--- /dev/null
+++ b/connector/src/main/java/org/geysermc/connector/utils/GeyserUtils.java
@@ -0,0 +1,653 @@
+package org.geysermc.connector.utils;
+
+import com.flowpowered.math.vector.Vector2i;
+import com.flowpowered.math.vector.Vector3d;
+import com.flowpowered.math.vector.Vector3i;
+import io.netty.buffer.ByteBuf;
+import io.netty.handler.codec.DecoderException;
+
+import java.lang.reflect.Array;
+import java.text.MessageFormat;
+import java.util.List;
+import java.util.UUID;
+import java.util.function.*;
+
+public class GeyserUtils {
+
+    public static final int FLAG_RUNTIME = 1;
+
+    public static final int GLOBAL_PALETTE_BITS_PER_BLOCK = 14;
+
+    public static final int SECTION_COUNT_BLOCKS = 16;
+
+    public static final int SECTION_COUNT_LIGHT = 18;
+
+    public static final int BLOCKS_IN_SECTION = 16 * 16 * 16;
+
+    public static final int LIGHT_DATA_LENGTH = BLOCKS_IN_SECTION / 2;
+
+    public static final int EMPTY_SUBCHUNK_BYTES = BLOCKS_IN_SECTION / 8;
+
+    public static final int SUBCHUNK_VERSION = 8;
+
+    public static void writeEmpty(ByteBuf to) {
+
+        to.writeByte(storageHeader(1));
+
+        to.writeZero(EMPTY_SUBCHUNK_BYTES);
+
+    }
+
+
+
+    protected static final int storageHeader(int bitsPerBlock) {
+
+        return (bitsPerBlock << 1) | FLAG_RUNTIME;
+
+    }
+
+    public static void writeEmptySubChunk(ByteBuf out) {
+
+        out.writeBytes(new byte[4096 + 4096]);
+
+    }
+
+    public static void skipPosition(ByteBuf from) {
+        from.skipBytes(Long.BYTES);
+    }
+
+    public static Vector3d readPosition(ByteBuf from) {
+        long l = from.readLong();
+        return new Vector3d(
+                (int) (l >> 38), (int) (l & 0xFFF), (int) ((l << 26) >> 38)
+        );
+    }
+
+    public static void readPEPosition(ByteBuf from) {
+        readSVarInt(from);
+        readVarInt(from);
+        readSVarInt(from);
+    }
+
+    public static Vector3d readLegacyPositionI(ByteBuf from) {
+        return new Vector3d(from.readInt(), from.readInt(), from.readInt());
+    }
+
+    public static void writePosition(ByteBuf to, Vector3i position) {
+        to.writeLong(((position.getX() & 0x3FFFFFFL) << 38) | ((position.getZ() & 0x3FFFFFFL) << 12) | (position.getY() & 0xFFFL));
+    }
+
+    public static void writeLegacyPositionL(ByteBuf to, Vector3d position) {
+        to.writeLong((((int) position.getX() & 0x3FFFFFFL) << 38) | (((int) position.getY() & 0xFFFL) << 26) | ((int) position.getZ() & 0x3FFFFFFL));
+    }
+
+    public static void writePEPosition(ByteBuf to, Vector3d position) {
+        writeSVarInt(to, (int) position.getX());
+        writeVarInt(to, (int) position.getY());
+        writeSVarInt(to, (int) position.getZ());
+    }
+
+    public static void writeLegacyPositionB(ByteBuf to, Vector3d position) {
+        to.writeInt((int) position.getX());
+        to.writeByte((int) position.getY());
+        to.writeInt((int) position.getZ());
+    }
+
+    public static void writeLegacyPositionS(ByteBuf to, Vector3d position) {
+        to.writeInt((int) position.getX());
+        to.writeShort((int) position.getY());
+        to.writeInt((int) position.getZ());
+    }
+
+    public static void writeLegacyPositionI(ByteBuf to, Vector3d position) {
+        to.writeInt((int) position.getX());
+        to.writeInt((int) position.getY());
+        to.writeInt((int) position.getZ());
+    }
+
+    public static Vector2i readIntChunkCoord(ByteBuf from) {
+        return new Vector2i(from.readInt(), from.readInt());
+    }
+
+    public static Vector2i readVarIntChunkCoord(ByteBuf from) {
+        return new Vector2i(readVarInt(from), readVarInt(from));
+    }
+
+    public static void writeIntChunkCoord(ByteBuf to, Vector2i chunk) {
+        to.writeInt(chunk.getX());
+        to.writeInt(chunk.getY());
+    }
+
+    public static Vector2i readPEChunkCoord(ByteBuf from) {
+        return new Vector2i(readSVarInt(from), readSVarInt(from));
+    }
+
+    public static void writePEChunkCoord(ByteBuf to, Vector2i chunk) {
+        writeSVarInt(to, chunk.getX());
+        writeSVarInt(to, chunk.getY());
+    }
+
+    public static int readLocalCoord(ByteBuf from) {
+        return from.readUnsignedShort();
+    }
+
+    public static void writeLocalCoord(ByteBuf to, int coord) {
+        to.writeShort(coord);
+    }
+
+    public static void writeVarIntChunkCoord(ByteBuf to, Vector2i chunk) {
+        writeVarInt(to, chunk.getX());
+        writeVarInt(to, chunk.getY());
+    }
+
+
+
+    public static final int MAX_LENGTH = 5;
+
+
+
+    public static void writeFixedSizeVarInt(ByteBuf to, int i) {
+
+        int writerIndex = to.writerIndex();
+
+        while ((i & 0xFFFFFF80) != 0x0) {
+
+            to.writeByte(i | 0x80);
+
+            i >>>= 7;
+
+        }
+
+        int paddingBytes = MAX_LENGTH - (to.writerIndex() - writerIndex) - 1;
+
+        if (paddingBytes == 0) {
+
+            to.writeByte(i);
+
+        } else {
+
+            to.writeByte(i | 0x80);
+
+            while (--paddingBytes > 0) {
+
+                to.writeByte(0x80);
+
+            }
+
+            to.writeByte(0);
+
+        }
+
+    }
+
+
+
+    public static int readVarInt(ByteBuf from) {
+
+        int value = 0;
+
+        int length = 0;
+
+        byte part;
+
+        do {
+
+            part = from.readByte();
+
+            value |= (part & 0x7F) << (length++ * 7);
+
+            if (length > MAX_LENGTH) {
+
+                throw new DecoderException("VarInt too big");
+
+            }
+
+        } while (part < 0);
+
+        return value;
+
+    }
+
+
+
+    public static void writeVarInt(ByteBuf to, int i) {
+
+        while ((i & 0xFFFFFF80) != 0x0) {
+
+            to.writeByte(i | 0x80);
+
+            i >>>= 7;
+
+        }
+
+        to.writeByte(i);
+
+    }
+
+
+
+    public static int readSVarInt(ByteBuf from) {
+
+        int varint = readVarInt(from);
+
+        return (varint >> 1) ^ -(varint & 1);
+
+    }
+
+
+
+    public static void writeSVarInt(ByteBuf to, int varint) {
+
+        writeVarInt(to, (varint << 1) ^ (varint >> 31));
+
+    }
+
+
+
+    public static long readVarLong(ByteBuf from) {
+
+        long varlong = 0L;
+
+        int length = 0;
+
+        byte part;
+
+        do {
+
+            part = from.readByte();
+
+            varlong |= (part & 0x7F) << (length++ * 7);
+
+            if (length > 10) {
+
+                throw new RuntimeException("VarLong too big");
+
+            }
+
+        } while ((part & 0x80) == 0x80);
+
+        return varlong;
+
+    }
+
+
+
+    public static void writeVarLong(ByteBuf to, long varlong) {
+
+        while ((varlong & 0xFFFFFFFFFFFFFF80L) != 0x0L) {
+
+            to.writeByte((int) (varlong & 0x7FL) | 0x80);
+
+            varlong >>>= 7;
+
+        }
+
+        to.writeByte((int) varlong);
+
+    }
+
+
+
+    public static long readSVarLong(ByteBuf from) {
+
+        long varlong = readVarLong(from);
+
+        return (varlong >> 1) ^ -(varlong & 1);
+
+    }
+
+
+
+    public static void writeSVarLong(ByteBuf to, long varlong) {
+
+        writeVarLong(to, (varlong << 1) ^ (varlong >> 63));
+
+    }
+
+
+    public static ByteBuf readShortByteArraySlice(ByteBuf from, int limit) {
+
+        int length = from.readShort();
+
+        checkLimit(length, limit);
+
+        return from.readSlice(length);
+
+    }
+
+
+
+    @SuppressWarnings("unchecked")
+
+    public static <T> T[] readShortTArray(ByteBuf from, Class<T> tclass, Function<ByteBuf, T> elementReader) {
+
+        T[] array = (T[]) Array.newInstance(tclass, from.readShort());
+
+        for (int i = 0; i < array.length; i++) {
+
+            array[i] = elementReader.apply(from);
+
+        }
+
+        return array;
+
+    }
+
+
+
+
+
+    public static byte[] readVarIntByteArray(ByteBuf from) {
+
+        return readBytes(from, readVarInt(from));
+
+    }
+
+
+
+    public static ByteBuf readVarIntByteArraySlice(ByteBuf from, int limit) {
+
+        int length = readVarInt(from);
+
+        checkLimit(length, limit);
+
+        return from.readSlice(length);
+
+    }
+
+
+
+    public static ByteBuf readVarIntByteArraySlice(ByteBuf from) {
+
+        return from.readSlice(readVarInt(from));
+
+    }
+
+
+
+    @SuppressWarnings("unchecked")
+
+    public static <T> T[] readVarIntTArray(ByteBuf from, Class<T> tclass, Function<ByteBuf, T> elementReader) {
+
+        T[] array = (T[]) Array.newInstance(tclass, readVarInt(from));
+
+        for (int i = 0; i < array.length; i++) {
+
+            array[i] = elementReader.apply(from);
+
+        }
+
+        return array;
+
+    }
+
+
+
+    public static int[] readVarIntVarIntArray(ByteBuf from) {
+
+        int[] array = new int[readVarInt(from)];
+
+        for (int i = 0; i < array.length; i++) {
+
+            array[i] = readVarInt(from);
+
+        }
+
+        return array;
+
+    }
+
+
+
+
+
+    public static void writeShortByteArray(ByteBuf to, ByteBuf data) {
+
+        to.writeShort(data.readableBytes());
+
+        to.writeBytes(data);
+
+    }
+
+
+
+    public static void writeShortByteArray(ByteBuf to, byte[] data) {
+
+        to.writeShort(data.length);
+
+        to.writeBytes(data);
+
+    }
+
+
+
+    public static void writeShortByteArray(ByteBuf to, Consumer<ByteBuf> dataWriter) {
+
+        writeLengthPrefixedBytes(to, (lTo, length) -> lTo.writeShort(length), dataWriter);
+
+    }
+
+
+
+    public static <T> void writeShortTArray(ByteBuf to, T[] array, BiConsumer<ByteBuf, T> elementWriter) {
+
+        to.writeShort(array.length);
+
+        for (T element : array) {
+
+            elementWriter.accept(to, element);
+
+        }
+
+    }
+
+
+
+
+
+    public static void writeVarIntByteArray(ByteBuf to, ByteBuf data) {
+
+        writeVarInt(to, data.readableBytes());
+
+        to.writeBytes(data);
+
+    }
+
+
+
+    public static void writeVarIntByteArray(ByteBuf to, byte[] data) {
+
+        writeVarInt(to, data.length);
+
+        to.writeBytes(data);
+
+    }
+
+
+
+    public static void writeVarIntByteArray(ByteBuf to, Consumer<ByteBuf> dataWriter) {
+
+        writeLengthPrefixedBytes(to, GeyserUtils::writeFixedSizeVarInt, dataWriter);
+
+    }
+
+
+
+    public static void writeVarIntTArray(ByteBuf to, ToIntFunction<ByteBuf> arrayWriter) {
+
+        writeSizePrefixedData(to, GeyserUtils::writeFixedSizeVarInt, arrayWriter);
+
+    }
+
+
+
+    public static <T> void writeVarIntTArray(ByteBuf to, T[] array, BiConsumer<ByteBuf, T> elementWriter) {
+
+        writeVarInt(to, array.length);
+
+        for (T element : array) {
+
+            elementWriter.accept(to, element);
+
+        }
+
+    }
+
+
+
+    public static <T> void writeVarIntTArray(ByteBuf to, List<T> array, BiConsumer<ByteBuf, T> elementWriter) {
+
+        writeVarInt(to, array.size());
+
+        for (T element : array) {
+
+            elementWriter.accept(to, element);
+
+        }
+
+    }
+
+
+    public static void writeVarIntEnum(ByteBuf to, Enum<?> e) {
+
+        writeVarInt(to, e.ordinal());
+
+    }
+
+
+
+    public static void writeByteEnum(ByteBuf to, Enum<?> e) {
+
+        to.writeByte(e.ordinal());
+
+    }
+
+
+
+    public static UUID readUUID(ByteBuf from) {
+
+        return new UUID(from.readLong(), from.readLong());
+
+    }
+
+
+
+    public static void writeUUID(ByteBuf to, UUID uuid) {
+
+        to.writeLong(uuid.getMostSignificantBits());
+
+        to.writeLong(uuid.getLeastSignificantBits());
+
+    }
+
+
+
+    public static void writePEUUID(ByteBuf to, UUID uuid) {
+
+        to.writeLongLE(uuid.getMostSignificantBits());
+
+        to.writeLongLE(uuid.getLeastSignificantBits());
+
+    }
+
+
+
+    public static byte[] readAllBytes(ByteBuf buf) {
+
+        return readBytes(buf, buf.readableBytes());
+
+    }
+
+
+
+    public static ByteBuf readAllBytesSlice(ByteBuf from) {
+
+        return from.readSlice(from.readableBytes());
+
+    }
+
+
+
+    public static ByteBuf readAllBytesSlice(ByteBuf buf, int limit) {
+
+        checkLimit(buf.readableBytes(), limit);
+
+        return readAllBytesSlice(buf);
+
+    }
+
+
+
+    public static byte[] readBytes(ByteBuf buf, int length) {
+
+        byte[] result = new byte[length];
+
+        buf.readBytes(result);
+
+        return result;
+
+    }
+
+
+
+    protected static void checkLimit(int length, int limit) {
+
+        if (length > limit) {
+
+            throw new DecoderException(MessageFormat.format("Size {0} is bigger than allowed {1}", length, limit));
+
+        }
+
+    }
+
+
+
+    public static void writeLengthPrefixedBytes(ByteBuf to, ObjIntConsumer<ByteBuf> lengthWriter, Consumer<ByteBuf> dataWriter) {
+
+        int lengthWriterIndex = to.writerIndex();
+
+        lengthWriter.accept(to, 0);
+
+        int writerIndexDataStart = to.writerIndex();
+
+        dataWriter.accept(to);
+
+        int writerIndexDataEnd = to.writerIndex();
+
+        to.writerIndex(lengthWriterIndex);
+
+        lengthWriter.accept(to, writerIndexDataEnd - writerIndexDataStart);
+
+        to.writerIndex(writerIndexDataEnd);
+
+    }
+
+
+
+    public static void writeSizePrefixedData(ByteBuf to, ObjIntConsumer<ByteBuf> sizeWriter, ToIntFunction<ByteBuf> dataWriter) {
+
+        int sizeWriterIndex = to.writerIndex();
+
+        sizeWriter.accept(to, 0);
+
+        int size = dataWriter.applyAsInt(to);
+
+        int writerIndexDataEnd = to.writerIndex();
+
+        to.writerIndex(sizeWriterIndex);
+
+        sizeWriter.accept(to, size);
+
+        to.writerIndex(writerIndexDataEnd);
+
+    }
+
+
+    private static int getAnvilIndex(int x, int y, int z) {
+
+        return (y << 8) + (z << 4) + x;
+
+    }
+
+
+}
diff --git a/connector/src/main/java/org/geysermc/connector/utils/MiscSerializer.java b/connector/src/main/java/org/geysermc/connector/utils/MiscSerializer.java
deleted file mode 100644
index f928106de..000000000
--- a/connector/src/main/java/org/geysermc/connector/utils/MiscSerializer.java
+++ /dev/null
@@ -1,159 +0,0 @@
-package org.geysermc.connector.utils;
-
-import java.text.MessageFormat;
-
-import java.util.UUID;
-
-import java.util.function.Consumer;
-
-import java.util.function.ObjIntConsumer;
-
-import java.util.function.ToIntFunction;
-
-
-
-import io.netty.buffer.ByteBuf;
-
-import io.netty.handler.codec.DecoderException;
-
-
-public class MiscSerializer {
-
-
-    public static void writeVarIntEnum(ByteBuf to, Enum<?> e) {
-
-        VarNumberSerializer.writeVarInt(to, e.ordinal());
-
-    }
-
-
-
-    public static void writeByteEnum(ByteBuf to, Enum<?> e) {
-
-        to.writeByte(e.ordinal());
-
-    }
-
-
-
-    public static UUID readUUID(ByteBuf from) {
-
-        return new UUID(from.readLong(), from.readLong());
-
-    }
-
-
-
-    public static void writeUUID(ByteBuf to, UUID uuid) {
-
-        to.writeLong(uuid.getMostSignificantBits());
-
-        to.writeLong(uuid.getLeastSignificantBits());
-
-    }
-
-
-
-    public static void writePEUUID(ByteBuf to, UUID uuid) {
-
-        to.writeLongLE(uuid.getMostSignificantBits());
-
-        to.writeLongLE(uuid.getLeastSignificantBits());
-
-    }
-
-
-
-    public static byte[] readAllBytes(ByteBuf buf) {
-
-        return MiscSerializer.readBytes(buf, buf.readableBytes());
-
-    }
-
-
-
-    public static ByteBuf readAllBytesSlice(ByteBuf from) {
-
-        return from.readSlice(from.readableBytes());
-
-    }
-
-
-
-    public static ByteBuf readAllBytesSlice(ByteBuf buf, int limit) {
-
-        checkLimit(buf.readableBytes(), limit);
-
-        return readAllBytesSlice(buf);
-
-    }
-
-
-
-    public static byte[] readBytes(ByteBuf buf, int length) {
-
-        byte[] result = new byte[length];
-
-        buf.readBytes(result);
-
-        return result;
-
-    }
-
-
-
-    protected static void checkLimit(int length, int limit) {
-
-        if (length > limit) {
-
-            throw new DecoderException(MessageFormat.format("Size {0} is bigger than allowed {1}", length, limit));
-
-        }
-
-    }
-
-
-
-    public static void writeLengthPrefixedBytes(ByteBuf to, ObjIntConsumer<ByteBuf> lengthWriter, Consumer<ByteBuf> dataWriter) {
-
-        int lengthWriterIndex = to.writerIndex();
-
-        lengthWriter.accept(to, 0);
-
-        int writerIndexDataStart = to.writerIndex();
-
-        dataWriter.accept(to);
-
-        int writerIndexDataEnd = to.writerIndex();
-
-        to.writerIndex(lengthWriterIndex);
-
-        lengthWriter.accept(to, writerIndexDataEnd - writerIndexDataStart);
-
-        to.writerIndex(writerIndexDataEnd);
-
-    }
-
-
-
-    public static void writeSizePrefixedData(ByteBuf to, ObjIntConsumer<ByteBuf> sizeWriter, ToIntFunction<ByteBuf> dataWriter) {
-
-        int sizeWriterIndex = to.writerIndex();
-
-        sizeWriter.accept(to, 0);
-
-        int size = dataWriter.applyAsInt(to);
-
-        int writerIndexDataEnd = to.writerIndex();
-
-        to.writerIndex(sizeWriterIndex);
-
-        sizeWriter.accept(to, size);
-
-        to.writerIndex(writerIndexDataEnd);
-
-    }
-
-
-
-}
diff --git a/connector/src/main/java/org/geysermc/connector/utils/NibbleArray.java b/connector/src/main/java/org/geysermc/connector/utils/NibbleArray.java
new file mode 100644
index 000000000..85be81f83
--- /dev/null
+++ b/connector/src/main/java/org/geysermc/connector/utils/NibbleArray.java
@@ -0,0 +1,129 @@
+package org.geysermc.connector.utils;
+
+import com.google.common.base.Preconditions;
+
+
+
+public class NibbleArray implements Cloneable {
+
+    private final byte[] data;
+
+
+
+    public NibbleArray(int length) {
+
+        data = new byte[length / 2];
+
+    }
+
+
+
+    public NibbleArray(byte[] array) {
+
+        data = array;
+
+    }
+
+
+
+    public byte get(int index) {
+
+        Preconditions.checkElementIndex(index, data.length * 2);
+
+        byte val = data[index / 2];
+
+        if ((index & 1) == 0) {
+
+            return (byte) (val & 0x0f);
+
+        } else {
+
+            return (byte) ((val & 0xf0) >>> 4);
+
+        }
+
+    }
+
+
+
+    public void set(int index, byte value) {
+
+        Preconditions.checkArgument(value >= 0 && value < 16, "Nibbles must have a value between 0 and 15.");
+
+        Preconditions.checkElementIndex(index, data.length * 2);
+
+        value &= 0xf;
+
+        int half = index / 2;
+
+        byte previous = data[half];
+
+        if ((index & 1) == 0) {
+
+            data[half] = (byte) (previous & 0xf0 | value);
+
+        } else {
+
+            data[half] = (byte) (previous & 0x0f | value << 4);
+
+        }
+
+    }
+
+
+
+    public void fill(byte value) {
+
+        Preconditions.checkArgument(value >= 0 && value < 16, "Nibbles must have a value between 0 and 15.");
+
+        value &= 0xf;
+
+        for (int i = 0; i < data.length; i++) {
+
+            data[i] = (byte) ((value << 4) | value);
+
+        }
+
+    }
+
+
+
+    public void copyFrom(byte[] bytes) {
+
+        Preconditions.checkNotNull(bytes, "bytes");
+
+        Preconditions.checkArgument(bytes.length == data.length, "length of provided byte array is %s but expected %s", bytes.length,
+
+                data.length);
+
+        System.arraycopy(bytes, 0, data, 0, data.length);
+
+    }
+
+
+
+    public void copyFrom(NibbleArray array) {
+
+        Preconditions.checkNotNull(array, "array");
+
+        copyFrom(array.data);
+
+    }
+
+
+
+    public byte[] getData() {
+
+        return data;
+
+    }
+
+
+
+    public NibbleArray copy() {
+
+        return new NibbleArray(getData().clone());
+
+    }
+
+}
\ No newline at end of file
diff --git a/connector/src/main/java/org/geysermc/connector/utils/PSPEStuff.java b/connector/src/main/java/org/geysermc/connector/utils/PSPEStuff.java
deleted file mode 100644
index c513be3fd..000000000
--- a/connector/src/main/java/org/geysermc/connector/utils/PSPEStuff.java
+++ /dev/null
@@ -1,52 +0,0 @@
-package org.geysermc.connector.utils;
-
-import io.netty.buffer.ByteBuf;
-
-public class PSPEStuff {
-
-    public static final int FLAG_RUNTIME = 1;
-
-    public static final int GLOBAL_PALETTE_BITS_PER_BLOCK = 14;
-
-    public static final int SECTION_COUNT_BLOCKS = 16;
-
-    public static final int SECTION_COUNT_LIGHT = 18;
-
-    public static final int BLOCKS_IN_SECTION = 16 * 16 * 16;
-
-    public static final int LIGHT_DATA_LENGTH = BLOCKS_IN_SECTION / 2;
-
-    public static final int EMPTY_SUBCHUNK_BYTES = BLOCKS_IN_SECTION / 8;
-
-    public static final int SUBCHUNK_VERSION = 8;
-
-    public static void writeEmpty(ByteBuf to) {
-
-        to.writeByte(storageHeader(1));
-
-        to.writeZero(EMPTY_SUBCHUNK_BYTES);
-
-    }
-
-
-
-    protected static final int storageHeader(int bitsPerBlock) {
-
-        return (bitsPerBlock << 1) | FLAG_RUNTIME;
-
-    }
-
-    public static void writeEmptySubChunk(ByteBuf out) {
-
-        out.writeByte(SUBCHUNK_VERSION);
-
-        out.writeByte(1); //only blockstate storage
-
-        writeEmpty(out);
-
-        VarNumberSerializer.writeSVarInt(out, 1); //Palette size
-
-        VarNumberSerializer.writeSVarInt(out, 0); //Palette: Air
-
-    }
-}
diff --git a/connector/src/main/java/org/geysermc/connector/utils/PositionSerializer.java b/connector/src/main/java/org/geysermc/connector/utils/PositionSerializer.java
deleted file mode 100644
index 2a63fcc8e..000000000
--- a/connector/src/main/java/org/geysermc/connector/utils/PositionSerializer.java
+++ /dev/null
@@ -1,97 +0,0 @@
-package org.geysermc.connector.utils;
-
-import com.flowpowered.math.vector.Vector2i;
-import com.flowpowered.math.vector.Vector3d;
-import com.flowpowered.math.vector.Vector3i;
-import io.netty.buffer.ByteBuf;
-
-public class PositionSerializer {
-
-    public static void skipPosition(ByteBuf from) {
-        from.skipBytes(Long.BYTES);
-    }
-
-    public static Vector3d readPosition(ByteBuf from) {
-        long l = from.readLong();
-        return new Vector3d(
-            (int) (l >> 38), (int) (l & 0xFFF), (int) ((l << 26) >> 38)
-        );
-    }
-
-    public static void readPEPosition(ByteBuf from) {
-        VarNumberSerializer.readSVarInt(from);
-        VarNumberSerializer.readVarInt(from);
-        VarNumberSerializer.readSVarInt(from);
-    }
-
-    public static Vector3d readLegacyPositionI(ByteBuf from) {
-        return new Vector3d(from.readInt(), from.readInt(), from.readInt());
-    }
-
-    public static void writePosition(ByteBuf to, Vector3i position) {
-        to.writeLong(((position.getX() & 0x3FFFFFFL) << 38) | ((position.getZ() & 0x3FFFFFFL) << 12) | (position.getY() & 0xFFFL));
-    }
-
-    public static void writeLegacyPositionL(ByteBuf to, Vector3d position) {
-        to.writeLong((((int) position.getX() & 0x3FFFFFFL) << 38) | (((int) position.getY() & 0xFFFL) << 26) | ((int) position.getZ() & 0x3FFFFFFL));
-    }
-
-    public static void writePEPosition(ByteBuf to, Vector3d position) {
-        VarNumberSerializer.writeSVarInt(to, (int) position.getX());
-        VarNumberSerializer.writeVarInt(to, (int) position.getY());
-        VarNumberSerializer.writeSVarInt(to, (int) position.getZ());
-    }
-
-    public static void writeLegacyPositionB(ByteBuf to, Vector3d position) {
-        to.writeInt((int) position.getX());
-        to.writeByte((int) position.getY());
-        to.writeInt((int) position.getZ());
-    }
-
-    public static void writeLegacyPositionS(ByteBuf to, Vector3d position) {
-        to.writeInt((int) position.getX());
-        to.writeShort((int) position.getY());
-        to.writeInt((int) position.getZ());
-    }
-
-    public static void writeLegacyPositionI(ByteBuf to, Vector3d position) {
-		to.writeInt((int) position.getX());
-		to.writeInt((int) position.getY());
-		to.writeInt((int) position.getZ());
-	}
-
-    public static Vector2i readIntChunkCoord(ByteBuf from) {
-        return new Vector2i(from.readInt(), from.readInt());
-    }
-
-    public static Vector2i readVarIntChunkCoord(ByteBuf from) {
-        return new Vector2i(VarNumberSerializer.readVarInt(from), VarNumberSerializer.readVarInt(from));
-    }
-
-    public static void writeIntChunkCoord(ByteBuf to, Vector2i chunk) {
-		to.writeInt(chunk.getX());
-		to.writeInt(chunk.getY());
-	}
-
-    public static Vector2i readPEChunkCoord(ByteBuf from) {
-        return new Vector2i(VarNumberSerializer.readSVarInt(from), VarNumberSerializer.readSVarInt(from));
-    }
-
-    public static void writePEChunkCoord(ByteBuf to, Vector2i chunk) {
-        VarNumberSerializer.writeSVarInt(to, chunk.getX());
-        VarNumberSerializer.writeSVarInt(to, chunk.getY());
-    }
-
-    public static int readLocalCoord(ByteBuf from) {
-        return from.readUnsignedShort();
-    }
-
-    public static void writeLocalCoord(ByteBuf to, int coord) {
-        to.writeShort(coord);
-    }
-
-    public static void writeVarIntChunkCoord(ByteBuf to, Vector2i chunk) {
-        VarNumberSerializer.writeVarInt(to, chunk.getX());
-        VarNumberSerializer.writeVarInt(to, chunk.getY());
-    }
-}
\ No newline at end of file
diff --git a/connector/src/main/java/org/geysermc/connector/utils/Toolbox.java b/connector/src/main/java/org/geysermc/connector/utils/Toolbox.java
index 0b6fe955a..59ae39922 100644
--- a/connector/src/main/java/org/geysermc/connector/utils/Toolbox.java
+++ b/connector/src/main/java/org/geysermc/connector/utils/Toolbox.java
@@ -1,15 +1,12 @@
 package org.geysermc.connector.utils;
 
-import com.fasterxml.jackson.annotation.JsonProperty;
 import com.fasterxml.jackson.databind.ObjectMapper;
-import com.fasterxml.jackson.databind.type.CollectionType;
 import com.nukkitx.network.VarInts;
 import com.nukkitx.protocol.bedrock.packet.StartGamePacket;
 import com.nukkitx.protocol.bedrock.v361.BedrockUtils;
 import io.netty.buffer.ByteBuf;
 import io.netty.buffer.Unpooled;
 
-import java.io.IOException;
 import java.io.InputStream;
 import java.util.*;
 
@@ -64,18 +61,18 @@ public class Toolbox {
 
         ITEMS = l;
 
-        ByteBuf serializer;
+        /*ByteBuf serializer;
 
         serializer = Unpooled.buffer();
         serializer.writeShortLE(1);
-        ArraySerializer.writeVarIntByteArray(serializer, (chunkdata) -> {
-            PSPEStuff.writeEmptySubChunk(chunkdata);
+        GeyserUtils.writeVarIntByteArray(serializer, (chunkdata) -> {
+            GeyserUtils.writeEmptySubChunk(chunkdata);
             chunkdata.writeZero(512);
             chunkdata.writeZero(256);
             chunkdata.writeByte(0);
         });
 
-        EMPTY_CHUNK = MiscSerializer.readAllBytes(serializer);
+        EMPTY_CHUNK = GeyserUtils.readAllBytes(serializer);*/
 
     }
 
@@ -83,6 +80,6 @@ public class Toolbox {
 
     public static final ByteBuf CACHED_PALLETE;
 
-    public static final byte[] EMPTY_CHUNK;
+    //public static final byte[] EMPTY_CHUNK;
 
 }
\ No newline at end of file
diff --git a/connector/src/main/java/org/geysermc/connector/utils/VarNumberSerializer.java b/connector/src/main/java/org/geysermc/connector/utils/VarNumberSerializer.java
deleted file mode 100644
index 02d055791..000000000
--- a/connector/src/main/java/org/geysermc/connector/utils/VarNumberSerializer.java
+++ /dev/null
@@ -1,177 +0,0 @@
-package org.geysermc.connector.utils;
-
-import io.netty.buffer.ByteBuf;
-
-import io.netty.handler.codec.DecoderException;
-
-
-
-public class VarNumberSerializer {
-
-
-
-    public static final int MAX_LENGTH = 5;
-
-
-
-    public static void writeFixedSizeVarInt(ByteBuf to, int i) {
-
-        int writerIndex = to.writerIndex();
-
-        while ((i & 0xFFFFFF80) != 0x0) {
-
-            to.writeByte(i | 0x80);
-
-            i >>>= 7;
-
-        }
-
-        int paddingBytes = MAX_LENGTH - (to.writerIndex() - writerIndex) - 1;
-
-        if (paddingBytes == 0) {
-
-            to.writeByte(i);
-
-        } else {
-
-            to.writeByte(i | 0x80);
-
-            while (--paddingBytes > 0) {
-
-                to.writeByte(0x80);
-
-            }
-
-            to.writeByte(0);
-
-        }
-
-    }
-
-
-
-    public static int readVarInt(ByteBuf from) {
-
-        int value = 0;
-
-        int length = 0;
-
-        byte part;
-
-        do {
-
-            part = from.readByte();
-
-            value |= (part & 0x7F) << (length++ * 7);
-
-            if (length > MAX_LENGTH) {
-
-                throw new DecoderException("VarInt too big");
-
-            }
-
-        } while (part < 0);
-
-        return value;
-
-    }
-
-
-
-    public static void writeVarInt(ByteBuf to, int i) {
-
-        while ((i & 0xFFFFFF80) != 0x0) {
-
-            to.writeByte(i | 0x80);
-
-            i >>>= 7;
-
-        }
-
-        to.writeByte(i);
-
-    }
-
-
-
-    public static int readSVarInt(ByteBuf from) {
-
-        int varint = readVarInt(from);
-
-        return (varint >> 1) ^ -(varint & 1);
-
-    }
-
-
-
-    public static void writeSVarInt(ByteBuf to, int varint) {
-
-        writeVarInt(to, (varint << 1) ^ (varint >> 31));
-
-    }
-
-
-
-    public static long readVarLong(ByteBuf from) {
-
-        long varlong = 0L;
-
-        int length = 0;
-
-        byte part;
-
-        do {
-
-            part = from.readByte();
-
-            varlong |= (part & 0x7F) << (length++ * 7);
-
-            if (length > 10) {
-
-                throw new RuntimeException("VarLong too big");
-
-            }
-
-        } while ((part & 0x80) == 0x80);
-
-        return varlong;
-
-    }
-
-
-
-    public static void writeVarLong(ByteBuf to, long varlong) {
-
-        while ((varlong & 0xFFFFFFFFFFFFFF80L) != 0x0L) {
-
-            to.writeByte((int) (varlong & 0x7FL) | 0x80);
-
-            varlong >>>= 7;
-
-        }
-
-        to.writeByte((int) varlong);
-
-    }
-
-
-
-    public static long readSVarLong(ByteBuf from) {
-
-        long varlong = readVarLong(from);
-
-        return (varlong >> 1) ^ -(varlong & 1);
-
-    }
-
-
-
-    public static void writeSVarLong(ByteBuf to, long varlong) {
-
-        writeVarLong(to, (varlong << 1) ^ (varlong >> 63));
-
-    }
-
-
-
-}