mirror of
https://github.com/PaperMC/Paper.git
synced 2024-11-06 10:49:40 +01:00
209 lines
12 KiB
Diff
209 lines
12 KiB
Diff
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||
|
From: Spottedleaf <Spottedleaf@users.noreply.github.com>
|
||
|
Date: Sat, 19 Jun 2021 10:54:52 -0700
|
||
|
Subject: [PATCH] Fix Codec log spam
|
||
|
|
||
|
Mojang did NOT add dataconverters for world gen configurations
|
||
|
that they CHANGED. So, the codec fails to parse old data.
|
||
|
|
||
|
This fixes two instances:
|
||
|
- IntProvider is new and Mojang did not account for old data.
|
||
|
Thankfully, only ColumnPlace needed to be special cased.
|
||
|
- TreeConfiguration had changes. Thankfully, they were
|
||
|
only renames for one value and thankfully defaults could
|
||
|
be provided for two new values (WITHOUT changing behavior).
|
||
|
|
||
|
diff --git a/src/main/java/net/minecraft/server/MCUtil.java b/src/main/java/net/minecraft/server/MCUtil.java
|
||
|
index 7684f0146fa522287d223d4b3cb1c999458b872e..3d1e1cb8a1ca32e11ccea7e554827cf88dd28c1b 100644
|
||
|
--- a/src/main/java/net/minecraft/server/MCUtil.java
|
||
|
+++ b/src/main/java/net/minecraft/server/MCUtil.java
|
||
|
@@ -718,4 +718,70 @@ public final class MCUtil {
|
||
|
public static int getTicketLevelFor(net.minecraft.world.level.chunk.ChunkStatus status) {
|
||
|
return net.minecraft.server.level.ChunkMap.MAX_VIEW_DISTANCE + net.minecraft.world.level.chunk.ChunkStatus.getDistance(status);
|
||
|
}
|
||
|
+
|
||
|
+ public static <A> com.mojang.serialization.MapCodec<A> fieldWithFallbacks(com.mojang.serialization.Codec<A> codec, String name, String ...fallback) {
|
||
|
+ return com.mojang.serialization.MapCodec.of(
|
||
|
+ new com.mojang.serialization.codecs.FieldEncoder<>(name, codec),
|
||
|
+ new FieldFallbackDecoder<>(name, java.util.Arrays.asList(fallback), codec),
|
||
|
+ () -> "FieldFallback[" + name + ": " + codec.toString() + "]"
|
||
|
+ );
|
||
|
+ }
|
||
|
+
|
||
|
+ // This is likely a common occurrence, sadly
|
||
|
+ public static final class FieldFallbackDecoder<A> extends com.mojang.serialization.MapDecoder.Implementation<A> {
|
||
|
+ protected final String name;
|
||
|
+ protected final List<String> fallback;
|
||
|
+ private final com.mojang.serialization.Decoder<A> elementCodec;
|
||
|
+
|
||
|
+ public FieldFallbackDecoder(final String name, final List<String> fallback, final com.mojang.serialization.Decoder<A> elementCodec) {
|
||
|
+ this.name = name;
|
||
|
+ this.fallback = fallback;
|
||
|
+ this.elementCodec = elementCodec;
|
||
|
+ }
|
||
|
+
|
||
|
+ @Override
|
||
|
+ public <T> com.mojang.serialization.DataResult<A> decode(final com.mojang.serialization.DynamicOps<T> ops, final com.mojang.serialization.MapLike<T> input) {
|
||
|
+ T value = input.get(name);
|
||
|
+ if (value == null) {
|
||
|
+ for (String fall : fallback) {
|
||
|
+ value = input.get(fall);
|
||
|
+ if (value != null) {
|
||
|
+ break;
|
||
|
+ }
|
||
|
+ }
|
||
|
+ if (value == null) {
|
||
|
+ return com.mojang.serialization.DataResult.error("No key " + name + " in " + input);
|
||
|
+ }
|
||
|
+ }
|
||
|
+ return elementCodec.parse(ops, value);
|
||
|
+ }
|
||
|
+
|
||
|
+ @Override
|
||
|
+ public <T> java.util.stream.Stream<T> keys(final com.mojang.serialization.DynamicOps<T> ops) {
|
||
|
+ return java.util.stream.Stream.of(ops.createString(name));
|
||
|
+ }
|
||
|
+
|
||
|
+ @Override
|
||
|
+ public boolean equals(final Object o) {
|
||
|
+ if (this == o) {
|
||
|
+ return true;
|
||
|
+ }
|
||
|
+ if (o == null || getClass() != o.getClass()) {
|
||
|
+ return false;
|
||
|
+ }
|
||
|
+ final FieldFallbackDecoder<?> that = (FieldFallbackDecoder<?>)o;
|
||
|
+ return java.util.Objects.equals(name, that.name) && java.util.Objects.equals(elementCodec, that.elementCodec)
|
||
|
+ && java.util.Objects.equals(fallback, that.fallback);
|
||
|
+ }
|
||
|
+
|
||
|
+ @Override
|
||
|
+ public int hashCode() {
|
||
|
+ return java.util.Objects.hash(name, fallback, elementCodec);
|
||
|
+ }
|
||
|
+
|
||
|
+ @Override
|
||
|
+ public String toString() {
|
||
|
+ return "FieldDecoder[" + name + ": " + elementCodec + ']';
|
||
|
+ }
|
||
|
+ }
|
||
|
}
|
||
|
diff --git a/src/main/java/net/minecraft/util/valueproviders/IntProvider.java b/src/main/java/net/minecraft/util/valueproviders/IntProvider.java
|
||
|
index 020a19cd683dd3779c5116d12b3cdcd3b3ca69b4..c81a0eec12436c10869bfdcc21af09173f438331 100644
|
||
|
--- a/src/main/java/net/minecraft/util/valueproviders/IntProvider.java
|
||
|
+++ b/src/main/java/net/minecraft/util/valueproviders/IntProvider.java
|
||
|
@@ -9,13 +9,44 @@ import net.minecraft.core.Registry;
|
||
|
|
||
|
public abstract class IntProvider {
|
||
|
private static final Codec<Either<Integer, IntProvider>> CONSTANT_OR_DISPATCH_CODEC = Codec.either(Codec.INT, Registry.INT_PROVIDER_TYPES.dispatch(IntProvider::getType, IntProviderType::codec));
|
||
|
- public static final Codec<IntProvider> CODEC = CONSTANT_OR_DISPATCH_CODEC.xmap((either) -> {
|
||
|
+ public static final Codec<IntProvider> CODEC_REAL = CONSTANT_OR_DISPATCH_CODEC.xmap((either) -> { // Paper - used by CODEC below
|
||
|
return either.map(ConstantInt::of, (intProvider) -> {
|
||
|
return intProvider;
|
||
|
});
|
||
|
}, (intProvider) -> {
|
||
|
return intProvider.getType() == IntProviderType.CONSTANT ? Either.left(((ConstantInt)intProvider).getValue()) : Either.right(intProvider);
|
||
|
});
|
||
|
+ // Paper start
|
||
|
+ public static final Codec<IntProvider> CODEC = new Codec<>() {
|
||
|
+ @Override
|
||
|
+ public <T> DataResult<com.mojang.datafixers.util.Pair<IntProvider, T>> decode(com.mojang.serialization.DynamicOps<T> ops, T input) {
|
||
|
+ /*
|
||
|
+ UniformInt:
|
||
|
+ count -> { (old format)
|
||
|
+ base, spread
|
||
|
+ } -> {UniformInt} { (new format & type)
|
||
|
+ base, base + spread
|
||
|
+ } */
|
||
|
+
|
||
|
+
|
||
|
+ if (ops.get(input, "base").result().isPresent() && ops.get(input, "spread").result().isPresent()) {
|
||
|
+ // detected old format
|
||
|
+ int base = ops.getNumberValue(ops.get(input, "base").result().get()).result().get().intValue();
|
||
|
+ int spread = ops.getNumberValue(ops.get(input, "spread").result().get()).result().get().intValue();
|
||
|
+ return DataResult.success(new com.mojang.datafixers.util.Pair<>(UniformInt.of(base, base + spread), input));
|
||
|
+ }
|
||
|
+
|
||
|
+ // not old format, forward to real codec
|
||
|
+ return CODEC_REAL.decode(ops, input);
|
||
|
+ }
|
||
|
+
|
||
|
+ @Override
|
||
|
+ public <T> DataResult<T> encode(IntProvider input, com.mojang.serialization.DynamicOps<T> ops, T prefix) {
|
||
|
+ // forward to real codec
|
||
|
+ return CODEC_REAL.encode(input, ops, prefix);
|
||
|
+ }
|
||
|
+ };
|
||
|
+ // Paper end
|
||
|
public static final Codec<IntProvider> NON_NEGATIVE_CODEC = codec(0, Integer.MAX_VALUE);
|
||
|
public static final Codec<IntProvider> POSITIVE_CODEC = codec(1, Integer.MAX_VALUE);
|
||
|
|
||
|
diff --git a/src/main/java/net/minecraft/world/level/levelgen/feature/blockplacers/ColumnPlacer.java b/src/main/java/net/minecraft/world/level/levelgen/feature/blockplacers/ColumnPlacer.java
|
||
|
index 05bba5410fbd9f8e333584ccbd65a909f3040322..0cac5869be03bbbfb090c00447f75b4183a06781 100644
|
||
|
--- a/src/main/java/net/minecraft/world/level/levelgen/feature/blockplacers/ColumnPlacer.java
|
||
|
+++ b/src/main/java/net/minecraft/world/level/levelgen/feature/blockplacers/ColumnPlacer.java
|
||
|
@@ -10,11 +10,41 @@ import net.minecraft.world.level.LevelAccessor;
|
||
|
import net.minecraft.world.level.block.state.BlockState;
|
||
|
|
||
|
public class ColumnPlacer extends BlockPlacer {
|
||
|
- public static final Codec<ColumnPlacer> CODEC = RecordCodecBuilder.create((instance) -> {
|
||
|
+ public static final Codec<ColumnPlacer> CODEC_REAL = RecordCodecBuilder.create((instance) -> { // Paper - used by CODEC below
|
||
|
return instance.group(IntProvider.NON_NEGATIVE_CODEC.fieldOf("size").forGetter((columnPlacer) -> {
|
||
|
return columnPlacer.size;
|
||
|
})).apply(instance, ColumnPlacer::new);
|
||
|
});
|
||
|
+ // Paper start
|
||
|
+ public static final Codec<ColumnPlacer> CODEC = new Codec<>() {
|
||
|
+ @Override
|
||
|
+ public <T> com.mojang.serialization.DataResult<com.mojang.datafixers.util.Pair<ColumnPlacer, T>> decode(com.mojang.serialization.DynamicOps<T> ops, T input) {
|
||
|
+ /*
|
||
|
+ Old format:
|
||
|
+ min_size, extra_size -> BiasedToBottomInt(min_size, min_size + extra_size) to place @ root.size
|
||
|
+ */
|
||
|
+ if (ops.get(input, "min_size").result().isPresent() && ops.get(input, "extra_size").result().isPresent()) {
|
||
|
+ // detected old format
|
||
|
+ int min_size = ops.getNumberValue(ops.get(input, "min_size").result().get()).result().get().intValue();
|
||
|
+ int extra_size = ops.getNumberValue(ops.get(input, "extra_size").result().get()).result().get().intValue();
|
||
|
+ return com.mojang.serialization.DataResult.success(
|
||
|
+ new com.mojang.datafixers.util.Pair<>(new ColumnPlacer(net.minecraft.util.valueproviders.BiasedToBottomInt.of(
|
||
|
+ min_size, min_size + extra_size
|
||
|
+ )), input)
|
||
|
+ );
|
||
|
+ }
|
||
|
+
|
||
|
+ // not old format, forward to real codec
|
||
|
+ return CODEC_REAL.decode(ops, input);
|
||
|
+ }
|
||
|
+
|
||
|
+ @Override
|
||
|
+ public <T> com.mojang.serialization.DataResult<T> encode(ColumnPlacer input, com.mojang.serialization.DynamicOps<T> ops, T prefix) {
|
||
|
+ // forward to real codec
|
||
|
+ return CODEC_REAL.encode(input, ops, prefix);
|
||
|
+ }
|
||
|
+ };
|
||
|
+ // Paper end
|
||
|
private final IntProvider size;
|
||
|
|
||
|
public ColumnPlacer(IntProvider size) {
|
||
|
diff --git a/src/main/java/net/minecraft/world/level/levelgen/feature/configurations/TreeConfiguration.java b/src/main/java/net/minecraft/world/level/levelgen/feature/configurations/TreeConfiguration.java
|
||
|
index 5da68897148192905c2747676c1ee2ee649f923f..b990099cf274f8cb0d96c139345cf0bf328affd6 100644
|
||
|
--- a/src/main/java/net/minecraft/world/level/levelgen/feature/configurations/TreeConfiguration.java
|
||
|
+++ b/src/main/java/net/minecraft/world/level/levelgen/feature/configurations/TreeConfiguration.java
|
||
|
@@ -18,13 +18,13 @@ public class TreeConfiguration implements FeatureConfiguration {
|
||
|
return treeConfiguration.trunkProvider;
|
||
|
}), TrunkPlacer.CODEC.fieldOf("trunk_placer").forGetter((treeConfiguration) -> {
|
||
|
return treeConfiguration.trunkPlacer;
|
||
|
- }), BlockStateProvider.CODEC.fieldOf("foliage_provider").forGetter((treeConfiguration) -> {
|
||
|
+ }), net.minecraft.server.MCUtil.fieldWithFallbacks(BlockStateProvider.CODEC, "foliage_provider", "leaves_provider").forGetter((treeConfiguration) -> { // Paper - provide fallback for rename
|
||
|
return treeConfiguration.foliageProvider;
|
||
|
- }), BlockStateProvider.CODEC.fieldOf("sapling_provider").forGetter((treeConfiguration) -> {
|
||
|
+ }), BlockStateProvider.CODEC.optionalFieldOf("sapling_provider", new SimpleStateProvider(Blocks.OAK_SAPLING.defaultBlockState())).forGetter((treeConfiguration) -> { // Paper - provide default - it looks like for now this is OK because it's just used to check canSurvive. Same check happens in 1.16.5 for the default we provide - so it should retain behavior...
|
||
|
return treeConfiguration.saplingProvider;
|
||
|
}), FoliagePlacer.CODEC.fieldOf("foliage_placer").forGetter((treeConfiguration) -> {
|
||
|
return treeConfiguration.foliagePlacer;
|
||
|
- }), BlockStateProvider.CODEC.fieldOf("dirt_provider").forGetter((treeConfiguration) -> {
|
||
|
+ }), BlockStateProvider.CODEC.optionalFieldOf("dirt_provider", new SimpleStateProvider(Blocks.DIRT.defaultBlockState())).forGetter((treeConfiguration) -> { // Paper - provide defaults, old data DOES NOT have this key (thankfully ALL OLD DATA used DIRT)
|
||
|
return treeConfiguration.dirtProvider;
|
||
|
}), FeatureSize.CODEC.fieldOf("minimum_size").forGetter((treeConfiguration) -> {
|
||
|
return treeConfiguration.minimumSize;
|