PaperMC/Spigot-Server-Patches/0736-Fix-incorrect-status-dataconverter-for-pre-1.13-chun.patch
Jake Potrebic aed5031e31
Fix/Optimize world and light datafixes (#5693)
Co-authored-by: Spottedleaf <Spottedleaf@users.noreply.github.com>
2021-05-20 20:31:08 -04:00

91 lines
5.3 KiB
Diff

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.
diff --git a/src/main/java/net/minecraft/util/datafix/fixes/DataConverterProtoChunk.java b/src/main/java/net/minecraft/util/datafix/fixes/DataConverterProtoChunk.java
index 3a114931cb88791bf73d08accf13993ba8842af2..7c0efe98af0bf99b04c0be6d6208d13af6e3cee4 100644
--- a/src/main/java/net/minecraft/util/datafix/fixes/DataConverterProtoChunk.java
+++ b/src/main/java/net/minecraft/util/datafix/fixes/DataConverterProtoChunk.java
@@ -43,13 +43,21 @@ public class DataConverterProtoChunk extends DataFix {
return dynamic.asStreamOpt().result();
});
Dynamic<?> dynamic = (Dynamic) typed1.get(DSL.remainderFinder());
- boolean flag = dynamic.get("TerrainPopulated").asBoolean(false) && (!dynamic.get("LightPopulated").asNumber().result().isPresent() || dynamic.get("LightPopulated").asBoolean(false));
-
- dynamic = dynamic.set("Status", dynamic.createString(flag ? "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));
dynamic = dynamic.set("hasLegacyStructureData", dynamic.createBoolean(true));
- Dynamic dynamic1;
+ // Paper end - fix incorrect status conversion
+ Dynamic<?> dynamic1; // Paper - decompile fix
- if (flag) {
+ if (true) { // Paper - fix incorrect status conversion
Optional<ByteBuffer> optional1 = dynamic.get("Biomes").asByteBufferOpt().result();
if (optional1.isPresent()) {
@@ -70,7 +78,7 @@ public class DataConverterProtoChunk extends DataFix {
}).collect(Collectors.toList());
if (optional.isPresent()) {
- ((Stream) optional.get()).forEach((dynamic2) -> {
+ optional.get().forEach((dynamic2) -> { // Paper - decompile fix
int j = dynamic2.get("x").asInt(0);
int k = dynamic2.get("y").asInt(0);
int l = dynamic2.get("z").asInt(0);
@@ -78,11 +86,11 @@ public class DataConverterProtoChunk extends DataFix {
((ShortList) list.get(k >> 4)).add(short0);
});
+ Dynamic<?> finalDynamic = dynamic; // Paper - decompile fix
dynamic = dynamic.set("ToBeTicked", dynamic.createList(list.stream().map((shortlist) -> {
- Stream stream = shortlist.stream();
+ Stream<Short> stream = shortlist.stream(); // Paper - decompile fix
- dynamic.getClass();
- return dynamic.createList(stream.map(dynamic::createShort));
+ return finalDynamic.createList(stream.map(finalDynamic::createShort));
})));
}