diff --git a/patches/server/Fix-incorrect-status-dataconverter-for-pre-1.13-chun.patch b/patches/server/Fix-incorrect-status-dataconverter-for-pre-1.13-chun.patch new file mode 100644 index 0000000000..2e9f6d0ef7 --- /dev/null +++ b/patches/server/Fix-incorrect-status-dataconverter-for-pre-1.13-chun.patch @@ -0,0 +1,74 @@ +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. + +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 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/util/datafix/fixes/ChunkToProtochunkFix.java ++++ b/src/main/java/net/minecraft/util/datafix/fixes/ChunkToProtochunkFix.java +@@ -0,0 +0,0 @@ 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();