| Line 5: |
Line 5: |
| | == Serialization and Deserialization == | | == Serialization and Deserialization == |
| | | | |
| − | The primary use for Codecs is to serialize java objects to some serialized type, such as a JsonElement or a Tag, and to deserialize an serialized object back to its proper java type. This is accomplished with <code>Codec#encodeStart</code> and <code>Codec#parse</code>, respectively. Given a Codec<SomeJavaType> and a DynamicOps<SomeSerializedType>, we can convert instances of SomeJavaType to instances of SomeSerializedType and back. | + | The primary use for Codecs is to serialize java objects to some serialized type, such as a JsonElement or a Tag, and to deserialize a serialized object back to its proper java type. This is accomplished with <code>Codec#encodeStart</code> and <code>Codec#parse</code>, respectively. Given a Codec<SomeJavaType> and a DynamicOps<SomeSerializedType>, we can convert instances of SomeJavaType to instances of SomeSerializedType and back. |
| | | | |
| | Each of these methods take a [[DynamicOps]] instance and an instance of the object we are serializing or deserializing, and returns a DataResult: | | Each of these methods take a [[DynamicOps]] instance and an instance of the object we are serializing or deserializing, and returns a DataResult: |
| Line 18: |
Line 18: |
| | | | |
| | // deserialize some Tag instance back to a proper java object | | // deserialize some Tag instance back to a proper java object |
| − | DataResult<SomeJavaType> result = someCodec.parse(NBTOps.INSTANCE, someTag ); | + | DataResult<SomeJavaType> result = someCodec.parse(NBTOps.INSTANCE, someTag); |
| | | | |
| | // serialize some java object to a JsonElement | | // serialize some java object to a JsonElement |
| Line 92: |
Line 92: |
| | As previously mentioned, we can use <code>Codec.INT</code> for the integer codec, and <code>Registry.ITEM</code> for the Item codec. We don't have a builtin codec for list-of-blockpos, but we can use BlockPos.CODEC to create one. | | As previously mentioned, we can use <code>Codec.INT</code> for the integer codec, and <code>Registry.ITEM</code> for the Item codec. We don't have a builtin codec for list-of-blockpos, but we can use BlockPos.CODEC to create one. |
| | | | |
| − | == Lists == | + | ==Lists== |
| | The <code>Codec#listOf</code> instance method can be used to generate a codec for a List from an existing codec: | | The <code>Codec#listOf</code> instance method can be used to generate a codec for a List from an existing codec: |
| | | | |
| | <syntaxhighlight lang="java"> | | <syntaxhighlight lang="java"> |
| | // BlockPos.CODEC is a Codec<BlockPos> | | // BlockPos.CODEC is a Codec<BlockPos> |
| − | Codec<List<BlockPos>> = BlockPos.CODEC.listOf(); | + | Codec<List<BlockPos>> blockPosListCodec = BlockPos.CODEC.listOf(); |
| | </syntaxhighlight> | | </syntaxhighlight> |
| | | | |
| Line 166: |
Line 166: |
| | Codec.STRING.fieldOf("name").codec()); | | Codec.STRING.fieldOf("name").codec()); |
| | | | |
| − | JsonElement encodedPair = BOXED_INT_CODEC.encodeStart(JsonOps.INSTANCE, Pair.of(5, "cheese").result().get(); | + | JsonElement encodedPair = PAIR_CODEC.encodeStart(JsonOps.INSTANCE, Pair.of(5, "cheese").result().get(); |
| | </syntaxhighlight> | | </syntaxhighlight> |
| | This codec serializes the above value to: | | This codec serializes the above value to: |
| Line 267: |
Line 267: |
| | * BlockPlacer and BlockPlacerType | | * BlockPlacer and BlockPlacerType |
| | * ConfiguredDecorator and FeatureDecorator | | * ConfiguredDecorator and FeatureDecorator |
| | + | |
| | + | === Registering MapCodecCodecs for Dispatch Subcodecs === |
| | + | |
| | + | When registering a subcodec to any dispatch codec registry, the registered subcodec should be an instance of MapCodecCodec, or the subcodec will be nested in its own object when serialized. |
| | + | |
| | + | For example, suppose we register a single-field subcodec, where we use fieldOf-and-xmap to convert an int to our int-holding Thing: |
| | + | |
| | + | <syntaxhighlight lang="java"> |
| | + | public record Thing(int n){} |
| | + | public static Codec<Thing> CODEC = Codec.INT.fieldOf("n").codec().xmap(Thing::new, Thing::n); |
| | + | </syntaxhighlight> |
| | + | |
| | + | This results in this json when serialized: |
| | + | |
| | + | <syntaxhighlight lang="json"> |
| | + | "some_thing": |
| | + | { |
| | + | "type": "ourmod:thing", |
| | + | "value": { |
| | + | "n": 5 |
| | + | } |
| | + | } |
| | + | </syntaxhighlight> |
| | + | |
| | + | This occurs because xmap does not produce a MapCodecCodec, and if this nested object is not desired, then our registered subcodec must be a MapCodecCodec. |
| | + | |
| | + | However, fieldOf() produces a MapCodec, which has a codec() method, which does produce a MapCodecCodec. We can rearrange our codec builder, which then produces a cleaner json: |
| | + | |
| | + | <syntaxhighlight lang="java"> |
| | + | public static Codec<Thing> CODEC = Codec.INT // Primitive codec |
| | + | .fieldOf("n") // MapCodec |
| | + | .xmap(Thing::new, Thing::n) // MapCodec |
| | + | .codec(); // MapCodecCodec! That's what we want. |
| | + | </syntaxhighlight> |
| | + | |
| | + | <syntaxhighlight lang="json"> |
| | + | "some_thing": |
| | + | { |
| | + | "type": "ourmod:thing", |
| | + | "n": 5 |
| | + | } |
| | + | </syntaxhighlight> |
| | + | |
| | + | RecordCodecBuilder also produces MapCodecCodecs. |
| | | | |
| | =External Links= | | =External Links= |
| | * [https://github.com/Mojang/DataFixerUpper/blob/master/src/main/java/com/mojang/serialization/Codec.java Codecs in Mojang's official public DataFixerUpper repository] | | * [https://github.com/Mojang/DataFixerUpper/blob/master/src/main/java/com/mojang/serialization/Codec.java Codecs in Mojang's official public DataFixerUpper repository] |
| | * [https://kvverti.github.io/Documented-DataFixerUpper/snapshot/com/mojang/serialization/Codec.html#flatXmap-java.util.function.Function-java.util.function.Function- Unofficial Codec Javadocs] | | * [https://kvverti.github.io/Documented-DataFixerUpper/snapshot/com/mojang/serialization/Codec.html#flatXmap-java.util.function.Function-java.util.function.Function- Unofficial Codec Javadocs] |