Open 22dm opened 2 years ago
You don't need to restrain yourself to only blending full
chunks. The game (tested in 1.19.4) actually tags all visited chunks with a status of noise
or after/above when updating worlds through major versions. I tested this ingame and it can also be confirmed by some parts of game code:
public class BlendingDataFix
extends DataFix {
private final String name;
private static final Set<String> STATUSES_TO_SKIP_BLENDING = Set.of("minecraft:empty", "minecraft:structure_starts", "minecraft:structure_references", "minecraft:biomes");
...
private static Dynamic<?> updateChunkTag(Dynamic<?> dynamic, OptionalDynamic<?> optionalDynamic) {
dynamic = dynamic.remove("blending_data");
boolean bl = "minecraft:overworld".equals(optionalDynamic.get("dimension").asString().result().orElse(""));
Optional optional = dynamic.get("Status").result();
if (bl && optional.isPresent()) {
Dynamic dynamic2;
String string;
String string2 = NamespacedSchema.ensureNamespaced(((Dynamic)optional.get()).asString("empty"));
Optional optional2 = dynamic.get("below_zero_retrogen").result();
if (!STATUSES_TO_SKIP_BLENDING.contains(string2)) {
dynamic = BlendingDataFix.updateBlendingData(dynamic, 384, -64);
} else if (optional2.isPresent() && !STATUSES_TO_SKIP_BLENDING.contains(string = NamespacedSchema.ensureNamespaced((dynamic2 = (Dynamic)optional2.get()).get("target_status").asString("empty")))) {
dynamic = BlendingDataFix.updateBlendingData(dynamic, 256, 0);
}
}
return dynamic;
}
private static Dynamic<?> updateBlendingData(Dynamic<?> dynamic, int n, int n2) {
return dynamic.set("blending_data", dynamic.createMap(Map.of(dynamic.createString("min_section"), dynamic.createInt(SectionPos.blockToSectionCoord(n2)), dynamic.createString("max_section"), dynamic.createInt(SectionPos.blockToSectionCoord(n2 + n)))));
}
}
public class ChunkHeightAndBiomeFix
extends DataFix {
...
private static final Set<String> STATUS_IS_OR_AFTER_SURFACE = Set.of("surface", "carvers", "liquid_carvers", "features", "light", "spawn", "heightmaps", "full");
private static final Set<String> STATUS_IS_OR_AFTER_NOISE = Set.of("noise", "surface", "carvers", "liquid_carvers", "features", "light", "spawn", "heightmaps", "full");
...
...
private static Dynamic<?> updateChunkTag(Dynamic<?> dynamic, boolean bl, boolean bl2, boolean bl3, Supplier<ChunkProtoTickListFix.PoorMansPalettedContainer> supplier) {
...
Optional optional = dynamic.get("Status").result();
if (optional.isPresent() && !"empty".equals(string = (dynamic2 = (Dynamic)optional.get()).asString(""))) {
dynamic = dynamic.set("blending_data", dynamic.createMap((Map)ImmutableMap.of((Object)dynamic.createString("old_noise"), (Object)dynamic.createBoolean(STATUS_IS_OR_AFTER_NOISE.contains(string)))));
ChunkProtoTickListFix.PoorMansPalettedContainer poorMansPalettedContainer = supplier.get();
if (poorMansPalettedContainer != null) {
BitSet bitSet = new BitSet(256);
boolean bl4 = string.equals("noise");
for (int i = 0; i < 16; ++i) {
for (int j = 0; j < 16; ++j) {
boolean bl5;
Dynamic<?> dynamic3 = poorMansPalettedContainer.get(j, 0, i);
boolean bl6 = dynamic3 != null && "minecraft:bedrock".equals(dynamic3.get("Name").asString(""));
boolean bl7 = bl5 = dynamic3 != null && "minecraft:air".equals(dynamic3.get("Name").asString(""));
if (bl5) {
bitSet.set(i * 16 + j);
}
bl4 |= bl6;
}
}
if (bl4 && bitSet.cardinality() != bitSet.size()) {
Dynamic dynamic4 = "full".equals(string) ? dynamic.createString("heightmaps") : dynamic2;
dynamic = dynamic.set("below_zero_retrogen", dynamic.createMap((Map)ImmutableMap.of((Object)dynamic.createString("target_status"), (Object)dynamic4, (Object)dynamic.createString("missing_bedrock"), (Object)dynamic.createLongList(LongStream.of(bitSet.toLongArray())))));
dynamic = dynamic.set("Status", dynamic.createString("empty"));
}
dynamic = dynamic.set("isLightOn", dynamic.createBoolean(false));
}
}
return dynamic;
}
...
}
In fact, you could even tag biomes
chunks and not get a crash, but since these still don't have any terrain shape, blending is horrible as they are blended with empty/ugly oceans. MCA Selector should warn when trying to tag biomes
chunks and not let users tag structure_starts
chunks (I think empty
and structure_references
chunks also crash, but I haven't tested).
Interestingly, the Nether and End dimensions seem to be skipped for blending, perhaps because their generation hasn't changed much since 1.18:
public class BlendingDataRemoveFromNetherEndFix
extends DataFix {
...
private static Dynamic<?> updateChunkTag(Dynamic<?> dynamic, OptionalDynamic<?> optionalDynamic) {
boolean bl = "minecraft:overworld".equals(optionalDynamic.get("dimension").asString().result().orElse(""));
return bl ? dynamic : dynamic.remove("blending_data");
}
}
Describe the bug MCA Selector's ForceBlend feature can crash the game, as I mentioned here. MCA Selector may tag unfinished chunks with "blending_data", causing the game to crash when loading the chunks with the error message "java.lang.IllegalStateException: Asking for biomes before we have biomes".
To Reproduce
Expected behavior Not sure how MCA Selector can do it better, but at least users can find a manual solution from this issue.
Environment (please complete the following information):
Solution TLDR: Select all unfinished blocks (Status != full) in the MCA Selector, then delete them, the world will return to normal.