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 fcef782d5..a2fb6ff2f 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
@@ -100,7 +100,7 @@ import org.geysermc.connector.network.translators.java.entity.spawn.JavaSpawnPla
 import org.geysermc.connector.network.translators.java.scoreboard.JavaDisplayScoreboardTranslator;
 import org.geysermc.connector.network.translators.java.scoreboard.JavaScoreboardObjectiveTranslator;
 import org.geysermc.connector.network.translators.java.scoreboard.JavaUpdateScoreTranslator;
-import org.geysermc.connector.network.translators.java.world.JavaChunkDataPacket;
+import org.geysermc.connector.network.translators.java.world.JavaChunkDataTranslator;
 import org.geysermc.connector.network.translators.java.world.JavaNotifyClientTranslator;
 import org.geysermc.connector.network.translators.java.window.JavaOpenWindowTranslator;
 import org.geysermc.connector.network.translators.java.window.JavaSetSlotTranslator;
@@ -168,7 +168,7 @@ public class TranslatorsInit {
         Registry.registerJava(ServerPlayerHealthPacket.class, new JavaPlayerHealthTranslator());
 
         Registry.registerJava(ServerNotifyClientPacket.class, new JavaNotifyClientTranslator());
-        Registry.registerJava(ServerChunkDataPacket.class, new JavaChunkDataPacket());
+        Registry.registerJava(ServerChunkDataPacket.class, new JavaChunkDataTranslator());
         Registry.registerJava(ServerEntityDestroyPacket.class, new JavaEntityDestroyTranslator());
         Registry.registerJava(ServerWindowItemsPacket.class, new JavaWindowItemsTranslator());
         Registry.registerJava(ServerOpenWindowPacket.class, new JavaOpenWindowTranslator());
diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaChunkDataPacket.java b/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaChunkDataPacket.java
deleted file mode 100644
index a7656ed82..000000000
--- a/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaChunkDataPacket.java
+++ /dev/null
@@ -1,55 +0,0 @@
-package org.geysermc.connector.network.translators.java.world;
-
-import com.github.steveice10.mc.protocol.packet.ingame.server.world.ServerChunkDataPacket;
-import com.nukkitx.protocol.bedrock.packet.LevelChunkPacket;
-import io.netty.buffer.ByteBuf;
-import io.netty.buffer.Unpooled;
-import org.geysermc.connector.console.GeyserLogger;
-import org.geysermc.connector.network.session.GeyserSession;
-import org.geysermc.connector.network.translators.PacketTranslator;
-import org.geysermc.connector.utils.ChunkUtils;
-import org.geysermc.connector.world.chunk.ChunkSection;
-
-public class JavaChunkDataPacket extends PacketTranslator<ServerChunkDataPacket> {
-
-    @Override
-    public void translate(ServerChunkDataPacket packet, GeyserSession session) {
-
-        try {
-            byte[] buffer = new byte[32];
-            ChunkUtils.ChunkData chunkData = ChunkUtils.translateToBedrock(packet.getColumn());
-
-            int count = 0;
-            ChunkSection[] sections = chunkData.sections;
-            for (int i = sections.length - 1; i >= 0; i--) {
-                if (sections[i].isEmpty())
-                    continue;
-
-                count = i + 1;
-                break;
-            }
-
-            for (int i = 0; i < count; i++) {
-                ChunkUtils.putBytes(count, buffer, new byte[]{(byte) 0});
-                ChunkSection section = chunkData.sections[i];
-
-                ByteBuf byteBuf = Unpooled.buffer();
-                section.writeToNetwork(byteBuf);
-                byte[] byteData = byteBuf.array();
-                ChunkUtils.putBytes(count, buffer, byteData);
-            }
-
-            LevelChunkPacket levelChunkPacket = new LevelChunkPacket();
-            levelChunkPacket.setSubChunksLength(16);
-            levelChunkPacket.setCachingEnabled(true);
-            levelChunkPacket.setChunkX(packet.getColumn().getX());
-            levelChunkPacket.setChunkZ(packet.getColumn().getZ());
-            levelChunkPacket.setData(buffer);
-            session.getUpstream().sendPacket(levelChunkPacket);
-        } catch (Exception ex) {
-            ex.printStackTrace();
-        }
-
-        GeyserLogger.DEFAULT.info("Sent chunk packet!");
-    }
-}
diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaChunkDataTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaChunkDataTranslator.java
new file mode 100644
index 000000000..3b77619f3
--- /dev/null
+++ b/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaChunkDataTranslator.java
@@ -0,0 +1,59 @@
+package org.geysermc.connector.network.translators.java.world;
+
+import com.github.steveice10.mc.protocol.packet.ingame.server.world.ServerChunkDataPacket;
+import com.nukkitx.network.VarInts;
+import com.nukkitx.protocol.bedrock.packet.LevelChunkPacket;
+import io.netty.buffer.ByteBuf;
+import io.netty.buffer.Unpooled;
+import org.geysermc.api.Geyser;
+import org.geysermc.connector.console.GeyserLogger;
+import org.geysermc.connector.network.session.GeyserSession;
+import org.geysermc.connector.network.translators.PacketTranslator;
+import org.geysermc.connector.utils.ChunkUtils;
+import org.geysermc.connector.world.chunk.ChunkSection;
+
+public class JavaChunkDataTranslator extends PacketTranslator<ServerChunkDataPacket> {
+
+    @Override
+    public void translate(ServerChunkDataPacket packet, GeyserSession session) {
+        // Not sure if this is safe or not, however without this the client usually times out
+        Geyser.getConnector().getGeneralThreadPool().execute(() -> {
+            try {
+                ChunkUtils.ChunkData chunkData = ChunkUtils.translateToBedrock(packet.getColumn());
+                ByteBuf byteBuf = Unpooled.buffer(32);
+                int count = 0;
+                ChunkSection[] sections = chunkData.sections;
+                for (int i = sections.length - 1; i >= 0; i--) {
+                    if (sections[i].isEmpty())
+                        continue;
+
+                    count = i + 1;
+                    break;
+                }
+
+                for (int i = 0; i < count; i++) {
+                    ChunkSection section = chunkData.sections[i];
+                    section.writeToNetwork(byteBuf);
+                }
+
+                byteBuf.writeBytes(chunkData.biomes); // Biomes - 256 bytes
+                byteBuf.writeByte(0); // Border blocks - Edu edition only
+                VarInts.writeUnsignedInt(byteBuf, 0); // extra data length, 0 for now
+
+                byte[] payload = new byte[byteBuf.writerIndex()];
+                byteBuf.readBytes(payload);
+
+                LevelChunkPacket levelChunkPacket = new LevelChunkPacket();
+                levelChunkPacket.setSubChunksLength(count);
+                levelChunkPacket.setCachingEnabled(false);
+                levelChunkPacket.setChunkX(packet.getColumn().getX());
+                levelChunkPacket.setChunkZ(packet.getColumn().getZ());
+                levelChunkPacket.setData(payload);
+                session.getUpstream().sendPacket(levelChunkPacket);
+            } catch (Exception ex) {
+                ex.printStackTrace();
+            }
+            GeyserLogger.DEFAULT.info("Sent chunk packet!");
+        });
+    }
+}
diff --git a/connector/src/main/java/org/geysermc/connector/utils/ChunkUtils.java b/connector/src/main/java/org/geysermc/connector/utils/ChunkUtils.java
index 196adce80..9e7ad391d 100644
--- a/connector/src/main/java/org/geysermc/connector/utils/ChunkUtils.java
+++ b/connector/src/main/java/org/geysermc/connector/utils/ChunkUtils.java
@@ -8,12 +8,8 @@ import org.geysermc.connector.network.translators.TranslatorsInit;
 import org.geysermc.connector.network.translators.item.BedrockItem;
 import org.geysermc.connector.world.chunk.ChunkSection;
 
-import java.util.Arrays;
-
 public class ChunkUtils {
 
-    private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
-
     public static ChunkData translateToBedrock(Column column) {
         ChunkData chunkData = new ChunkData();
         chunkData.sections = new ChunkSection[16];
@@ -21,6 +17,7 @@ public class ChunkUtils {
             chunkData.sections[i] = new ChunkSection();
         }
 
+        /*
         for (int y = 0; y < 256; y++) {
             int chunkY = y >> 4;
 
@@ -37,55 +34,61 @@ public class ChunkUtils {
             BlockStorage storage = chunk.getBlocks();
             for (int x = 0; x < 16; x++) {
                 for (int z = 0; z < 16; z++) {
-                    BlockState block = storage.get(x, y & 0xF, z);
+                    BlockState block = storage.get(x, chunkY, z);
+                    if (block == null)
+                        block = new BlockState(0);
+
                     BedrockItem bedrockBlock = TranslatorsInit.getItemTranslator().getBedrockBlock(block);
 
                     ChunkSection section = chunkData.sections[chunkY];
 
-                    org.geysermc.connector.world.chunk.BlockStorage blockStorage = new org.geysermc.connector.world.chunk.BlockStorage();
-                    blockStorage.setFullBlock(ChunkSection.blockPosition(x, y, z), bedrockBlock.getId());
+                    //org.geysermc.connector.world.chunk.BlockStorage blockStorage = new org.geysermc.connector.world.chunk.BlockStorage();
+                    int runtimeId = GlobalBlockPalette.getOrCreateRuntimeId(bedrockBlock.getId(), bedrockBlock.getData());
+                    section.setFullBlock(x, y >> 4, z, 0, runtimeId << 2 | bedrockBlock.getData());
 
-                    section.getBlockStorageArray()[0] = blockStorage;
-                    section.getBlockStorageArray()[1] = blockStorage;
+                    //section.getBlockStorageArray()[0] = blockStorage;
+                    //section.getBlockStorageArray()[1] = blockStorage;
                 }
             }
         }
 
+         */
+
+        for (int chunkY = 0; chunkY < 16; chunkY++) {
+            Chunk chunk = null;
+            try {
+                chunk = column.getChunks()[chunkY];
+            } catch (Exception ex) {
+                ex.printStackTrace();
+            }
+
+            if (chunk == null || chunk.isEmpty())
+                continue;
+
+            BlockStorage storage = chunk.getBlocks();
+            ChunkSection section = chunkData.sections[chunkY];
+
+            section.getBlockStorageArray()[0] = new org.geysermc.connector.world.chunk.BlockStorage();
+            section.getBlockStorageArray()[1] = new org.geysermc.connector.world.chunk.BlockStorage();
+
+            for (int x = 0; x < 16; x++) {
+                for (int y = 0; y < 16; y++) {
+                    for (int z = 0; z < 16; z++) {
+                        BlockState block = storage.get(x, y, z);
+                        BedrockItem bedrockBlock = TranslatorsInit.getItemTranslator().getBedrockBlock(block);
+
+                        section.getBlockStorageArray()[0].setFullBlock(ChunkSection.blockPosition(x, y, z), bedrockBlock.getId() << 4 | bedrockBlock.getData());
+                    }
+                }
+            }
+        }
         return chunkData;
     }
 
     public static final class ChunkData {
         public ChunkSection[] sections;
-    }
 
-    public static void putBytes(int count, byte[] buffer, byte[] bytes) {
-        if (bytes == null) {
-            return;
-        }
-
-        int minCapacity = count + bytes.length;
-        if ((minCapacity) - buffer.length > 0) {
-            int oldCapacity = buffer.length;
-            int newCapacity = oldCapacity << 1;
-
-            if (newCapacity - minCapacity < 0) {
-                newCapacity = minCapacity;
-            }
-
-            if (newCapacity - MAX_ARRAY_SIZE > 0) {
-                newCapacity = hugeCapacity(minCapacity);
-            }
-
-            buffer = Arrays.copyOf(buffer, newCapacity);
-        }
-
-        System.arraycopy(bytes, 0, buffer, count, bytes.length);
-    }
-
-    private static int hugeCapacity(int minCapacity) {
-        if (minCapacity < 0) { // overflow
-            throw new OutOfMemoryError();
-        }
-        return (minCapacity > MAX_ARRAY_SIZE) ? Integer.MAX_VALUE : MAX_ARRAY_SIZE;
+        public byte[] biomes = new byte[256];
+        public byte[] blockEntities = new byte[0];
     }
 }
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 d94d97f20..1447c5726 100644
--- a/connector/src/main/java/org/geysermc/connector/utils/Toolbox.java
+++ b/connector/src/main/java/org/geysermc/connector/utils/Toolbox.java
@@ -40,7 +40,7 @@ public class Toolbox {
         ByteBuf b = Unpooled.buffer();
         VarInts.writeUnsignedInt(b, entries.size());
         for (Map<String, Object> e : entries) {
-            GlobalBlockPalette.registerMapping((int) e.get("id"));
+            GlobalBlockPalette.registerMapping((int) e.get("id") << 4 | (int) e.get("data"));
             BedrockUtils.writeString(b, (String) e.get("name"));
             b.writeShortLE((int) e.get("data"));
             b.writeShortLE((int) e.get("id"));