From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: Spottedleaf 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. SPOTTEDLEAF!!!!!!!!!!! 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>> optional = typedx.getOptionalTyped(opticFinder2).flatMap((typed) -> { - return typed.write().result(); + Optional>> 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 optional2 = dynamic.get("Biomes").asByteBufferOpt().result(); if (optional2.isPresent()) { ByteBuffer byteBuffer = optional2.get();