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 a19de3f29..072b7aedb 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
@@ -45,6 +45,9 @@ import com.nukkitx.protocol.bedrock.packet.*;
 import lombok.Getter;
 import org.geysermc.connector.network.translators.bedrock.*;
 import org.geysermc.connector.network.translators.block.BlockTranslator;
+import org.geysermc.connector.network.translators.block.entity.BlockEntityTranslator;
+import org.geysermc.connector.network.translators.block.entity.EmptyBlockEntityTranslator;
+import org.geysermc.connector.network.translators.block.entity.SignBlockEntityTranslator;
 import org.geysermc.connector.network.translators.inventory.GenericInventoryTranslator;
 import org.geysermc.connector.network.translators.inventory.InventoryTranslator;
 import org.geysermc.connector.network.translators.item.ItemTranslator;
@@ -64,6 +67,8 @@ import org.geysermc.connector.network.translators.java.world.*;
 
 import java.io.ByteArrayOutputStream;
 import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
 
 public class TranslatorsInit {
 
@@ -76,6 +81,9 @@ public class TranslatorsInit {
     @Getter
     private static InventoryTranslator inventoryTranslator = new GenericInventoryTranslator();
 
+    @Getter
+    private static Map<String, BlockEntityTranslator> blockEntityTranslators = new HashMap<>();
+
     private static final CompoundTag EMPTY_TAG = CompoundTagBuilder.builder().buildRootTag();
     public static final byte[] EMPTY_LEVEL_CHUNK_DATA;
 
@@ -144,6 +152,7 @@ public class TranslatorsInit {
         Registry.registerJava(ServerBlockChangePacket.class, new JavaBlockChangeTranslator());
         Registry.registerJava(ServerMultiBlockChangePacket.class, new JavaMultiBlockChangeTranslator());
         Registry.registerJava(ServerUnloadChunkPacket.class, new JavaUnloadChunkTranslator());
+        Registry.registerJava(ServerUpdateTileEntityPacket.class, new JavaUpdateTileEntityTranslator());
 
         Registry.registerJava(ServerOpenWindowPacket.class, new OpenWindowPacketTranslator());
 
@@ -160,9 +169,15 @@ public class TranslatorsInit {
         itemTranslator = new ItemTranslator();
         blockTranslator = new BlockTranslator();
 
+        registerBlockEntityTranslators();
         registerInventoryTranslators();
     }
 
+    private static void registerBlockEntityTranslators() {
+        blockEntityTranslators.put("Empty", new EmptyBlockEntityTranslator());
+        blockEntityTranslators.put("Sign", new SignBlockEntityTranslator());
+    }
+
     private static void registerInventoryTranslators() {
         /*inventoryTranslators.put(WindowType.GENERIC_9X1, new GenericInventoryTranslator());
         inventoryTranslators.put(WindowType.GENERIC_9X2, new GenericInventoryTranslator());
diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/block/entity/BlockEntityTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/block/entity/BlockEntityTranslator.java
new file mode 100644
index 000000000..4913a300d
--- /dev/null
+++ b/connector/src/main/java/org/geysermc/connector/network/translators/block/entity/BlockEntityTranslator.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2019 GeyserMC. http://geysermc.org
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ * @author GeyserMC
+ * @link https://github.com/GeyserMC/Geyser
+ */
+
+package org.geysermc.connector.network.translators.block.entity;
+
+import com.github.steveice10.opennbt.tag.builtin.CompoundTag;
+import com.github.steveice10.opennbt.tag.builtin.IntTag;
+import com.github.steveice10.opennbt.tag.builtin.StringTag;
+import com.nukkitx.nbt.CompoundTagBuilder;
+import com.nukkitx.nbt.tag.Tag;
+import org.geysermc.connector.utils.BlockEntityUtils;
+
+import java.util.List;
+
+public abstract class BlockEntityTranslator {
+
+    public abstract List<Tag<?>> translateTag(CompoundTag tag);
+
+    public abstract CompoundTag getDefaultJavaTag(int x, int y, int z);
+
+    public abstract com.nukkitx.nbt.tag.CompoundTag getDefaultBedrockTag(int x, int y, int z);
+
+    public com.nukkitx.nbt.tag.CompoundTag getBlockEntityTag(CompoundTag tag) {
+        String id = BlockEntityUtils.getBedrockBlockEntityId((String) tag.get("id").getValue());
+        int x = Integer.parseInt(String.valueOf(tag.getValue().get("x").getValue()));
+        int y = Integer.parseInt(String.valueOf(tag.getValue().get("y").getValue()));
+        int z = Integer.parseInt(String.valueOf(tag.getValue().get("z").getValue()));
+
+        CompoundTagBuilder tagBuilder = getConstantBedrockTag(id, x, y, z).toBuilder();
+        translateTag(tag).forEach(tagBuilder::tag);
+        return tagBuilder.buildRootTag();
+    }
+
+    protected CompoundTag getConstantJavaTag(String id, int x, int y, int z) {
+        CompoundTag tag = new CompoundTag("");
+        tag.put(new IntTag("x", x));
+        tag.put(new IntTag("y", y));
+        tag.put(new IntTag("z", z));
+        tag.put(new StringTag("id", id));
+        return tag;
+    }
+
+    protected com.nukkitx.nbt.tag.CompoundTag getConstantBedrockTag(String id, int x, int y, int z) {
+        CompoundTagBuilder tagBuilder = CompoundTagBuilder.builder()
+                .intTag("x", x)
+                .intTag("y", y)
+                .intTag("z", z)
+                .stringTag("id", id);
+        return tagBuilder.buildRootTag();
+    }
+}
diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/block/entity/EmptyBlockEntityTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/block/entity/EmptyBlockEntityTranslator.java
new file mode 100644
index 000000000..927337bc1
--- /dev/null
+++ b/connector/src/main/java/org/geysermc/connector/network/translators/block/entity/EmptyBlockEntityTranslator.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2019 GeyserMC. http://geysermc.org
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ * @author GeyserMC
+ * @link https://github.com/GeyserMC/Geyser
+ */
+
+package org.geysermc.connector.network.translators.block.entity;
+
+import com.github.steveice10.opennbt.tag.builtin.CompoundTag;
+import com.nukkitx.nbt.tag.Tag;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class EmptyBlockEntityTranslator extends BlockEntityTranslator {
+
+    @Override
+    public List<Tag<?>> translateTag(CompoundTag tag) {
+        return new ArrayList<>();
+    }
+
+    @Override
+    public CompoundTag getDefaultJavaTag(int x, int y, int z) {
+        return getConstantJavaTag("empty", x, y, z);
+    }
+
+    @Override
+    public com.nukkitx.nbt.tag.CompoundTag getDefaultBedrockTag(int x, int y, int z) {
+        return getConstantBedrockTag("Empty", x, y, z);
+    }
+}
diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/block/entity/SignBlockEntityTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/block/entity/SignBlockEntityTranslator.java
new file mode 100644
index 000000000..414455c77
--- /dev/null
+++ b/connector/src/main/java/org/geysermc/connector/network/translators/block/entity/SignBlockEntityTranslator.java
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2019 GeyserMC. http://geysermc.org
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ * @author GeyserMC
+ * @link https://github.com/GeyserMC/Geyser
+ */
+
+package org.geysermc.connector.network.translators.block.entity;
+
+import com.github.steveice10.mc.protocol.data.message.Message;
+import com.github.steveice10.opennbt.tag.builtin.CompoundTag;
+import com.nukkitx.nbt.CompoundTagBuilder;
+import com.nukkitx.nbt.tag.ByteTag;
+import com.nukkitx.nbt.tag.StringTag;
+import com.nukkitx.nbt.tag.Tag;
+import org.geysermc.connector.utils.MessageUtils;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class SignBlockEntityTranslator extends BlockEntityTranslator {
+
+    @Override
+    public List<Tag<?>> translateTag(CompoundTag tag) {
+        List<Tag<?>> tags = new ArrayList<>();
+
+        String line1 = (String) tag.getValue().get("Text1").getValue();
+        String line2 = (String) tag.getValue().get("Text2").getValue();
+        String line3 = (String) tag.getValue().get("Text3").getValue();
+        String line4 = (String) tag.getValue().get("Text4").getValue();
+
+        tags.add(new StringTag("Text", MessageUtils.getBedrockMessage(Message.fromString(line1))
+                + "\n" + MessageUtils.getBedrockMessage(Message.fromString(line2))
+                + "\n" + MessageUtils.getBedrockMessage(Message.fromString(line3))
+                + "\n" + MessageUtils.getBedrockMessage(Message.fromString(line4))
+        ));
+
+        tags.add(new ByteTag("isMovable", (byte) 0));
+        return tags;
+    }
+
+    @Override
+    public CompoundTag getDefaultJavaTag(int x, int y, int z) {
+        CompoundTag tag = getConstantJavaTag("minecraft:sign", x, y, z);
+        tag.put(new com.github.steveice10.opennbt.tag.builtin.StringTag("Text1", "\"text\":\"\""));
+        tag.put(new com.github.steveice10.opennbt.tag.builtin.StringTag("Text2", "\"text\":\"\""));
+        tag.put(new com.github.steveice10.opennbt.tag.builtin.StringTag("Text3", "\"text\":\"\""));
+        tag.put(new com.github.steveice10.opennbt.tag.builtin.StringTag("Text4", "\"text\":\"\""));
+        return tag;
+    }
+
+    @Override
+    public com.nukkitx.nbt.tag.CompoundTag getDefaultBedrockTag(int x, int y, int z) {
+        CompoundTagBuilder tagBuilder = getConstantBedrockTag("Sign", x, y, z).toBuilder();
+        tagBuilder.stringTag("Text", "");
+        tagBuilder.byteTag("isMovable", (byte) 0);
+        return tagBuilder.buildRootTag();
+    }
+}
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
index a620197e0..1c83579a5 100644
--- 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
@@ -3,10 +3,14 @@ package org.geysermc.connector.network.translators.java.world;
 import com.github.steveice10.mc.protocol.packet.ingame.server.world.ServerChunkDataPacket;
 import com.nukkitx.math.vector.Vector2i;
 import com.nukkitx.math.vector.Vector3f;
+import com.nukkitx.nbt.NbtUtils;
+import com.nukkitx.nbt.stream.NBTOutputStream;
+import com.nukkitx.nbt.tag.CompoundTag;
 import com.nukkitx.network.VarInts;
 import com.nukkitx.protocol.bedrock.packet.LevelChunkPacket;
 import com.nukkitx.protocol.bedrock.packet.NetworkChunkPublisherUpdatePacket;
 import io.netty.buffer.ByteBuf;
+import io.netty.buffer.ByteBufOutputStream;
 import io.netty.buffer.Unpooled;
 import org.geysermc.api.Geyser;
 import org.geysermc.connector.network.session.GeyserSession;
@@ -53,6 +57,14 @@ public class JavaChunkDataTranslator extends PacketTranslator<ServerChunkDataPac
                 byteBuf.writeByte(0); // Border blocks - Edu edition only
                 VarInts.writeUnsignedInt(byteBuf, 0); // extra data length, 0 for now
 
+                ByteBufOutputStream stream = new ByteBufOutputStream(Unpooled.buffer());
+                NBTOutputStream nbtStream = NbtUtils.createNetworkWriter(stream);
+                for (CompoundTag blockEntity : chunkData.blockEntities) {
+                    nbtStream.write(blockEntity);
+                }
+
+                byteBuf.writeBytes(stream.buffer());
+
                 byte[] payload = new byte[byteBuf.writerIndex()];
                 byteBuf.readBytes(payload);
 
diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaUpdateTileEntityTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaUpdateTileEntityTranslator.java
new file mode 100644
index 000000000..ca9d63f4f
--- /dev/null
+++ b/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaUpdateTileEntityTranslator.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2019 GeyserMC. http://geysermc.org
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ * @author GeyserMC
+ * @link https://github.com/GeyserMC/Geyser
+ */
+
+package org.geysermc.connector.network.translators.java.world;
+
+import com.github.steveice10.mc.protocol.packet.ingame.server.world.ServerUpdateTileEntityPacket;
+import com.nukkitx.math.vector.Vector3i;
+import com.nukkitx.protocol.bedrock.packet.BlockEntityDataPacket;
+import org.geysermc.connector.network.session.GeyserSession;
+import org.geysermc.connector.network.translators.PacketTranslator;
+import org.geysermc.connector.network.translators.block.entity.BlockEntityTranslator;
+import org.geysermc.connector.utils.BlockEntityUtils;
+
+public class JavaUpdateTileEntityTranslator extends PacketTranslator<ServerUpdateTileEntityPacket> {
+
+    @Override
+    public void translate(ServerUpdateTileEntityPacket packet, GeyserSession session) {
+        BlockEntityDataPacket blockEntityPacket = new BlockEntityDataPacket();
+        blockEntityPacket.setBlockPosition(Vector3i.from(packet.getPosition().getX(),
+                packet.getPosition().getY(),
+                packet.getPosition().getZ())
+        );
+
+        String id = BlockEntityUtils.getBedrockBlockEntityId(packet.getType().name());
+        BlockEntityTranslator translator = BlockEntityUtils.getBlockEntityTranslator(id);
+        blockEntityPacket.setData(translator.getBlockEntityTag(packet.getNbt()));
+        session.getUpstream().sendPacket(blockEntityPacket);
+    }
+}
diff --git a/connector/src/main/java/org/geysermc/connector/utils/BlockEntityUtils.java b/connector/src/main/java/org/geysermc/connector/utils/BlockEntityUtils.java
new file mode 100644
index 000000000..6fb62b552
--- /dev/null
+++ b/connector/src/main/java/org/geysermc/connector/utils/BlockEntityUtils.java
@@ -0,0 +1,32 @@
+package org.geysermc.connector.utils;
+
+import org.geysermc.connector.network.translators.TranslatorsInit;
+import org.geysermc.connector.network.translators.block.entity.BlockEntityTranslator;
+
+public class BlockEntityUtils {
+
+    public static String getBedrockBlockEntityId(String id) {
+        // This is the only exception when it comes to block entity ids
+        if (id.contains("piston_head"))
+            return "PistonArm";
+
+        id = id.replace("minecraft:", "");
+        id = id.replace("_", " ");
+        String[] words = id.split(" ");
+        for (int i = 0; i < words.length; i++) {
+            words[i] = words[i].substring(0, 1).toUpperCase() + words[i].substring(1).toLowerCase();
+        }
+
+        id = String.join(" ", words);
+        return id.replace(" ", "");
+    }
+
+    public static BlockEntityTranslator getBlockEntityTranslator(String name) {
+        BlockEntityTranslator blockEntityTranslator = TranslatorsInit.getBlockEntityTranslators().get(name);
+        if (blockEntityTranslator == null) {
+            return TranslatorsInit.getBlockEntityTranslators().get("Empty");
+        }
+
+        return blockEntityTranslator;
+    }
+}
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 6f2b6d3cc..59a5fe848 100644
--- a/connector/src/main/java/org/geysermc/connector/utils/ChunkUtils.java
+++ b/connector/src/main/java/org/geysermc/connector/utils/ChunkUtils.java
@@ -3,10 +3,19 @@ package org.geysermc.connector.utils;
 import com.github.steveice10.mc.protocol.data.game.chunk.Chunk;
 import com.github.steveice10.mc.protocol.data.game.chunk.Column;
 import com.github.steveice10.mc.protocol.data.game.world.block.BlockState;
+import com.github.steveice10.opennbt.tag.builtin.CompoundTag;
+import com.github.steveice10.opennbt.tag.builtin.Tag;
+import org.geysermc.connector.console.GeyserLogger;
 import org.geysermc.connector.network.translators.TranslatorsInit;
 import org.geysermc.connector.network.translators.block.BlockEntry;
+import org.geysermc.connector.network.translators.block.entity.BlockEntityTranslator;
+import org.geysermc.connector.network.translators.block.entity.SignBlockEntityTranslator;
 import org.geysermc.connector.world.chunk.ChunkSection;
 
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
 public class ChunkUtils {
 
     public static ChunkData translateToBedrock(Column column) {
@@ -16,6 +25,7 @@ public class ChunkUtils {
         int chunkSectionCount = chunks.length;
         chunkData.sections = new ChunkSection[chunkSectionCount];
 
+        List<CompoundTag> blockEntities = new ArrayList<>(Arrays.asList(column.getTileEntities()));
         for (int chunkY = 0; chunkY < chunkSectionCount; chunkY++) {
             chunkData.sections[chunkY] = new ChunkSection();
             Chunk chunk = chunks[chunkY];
@@ -38,10 +48,32 @@ public class ChunkUtils {
                             section.getBlockStorageArray()[1].setFullBlock(ChunkSection.blockPosition(x, y, z),
                                     9 << 4); // water id
                         }
+
+                        // Block entity data for signs is not sent in this packet, which is needed
+                        // for bedrock, so we need to check the block itself
+                        if (block.getJavaIdentifier().contains("sign")) {
+                            SignBlockEntityTranslator sign = (SignBlockEntityTranslator) BlockEntityUtils.getBlockEntityTranslator("Sign");
+                            blockEntities.add(sign.getDefaultJavaTag(x, y, z));
+                        }
                     }
                 }
             }
         }
+
+        List<com.nukkitx.nbt.tag.CompoundTag> bedrockBlockEntities = new ArrayList<>();
+        for (CompoundTag tag : blockEntities) {
+            Tag idTag = tag.get("id");
+            if (idTag == null) {
+                GeyserLogger.DEFAULT.debug("Got tag with no id: " + tag.getValue());
+                continue;
+            }
+
+            String id = BlockEntityUtils.getBedrockBlockEntityId((String) tag.get("id").getValue());
+            BlockEntityTranslator blockEntityTranslator = BlockEntityUtils.getBlockEntityTranslator(id);
+            bedrockBlockEntities.add(blockEntityTranslator.getBlockEntityTag(tag));
+        }
+
+        chunkData.blockEntities = bedrockBlockEntities;
         return chunkData;
     }
 
@@ -49,6 +81,6 @@ public class ChunkUtils {
         public ChunkSection[] sections;
 
         public byte[] biomes = new byte[256];
-        public byte[] blockEntities = new byte[0];
+        public List<com.nukkitx.nbt.tag.CompoundTag> blockEntities = new ArrayList<>();
     }
 }