Make UnboundedMapCodec more lenient in decoding dimensions. Fixes MC-197860 (#7527)

This commit is contained in:
Alex O'Neill 2021-01-05 22:17:24 -05:00 committed by GitHub
parent f101700969
commit 020102d87f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 112 additions and 0 deletions

View File

@ -949,6 +949,7 @@ project(':forge') {
exclude 'net/minecraftforge/fml/common/versioning/InvalidVersionSpecificationException.java'
exclude 'net/minecraftforge/fml/common/versioning/Restriction.java'
exclude 'net/minecraftforge/fml/common/versioning/VersionRange.java'
exclude 'net/minecraftforge/common/LenientUnboundedMapCodec.java'
tasks {
main {

View File

@ -0,0 +1,12 @@
--- a/net/minecraft/util/registry/SimpleRegistry.java
+++ b/net/minecraft/util/registry/SimpleRegistry.java
@@ -212,7 +212,8 @@
}
public static <T> Codec<SimpleRegistry<T>> func_241745_c_(RegistryKey<? extends Registry<T>> p_241745_0_, Lifecycle p_241745_1_, Codec<T> p_241745_2_) {
- return Codec.unboundedMap(ResourceLocation.field_240908_a_.xmap(RegistryKey.func_240902_a_(p_241745_0_), RegistryKey::func_240901_a_), p_241745_2_).xmap((p_239656_2_) -> {
+ // FORGE: Fix MC-197860
+ return new net.minecraftforge.common.LenientUnboundedMapCodec<>(ResourceLocation.field_240908_a_.xmap(RegistryKey.func_240902_a_(p_241745_0_), RegistryKey::func_240901_a_), p_241745_2_).xmap((p_239656_2_) -> {
SimpleRegistry<T> simpleregistry = new SimpleRegistry<>(p_241745_0_, p_241745_1_);
p_239656_2_.forEach((p_239653_2_, p_239653_3_) -> {
simpleregistry.func_218381_a(p_239653_2_, p_239653_3_, p_241745_1_);

View File

@ -0,0 +1,99 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.
package net.minecraftforge.common;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.mojang.datafixers.util.Pair;
import com.mojang.datafixers.util.Unit;
import com.mojang.serialization.Codec;
import com.mojang.serialization.DataResult;
import com.mojang.serialization.DynamicOps;
import com.mojang.serialization.Lifecycle;
import com.mojang.serialization.MapLike;
import com.mojang.serialization.codecs.BaseMapCodec;
import java.util.Map;
import java.util.Objects;
/**
* Key and value decoded independently, unknown set of keys
*/
public class LenientUnboundedMapCodec<K, V> implements BaseMapCodec<K, V>, Codec<Map<K, V>>
{
private final Codec<K> keyCodec;
private final Codec<V> elementCodec;
public LenientUnboundedMapCodec(final Codec<K> keyCodec, final Codec<V> elementCodec) {
this.keyCodec = keyCodec;
this.elementCodec = elementCodec;
}
@Override
public Codec<K> keyCodec() {
return keyCodec;
}
@Override
public Codec<V> elementCodec() {
return elementCodec;
}
@Override // FORGE: Modified from decode() in BaseMapCodec
public <T> DataResult<Map<K, V>> decode(DynamicOps<T> ops, MapLike<T> input)
{
final ImmutableMap.Builder<K, V> read = ImmutableMap.builder();
final ImmutableList.Builder<Pair<T, T>> failed = ImmutableList.builder();
final DataResult<Unit> result = input.entries().reduce(
DataResult.success(Unit.INSTANCE, Lifecycle.stable()),
(r, pair) -> {
final DataResult<K> k = keyCodec().parse(ops, pair.getFirst());
final DataResult<V> v = elementCodec().parse(ops, pair.getSecond());
final DataResult<Pair<K, V>> entry = k.apply2stable(Pair::of, v);
entry.error().ifPresent(e -> failed.add(pair));
entry.result().ifPresent(e -> read.put(e.getFirst(), e.getSecond())); // FORGE: This line moved outside the below apply2stable condition
return r.apply2stable((u, p) -> u, entry);
},
(r1, r2) -> r1.apply2stable((u1, u2) -> u1, r2)
);
final Map<K, V> elements = read.build();
final T errors = ops.createMap(failed.build().stream());
return result.map(unit -> elements).setPartial(elements).mapError(e -> e + " missed input: " + errors);
}
@Override
public <T> DataResult<Pair<Map<K, V>, T>> decode(final DynamicOps<T> ops, final T input) {
return ops.getMap(input).setLifecycle(Lifecycle.stable()).flatMap(map -> decode(ops, map)).map(r -> Pair.of(r, input));
}
@Override
public <T> DataResult<T> encode(final Map<K, V> input, final DynamicOps<T> ops, final T prefix) {
return encode(input, ops, ops.mapBuilder()).build(prefix);
}
@Override
public boolean equals(final Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
final LenientUnboundedMapCodec<?, ?> that = (LenientUnboundedMapCodec<?, ?>) o;
return Objects.equals(keyCodec, that.keyCodec) && Objects.equals(elementCodec, that.elementCodec);
}
@Override
public int hashCode() {
return Objects.hash(keyCodec, elementCodec);
}
@Override
public String toString() {
return "LenientUnboundedMapCodec[" + keyCodec + " -> " + elementCodec + ']';
}
}