--- a/net/minecraft/network/protocol/game/ClientboundLevelChunkPacketData.java
+++ b/net/minecraft/network/protocol/game/ClientboundLevelChunkPacketData.java
@@ -27,8 +27,19 @@
     private final CompoundTag heightmaps;
     private final byte[] buffer;
     private final List<ClientboundLevelChunkPacketData.BlockEntityInfo> blockEntitiesData;
+    // Paper start - Handle oversized block entities in chunks
+    private final java.util.List<net.minecraft.network.protocol.Packet<?>> extraPackets = new java.util.ArrayList<>();
+    private static final int TE_LIMIT = Integer.getInteger("Paper.excessiveTELimit", 750);
 
-    public ClientboundLevelChunkPacketData(LevelChunk chunk) {
+    public List<net.minecraft.network.protocol.Packet<?>> getExtraPackets() {
+        return this.extraPackets;
+    }
+    // Paper end - Handle oversized block entities in chunks
+
+    // Paper start - Anti-Xray - Add chunk packet info
+    @Deprecated @io.papermc.paper.annotation.DoNotUse public ClientboundLevelChunkPacketData(LevelChunk chunk) { this(chunk, null); }
+    public ClientboundLevelChunkPacketData(LevelChunk chunk, com.destroystokyo.paper.antixray.ChunkPacketInfo<net.minecraft.world.level.block.state.BlockState> chunkPacketInfo) {
+        // Paper end
         this.heightmaps = new CompoundTag();
 
         for (Entry<Heightmap.Types, Heightmap> entry : chunk.getHeightmaps()) {
@@ -38,10 +49,27 @@
         }
 
         this.buffer = new byte[calculateChunkSize(chunk)];
-        extractChunkData(new FriendlyByteBuf(this.getWriteBuffer()), chunk);
+
+        // Paper start - Anti-Xray - Add chunk packet info
+        if (chunkPacketInfo != null) {
+            chunkPacketInfo.setBuffer(this.buffer);
+        }
+
+        extractChunkData(new FriendlyByteBuf(this.getWriteBuffer()), chunk, chunkPacketInfo);
+        // Paper end
         this.blockEntitiesData = Lists.newArrayList();
+        int totalTileEntities = 0; // Paper - Handle oversized block entities in chunks
 
         for (Entry<BlockPos, BlockEntity> entry2 : chunk.getBlockEntities().entrySet()) {
+            // Paper start - Handle oversized block entities in chunks
+            if (++totalTileEntities > TE_LIMIT) {
+                var packet = entry2.getValue().getUpdatePacket();
+                if (packet != null) {
+                    this.extraPackets.add(packet);
+                    continue;
+                }
+            }
+            // Paper end - Handle oversized block entities in chunks
             this.blockEntitiesData.add(ClientboundLevelChunkPacketData.BlockEntityInfo.create(entry2.getValue()));
         }
     }
@@ -52,7 +80,7 @@
             throw new RuntimeException("Can't read heightmap in packet for [" + x + ", " + z + "]");
         } else {
             int i = buf.readVarInt();
-            if (i > 2097152) {
+            if (i > 2097152) { // Paper - diff on change - if this changes, update PacketEncoder
                 throw new RuntimeException("Chunk Packet trying to allocate too much memory on read.");
             } else {
                 this.buffer = new byte[i];
@@ -85,9 +113,15 @@
         return byteBuf;
     }
 
-    public static void extractChunkData(FriendlyByteBuf buf, LevelChunk chunk) {
+    // Paper start - Anti-Xray - Add chunk packet info
+    @Deprecated @io.papermc.paper.annotation.DoNotUse public static void extractChunkData(FriendlyByteBuf buf, LevelChunk chunk) { ClientboundLevelChunkPacketData.extractChunkData(buf, chunk, null); }
+    public static void extractChunkData(FriendlyByteBuf buf, LevelChunk chunk, com.destroystokyo.paper.antixray.ChunkPacketInfo<net.minecraft.world.level.block.state.BlockState> chunkPacketInfo) {
+        int chunkSectionIndex = 0;
+
         for (LevelChunkSection levelChunkSection : chunk.getSections()) {
-            levelChunkSection.write(buf);
+            levelChunkSection.write(buf, chunkPacketInfo, chunkSectionIndex);
+            chunkSectionIndex++;
+            // Paper end
         }
     }
 
@@ -154,6 +188,7 @@
             CompoundTag compoundTag = blockEntity.getUpdateTag(blockEntity.getLevel().registryAccess());
             BlockPos blockPos = blockEntity.getBlockPos();
             int i = SectionPos.sectionRelative(blockPos.getX()) << 4 | SectionPos.sectionRelative(blockPos.getZ());
+            blockEntity.sanitizeSentNbt(compoundTag); // Paper - Sanitize sent data
             return new ClientboundLevelChunkPacketData.BlockEntityInfo(i, blockPos.getY(), blockEntity.getType(), compoundTag.isEmpty() ? null : compoundTag);
         }
     }
