Skip to content

Commit fbbbfa2

Browse files
committed
Improve the record codec error message
1 parent d236900 commit fbbbfa2

File tree

6 files changed

+123
-4
lines changed

6 files changed

+123
-4
lines changed

src/main/java/net/errorcraft/codecium/mixin/mojang/serialization/CodecExtender.java

+15-3
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,18 @@
11
package net.errorcraft.codecium.mixin.mojang.serialization;
22

3-
import com.mojang.serialization.Codec;
4-
import com.mojang.serialization.DataResult;
3+
import com.mojang.serialization.*;
4+
import net.errorcraft.codecium.serialization.FieldMapCodec;
55
import net.errorcraft.codecium.util.codec.NumberUtil;
66
import org.spongepowered.asm.mixin.Mixin;
77
import org.spongepowered.asm.mixin.Overwrite;
88
import org.spongepowered.asm.mixin.injection.At;
99
import org.spongepowered.asm.mixin.injection.Redirect;
1010

1111
import java.util.function.Function;
12+
import java.util.function.Supplier;
1213

1314
@Mixin(value = Codec.class, remap = false)
14-
public interface CodecExtender {
15+
public interface CodecExtender<A> {
1516
@Redirect(
1617
method = "intRange",
1718
at = @At(
@@ -62,4 +63,15 @@ static Codec<String> string(final int minSize, final int maxSize) {
6263
return DataResult.success(value);
6364
});
6465
}
66+
67+
@Redirect(
68+
method = "fieldOf(Ljava/lang/String;)Lcom/mojang/serialization/MapCodec;",
69+
at = @At(
70+
value = "INVOKE",
71+
target = "Lcom/mojang/serialization/MapCodec;of(Lcom/mojang/serialization/MapEncoder;Lcom/mojang/serialization/MapDecoder;Ljava/util/function/Supplier;)Lcom/mojang/serialization/MapCodec;"
72+
)
73+
)
74+
private MapCodec<A> createFieldCodecPassName(MapEncoder<A> encoder, MapDecoder<A> decoder, Supplier<String> nameSupplier, final String name) {
75+
return new FieldMapCodec<>(name, encoder, decoder, nameSupplier);
76+
}
6577
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
package net.errorcraft.codecium.mixin.mojang.serialization;
2+
3+
import com.mojang.serialization.DataResult;
4+
import org.spongepowered.asm.mixin.Mixin;
5+
import org.spongepowered.asm.mixin.Overwrite;
6+
7+
@Mixin(value = DataResult.class, remap = false)
8+
public interface DataResultExtender {
9+
/**
10+
* @author ErrorCraft
11+
* @reason Uses a line feed for a better error message. Also swaps the order of the messages to preserve the order in the codecs.
12+
*/
13+
@Overwrite
14+
static String appendMessages(final String first, final String second) {
15+
return second + "\n" + first;
16+
}
17+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
package net.errorcraft.codecium.mixin.mojang.serialization.codecs;
2+
3+
import com.llamalad7.mixinextras.injector.ModifyReturnValue;
4+
import com.mojang.serialization.DataResult;
5+
import com.mojang.serialization.codecs.OptionalFieldCodec;
6+
import org.spongepowered.asm.mixin.Final;
7+
import org.spongepowered.asm.mixin.Mixin;
8+
import org.spongepowered.asm.mixin.Shadow;
9+
import org.spongepowered.asm.mixin.injection.At;
10+
11+
import java.util.Optional;
12+
13+
@Mixin(value = OptionalFieldCodec.class, remap = false)
14+
public class OptionalFieldCodecExtender<A> {
15+
@Shadow
16+
@Final
17+
private String name;
18+
19+
@ModifyReturnValue(
20+
method = "decode",
21+
at = @At("TAIL")
22+
)
23+
private DataResult<Optional<A>> modifyPotentialErrorMessage(DataResult<Optional<A>> original) {
24+
return original.mapError(message -> "'" + this.name + "': " + message);
25+
}
26+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
package net.errorcraft.codecium.mixin.mojang.serialization.codecs;
2+
3+
import com.llamalad7.mixinextras.injector.ModifyReturnValue;
4+
import com.mojang.serialization.DataResult;
5+
import net.errorcraft.codecium.util.StringUtil;
6+
import org.spongepowered.asm.mixin.Mixin;
7+
import org.spongepowered.asm.mixin.injection.At;
8+
9+
public class RecordCodecBuilderExtender {
10+
@Mixin(targets = "com/mojang/serialization/codecs/RecordCodecBuilder$2", remap = false)
11+
public static class RecordMapCodecExtender<O> {
12+
@ModifyReturnValue(
13+
method = "decode",
14+
at = @At("RETURN")
15+
)
16+
private DataResult<O> useBetterErrorMessage(DataResult<O> original) {
17+
return original.mapError(message -> "Map has errors for the following fields:\n" + StringUtil.indent(message));
18+
}
19+
}
20+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
package net.errorcraft.codecium.serialization;
2+
3+
import com.mojang.serialization.*;
4+
5+
import java.util.function.Supplier;
6+
import java.util.stream.Stream;
7+
8+
public class FieldMapCodec<A> extends MapCodec<A> {
9+
private final String name;
10+
private final MapEncoder<A> encoder;
11+
private final MapDecoder<A> decoder;
12+
private final Supplier<String> toStringSupplier;
13+
14+
public FieldMapCodec(String name, MapEncoder<A> encoder, MapDecoder<A> decoder, Supplier<String> toStringSupplier) {
15+
this.name = name;
16+
this.encoder = encoder;
17+
this.decoder = decoder;
18+
this.toStringSupplier = toStringSupplier;
19+
}
20+
21+
@Override
22+
public <T> Stream<T> keys(final DynamicOps<T> ops) {
23+
return Stream.concat(this.encoder.keys(ops), this.decoder.keys(ops));
24+
}
25+
26+
@Override
27+
public <T> DataResult<A> decode(final DynamicOps<T> ops, final MapLike<T> input) {
28+
return this.decoder.decode(ops, input)
29+
.mapError(message -> "'" + this.name + "': " + message);
30+
}
31+
32+
@Override
33+
public <T> RecordBuilder<T> encode(final A input, final DynamicOps<T> ops, final RecordBuilder<T> prefix) {
34+
return this.encoder.encode(input, ops, prefix);
35+
}
36+
37+
@Override
38+
public String toString() {
39+
return this.toStringSupplier.get();
40+
}
41+
}

src/main/resources/codecium.mixins.json

+4-1
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,12 @@
66
"minecraft.nbt.NbtOpsExtender",
77
"minecraft.util.dynamic.CodecsExtender",
88
"mojang.serialization.CodecExtender",
9+
"mojang.serialization.DataResultExtender",
910
"mojang.serialization.JavaOpsExtender",
1011
"mojang.serialization.JsonOpsExtender",
11-
"mojang.serialization.codecs.EitherCodecExtender"
12+
"mojang.serialization.codecs.EitherCodecExtender",
13+
"mojang.serialization.codecs.OptionalFieldCodecExtender",
14+
"mojang.serialization.codecs.RecordCodecBuilderExtender$RecordMapCodecExtender"
1215
],
1316
"injectors": {
1417
"defaultRequire": 1

0 commit comments

Comments
 (0)