--- a/net/minecraft/network/protocol/game/ClientboundLevelChunkPacketData.java
+++ b/net/minecraft/network/protocol/game/ClientboundLevelChunkPacketData.java
@@ -27,8 +_,22 @@
     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 BLOCK_ENTITY_LIMIT = Integer.getInteger("Paper.excessiveTELimit", 750);
+
+    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 levelChunk) {
+        this(levelChunk, null);
+    }
+    public ClientboundLevelChunkPacketData(LevelChunk levelChunk, io.papermc.paper.antixray.ChunkPacketInfo<net.minecraft.world.level.block.state.BlockState> chunkPacketInfo) {
+        // Paper end
         this.heightmaps = new CompoundTag();
 
         for (Entry<Heightmap.Types, Heightmap> entry : levelChunk.getHeightmaps()) {
@@ -38,10 +_,24 @@
         }
 
         this.buffer = new byte[calculateChunkSize(levelChunk)];
-        extractChunkData(new FriendlyByteBuf(this.getWriteBuffer()), levelChunk);
+        // Paper start - Anti-Xray - Add chunk packet info
+        if (chunkPacketInfo != null) {
+            chunkPacketInfo.setBuffer(this.buffer);
+        }
+        extractChunkData(new FriendlyByteBuf(this.getWriteBuffer()), levelChunk, chunkPacketInfo);
         this.blockEntitiesData = Lists.newArrayList();
+        int totalTileEntities = 0; // Paper - Handle oversized block entities in chunks
 
         for (Entry<BlockPos, BlockEntity> entryx : levelChunk.getBlockEntities().entrySet()) {
+            // Paper start - Handle oversized block entities in chunks
+            if (++totalTileEntities > BLOCK_ENTITY_LIMIT) {
+                net.minecraft.network.protocol.Packet<ClientGamePacketListener> packet = entryx.getValue().getUpdatePacket();
+                if (packet != null) {
+                    this.extraPackets.add(packet);
+                    continue;
+                }
+            }
+            // Paper end - Handle oversized block entities in chunks
             this.blockEntitiesData.add(ClientboundLevelChunkPacketData.BlockEntityInfo.create(entryx.getValue()));
         }
     }
@@ -52,7 +_,7 @@
             throw new RuntimeException("Can't read heightmap in packet for [" + x + ", " + z + "]");
         } else {
             int varInt = buffer.readVarInt();
-            if (varInt > 2097152) {
+            if (varInt > 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[varInt];
@@ -85,9 +_,17 @@
         return byteBuf;
     }
 
+    // Paper start - Anti-Xray - Add chunk packet info
+    @Deprecated @io.papermc.paper.annotation.DoNotUse
     public static void extractChunkData(FriendlyByteBuf buffer, LevelChunk chunk) {
+        ClientboundLevelChunkPacketData.extractChunkData(buffer, chunk, null);
+    }
+    public static void extractChunkData(FriendlyByteBuf buffer, LevelChunk chunk, io.papermc.paper.antixray.ChunkPacketInfo<net.minecraft.world.level.block.state.BlockState> chunkPacketInfo) {
+        int chunkSectionIndex = 0;
         for (LevelChunkSection levelChunkSection : chunk.getSections()) {
-            levelChunkSection.write(buffer);
+            levelChunkSection.write(buffer, chunkPacketInfo, chunkSectionIndex);
+            chunkSectionIndex++;
+            // Paper end  - Anti-Xray - Add chunk packet info
         }
     }
 
@@ -154,6 +_,7 @@
             CompoundTag updateTag = blockEntity.getUpdateTag(blockEntity.getLevel().registryAccess());
             BlockPos blockPos = blockEntity.getBlockPos();
             int i = SectionPos.sectionRelative(blockPos.getX()) << 4 | SectionPos.sectionRelative(blockPos.getZ());
+            blockEntity.sanitizeSentNbt(updateTag); // Paper - Sanitize sent data
             return new ClientboundLevelChunkPacketData.BlockEntityInfo(i, blockPos.getY(), blockEntity.getType(), updateTag.isEmpty() ? null : updateTag);
         }
     }
