From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Spottedleaf <Spottedleaf@users.noreply.github.com>
Date: Mon, 23 Aug 2021 04:50:05 -0700
Subject: [PATCH] Always parse protochunk light sources unless it is marked as
 non-lit

Chunks not marked as lit will always go through the light engine,
so they should always have their block sources parsed.

diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java
index e54376b463b017d5e371f8d3204a37993b0e78e7..9b7bc1c9091d20671d281fa304722ac45fbf6e2e 100644
--- a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java
+++ b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java
@@ -304,16 +304,33 @@ public class ChunkSerializer {
             BelowZeroRetrogen belowzeroretrogen = protochunk.getBelowZeroRetrogen();
             boolean flag2 = chunkstatus.isOrAfter(ChunkStatus.LIGHT) || belowzeroretrogen != null && belowzeroretrogen.targetStatus().isOrAfter(ChunkStatus.LIGHT);
 
-            if (!flag && flag2) {
-                Iterator iterator = BlockPos.betweenClosed(chunkPos.getMinBlockX(), world.getMinBuildHeight(), chunkPos.getMinBlockZ(), chunkPos.getMaxBlockX(), world.getMaxBuildHeight() - 1, chunkPos.getMaxBlockZ()).iterator();
+            if (!flag) { // Paper - fix incorrect parsing of blocks that emit light - it should always parse it, unless the chunk is marked as lit
+                // Paper start - let's make sure the implementation isn't as slow as possible
+                int offX = chunkPos.x << 4;
+                int offZ = chunkPos.z << 4;
+
+                int minChunkSection = io.papermc.paper.util.WorldUtil.getMinSection(world);
+                int maxChunkSection = io.papermc.paper.util.WorldUtil.getMaxSection(world);
+
+                LevelChunkSection[] sections = achunksection;
+                for (int sectionY = minChunkSection; sectionY <= maxChunkSection; ++sectionY) {
+                    LevelChunkSection section = sections[sectionY - minChunkSection];
+                    if (section == null || section.hasOnlyAir()) {
+                        // no sources in empty sections
+                        continue;
+                    }
+                    int offY = sectionY << 4;
 
-                while (iterator.hasNext()) {
-                    BlockPos blockposition = (BlockPos) iterator.next();
+                    for (int index = 0; index < (16 * 16 * 16); ++index) {
+                        if (section.states.get(index).getLightEmission() <= 0) {
+                            continue;
+                        }
 
-                    if (((ChunkAccess) object).getBlockState(blockposition).getLightEmission() != 0) {
-                        protochunk.addLight(blockposition);
+                        // index = x | (z << 4) | (y << 8)
+                        protochunk.addLight(new BlockPos(offX | (index & 15), offY | (index >>> 8), offZ | ((index >>> 4) & 15)));
                     }
                 }
+                // Paper end
             }
         }
 
