From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Spottedleaf <Spottedleaf@users.noreply.github.com>
Date: Mon, 10 May 2021 15:46:57 -0700
Subject: [PATCH] Fix incorrect status dataconverter for pre 1.13 chunks

Vanilla was setting non-populated OR non-lit chunks to empty, but
really this is just completely wrong. It should be set to "carved"
at minmum, because pre 1.13 chunks went through 3 distinct stages
of generation: carving, population, and lighting - in this order.
There is no "empty" status, because a chunk was simply carved
or it didn't exist. So mapping any chunk data to empty is simply
invalid.

If the chunk is terrain populated, then obviously it must be at
minmum "decorated." If the chunk is lit and populated, then it is marked
"mobs_spawned" (which is what Vanilla is doing, and this is the last
stage before moving to full so it looks correct).

So now here is a table representing the new status conversion:

Chunk is lit        Chunk is populated       Vanilla
     F                       F                empty
     T                       F                empty
     F                       T                empty
     T                       T             mobs_spawned

Chunk is lit        Chunk is populated         Paper
     F                       F                carved
     T                       F                carved
     F                       T              decorated
     T                       T             mobs_spawned

This should fix some problems converting old data, as the
changes here are going to prevent the chunk from being regenerated
incorrectly.

# 1.18: No longer needed, DataConverter handles this

diff --git a/src/main/java/net/minecraft/util/datafix/fixes/ChunkToProtochunkFix.java b/src/main/java/net/minecraft/util/datafix/fixes/ChunkToProtochunkFix.java
index 081bcae48ae34d8354635ea57952f09f14f7fa7a..a4305f58f793e1577de5e13132381ce81304cae4 100644
--- a/src/main/java/net/minecraft/util/datafix/fixes/ChunkToProtochunkFix.java
+++ b/src/main/java/net/minecraft/util/datafix/fixes/ChunkToProtochunkFix.java
@@ -36,17 +36,26 @@ public class ChunkToProtochunkFix extends DataFix {
         OpticFinder<?> opticFinder2 = DSL.fieldFinder("TileTicks", type5);
         return TypeRewriteRule.seq(this.fixTypeEverywhereTyped("ChunkToProtoChunkFix", type, this.getOutputSchema().getType(References.CHUNK), (typed) -> {
             return typed.updateTyped(opticFinder, type4, (typedx) -> {
-                Optional<? extends Stream<? extends Dynamic<?>>> optional = typedx.getOptionalTyped(opticFinder2).flatMap((typed) -> {
-                    return typed.write().result();
+                Optional<? extends Stream<? extends Dynamic<?>>> optional = typedx.getOptionalTyped(opticFinder2).flatMap((it) -> { // Paper - remap fix
+                    return it.write().result(); // Paper - remap fix
                 }).flatMap((dynamicx) -> {
                     return dynamicx.asStreamOpt().result();
                 });
                 Dynamic<?> dynamic = typedx.get(DSL.remainderFinder());
-                boolean bl = dynamic.get("TerrainPopulated").asBoolean(false) && (!dynamic.get("LightPopulated").asNumber().result().isPresent() || dynamic.get("LightPopulated").asBoolean(false));
-                dynamic = dynamic.set("Status", dynamic.createString(bl ? "mobs_spawned" : "empty"));
+                // Paper start - fix incorrect status conversion
+                // Vanilla is setting chunks to incorrect status here, they should be using at minimum carved.
+                // for populated chunks, it should be at minimum decorated
+                // and for lit and populated, mobs_spawned is correct (technically mobs_spawned should be for populated,
+                // but if it's not lit then it can't be set above lit)
+                final boolean terrainPopulated = dynamic.get("TerrainPopulated").asBoolean(false);
+                final boolean lightPopulated = dynamic.get("LightPopulated").asBoolean(false) || dynamic.get("LightPopulated").asNumber().result().isPresent();
+                final String newStatus = !terrainPopulated ? "carved" : (lightPopulated ? "mobs_spawned" : "decorated");
+
+                dynamic = dynamic.set("Status", dynamic.createString(newStatus));
+                // Paper end - fix incorrect status conversion
                 dynamic = dynamic.set("hasLegacyStructureData", dynamic.createBoolean(true));
                 Dynamic<?> dynamic3;
-                if (bl) {
+                if (true) { // Paper - fix incorrect status conversion
                     Optional<ByteBuffer> optional2 = dynamic.get("Biomes").asByteBufferOpt().result();
                     if (optional2.isPresent()) {
                         ByteBuffer byteBuffer = optional2.get();
