<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en-GB">
	<id>https://forge.gemwire.uk/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Commoble</id>
	<title>Forge Community Wiki - User contributions [en-gb]</title>
	<link rel="self" type="application/atom+xml" href="https://forge.gemwire.uk/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Commoble"/>
	<link rel="alternate" type="text/html" href="https://forge.gemwire.uk/wiki/Special:Contributions/Commoble"/>
	<updated>2026-06-02T06:42:59Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.35.0</generator>
	<entry>
		<id>https://forge.gemwire.uk/index.php?title=Codecs&amp;diff=3414</id>
		<title>Codecs</title>
		<link rel="alternate" type="text/html" href="https://forge.gemwire.uk/index.php?title=Codecs&amp;diff=3414"/>
		<updated>2023-11-23T17:22:38Z</updated>

		<summary type="html">&lt;p&gt;Commoble: /* Registry Dispatch */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Codecs are a serialization tool from mojang's DataFixerUpper library. Codecs are used alongside [[DynamicOps|DynamicOps]] to allow objects to be serialized to different formats and back, such as JSON or [[Using_NBT|NBT]]. While the DynamicOps describes the format the object is to be serialized to, the Codec describes the manner in which the object is to be serialized; a single Codec can be used to serialize an object to any format for which a DynamicOps exists. Codecs and DynamicOps jointly form an abstraction layer over data serialization, simplifying the effort needed to serialize or deserialize data.&lt;br /&gt;
&lt;br /&gt;
= Using Codecs =&lt;br /&gt;
&lt;br /&gt;
== Serialization and Deserialization ==&lt;br /&gt;
&lt;br /&gt;
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 &amp;lt;code&amp;gt;Codec#encodeStart&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;Codec#parse&amp;lt;/code&amp;gt;, respectively. Given a Codec&amp;lt;SomeJavaType&amp;gt; and a DynamicOps&amp;lt;SomeSerializedType&amp;gt;, we can convert instances of SomeJavaType to instances of SomeSerializedType and back.&lt;br /&gt;
&lt;br /&gt;
Each of these methods take a [[DynamicOps]] instance and an instance of the object we are serializing or deserializing, and returns a DataResult:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
// let someCodec be a Codec&amp;lt;SomeJavaType&amp;gt;&lt;br /&gt;
// let someJavaObject be an instance of SomeJavaType&lt;br /&gt;
// let someTag and someJsonElement be instances of Tag and JsonElement, respectively&lt;br /&gt;
&lt;br /&gt;
// serialize some java object to Tag&lt;br /&gt;
DataResult&amp;lt;Tag&amp;gt; result = someCodec.encodeStart(NBTOps.INSTANCE, someJavaObject);&lt;br /&gt;
&lt;br /&gt;
// deserialize some Tag instance back to a proper java object&lt;br /&gt;
DataResult&amp;lt;SomeJavaType&amp;gt; result = someCodec.parse(NBTOps.INSTANCE, someTag );&lt;br /&gt;
&lt;br /&gt;
// serialize some java object to a JsonElement&lt;br /&gt;
DataResult&amp;lt;JsonElement&amp;gt; result = someCodec.encodeStart(JsonOps.INSTANCE, someJavaObject);&lt;br /&gt;
&lt;br /&gt;
// deserialize a JsonElement back to a proper java object&lt;br /&gt;
DataResult&amp;lt;SomeJavaType&amp;gt; result = someCodec.parse(JsonOps.INSTANCE, someJsonElement);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A DataResult either holds the converted instance, or it holds some error data, depending on whether the conversion was successful or not, respectively. There are several things we can do with this DataResult; &amp;lt;code&amp;gt;DataResult#result&amp;lt;/code&amp;gt; simply returns an Optional containing the converted object if the conversion was successful, while &amp;lt;code&amp;gt;DataResult#resultOrPartial&amp;lt;/code&amp;gt; also runs a given function if the conversion was unsuccessful (in addition to returning the Optional). #resultOrPartial is particularly useful for logging errors during datapack deserialization:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
// deserialize something from json&lt;br /&gt;
someCodec.parse(JsonOps.INSTANCE, someJsonElement)&lt;br /&gt;
	.resultOrPartial(errorMessage -&amp;gt; doSomethingIfBadData(errorMessage))&lt;br /&gt;
	.ifPresent(someJavaObject -&amp;gt; doSomethingIfGoodData(someJavaObject))&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Builtin Codecs ==&lt;br /&gt;
=== Primitive Codecs ===&lt;br /&gt;
The Codec class itself contains static instances of codecs for all supported primitive types, e.g. &amp;lt;code&amp;gt;Codec.STRING&amp;lt;/code&amp;gt; is the canonical &amp;lt;code&amp;gt;Codec&amp;lt;String&amp;gt;&amp;lt;/code&amp;gt; implementation. Primitive codecs include:&lt;br /&gt;
* BOOL, which serializes to a boolean value&lt;br /&gt;
* BYTE, SHORT, INT, LONG, FLOAT, and DOUBLE, which serialize to numeric values&lt;br /&gt;
* STRING, which serializes to a string&lt;br /&gt;
* BYTE_BUFFER, INT_STREAM, and LONG_STREAM, which serialize to lists of numbers&lt;br /&gt;
* EMPTY, which represents null objects&lt;br /&gt;
&lt;br /&gt;
=== Other Builtin Codecs ===&lt;br /&gt;
Vanilla minecraft has many builtin codecs for objects that it frequently serializes. These codecs are typically static instances in the class the codec is serializing; e.g. &amp;lt;code&amp;gt;ResourceLocation.CODEC&amp;lt;/code&amp;gt; is the canonical &amp;lt;code&amp;gt;Codec&amp;lt;ResourceLocation&amp;gt;&amp;lt;/code&amp;gt;, while &amp;lt;code&amp;gt;BlockPos.CODEC&amp;lt;/code&amp;gt; is the codec used for serializing a BlockPos.&lt;br /&gt;
&lt;br /&gt;
Each vanilla &amp;lt;code&amp;gt;Registry&amp;lt;/code&amp;gt; acts as the Codec for the type of object the registry contains; e.g. &amp;lt;code&amp;gt;Registry.BLOCK&amp;lt;/code&amp;gt; is itself a &amp;lt;code&amp;gt;Codec&amp;lt;Block&amp;gt;&amp;lt;/code&amp;gt;. Forge Registries, however, do not currently implement Codec and cannot yet be used in this way; custom codecs must be created for forge-specific registries that are not tied to specific vanilla registries.&lt;br /&gt;
&lt;br /&gt;
Of particular note here is the CompoundTag.CODEC, which can be used to e.g. serialize a CompoundTag into a json file. This has a notable limitation in that CompoundTag.CODEC *cannot* safely deserialize lists of numbers from json, due to the strong typing of ListTag and the way that the NBTOps deserializer reads numeric values.&lt;br /&gt;
&lt;br /&gt;
= Creating Codecs =&lt;br /&gt;
&lt;br /&gt;
Suppose we have the following class, and we want to deserialize json files to instances of this class:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
public class ExampleCodecClass {&lt;br /&gt;
&lt;br /&gt;
    private final int someInt;&lt;br /&gt;
    private final Item item;&lt;br /&gt;
    private final List&amp;lt;BlockPos&amp;gt; blockPositions;&lt;br /&gt;
&lt;br /&gt;
    public ExampleCodecClass(int someInt, Item item, List&amp;lt;BlockPos&amp;gt; blockPositions) {...}&lt;br /&gt;
&lt;br /&gt;
    public int getSomeInt() { return this.someInt; }&lt;br /&gt;
    public Item getItem() { return this.item; }&lt;br /&gt;
    public List&amp;lt;BlockPos&amp;gt; getBlockPositions() { return this.blockPositions; }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Where a json file for an instance of this class might look like:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;json&amp;quot;&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
	&amp;quot;some_int&amp;quot;: 42,&lt;br /&gt;
	&amp;quot;item&amp;quot;: &amp;quot;minecraft:gold_ingot&amp;quot;,&lt;br /&gt;
	&amp;quot;block_positions&amp;quot;:&lt;br /&gt;
	[&lt;br /&gt;
		[0,0,0],&lt;br /&gt;
		[10,20,-100]&lt;br /&gt;
	]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We can assemble a codec for this class by building a new codec out of smaller codecs. We'll need a codec for each of these fields:&lt;br /&gt;
* a &amp;lt;code&amp;gt;Codec&amp;lt;Integer&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
* a &amp;lt;code&amp;gt;Codec&amp;lt;Item&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
* a &amp;lt;code&amp;gt;Codec&amp;lt;List&amp;lt;BlockPos&amp;gt;&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
And then we'll need to assemble these into a &amp;lt;code&amp;gt;Codec&amp;lt;ExampleCodecClass&amp;gt;&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
As previously mentioned, we can use &amp;lt;code&amp;gt;Codec.INT&amp;lt;/code&amp;gt; for the integer codec, and &amp;lt;code&amp;gt;Registry.ITEM&amp;lt;/code&amp;gt; for the Item codec. We don't have a builtin codec for list-of-blockpos, but we can use BlockPos.CODEC to create one.&lt;br /&gt;
&lt;br /&gt;
== Lists ==&lt;br /&gt;
The &amp;lt;code&amp;gt;Codec#listOf&amp;lt;/code&amp;gt; instance method can be used to generate a codec for a List from an existing codec:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
// BlockPos.CODEC is a Codec&amp;lt;BlockPos&amp;gt;&lt;br /&gt;
Codec&amp;lt;List&amp;lt;BlockPos&amp;gt;&amp;gt; = BlockPos.CODEC.listOf();&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Codecs created via listOf() serialize things to listlike objects, such as [] json arrays or ListTags.&lt;br /&gt;
&lt;br /&gt;
Deserializing a list in this manner produces an ''immutable'' list. If a mutable list is needed, [[Codecs#Equivalent_Types_and_xmap|xmap]] can be used to convert the list after deserializing.&lt;br /&gt;
&lt;br /&gt;
== Records ==&lt;br /&gt;
RecordCodecBuilder is used to generate codecs that serialize instances of classes with explicitly named fields, like our example above. Codecs created via RecordCodecBuilder serialize things to maplike objects, such as {} json objects or CompoundTags.&lt;br /&gt;
&lt;br /&gt;
RecordCodecBuilder can be used in several ways, but the simplest form is as follows:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
public static final Codec&amp;lt;SomeJavaClass&amp;gt; = RecordCodecBuilder.create(instance -&amp;gt; instance.group(&lt;br /&gt;
		someFieldCodecA.fieldOf(&amp;quot;field_name_a&amp;quot;).forGetter(SomeJavaClass::getFieldA),&lt;br /&gt;
		someFieldCodecB.fieldOf(&amp;quot;field_name_b&amp;quot;).forGetter(SomeJavaClass::getFieldB),&lt;br /&gt;
		someFieldCodecC.fieldOf(&amp;quot;field_name_c&amp;quot;).forGetter(SomeJavaClass::getFieldC),&lt;br /&gt;
		// up to 16 fields can be declared here&lt;br /&gt;
	).apply(instance, SomeJavaClass::new));&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Where each line in the group specifies a codec instance for the type of that field, the field name in the serialized object, and the corresponding getter function in the java class. The builder is concluded by specifying a constructor or factory for the java class whose arguments are the previously defined fields in the same order.&lt;br /&gt;
&lt;br /&gt;
For example, using RecordCodecBuilder to create a codec for our example class above:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
public static final Codec&amp;lt;ExampleCodecClass&amp;gt; = RecordCodecBuilder.create(instance -&amp;gt; instance.group(&lt;br /&gt;
		Codec.INT.fieldOf(&amp;quot;some_int&amp;quot;).forGetter(ExampleCodecClass::getSomeInt),&lt;br /&gt;
		Registry.ITEM.fieldOf(&amp;quot;item&amp;quot;).forGetter(ExampleCodecClass::getItem),&lt;br /&gt;
		BlockPos.CODEC.listOf().fieldOf(&amp;quot;block_positions&amp;quot;).forGetter(ExampleCodecClass::getBlockPositions)&lt;br /&gt;
	).apply(instance, ExampleCodecClass::new));&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Optional and Default Values in Record Fields===&lt;br /&gt;
When RecordCodecBuilder is used as shown above, all of the fields are *required* to be in the serialized object (the JsonObject/CompoundTag/etc), or the entire thing will fail to parse when the codec tries to deserialize it. If we wish to have optional or default values, we have several alternatives of fieldOf() we can use.&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;someCodec.optionalFieldOf(&amp;quot;field_name&amp;quot;)&amp;lt;/code&amp;gt; creates a field for an Optional. If the field in the json/nbt is not present or invalid, it will deserialize as an empty optional. Empty optionals will not be serialized; the field will be omitted from the json or nbt.&lt;br /&gt;
* &amp;lt;code&amp;gt;someCodec.optionalFieldOf(&amp;quot;field_name&amp;quot;, someDefaultValue)&amp;lt;/code&amp;gt; creates an optional field that deserializes as the given default value if the field is not present in the json/nbt. When serializing, if the field in the java object equals the default value, the value will not be serialized and the field will be omitted from the json or nbt.&lt;br /&gt;
&lt;br /&gt;
When using optional fields, be wary that if the field contains bad data or otherwise fails to serialize, the error will be silently caught, and the field will serialize as the default value instead!&lt;br /&gt;
&lt;br /&gt;
===Boxing values as objects===&lt;br /&gt;
In some situations, we may need to serialize a single value as a single-field object. We can use fieldOf to box a single value in this way without needing the entire RecordCodecBuilder process:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
public static final Codec&amp;lt;Integer&amp;gt; BOXED_INT_CODEC = Codec.INT.fieldOf(&amp;quot;value&amp;quot;).codec();&lt;br /&gt;
&lt;br /&gt;
JsonElement value = BOXED_INT_CODEC.encodeStart(JsonOps.INSTANCE, 5).result().get();&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Which serializes the following output:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;json&amp;quot;&amp;gt;&lt;br /&gt;
{&amp;quot;value&amp;quot;:5}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Unit==&lt;br /&gt;
The &amp;lt;code&amp;gt;Codec.unit(defaultValue)&amp;lt;/code&amp;gt; codec creates a Codec that always deserializes a specified default value, regardless of input. When serializing, it serializes nothing.&lt;br /&gt;
&lt;br /&gt;
==Pair==&lt;br /&gt;
The &amp;lt;code&amp;gt;Codec.pair(codecA, codecB)&amp;lt;/code&amp;gt; static method takes two codecs and generates a Codec&amp;lt;Pair&amp;lt;A,B&amp;gt;&amp;gt; from them.&lt;br /&gt;
&lt;br /&gt;
The only valid arguments for this method are codecs that serialize to objects with explicit fields, such as codecs created using [[Codecs#Records|RecordCodecBuilder]] or [[Codecs#Boxing_values_as_objects|fieldOf]]. Codecs that serialize nothing (such as [[Codecs#Unit|unit codecs]]) are also valid as they act as objects-with-no-fields.&lt;br /&gt;
&lt;br /&gt;
The resulting Pair codec will serialize a single object that has all of the fields of the two original codecs. For example:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
public static final Codec&amp;lt;Pair&amp;lt;Integer,String&amp;gt;&amp;gt; PAIR_CODEC = Codec.pair(&lt;br /&gt;
	Codec.INT.fieldOf(&amp;quot;value&amp;quot;).codec(),&lt;br /&gt;
	Codec.STRING.fieldOf(&amp;quot;name&amp;quot;).codec());&lt;br /&gt;
&lt;br /&gt;
JsonElement encodedPair = PAIR_CODEC.encodeStart(JsonOps.INSTANCE, Pair.of(5, &amp;quot;cheese&amp;quot;).result().get();&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
This codec serializes the above value to:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;json&amp;quot;&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
	&amp;quot;value&amp;quot;: 5,&lt;br /&gt;
	&amp;quot;name&amp;quot;: &amp;quot;cheese&amp;quot;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Codecs that serialize to objects with undefined fields such as [[Codecs#Maps|unboundedMap]] may cause strange and unpredictable behaviour when used here; these objects should be boxed via fieldOf when used in a pair codec.&lt;br /&gt;
&lt;br /&gt;
==Either==&lt;br /&gt;
The &amp;lt;code&amp;gt;Codec.either(codecA, codecB)&amp;lt;/code&amp;gt; static method takes two codecs and generates a Codec&amp;lt;Either&amp;lt;A,B&amp;gt;&amp;gt; from them.&lt;br /&gt;
&lt;br /&gt;
When this codec is used to de/serialize an object, it first attempts to use the first codec; if and only if that conversion fails, it then attempts to use the second codec. If that conversion also fails, then the returned DataResult will contain the error data from the *second* codec's conversion attempt.&lt;br /&gt;
&lt;br /&gt;
==Numeric Ranges==&lt;br /&gt;
The &amp;lt;code&amp;gt;Codec.intRange(min,max)&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;Codec.floatRange(min,max)&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;Codec.doubleRange(min,max)&amp;lt;/code&amp;gt; static methods generate Codecs for Integers, Floats, or Doubles, respectively, for which only a specified inclusive range is valid, and values outside that range will fail to de/serialize.&lt;br /&gt;
&lt;br /&gt;
==Maps==&lt;br /&gt;
Suppose we want to serialize a HashMap or other Map type, where we could have indefinitely many key-value pairs and we don't know what the keys are ahead of time.&lt;br /&gt;
&lt;br /&gt;
We can create a &amp;lt;code&amp;gt;Codec&amp;lt;Map&amp;lt;KEY,VALUE&amp;gt;&amp;gt;&amp;lt;/code&amp;gt; using the &amp;lt;code&amp;gt;Codec.unboundedMap&amp;lt;/code&amp;gt; static method, which takes a key codec and a value codec and creates a codec for a map type:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
public static final Codec&amp;lt;Map&amp;lt;String, BlockPos&amp;gt;&amp;gt; = Codec.unboundedMap(Codec.STRING, BlockPos.CODEC);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The serialized form of maps serialized by this codec will be a JsonObject or CompoundTag, whose fields are the key-value pairs in the map; the map's keys will be used as the field names, and the map's values will be the values of those fields&lt;br /&gt;
&lt;br /&gt;
A limitation of using unboundedMap is that it only supports key codecs that serialize to Strings (including codecs for things like ResourceLocation that aren't Strings themselves but still serialize to strings). To create a codec for a Map whose keys are not fundamentally strings, the Map must be serialized as a list of key-value pairs instead of using unboundedMap.&lt;br /&gt;
&lt;br /&gt;
==Equivalent Types and xmap==&lt;br /&gt;
Suppose we have two java classes, Amalgam and Box; any Amalgam instance can be converted to a Box, and vice-versa. Now suppose we have a Codec&amp;lt;Amalgam&amp;gt;, but we'd also like to have a Codec&amp;lt;Box&amp;gt;. Rather than creating an entirely new codec for Box from scratch, we can simply xmap our Amalgam codec instead.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;Codec#xmap&amp;lt;/code&amp;gt; instance method is used to generate a second codec for a fundamentally equivalent type to the first codec's type. The method takes two function objects as arguments, which are used to convert the first type to the second when deserializing, and converting the second type to the first when serializing:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
public static final Codec&amp;lt;Box&amp;gt; = Amalgam.CODEC.xmap(Amalgam::toBox, Box::toAmalgam);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Codecs created in this manner will serialize objects in the same format as the starting codec.&lt;br /&gt;
&lt;br /&gt;
==Partially Equivalent Types, flatComapMap, comapFlatMap, and flatXMap==&lt;br /&gt;
Consider the ResourceLocation: Any ResourceLocation can be converted to a String, but not all Strings can be converted to a ResourceLocation; ResourceLocations have strict limits on their format and allowed characters.&lt;br /&gt;
&lt;br /&gt;
While we *could* use xmap to convert the Codec.STRING to a codec for ResourceLocations, this would cause attempts to parse an invalid string like &amp;lt;code&amp;gt;SHOUTY:MOD:Invalid$Characters&amp;lt;/code&amp;gt; to throw a runtime exception, when we really should be returning a failed DataResult to the parser instead -- which indeed is what the vanilla ResourceLocation codec does.&lt;br /&gt;
&lt;br /&gt;
Codecs have three additional instance methods for creating equivalent codecs for when we can *potentially* convert one type to another, but are not guaranteed to be able to do so. These take conversion function arguments that return DataResults, allowing validation to be performed during serialization and deserialization.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ Codec Conversion Methods&lt;br /&gt;
|-&lt;br /&gt;
! Can A always be converted to B? !! Can B always be converted to A? !! Which method of codecA should be used to create codecB?&lt;br /&gt;
|-&lt;br /&gt;
| yes || yes || codecA.xmap&lt;br /&gt;
|-&lt;br /&gt;
| yes || no || codecA.flatComapMap&lt;br /&gt;
|-&lt;br /&gt;
| no || yes || codecA.comapFlatMap&lt;br /&gt;
|-&lt;br /&gt;
| no || no || codecA.flatXmap&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Registry Dispatch ==&lt;br /&gt;
Registry Dispatch Codecs allow us to define a registry of codecs and delegate to a specific codec to deserialize a particular json based on a type field in that json. Dispatch codecs are used extensively when deserializing worldgen data.&lt;br /&gt;
&lt;br /&gt;
To create a dispatch codec for a Thing class, the following steps can be performed:&lt;br /&gt;
# Create a Thing abstract class class and ThingType interface. The ThingType interface should have a method that supplies a Codec&amp;lt;Thing&amp;gt;, while Thing subclasses must define a method that supplies a ThingType.&lt;br /&gt;
# Create a map or registry of ThingTypes, and register a ThingType for each sub-codec we want to have.&lt;br /&gt;
# Create a Codec&amp;lt;ThingType&amp;gt;, or have the ThingType registry implement Codec.&lt;br /&gt;
# Create our Codec&amp;lt;Thing&amp;gt; master codec by invoking &amp;lt;code&amp;gt;Codec#dispatch&amp;lt;/code&amp;gt; on our ThingType codec. This method's arguments are:&lt;br /&gt;
## A field name for the ID of the sub-codec (the example json below is using &amp;quot;type&amp;quot;)&lt;br /&gt;
## A function to retrieve a ThingType from a Thing&lt;br /&gt;
## A function to retrieve a Codec&amp;lt;Thing&amp;gt; from a ThingType&lt;br /&gt;
&lt;br /&gt;
We can then use our Codec&amp;lt;Thing&amp;gt; to create Thing fields in other codecs whose serialized format depends on the specific sub-codec used by a Thing instance.&lt;br /&gt;
&lt;br /&gt;
As an example of this, consider the ExampleCodecClass earlier. Suppose we make this class extend Thing and register our codec for it to a codec dispatch registry with the id &amp;quot;ourmod:exampleclass&amp;quot;. If we were to define an instance of this class in a Thing field in some json, it would look like&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;json&amp;quot;&amp;gt;&lt;br /&gt;
&amp;quot;some_thing&amp;quot;:&lt;br /&gt;
{&lt;br /&gt;
	&amp;quot;type&amp;quot;: &amp;quot;ourmod:exampleclass&amp;quot;,&lt;br /&gt;
	&amp;quot;some_int&amp;quot;: 42,&lt;br /&gt;
	&amp;quot;item&amp;quot;: &amp;quot;minecraft:gold_ingot&amp;quot;,&lt;br /&gt;
	&amp;quot;block_positions&amp;quot;:&lt;br /&gt;
	[&lt;br /&gt;
		[0,0,0],&lt;br /&gt;
		[10,20,-100]&lt;br /&gt;
	]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Other ThingTypes we register would have different fields in this json object, but would still be valid for the &amp;quot;some_thing&amp;quot; field.&lt;br /&gt;
&lt;br /&gt;
Several examples of vanilla classes that use dispatch codecs:&lt;br /&gt;
* RuleTest and RuleTestType&lt;br /&gt;
* BlockPlacer and BlockPlacerType&lt;br /&gt;
* ConfiguredDecorator and FeatureDecorator&lt;br /&gt;
&lt;br /&gt;
=== Registering MapCodecCodecs for Dispatch Subcodecs ===&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
For example, suppose we register a single-field subcodec, where we use fieldOf-and-xmap to convert an int to our int-holding Thing:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
public record Thing(int n){}&lt;br /&gt;
public static Codec&amp;lt;Thing&amp;gt; CODEC = Codec.INT.fieldOf(&amp;quot;n&amp;quot;).codec().xmap(Thing::new, Thing::n);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This results in this json when serialized:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;json&amp;quot;&amp;gt;&lt;br /&gt;
&amp;quot;some_thing&amp;quot;:&lt;br /&gt;
{&lt;br /&gt;
	&amp;quot;type&amp;quot;: &amp;quot;ourmod:thing&amp;quot;,&lt;br /&gt;
	&amp;quot;value&amp;quot;: {&lt;br /&gt;
		&amp;quot;n&amp;quot;: 5&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
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:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
public static Codec&amp;lt;Thing&amp;gt; CODEC = Codec.INT // Primitive codec&lt;br /&gt;
	.fieldOf(&amp;quot;n&amp;quot;) // MapCodec&lt;br /&gt;
	.xmap(Thing::new, Thing::n) // MapCodec&lt;br /&gt;
	.codec(); // MapCodecCodec! That's what we want.&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;json&amp;quot;&amp;gt;&lt;br /&gt;
&amp;quot;some_thing&amp;quot;:&lt;br /&gt;
{&lt;br /&gt;
	&amp;quot;type&amp;quot;: &amp;quot;ourmod:thing&amp;quot;,&lt;br /&gt;
	&amp;quot;n&amp;quot;: 5&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
RecordCodecBuilder also produces MapCodecCodecs.&lt;br /&gt;
&lt;br /&gt;
=External Links=&lt;br /&gt;
* [https://github.com/Mojang/DataFixerUpper/blob/master/src/main/java/com/mojang/serialization/Codec.java Codecs in Mojang's official public DataFixerUpper repository]&lt;br /&gt;
* [https://kvverti.github.io/Documented-DataFixerUpper/snapshot/com/mojang/serialization/Codec.html#flatXmap-java.util.function.Function-java.util.function.Function- Unofficial Codec Javadocs]&lt;/div&gt;</summary>
		<author><name>Commoble</name></author>
	</entry>
	<entry>
		<id>https://forge.gemwire.uk/index.php?title=Biome_Modifiers&amp;diff=3320</id>
		<title>Biome Modifiers</title>
		<link rel="alternate" type="text/html" href="https://forge.gemwire.uk/index.php?title=Biome_Modifiers&amp;diff=3320"/>
		<updated>2022-09-04T17:43:12Z</updated>

		<summary type="html">&lt;p&gt;Commoble: Add warning about adding feature with multiple biome modifiers to best practices&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Biome Modifiers are a data-driven system for modifying biomes. They have the ability to modify biomes in several ways:&lt;br /&gt;
&lt;br /&gt;
* Adding or removing worldgen features and carvers&lt;br /&gt;
* Adding or removing mob spawns and mob spawn costs&lt;br /&gt;
* Modifying the climate of a biome&lt;br /&gt;
* Modifying a biome's client effects, such as water color&lt;br /&gt;
&lt;br /&gt;
&amp;lt;big&amp;gt;'''NOTE:'''&amp;lt;/big&amp;gt; Forge provides several [[#Builtin_Biome_Modifier_Types|builtin biome modifier types]], so some basic use cases such as adding features or mob spawns to biomes can be done without registering additional serializers. If you are looking to add a mob or feature to a biome, scroll down to the [[#Builtin_Biome_Modifier_Types|Builtin Biome Modifier Types]] section and use one of those pre-existing Biome Modifiers from Forge instead. No custom Biome Modifier implementation needed.&lt;br /&gt;
&lt;br /&gt;
Creating and using biome modifiers involves up to three steps:&lt;br /&gt;
&lt;br /&gt;
# Creating a [[#Biome_Modifier_Type|biome modifier type]], which defines how to modify a biome.&lt;br /&gt;
# Registering a [[#Biome_Modifier_Serializers|biome modifier codec]], which defines how to parse a json into your biome modifier type.&lt;br /&gt;
# Creating [[#Biome_Modifier_JSONs|biome modifier JSONs]] to define individual biome modifier instances; each json file provides a glob of data to your serializer to produce an instance of a biome modifier type. These can be [[#Datageneration|datagenerated]] if desired.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Biome Modifier Types=&lt;br /&gt;
To define a new type of biome modifier, begin by implementing a new class that extends &amp;lt;code&amp;gt;BiomeModifier&amp;lt;/code&amp;gt;. BiomeModifiers can usually be implemented as records, to reduce boilerplate.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
public record ExampleBiomeModifier() implements BiomeModifier&lt;br /&gt;
{&lt;br /&gt;
  public void modify(Holder&amp;lt;Biome&amp;gt; biome, Phase phase, Builder builder)&lt;br /&gt;
  {&lt;br /&gt;
    // This allows modifications to the given biome via the provided Builder.&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  public Codec&amp;lt;? extends BiomeModifier&amp;gt; codec()&lt;br /&gt;
  {&lt;br /&gt;
    // This must return a registered Codec, see Biome Modifier Serializers below.&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Beware! The modify method is called once per each phase per biome per biome modifier, so it's important to check which phase you're in and only make your changes in one phase.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
public void modify(Holder&amp;lt;Biome&amp;gt; biome, Phase phase, Builder builder)&lt;br /&gt;
{&lt;br /&gt;
  if (phase == Phase.ADD)&lt;br /&gt;
  {&lt;br /&gt;
    // add things to biomes&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Typically we also want to restrict biome modifiers to only apply to certain biomes. We can do that by accepting a HolderSet&amp;lt;biome&amp;gt; in our constructor:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
public record ExampleBiomeModifier(HolderSet&amp;lt;Biome&amp;gt; biomes) implements BiomeModifier&lt;br /&gt;
{&lt;br /&gt;
  public void modify(Holder&amp;lt;Biome&amp;gt; biome, Phase phase, Builder builder)&lt;br /&gt;
  {&lt;br /&gt;
    if (phase == Phase.ADD &amp;amp;&amp;amp; biomes.contains(biome))&lt;br /&gt;
    {&lt;br /&gt;
      // add things to biomes&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We can also accept [[Holders]] or [[HolderSets|HolderSets]] for other [[Registration#Data_Driven_Entries|datapack registry elements]], such as PlacedFeatures, which allows our BiomeModifier to refer to those elements, which can then be defined in their own JSON files.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
public record ExampleBiomeModifier(HolderSet&amp;lt;Biome&amp;gt; biomes, Holder&amp;lt;PlacedFeature&amp;gt; feature) implements BiomeModifier&lt;br /&gt;
{&lt;br /&gt;
  public void modify(Holder&amp;lt;Biome&amp;gt; biome, Phase phase, Builder builder)&lt;br /&gt;
  {&lt;br /&gt;
    // add a feature to all specified biomes&lt;br /&gt;
    if (phase == Phase.ADD &amp;amp;&amp;amp; biomes.contains(biome))&lt;br /&gt;
    {&lt;br /&gt;
      builder.getGenerationSettings().addFeature(Decoration.UNDERGROUND_ORES, feature);&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;/biome&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Biome Modifier Serializers =&lt;br /&gt;
&lt;br /&gt;
Each type of biome modifier must have a [[Codecs|Codec]] registered for it; [[Registration#DeferredRegister|Deferred Registers]] are the recommended way to register biome modifier codecs.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
public class YourMod&lt;br /&gt;
{&lt;br /&gt;
  static DeferredRegister&amp;lt;Codec&amp;lt;? extends BiomeModifier&amp;gt;&amp;gt; BIOME_MODIFIER_SERIALIZERS =&lt;br /&gt;
    DeferredRegister.create(ForgeRegistries.Keys.BIOME_MODIFIER_SERIALIZERS, &amp;quot;yourmodid&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
  static RegistryObject&amp;lt;Codec&amp;lt;ExampleBiomeModifier&amp;gt;&amp;gt; EXAMPLE_CODEC = BIOME_MODIFIER_SERIALIZERS.register(&amp;quot;example&amp;quot;, () -&amp;gt;&lt;br /&gt;
    RecordCodecBuilder.create(builder -&amp;gt; builder.group(&lt;br /&gt;
        // declare fields&lt;br /&gt;
        Biome.LIST_CODEC.fieldOf(&amp;quot;biomes&amp;quot;).forGetter(ExampleBiomeModifier::biomes),&lt;br /&gt;
        PlacedFeature.CODEC.fieldOf(&amp;quot;feature&amp;quot;).forGetter(ExampleBiomeModifier::feature)&lt;br /&gt;
      // declare constructor&lt;br /&gt;
      ).apply(builder, ExampleBiomeModifier::new)));&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We can now implement the codec() method in our biome modifier class:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
public record ExampleBiomeModifier(HolderSet&amp;lt;Biome&amp;gt; biomes, Holder&amp;lt;PlacedFeature&amp;gt; feature) implements BiomeModifier&lt;br /&gt;
{&lt;br /&gt;
  public void modify(Holder&amp;lt;Biome&amp;gt; biome, Phase phase, Builder builder)&lt;br /&gt;
  {&lt;br /&gt;
    // add a feature to all specified biomes&lt;br /&gt;
    if (phase == Phase.ADD &amp;amp;&amp;amp; biomes.contains(biome))&lt;br /&gt;
    {&lt;br /&gt;
      builder.getGenerationSettings().addFeature(Decoration.UNDERGROUND_ORES, feature);&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  public Codec&amp;lt;? extends BiomeModifier&amp;gt; codec()&lt;br /&gt;
  {&lt;br /&gt;
    return YourMod.EXAMPLE_CODEC.get();&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Biome Modifier JSONs =&lt;br /&gt;
&lt;br /&gt;
Once we've registered a codec for our biome modifier type, we can define jsons for it. Biome modifier jsons must be defined in the directory &amp;lt;code&amp;gt;data/modid/forge/biome_modifier/&amp;lt;/code&amp;gt;; a biome modifier at &amp;lt;code&amp;gt;data/modid/forge/biome_modifier/your_biome_modifier.json&amp;lt;/code&amp;gt; has the namespaced id &amp;lt;code&amp;gt;modid:your_biome_modifier&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Our codec above defines the json format:&lt;br /&gt;
&lt;br /&gt;
* &amp;quot;biomes&amp;quot; is a special HolderSet field that accepts a single biome id, [list of biome ids], or #biome_tag.&lt;br /&gt;
* &amp;quot;feature&amp;quot; accepts a single placed feature id. [https://minecraft.fandom.com/wiki/Placed_feature These can be defined in jsons as well].&lt;br /&gt;
* We must also specify &amp;quot;type&amp;quot;: &amp;quot;yourmodid:example&amp;quot; to tell the data loader to use our registered codec to read our json.&lt;br /&gt;
&lt;br /&gt;
A json instance of our biome modifier that adds some feature to badlands biomes might look like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;json&amp;quot;&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;type&amp;quot;: &amp;quot;yourmodid:example&amp;quot;,&lt;br /&gt;
  &amp;quot;biomes&amp;quot;: &amp;quot;#minecraft:is_badlands&amp;quot;,&lt;br /&gt;
  &amp;quot;feature&amp;quot;: &amp;quot;yourmod:some_feature&amp;quot;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Datageneration =&lt;br /&gt;
&lt;br /&gt;
Biome Modifier jsons can be [[Datageneration|datagenerated via GatherDataEvent]]. As biome modifiers are datapack registry objects, this can be done by using JsonCodecProvider#forDatapackRegistry as the data provider. Refer to [[Datageneration/Datapack_Registries]] for additional information on datagenerating datapack registry elements.&lt;br /&gt;
&lt;br /&gt;
= Builtin Biome Modifier Types =&lt;br /&gt;
&lt;br /&gt;
Forge provides the following builtin biome modifier types:&lt;br /&gt;
&lt;br /&gt;
== None ==&lt;br /&gt;
&lt;br /&gt;
A no-op biome modifier type, whose jsons have the following format:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;json&amp;quot;&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;type&amp;quot;: &amp;quot;forge:none&amp;quot;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This allows pack devs or server operators to disable mods' biome modifiers by overriding their biome modifier jsons with the above.&lt;br /&gt;
&lt;br /&gt;
== Add Features ==&lt;br /&gt;
&lt;br /&gt;
This biome modifier type adds placed features to biomes.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;json&amp;quot;&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;type&amp;quot;: &amp;quot;forge:add_features&amp;quot;, // required&lt;br /&gt;
  &amp;quot;biomes&amp;quot;: &amp;quot;#namespace:your_biome_tag&amp;quot;, // accepts a biome id, [list of biome ids], or #namespace:biome_tag&lt;br /&gt;
  &amp;quot;features&amp;quot;: &amp;quot;namespace:your_feature&amp;quot;, // accepts a placed feature id, [list of placed feature ids], or #namespace:feature_tag&lt;br /&gt;
  &amp;quot;step&amp;quot;: &amp;quot;underground_ores&amp;quot; // accepts a Decoration enum name&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Decoration steps in order of generation are:&lt;br /&gt;
* raw_generation&lt;br /&gt;
* lakes&lt;br /&gt;
* local_modifications&lt;br /&gt;
* underground_structures&lt;br /&gt;
* surface_structures&lt;br /&gt;
* underground_ores&lt;br /&gt;
* underground_decoration&lt;br /&gt;
* fluid_springs&lt;br /&gt;
* vegetal_decoration&lt;br /&gt;
* top_layer_modification&lt;br /&gt;
&lt;br /&gt;
== Remove Features ==&lt;br /&gt;
&lt;br /&gt;
This biome modifier type removes features from biomes.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;json&amp;quot;&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;type&amp;quot;: &amp;quot;forge:remove_features&amp;quot;, // required&lt;br /&gt;
  &amp;quot;biomes&amp;quot;: &amp;quot;#namespace:your_biome_tag&amp;quot;, // accepts a biome id, [list of biome ids], or #namespace:biome_tag&lt;br /&gt;
  &amp;quot;features&amp;quot;: &amp;quot;namespace:your_feature&amp;quot;, // accepts a placed feature id, [list of placed feature ids], or #namespace:feature_tag&lt;br /&gt;
  &amp;quot;steps&amp;quot;: &amp;quot;underground_ores&amp;quot; // optional field specifying a Decoration or list of Decorations to remove features from, defaults to all if not specified&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Add Spawns ==&lt;br /&gt;
&lt;br /&gt;
This biome modifier type adds mob spawns to biomes.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;json&amp;quot;&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;type&amp;quot;: &amp;quot;forge:add_spawns&amp;quot;, // Required&lt;br /&gt;
  &amp;quot;biomes&amp;quot;: &amp;quot;#namespace:biome_tag&amp;quot;, // Accepts a biome id, [list of biome ids], or #namespace:biome_tag&lt;br /&gt;
  &amp;quot;spawners&amp;quot;:&lt;br /&gt;
  {&lt;br /&gt;
    &amp;quot;type&amp;quot;: &amp;quot;namespace:entity_type&amp;quot;, // Type of mob to spawn&lt;br /&gt;
    &amp;quot;weight&amp;quot;: 100, // int, spawn weighting&lt;br /&gt;
    &amp;quot;minCount&amp;quot;: 1, // int, minimum pack size&lt;br /&gt;
    &amp;quot;maxCount&amp;quot;: 4 // int, maximum pack size&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Remove Spawns ==&lt;br /&gt;
&lt;br /&gt;
This biome modifier type removes mob spawns from biomes.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;json&amp;quot;&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;type&amp;quot;: &amp;quot;forge:remove_spawns&amp;quot;, // Required&lt;br /&gt;
  &amp;quot;biomes&amp;quot;: &amp;quot;#namespace:biome_tag&amp;quot;, // Accepts a biome id, [list of biome ids], or #namespace:biome_tag&lt;br /&gt;
  &amp;quot;entity_types&amp;quot;: &amp;quot;#namespace:entitytype_tag&amp;quot; // Accepts an entity type, list, or tag of entitytypes whose spawns are to be removed from the biomes&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Best Practices =&lt;br /&gt;
&lt;br /&gt;
* Avoid using biome modifiers to add vanilla placed features to biomes, as this may cause a feature cycle violation (the game will crash if two biomes have the same two features in their feature lists but in different orders). Placed features can be referenced in biome jsons or added via biome modifiers, but should not be used in both.&lt;br /&gt;
* Avoid adding the same placed feature with more than one biome modifier, as this can cause feature cycle violations.&lt;/div&gt;</summary>
		<author><name>Commoble</name></author>
	</entry>
	<entry>
		<id>https://forge.gemwire.uk/index.php?title=Holders&amp;diff=3304</id>
		<title>Holders</title>
		<link rel="alternate" type="text/html" href="https://forge.gemwire.uk/index.php?title=Holders&amp;diff=3304"/>
		<updated>2022-08-13T16:44:31Z</updated>

		<summary type="html">&lt;p&gt;Commoble: fix italics markup&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Holders are a component of vanilla registries representing a registrable value and/or the identifier of that value; they vaguely resemble a vanilla implementation of RegistryObjects, but with substantial semantic and implementation differences. They are used extensively by [[Tags|tags]] and [[Registration#Data_Driven_Entries|datapack registries]]; modders that use these systems should be aware of their functions and caveats.&lt;br /&gt;
&lt;br /&gt;
Datapack registry elements can have reference to HolderSets, which can use tag references to define sets of registry elements.&lt;br /&gt;
&lt;br /&gt;
== Holders == &lt;br /&gt;
&lt;br /&gt;
=== Properties of Holders ===&lt;br /&gt;
&lt;br /&gt;
Holders in general have the following properties:&lt;br /&gt;
* A holder may or may not have a key (a ResourceLocation/ResourceKey identifying the holder/value by name)&lt;br /&gt;
* A holder may or may not have a value (e.g. a block or a biome)&lt;br /&gt;
* A holder may or may not belong to a specific registry instance&lt;br /&gt;
* A holder may or may not be a mutable object&lt;br /&gt;
* A holder is associated with zero or more tags&lt;br /&gt;
&lt;br /&gt;
=== Types of Holder ===&lt;br /&gt;
&lt;br /&gt;
There are three categories of holders: direct holders, standalone reference holders, and intrusive reference holders.&lt;br /&gt;
&lt;br /&gt;
==== Direct Holders ====&lt;br /&gt;
&lt;br /&gt;
Direct holders always hold an unregistered value, and never hold a key. Direct holders are generally created when a datapack registry json inline-defines a value in a holder field instead of declaring a reference to another json. Direct holders are immutable records, and never have tags bound to them.&lt;br /&gt;
&lt;br /&gt;
A vanilla example of direct holders being used is in density functions; density functions are often composed of holders of other density functions, but the child functions themselves don't need to be registered, and so many vanilla density functions are created with inline/direct child functions.&lt;br /&gt;
&lt;br /&gt;
Direct holders should not be created for values that must always exist in the registry, or for values whose registry names must be determined at some point.&lt;br /&gt;
&lt;br /&gt;
==== Reference Holders ====&lt;br /&gt;
&lt;br /&gt;
Reference holders refer to registered values; they are created with either a key or a value, with the other property being bound to them later in the registration process. Reference holders belong to a specific registry instance and are aware of which registry they belong to (if multiple copies of a registry exist, as is the case for datapack registries, a reference holder is only valid for a single instance of that registry).&lt;br /&gt;
&lt;br /&gt;
Reference holders are mutable and may have tags bound to them.&lt;br /&gt;
&lt;br /&gt;
===== Standalone Reference Holders =====&lt;br /&gt;
&lt;br /&gt;
Most holders encountered will be standalone reference holders; they are created with a key, and have a value bound to them later. Each registry has at most one standalone reference holder per key; parsing a reference holder in a datapack registry json computes a holder in the relevant registry if it doesn't already exist.&lt;br /&gt;
&lt;br /&gt;
Standalone reference holders are the means by which datapack registry jsons can refer to each other. They have the following lifecycle:&lt;br /&gt;
&lt;br /&gt;
* A datapack registry json is loaded that refers to another registrable by id, e.g. &amp;quot;minecraft:desert&amp;quot;&lt;br /&gt;
* A standalone reference holder is retrieved from the relevant registry via a get-or-create operation&lt;br /&gt;
* When a datapack registry json is loaded and fully parsed, a holder for that json is get-or-created ''and'' the parsed value is bound to it&lt;br /&gt;
* When registries freeze, the get-or-create operation can no longer create new holders. If any reference holders in the registry are not fully bound at this time (with both a key and a value), an error is raised. This will occur if a datapack registry json refers by id to another datapack registry json that does not exist, and is how these references-by-id are validated.&lt;br /&gt;
* Whenever tags load, each tag file's TagKey is bound to all reference holders referred to in that tag (this modifiers the holders in-place).&lt;br /&gt;
&lt;br /&gt;
When datagenerating datapack registry jsons with reference holders, any reference holders ''must'' be created by the specific registry instances used by the RegistryOps/RegistryAccess used to datagen the jsons, or they will fail to serialize.&lt;br /&gt;
&lt;br /&gt;
===== Intrusive Reference Holders =====&lt;br /&gt;
&lt;br /&gt;
Intrusive reference holders are created with a value and have a key bound to them later. Several static registrable types (blocks, items, fluids, entitytypes, and gameevents) create intrusive holders of themselves when constructed, which have a value bound to them once the value is registered.&lt;br /&gt;
&lt;br /&gt;
Intrusive holders and the means of creating them are deprecated by mojang; this seems to be a hack to allow blocks and friends to quickly look up their registry name. Intrusive holders may be removed in future minecraft releases, and should not be used by mods (value-&amp;gt;key lookups can be done via a method in the relevant registry, or by creating standalone holders or RegistryObjects to create name-value pairs).&lt;br /&gt;
&lt;br /&gt;
== HolderSets ==&lt;br /&gt;
&lt;br /&gt;
A HolderSet is an indexable set of holders, and is the preferred means by which datapack registrables can refer to other datapack registrables. Vanilla frequently uses holdersets to wire worldgen jsons together, e.g. a structure json has a holderset field for which biomes the structure can spawn in.&lt;br /&gt;
&lt;br /&gt;
Vanilla has two types of holdersets and three json formats; forge expands the holderset serializer to allow additional types of holdersets. A holderset field in a json can accept a single element, a list of elements, a tag ID, or one of forge's special formats, making datapack creation very flexible when holderset fields are used.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;json&amp;quot;&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;a_biome&amp;quot;: &amp;quot;desert&amp;quot;, // single element holderset&lt;br /&gt;
  &amp;quot;some_biomes&amp;quot;: [&amp;quot;plains&amp;quot;, &amp;quot;forest&amp;quot;], // list holderset&lt;br /&gt;
  &amp;quot;biome_tag&amp;quot;: &amp;quot;#is_plains&amp;quot;, // tag holderset&lt;br /&gt;
  &amp;quot;expanded_forge_format&amp;quot;: // more on these later&lt;br /&gt;
  {&lt;br /&gt;
    &amp;quot;type&amp;quot;: &amp;quot;modid:custom_holderset_type&amp;quot;,&lt;br /&gt;
    // additional fields as specified by the type&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Codecs]] can be created for holdersets to allow holdersets to be read from jsons; however, a holderset codec must be created for each registry holdersets can be made for, e.g. Biome.LIST_OF_LISTS_CODEC is the codec for HolderSet&amp;lt;Biome&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
HolderSets should generally only be serialized when used as components of unsynced (server-only) datapack registry jsons, such as in worldgen features. HolderSets that are serialized without RegistryOps for registry context (including when synced to clients in synced datapack registries, which do not serialize with registry context) will be deserialized as lists of unregistered objects.&lt;br /&gt;
&lt;br /&gt;
=== Types of HolderSets ===&lt;br /&gt;
&lt;br /&gt;
==== Direct HolderSets ====&lt;br /&gt;
&lt;br /&gt;
Direct HolderSets represent an immutable list of holders. They can be defined in json as single elements or lists of elements (the single element format simply parses as a list holderset with one element in it).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;json&amp;quot;&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;a_biome&amp;quot;: &amp;quot;desert&amp;quot;, // single element holderset&lt;br /&gt;
  &amp;quot;some_biomes&amp;quot;: [&amp;quot;plains&amp;quot;, &amp;quot;forest&amp;quot;], // list holderset&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Named HolderSets ====&lt;br /&gt;
&lt;br /&gt;
Named HolderSets represent a tag. Named HolderSets are mutable; they cache a list and a set of holders, and this cache is reset each time tags reload.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;json&amp;quot;&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;biome_tag&amp;quot;: &amp;quot;#is_plains&amp;quot;, // tag holderset&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Custom HolderSet Types ====&lt;br /&gt;
&lt;br /&gt;
Forge expands the holderset codecs to allow additional json formats. Custom holderset serializers can be registered by creating a deferred register for ForgeRegistries.Keys.HOLDER_SET_TYPES, though the builtin types provided by forge should be sufficient for most use cases.&lt;br /&gt;
&lt;br /&gt;
====Builtin Custom HolderSet Types====&lt;br /&gt;
Forge provides four builtin holderset types, allowing for additional set operations and representations in datapack registry jsons. The &amp;lt;code&amp;gt;and&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;or&amp;lt;/code&amp;gt;, &lt;br /&gt;
and &amp;lt;code&amp;gt;not&amp;lt;/code&amp;gt; types are composed of other holdersets, and are therefore potentially mutable as they may be composed of mutable tag holdersets whose values are recalculated after tags reload.&lt;br /&gt;
=====Any=====&lt;br /&gt;
The &amp;lt;code&amp;gt;forge:any&amp;lt;/code&amp;gt; holderset type represents the set of all elements of the relevant registry.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;json&amp;quot;&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;biomes&amp;quot;:&lt;br /&gt;
  {&lt;br /&gt;
    &amp;quot;type&amp;quot;: &amp;quot;forge:any&amp;quot;&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=====And=====&lt;br /&gt;
The &amp;lt;code&amp;gt;forge:and&amp;lt;/code&amp;gt; type represents an intersection of other holdersets.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;json&amp;quot;&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;biomes&amp;quot;:&lt;br /&gt;
  {&lt;br /&gt;
    &amp;quot;type&amp;quot;: &amp;quot;forge:and&amp;quot;,&lt;br /&gt;
    &amp;quot;values&amp;quot;:&lt;br /&gt;
    [&lt;br /&gt;
      // list of holdersets of any format, different formats (string, list, object) can be mixed here&lt;br /&gt;
      &amp;quot;#is_plains&amp;quot;,&lt;br /&gt;
      &amp;quot;#is_overworld&amp;quot;&lt;br /&gt;
    ]&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
=====Or=====&lt;br /&gt;
The &amp;lt;code&amp;gt;forge:or&amp;lt;/code&amp;gt; type represents a union of other holdersets.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;json&amp;quot;&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;biomes&amp;quot;:&lt;br /&gt;
  {&lt;br /&gt;
    &amp;quot;type&amp;quot;: &amp;quot;forge:or&amp;quot;,&lt;br /&gt;
    &amp;quot;values&amp;quot;:&lt;br /&gt;
    [&lt;br /&gt;
      // list of holdersets of any format, different formats (string, list, object) can be mixed here&lt;br /&gt;
      &amp;quot;#is_plains&amp;quot;,&lt;br /&gt;
      [&amp;quot;swamp&amp;quot;, &amp;quot;mangrove_swamp&amp;quot;]&lt;br /&gt;
    ]&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
=====Not=====&lt;br /&gt;
The &amp;lt;code&amp;gt;forge:not&amp;lt;/code&amp;gt; type represents the set of all elements in the registry that do not belong to the specified holderset.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;json&amp;quot;&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;biomes&amp;quot;:&lt;br /&gt;
  {&lt;br /&gt;
    &amp;quot;type&amp;quot;: &amp;quot;forge:not&amp;quot;,&lt;br /&gt;
    &amp;quot;value&amp;quot;: &amp;quot;#is_plains&amp;quot; // holderset of any format (string, list, or object)&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>Commoble</name></author>
	</entry>
	<entry>
		<id>https://forge.gemwire.uk/index.php?title=Main_Page&amp;diff=3302</id>
		<title>Main Page</title>
		<link rel="alternate" type="text/html" href="https://forge.gemwire.uk/index.php?title=Main_Page&amp;diff=3302"/>
		<updated>2022-08-13T15:41:03Z</updated>

		<summary type="html">&lt;p&gt;Commoble: Add link to holders&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__NOTOC__&lt;br /&gt;
&amp;lt;templatestyles src=&amp;quot;:Main_Page/styles.css&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;center title&amp;quot;&amp;gt;Forge Community Wiki&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The Forge Community Wiki exists so that the community can:&lt;br /&gt;
&lt;br /&gt;
* collectively keep track of major changes and updates to Forge and Vanilla code;&lt;br /&gt;
* create and edit articles with in-depth explanations about a variety of Forge-related subjects; and&lt;br /&gt;
* contribute example code and tutorials for both simple and difficult concepts.&lt;br /&gt;
&lt;br /&gt;
This wiki is editable by any registered user with an account. This is to allow tracking of harmful edits, but isn't imposing any annoying limits. We welcome any edit, however small. Join the [https://discord.gg/Nn42eAh Discord] to discuss changes and edits to the wiki with others and the staff.&lt;br /&gt;
&lt;br /&gt;
{{Supported versions}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;center round_warning&amp;quot;&amp;gt;&lt;br /&gt;
Please read the [[FCWMeta:Wiki Policy|wiki policy]] before editing!&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;center&amp;quot; style=&amp;quot;margin-bottom: 2em&amp;quot;&amp;gt;&lt;br /&gt;
{{Supported versions|text=1}}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;box_container center&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;box&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;h3&amp;gt;Beginner Topics&amp;lt;/h3&amp;gt;&lt;br /&gt;
* [[Getting Started]]&lt;br /&gt;
* [[Proper Mod Structuring]]&lt;br /&gt;
* [[Mods.toml file]]&lt;br /&gt;
* [[Debug Profiler|The Debug Profiler]]&lt;br /&gt;
* [[Version Checker]]&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;box&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;h3&amp;gt;Advanced Topics&amp;lt;/h3&amp;gt;&lt;br /&gt;
* [[Jar-in-jar]]&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;box&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;h3&amp;gt;Common Concepts&amp;lt;/h3&amp;gt;&lt;br /&gt;
* [[Sides|Understanding Sides]]&lt;br /&gt;
* [[Events|Understanding Events]]&lt;br /&gt;
* [[Registration]]&lt;br /&gt;
* [[Internationalization]]&lt;br /&gt;
* [[Configs]]&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;box&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;h3&amp;gt;Forge Conventions&amp;lt;/h3&amp;gt;&lt;br /&gt;
* [[Semantic Versioning]]&lt;br /&gt;
* [[Stages of Modloading]]&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;box&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;h3&amp;gt;Resources and Data&amp;lt;/h3&amp;gt;&lt;br /&gt;
* [[Using Resources|Introduction]]&lt;br /&gt;
* [[Recipes]]&lt;br /&gt;
* [[Tags]]&lt;br /&gt;
* [[Holders]]&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;box&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;h3&amp;gt;Blocks&amp;lt;/h3&amp;gt;&lt;br /&gt;
* [[Making Blocks|Creating Blocks]]&lt;br /&gt;
* [[Understanding Blockstates]] &lt;br /&gt;
* [[Interacting With Blocks|Block Interactions]]&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;box&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;h3&amp;gt;Items&amp;lt;/h3&amp;gt;&lt;br /&gt;
* [[Making Items]]&lt;br /&gt;
* [[Making Tools]]&lt;br /&gt;
* [[BlockEntityWithoutLevelRenderer|&amp;lt;tt&amp;gt;BlockEntityWithoutLevelRenderer&amp;lt;/tt&amp;gt;]]&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;box&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;h3&amp;gt;Data Generation&amp;lt;/h3&amp;gt;&lt;br /&gt;
* [[Datageneration|Introduction]]&lt;br /&gt;
* [[Datageneration/Recipes|Recipes]]&lt;br /&gt;
* [[Datageneration/Tags|Tags]]&lt;br /&gt;
* [[Datageneration/Loot_Tables|Loot Tables]]&lt;br /&gt;
* [[Datageneration/I18n|Localization]]&lt;br /&gt;
* [[Datageneration/States and Models|&amp;lt;tt&amp;gt;BlockState&amp;lt;/tt&amp;gt;s and Models]]&lt;br /&gt;
* [[Datageneration/Datapack_Registries|Datapack Registries]]&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;box&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;h3&amp;gt;Block Entities&amp;lt;/h3&amp;gt;&lt;br /&gt;
* [[Block Entities|Introduction]]&lt;br /&gt;
* [[Block Entity Renderer|&amp;lt;tt&amp;gt;BlockEntityRenderer&amp;lt;/tt&amp;gt;]]&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;box&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;h3&amp;gt;Models&amp;lt;/h3&amp;gt;&lt;br /&gt;
* [[Introduction to Models|Introduction]]&lt;br /&gt;
* [[Model JSONs]]&lt;br /&gt;
* [[BlockState JSONs]]&lt;br /&gt;
* [[Coloring textures dynamically|Dynamically Colored Textures]]&lt;br /&gt;
* [[Item Properties]]&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;box&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;h3&amp;gt;Handling Information&amp;lt;/h3&amp;gt;&lt;br /&gt;
* [[Understanding Networking|Introduction]]&lt;br /&gt;
* [[Using NBT|Named Binary Tag (NBT)]]&lt;br /&gt;
* [[Using FriendlyByteBuf|Using &amp;lt;tt&amp;gt;FriendlyByteBuf&amp;lt;/tt&amp;gt;]]&lt;br /&gt;
* [[Sending Packets|Sending and Receiving Packets]]&lt;br /&gt;
* [[Using SimpleChannel|Using &amp;lt;tt&amp;gt;SimpleChannel&amp;lt;/tt&amp;gt;]]&lt;br /&gt;
* [[Networking with Entities]]&lt;br /&gt;
* [[DynamicOps|Using DynamicOps]]&lt;br /&gt;
* [[Codecs|Using Codecs]]&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;box&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;h3&amp;gt;Data Storage&amp;lt;/h3&amp;gt;&lt;br /&gt;
* [[Capabilities|Understanding Capabilities]] &lt;br /&gt;
* [[Capabilities/Attaching|Attaching Capabilities]]&lt;br /&gt;
* [[Saved Data]]&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;box&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;h3&amp;gt;Game Effects&amp;lt;/h3&amp;gt;&lt;br /&gt;
* [[Mob Effects]]&lt;br /&gt;
* [[Potions]]&lt;br /&gt;
* [[Particles]]&lt;br /&gt;
* [[Sounds]]&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;box&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;h3&amp;gt;Events&amp;lt;/h3&amp;gt;&lt;br /&gt;
* [[Events|Understanding Events]]&lt;br /&gt;
* [[Entity Events]]&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;box&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;h3&amp;gt;Others&amp;lt;/h3&amp;gt;&lt;br /&gt;
* [[Dependencies]]&lt;br /&gt;
* [[Dynamic Loot Modification]]&lt;br /&gt;
* [[Components|Components and Translation Keys]]&lt;br /&gt;
* [[Key Mappings]]&lt;br /&gt;
* [[Access Transformers]]&lt;br /&gt;
* [[Toolchain]]&lt;br /&gt;
* [[Game_Tests|Game Tests]]&lt;br /&gt;
* [[Biome_Modifiers|Biome Modifiers]]&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;box&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;h3&amp;gt;Recipes&amp;lt;/h3&amp;gt;&lt;br /&gt;
* [[Recipes]]&lt;br /&gt;
* [[Custom Recipes|Custom Recipe Types]]&lt;br /&gt;
* [[Datageneration/Recipes|Datageneration]]&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;/div&gt;</summary>
		<author><name>Commoble</name></author>
	</entry>
	<entry>
		<id>https://forge.gemwire.uk/index.php?title=Holders&amp;diff=3301</id>
		<title>Holders</title>
		<link rel="alternate" type="text/html" href="https://forge.gemwire.uk/index.php?title=Holders&amp;diff=3301"/>
		<updated>2022-08-13T15:40:36Z</updated>

		<summary type="html">&lt;p&gt;Commoble: Created page with &amp;quot;Holders are a component of vanilla registries representing a registrable value and/or the identifier of that value; they vaguely resemble a vanilla implementation of RegistryO...&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Holders are a component of vanilla registries representing a registrable value and/or the identifier of that value; they vaguely resemble a vanilla implementation of RegistryObjects, but with substantial semantic and implementation differences. They are used extensively by [[Tags|tags]] and [[Registration#Data_Driven_Entries|datapack registries]]; modders that use these systems should be aware of their functions and caveats.&lt;br /&gt;
&lt;br /&gt;
Datapack registry elements can have reference to HolderSets, which can use tag references to define sets of registry elements.&lt;br /&gt;
&lt;br /&gt;
== Holders == &lt;br /&gt;
&lt;br /&gt;
=== Properties of Holders ===&lt;br /&gt;
&lt;br /&gt;
Holders in general have the following properties:&lt;br /&gt;
* A holder may or may not have a key (a ResourceLocation/ResourceKey identifying the holder/value by name)&lt;br /&gt;
* A holder may or may not have a value (e.g. a block or a biome)&lt;br /&gt;
* A holder may or may not belong to a specific registry instance&lt;br /&gt;
* A holder may or may not be a mutable object&lt;br /&gt;
* A holder is associated with zero or more tags&lt;br /&gt;
&lt;br /&gt;
=== Types of Holder ===&lt;br /&gt;
&lt;br /&gt;
There are three categories of holders: direct holders, standalone reference holders, and intrusive reference holders.&lt;br /&gt;
&lt;br /&gt;
==== Direct Holders ====&lt;br /&gt;
&lt;br /&gt;
Direct holders always hold an unregistered value, and never hold a key. Direct holders are generally created when a datapack registry json inline-defines a value in a holder field instead of declaring a reference to another json. Direct holders are immutable records, and never have tags bound to them.&lt;br /&gt;
&lt;br /&gt;
A vanilla example of direct holders being used is in density functions; density functions are often composed of holders of other density functions, but the child functions themselves don't need to be registered, and so many vanilla density functions are created with inline/direct child functions.&lt;br /&gt;
&lt;br /&gt;
Direct holders should not be created for values that must always exist in the registry, or for values whose registry names must be determined at some point.&lt;br /&gt;
&lt;br /&gt;
==== Reference Holders ====&lt;br /&gt;
&lt;br /&gt;
Reference holders refer to registered values; they are created with either a key or a value, with the other property being bound to them later in the registration process. Reference holders belong to a specific registry instance and are aware of which registry they belong to (if multiple copies of a registry exist, as is the case for datapack registries, a reference holder is only valid for a single instance of that registry).&lt;br /&gt;
&lt;br /&gt;
Reference holders are mutable and may have tags bound to them.&lt;br /&gt;
&lt;br /&gt;
===== Standalone Reference Holders =====&lt;br /&gt;
&lt;br /&gt;
Most holders encountered will be standalone reference holders; they are created with a key, and have a value bound to them later. Each registry has at most one standalone reference holder per key; parsing a reference holder in a datapack registry json computes a holder in the relevant registry if it doesn't already exist.&lt;br /&gt;
&lt;br /&gt;
Standalone reference holders are the means by which datapack registry jsons can refer to each other. They have the following lifecycle:&lt;br /&gt;
&lt;br /&gt;
* A datapack registry json is loaded that refers to another registrable by id, e.g. &amp;quot;minecraft:desert&amp;quot;&lt;br /&gt;
* A standalone reference holder is retrieved from the relevant registry via a get-or-create operation&lt;br /&gt;
* When a datapack registry json is loaded and fully parsed, a holder for that json is get-or-created *and* the parsed value is bound to it&lt;br /&gt;
* When registries freeze, the get-or-create operation can no longer create new holders. If any reference holders in the registry are not fully bound at this time (with both a key and a value), an error is raised. This will occur if a datapack registry json refers by id to another datapack registry json that does not exist, and is how these references-by-id are validated.&lt;br /&gt;
* Whenever tags load, each tag file's TagKey is bound to all reference holders referred to in that tag (this modifiers the holders in-place).&lt;br /&gt;
&lt;br /&gt;
When datagenerating datapack registry jsons with reference holders, any reference holders *must* be created by the specific registry instances used by the RegistryOps/RegistryAccess used to datagen the jsons, or they will fail to serialize.&lt;br /&gt;
&lt;br /&gt;
===== Intrusive Reference Holders =====&lt;br /&gt;
&lt;br /&gt;
Intrusive reference holders are created with a value and have a key bound to them later. Several static registrable types (blocks, items, fluids, entitytypes, and gameevents) create intrusive holders of themselves when constructed, which have a value bound to them once the value is registered.&lt;br /&gt;
&lt;br /&gt;
Intrusive holders and the means of creating them are deprecated by mojang; this seems to be a hack to allow blocks and friends to quickly look up their registry name. Intrusive holders may be removed in future minecraft releases, and should not be used by mods (value-&amp;gt;key lookups can be done via a method in the relevant registry, or by creating standalone holders or RegistryObjects to create name-value pairs).&lt;br /&gt;
&lt;br /&gt;
== HolderSets ==&lt;br /&gt;
&lt;br /&gt;
A HolderSet is an indexable set of holders, and is the preferred means by which datapack registrables can refer to other datapack registrables. Vanilla frequently uses holdersets to wire worldgen jsons together, e.g. a structure json has a holderset field for which biomes the structure can spawn in.&lt;br /&gt;
&lt;br /&gt;
Vanilla has two types of holdersets and three json formats; forge expands the holderset serializer to allow additional types of holdersets. A holderset field in a json can accept a single element, a list of elements, a tag ID, or one of forge's special formats, making datapack creation very flexible when holderset fields are used.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;json&amp;quot;&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;a_biome&amp;quot;: &amp;quot;desert&amp;quot;, // single element holderset&lt;br /&gt;
  &amp;quot;some_biomes&amp;quot;: [&amp;quot;plains&amp;quot;, &amp;quot;forest&amp;quot;], // list holderset&lt;br /&gt;
  &amp;quot;biome_tag&amp;quot;: &amp;quot;#is_plains&amp;quot;, // tag holderset&lt;br /&gt;
  &amp;quot;expanded_forge_format&amp;quot;: // more on these later&lt;br /&gt;
  {&lt;br /&gt;
    &amp;quot;type&amp;quot;: &amp;quot;modid:custom_holderset_type&amp;quot;,&lt;br /&gt;
    // additional fields as specified by the type&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Codecs]] can be created for holdersets to allow holdersets to be read from jsons; however, a holderset codec must be created for each registry holdersets can be made for, e.g. Biome.LIST_OF_LISTS_CODEC is the codec for HolderSet&amp;lt;Biome&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
HolderSets should generally only be serialized when used as components of unsynced (server-only) datapack registry jsons, such as in worldgen features. HolderSets that are serialized without RegistryOps for registry context (including when synced to clients in synced datapack registries, which do not serialize with registry context) will be deserialized as lists of unregistered objects.&lt;br /&gt;
&lt;br /&gt;
=== Types of HolderSets ===&lt;br /&gt;
&lt;br /&gt;
==== Direct HolderSets ====&lt;br /&gt;
&lt;br /&gt;
Direct HolderSets represent an immutable list of holders. They can be defined in json as single elements or lists of elements (the single element format simply parses as a list holderset with one element in it).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;json&amp;quot;&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;a_biome&amp;quot;: &amp;quot;desert&amp;quot;, // single element holderset&lt;br /&gt;
  &amp;quot;some_biomes&amp;quot;: [&amp;quot;plains&amp;quot;, &amp;quot;forest&amp;quot;], // list holderset&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Named HolderSets ====&lt;br /&gt;
&lt;br /&gt;
Named HolderSets represent a tag. Named HolderSets are mutable; they cache a list and a set of holders, and this cache is reset each time tags reload.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;json&amp;quot;&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;biome_tag&amp;quot;: &amp;quot;#is_plains&amp;quot;, // tag holderset&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Custom HolderSet Types ====&lt;br /&gt;
&lt;br /&gt;
Forge expands the holderset codecs to allow additional json formats. Custom holderset serializers can be registered by creating a deferred register for ForgeRegistries.Keys.HOLDER_SET_TYPES, though the builtin types provided by forge should be sufficient for most use cases.&lt;br /&gt;
&lt;br /&gt;
==== Builtin Custom HolderSet Types ====&lt;br /&gt;
&lt;br /&gt;
Forge provides four builtin holderset types, allowing for additional set operations and representations in datapack registry jsons. The and, or, and not types are composed of other holdersets, and are therefore potentially mutable as they may be composed of mutable tag holdersets whose values are recalculated after tags reload.&lt;br /&gt;
&lt;br /&gt;
===== Any =====&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;forge:any&amp;lt;/code&amp;gt; holderset type represents the set of all elements of the relevant registry.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;json&amp;quot;&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;biomes&amp;quot;:&lt;br /&gt;
  {&lt;br /&gt;
    &amp;quot;type&amp;quot;: &amp;quot;forge:any&amp;quot;&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===== And =====&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;forge:and&amp;lt;/code&amp;gt; type represents an intersection of other holdersets.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;json&amp;quot;&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;biomes&amp;quot;:&lt;br /&gt;
  {&lt;br /&gt;
    &amp;quot;type&amp;quot;: &amp;quot;forge:and&amp;quot;,&lt;br /&gt;
    &amp;quot;values&amp;quot;:&lt;br /&gt;
    [&lt;br /&gt;
      // list of holdersets of any format, different formats (string, list, object) can be mixed here&lt;br /&gt;
      &amp;quot;#is_plains&amp;quot;,&lt;br /&gt;
      &amp;quot;#is_overworld&amp;quot;&lt;br /&gt;
    ]&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== Or =====&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;forge:or&amp;lt;/code&amp;gt; type represents a union of other holdersets.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;json&amp;quot;&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;biomes&amp;quot;:&lt;br /&gt;
  {&lt;br /&gt;
    &amp;quot;type&amp;quot;: &amp;quot;forge:or&amp;quot;,&lt;br /&gt;
    &amp;quot;values&amp;quot;:&lt;br /&gt;
    [&lt;br /&gt;
      // list of holdersets of any format, different formats (string, list, object) can be mixed here&lt;br /&gt;
      &amp;quot;#is_plains&amp;quot;,&lt;br /&gt;
      [&amp;quot;swamp&amp;quot;, &amp;quot;mangrove_swamp&amp;quot;]&lt;br /&gt;
    ]&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== Not =====&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;forge:not&amp;lt;/code&amp;gt; type represents the set of all elements in the registry that do not belong to the specified holderset.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;json&amp;quot;&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;biomes&amp;quot;:&lt;br /&gt;
  {&lt;br /&gt;
    &amp;quot;type&amp;quot;: &amp;quot;forge:not&amp;quot;,&lt;br /&gt;
    &amp;quot;value&amp;quot;: &amp;quot;#is_plains&amp;quot; // holderset of any format (string, list, or object)&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>Commoble</name></author>
	</entry>
	<entry>
		<id>https://forge.gemwire.uk/index.php?title=Biome_Modifiers&amp;diff=3280</id>
		<title>Biome Modifiers</title>
		<link rel="alternate" type="text/html" href="https://forge.gemwire.uk/index.php?title=Biome_Modifiers&amp;diff=3280"/>
		<updated>2022-06-15T23:53:30Z</updated>

		<summary type="html">&lt;p&gt;Commoble: Add summary&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Biome Modifiers are a data-driven system for modifying biomes. They have the ability to modify biomes in several ways:&lt;br /&gt;
&lt;br /&gt;
* Adding or removing worldgen features and carvers&lt;br /&gt;
* Adding or removing mob spawns and mob spawn costs&lt;br /&gt;
* Modifying the climate of a biome&lt;br /&gt;
* Modifying a biome's client effects, such as water color&lt;br /&gt;
&lt;br /&gt;
Creating and using biome modifiers involves up to three steps:&lt;br /&gt;
&lt;br /&gt;
# Creating a [[#Biome_Modifier_Type|biome modifier type]], which defines how to modify a biome.&lt;br /&gt;
# Registering a [[#Biome_Modifier_Serializers|biome modifier codec]], which defines how to parse a json into your biome modifier type.&lt;br /&gt;
# Creating [[#Biome_Modifier_JSONs|biome modifier JSONs]] to define individual biome modifier instances; each json file provides a glob of data to your serializer to produce an instance of a biome modifier type. These can be [[#Datageneration|datagenerated]] if desired.&lt;br /&gt;
&lt;br /&gt;
Forge provides several [[#Builtin_Biome_Modifier_Types|builtin biome modifier types]], so some basic use cases such as adding features or mob spawns to biomes can be done without registering additional serializers.&lt;br /&gt;
&lt;br /&gt;
= Biome Modifier Types =&lt;br /&gt;
&lt;br /&gt;
To define a new type of biome modifier, begin by implementing a new class that extends &amp;lt;code&amp;gt;BiomeModifier&amp;lt;/code&amp;gt;. BiomeModifiers can usually be implemented as records, to reduce boilerplate.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
public record ExampleBiomeModifier() implements BiomeModifier&lt;br /&gt;
{&lt;br /&gt;
  public void modify(Holder&amp;lt;Biome&amp;gt; biome, Phase phase, Builder builder)&lt;br /&gt;
  {&lt;br /&gt;
    // This allows modifications to the given biome via the provided Builder.&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  public Codec&amp;lt;? extends BiomeModifier&amp;gt; codec()&lt;br /&gt;
  {&lt;br /&gt;
    // This must return a registered Codec, see Biome Modifier Serializers below.&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Beware! The modify method is called once per each phase per biome per biome modifier, so it's important to check which phase you're in and only make your changes in one phase.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
public void modify(Holder&amp;lt;Biome&amp;gt; biome, Phase phase, Builder builder)&lt;br /&gt;
{&lt;br /&gt;
  if (phase == Phase.ADD)&lt;br /&gt;
  {&lt;br /&gt;
    // add things to biomes&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Typically we also want to restrict biome modifiers to only apply to certain biomes. We can do that by accepting a HolderSet&amp;lt;Biome&amp;gt; in our constructor:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
public record ExampleBiomeModifier(HolderSet&amp;lt;Biome&amp;gt; biomes) implements BiomeModifier&lt;br /&gt;
{&lt;br /&gt;
  public void modify(Holder&amp;lt;Biome&amp;gt; biome, Phase phase, Builder builder)&lt;br /&gt;
  {&lt;br /&gt;
    if (phase == Phase.ADD &amp;amp;&amp;amp; biomes.contains(biome))&lt;br /&gt;
    {&lt;br /&gt;
      // add things to biomes&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We can also accept Holders or HolderSets for other [[Registration#Data_Driven_Entries|datapack registry elements]], such as PlacedFeatures, which allows our BiomeModifier to refer to those elements, which can then be defined in their own JSON files.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
public record ExampleBiomeModifier(HolderSet&amp;lt;Biome&amp;gt; biomes, Holder&amp;lt;PlacedFeature&amp;gt; feature) implements BiomeModifier&lt;br /&gt;
{&lt;br /&gt;
  public void modify(Holder&amp;lt;Biome&amp;gt; biome, Phase phase, Builder builder)&lt;br /&gt;
  {&lt;br /&gt;
    // add a feature to all specified biomes&lt;br /&gt;
    if (phase == Phase.ADD &amp;amp;&amp;amp; biomes.contains(biome))&lt;br /&gt;
    {&lt;br /&gt;
      builder.getGenerationSettings().addFeature(Decoration.UNDERGROUND_ORES, feature);&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Biome Modifier Serializers =&lt;br /&gt;
&lt;br /&gt;
Each type of biome modifier must have a [[Codecs|Codec]] registered for it; [[Registration#DeferredRegister|Deferred Registers]] are the recommended way to register biome modifier codecs.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
public class YourMod&lt;br /&gt;
{&lt;br /&gt;
  static DeferredRegister&amp;lt;Codec&amp;lt;? extends BiomeModifier&amp;gt;&amp;gt; BIOME_MODIFIER_SERIALIZERS =&lt;br /&gt;
    DeferredRegister.create(ForgeRegistries.Keys.BIOME_MODIFIER_SERIALIZERS, &amp;quot;yourmodid&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
  static RegistryObject&amp;lt;Codec&amp;lt;ExampleBiomeModifier&amp;gt;&amp;gt; EXAMPLE_CODEC = BIOME_MODIFIER_SERIALIZERS.register(&amp;quot;example&amp;quot;, () -&amp;gt;&lt;br /&gt;
    RecordCodecBuilder.create(builder -&amp;gt; builder.group(&lt;br /&gt;
        // declare fields&lt;br /&gt;
        Biome.LIST_CODEC.fieldOf(&amp;quot;biomes&amp;quot;).forGetter(ExampleBiomeModifier::biomes),&lt;br /&gt;
        PlacedFeature.CODEC.fieldOf(&amp;quot;feature&amp;quot;).forGetter(ExampleBiomeModifier::feature)&lt;br /&gt;
      // declare constructor&lt;br /&gt;
      ).apply(builder, ExampleBiomeModifier::new)));&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We can now implement the codec() method in our biome modifier class:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
public record ExampleBiomeModifier(HolderSet&amp;lt;Biome&amp;gt; biomes, Holder&amp;lt;PlacedFeature&amp;gt; feature) implements BiomeModifier&lt;br /&gt;
{&lt;br /&gt;
  public void modify(Holder&amp;lt;Biome&amp;gt; biome, Phase phase, Builder builder)&lt;br /&gt;
  {&lt;br /&gt;
    // add a feature to all specified biomes&lt;br /&gt;
    if (phase == Phase.ADD &amp;amp;&amp;amp; biomes.contains(biome))&lt;br /&gt;
    {&lt;br /&gt;
      builder.getGenerationSettings().addFeature(Decoration.UNDERGROUND_ORES, feature);&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  public Codec&amp;lt;? extends BiomeModifier&amp;gt; codec()&lt;br /&gt;
  {&lt;br /&gt;
    return YourMod.EXAMPLE_CODEC.get();&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Biome Modifier JSONs =&lt;br /&gt;
&lt;br /&gt;
Once we've registered a codec for our biome modifier type, we can define jsons for it. Biome modifier jsons must be defined in the directory &amp;lt;code&amp;gt;data/modid/forge/biome_modifier/&amp;lt;/code&amp;gt;; a biome modifier at &amp;lt;code&amp;gt;data/modid/forge/biome_modifier/your_biome_modifier.json&amp;lt;/code&amp;gt; has the namespaced id &amp;lt;code&amp;gt;modid:your_biome_modifier&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Our codec above defines the json format:&lt;br /&gt;
&lt;br /&gt;
* &amp;quot;biomes&amp;quot; is a special HolderSet field that accepts a single biome id, [list of biome ids], or #biome_tag.&lt;br /&gt;
* &amp;quot;feature&amp;quot; accepts a single placed feature id. [https://minecraft.fandom.com/wiki/Placed_feature These can be defined in jsons as well].&lt;br /&gt;
* We must also specify &amp;quot;type&amp;quot;: &amp;quot;yourmodid:example&amp;quot; to tell the data loader to use our registered codec to read our json.&lt;br /&gt;
&lt;br /&gt;
A json instance of our biome modifier that adds some feature to badlands biomes might look like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;json&amp;quot;&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;type&amp;quot;: &amp;quot;yourmodid:example&amp;quot;,&lt;br /&gt;
  &amp;quot;biomes&amp;quot;: &amp;quot;#minecraft:is_badlands&amp;quot;,&lt;br /&gt;
  &amp;quot;feature&amp;quot;: &amp;quot;yourmod:some_feature&amp;quot;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Side Note on HolderSets ==&lt;br /&gt;
&lt;br /&gt;
HolderSets are a vanilla feature that, when defined in JSON, can be specified as a single id, list of ids, or tag. Our example above uses a holderset of biomes, so all three of these are valid biome fields:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;json&amp;quot;&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;biomes&amp;quot;: &amp;quot;forest&amp;quot;,&lt;br /&gt;
  &amp;quot;biomes&amp;quot;: [&amp;quot;forest&amp;quot;, &amp;quot;birch_forest&amp;quot;],&lt;br /&gt;
  &amp;quot;biomes&amp;quot;: &amp;quot;#is_forest&amp;quot;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Datageneration =&lt;br /&gt;
&lt;br /&gt;
Biome Modifier jsons can be [[Datageneration|datagenerated via GatherDataEvent]]. As biome modifiers are datapack registry objects, this can be done by using JsonCodecProvider#forDatapackRegistry as the data provider. Refer to [[Datageneration/Datapack_Registries]] for additional information on datagenerating datapack registry elements.&lt;br /&gt;
&lt;br /&gt;
= Builtin Biome Modifier Types =&lt;br /&gt;
&lt;br /&gt;
Forge provides the following builtin biome modifier types:&lt;br /&gt;
&lt;br /&gt;
== None ==&lt;br /&gt;
&lt;br /&gt;
A no-op biome modifier type, whose jsons have the following format:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;json&amp;quot;&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;type&amp;quot;: &amp;quot;forge:none&amp;quot;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This allows pack devs or server operators to disable mods' biome modifiers by overriding their biome modifier jsons with the above.&lt;br /&gt;
&lt;br /&gt;
== Add Features ==&lt;br /&gt;
&lt;br /&gt;
This biome modifier type adds placed features to biomes.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;json&amp;quot;&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;type&amp;quot;: &amp;quot;forge:add_features&amp;quot;, // required&lt;br /&gt;
  &amp;quot;biomes&amp;quot;: &amp;quot;#namespace:your_biome_tag&amp;quot; // accepts a biome id, [list of biome ids], or #namespace:biome_tag&lt;br /&gt;
  &amp;quot;features&amp;quot;: &amp;quot;namespace:your_feature&amp;quot;, // accepts a placed feature id, [list of placed feature ids], or #namespace:feature_tag&lt;br /&gt;
  &amp;quot;step&amp;quot;: &amp;quot;underground_ores&amp;quot; // accepts a Decoration enum name&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Decoration steps in order of generation are:&lt;br /&gt;
* raw_generation&lt;br /&gt;
* lakes&lt;br /&gt;
* local_modifications&lt;br /&gt;
* underground_structures&lt;br /&gt;
* surface_structures&lt;br /&gt;
* underground_ores&lt;br /&gt;
* underground_decoration&lt;br /&gt;
* fluid_springs&lt;br /&gt;
* vegetal_decoration&lt;br /&gt;
* top_layer_modification&lt;br /&gt;
&lt;br /&gt;
== Remove Features ==&lt;br /&gt;
&lt;br /&gt;
This biome modifier type removes features from biomes.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;json&amp;quot;&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;type&amp;quot;: &amp;quot;forge:remove_features&amp;quot;, // required&lt;br /&gt;
  &amp;quot;biomes&amp;quot;: &amp;quot;#namespace:your_biome_tag&amp;quot; // accepts a biome id, [list of biome ids], or #namespace:biome_tag&lt;br /&gt;
  &amp;quot;features&amp;quot;: &amp;quot;namespace:your_feature&amp;quot;, // accepts a placed feature id, [list of placed feature ids], or #namespace:feature_tag&lt;br /&gt;
  &amp;quot;steps&amp;quot;: &amp;quot;underground_ores&amp;quot; // optional field specifying a Decoration or list of Decorations to remove features from, defaults to all if not specified&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Add Spawns ==&lt;br /&gt;
&lt;br /&gt;
This biome modifier type adds mob spawns to biomes.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;json&amp;quot;&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;type&amp;quot;: &amp;quot;forge:add_spawns&amp;quot;, // Required&lt;br /&gt;
  &amp;quot;biomes&amp;quot;: &amp;quot;#namespace:biome_tag&amp;quot;, // Accepts a biome id, [list of biome ids], or #namespace:biome_tag&lt;br /&gt;
  &amp;quot;spawners&amp;quot;:&lt;br /&gt;
  {&lt;br /&gt;
    &amp;quot;type&amp;quot;: &amp;quot;namespace:entity_type&amp;quot;, // Type of mob to spawn&lt;br /&gt;
    &amp;quot;weight&amp;quot;: 100, // int, spawn weighting&lt;br /&gt;
    &amp;quot;minCount&amp;quot;: 1, // int, minimum pack size&lt;br /&gt;
    &amp;quot;maxCount&amp;quot;: 4, // int, maximum pack size&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Remove Spawns ==&lt;br /&gt;
&lt;br /&gt;
This biome modifier type removes mob spawns from biomes.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;json&amp;quot;&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;type&amp;quot;: &amp;quot;forge:remove_spawns&amp;quot;, // Required&lt;br /&gt;
  &amp;quot;biomes&amp;quot;: &amp;quot;#namespace:biome_tag&amp;quot;, // Accepts a biome id, [list of biome ids], or #namespace:biome_tag&lt;br /&gt;
  &amp;quot;entity_types&amp;quot;: &amp;quot;#namespace:entitytype_tag&amp;quot; // Accepts an entity type, list, or tag of entitytypes whose spawns are to be removed from the biomes&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Best Practices =&lt;br /&gt;
&lt;br /&gt;
* Avoid using biome modifiers to add vanilla placed features to biomes, as this may cause a feature cycle violation (the game will crash if two biomes have the same two features in their feature lists but in different orders). Placed features can be referenced in biome jsons or added via biome modifiers, but should not be used in both.&lt;/div&gt;</summary>
		<author><name>Commoble</name></author>
	</entry>
	<entry>
		<id>https://forge.gemwire.uk/index.php?title=Main_Page&amp;diff=3275</id>
		<title>Main Page</title>
		<link rel="alternate" type="text/html" href="https://forge.gemwire.uk/index.php?title=Main_Page&amp;diff=3275"/>
		<updated>2022-06-15T01:08:53Z</updated>

		<summary type="html">&lt;p&gt;Commoble: Add link to Datageneration/Datapack_Registries&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__NOTOC__&lt;br /&gt;
&amp;lt;templatestyles src=&amp;quot;:Main_Page/styles.css&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;center title&amp;quot;&amp;gt;Forge Community Wiki&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The Forge Community Wiki exists so that the community can:&lt;br /&gt;
&lt;br /&gt;
* collectively keep track of major changes and updates to Forge and Vanilla code;&lt;br /&gt;
* create and edit articles with in-depth explanations about a variety of Forge-related subjects; and&lt;br /&gt;
* contribute example code and tutorials for both simple and difficult concepts.&lt;br /&gt;
&lt;br /&gt;
This wiki is editable by any registered user with an account. This is to allow tracking of harmful edits, but isn't imposing any annoying limits. We welcome any edit, however small. Join the [https://discord.gg/Nn42eAh Discord] to discuss changes and edits to the wiki with others and the staff.&lt;br /&gt;
&lt;br /&gt;
{{Supported versions}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;center round_warning&amp;quot;&amp;gt;&lt;br /&gt;
Please read the [[FCWMeta:Wiki Policy|wiki policy]] before editing!&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;center&amp;quot; style=&amp;quot;margin-bottom: 2em&amp;quot;&amp;gt;&lt;br /&gt;
{{Supported versions|text=1}}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;box_container center&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;box&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;h3&amp;gt;Beginner Topics&amp;lt;/h3&amp;gt;&lt;br /&gt;
* [[Getting Started]]&lt;br /&gt;
* [[Proper Mod Structuring]]&lt;br /&gt;
* [[Mods.toml file]]&lt;br /&gt;
* [[Debug Profiler|The Debug Profiler]]&lt;br /&gt;
* [[Version Checker]]&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;box&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;h3&amp;gt;Common Concepts&amp;lt;/h3&amp;gt;&lt;br /&gt;
* [[Sides|Understanding Sides]]&lt;br /&gt;
* [[Events|Understanding Events]]&lt;br /&gt;
* [[Registration]]&lt;br /&gt;
* [[Internationalization]]&lt;br /&gt;
* [[Configs]]&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;box&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;h3&amp;gt;Forge Conventions&amp;lt;/h3&amp;gt;&lt;br /&gt;
* [[Semantic Versioning]]&lt;br /&gt;
* [[Stages of Modloading]]&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;box&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;h3&amp;gt;Resources and Data&amp;lt;/h3&amp;gt;&lt;br /&gt;
* [[Using Resources|Introduction]]&lt;br /&gt;
* [[Recipes]]&lt;br /&gt;
* [[Tags]]&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;box&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;h3&amp;gt;Blocks&amp;lt;/h3&amp;gt;&lt;br /&gt;
* [[Making Blocks|Creating Blocks]]&lt;br /&gt;
* [[Understanding Blockstates]] &lt;br /&gt;
* [[Interacting With Blocks|Block Interactions]]&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;box&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;h3&amp;gt;Items&amp;lt;/h3&amp;gt;&lt;br /&gt;
* [[Making Items]]&lt;br /&gt;
* [[Making Tools]]&lt;br /&gt;
* [[BlockEntityWithoutLevelRenderer|&amp;lt;tt&amp;gt;BlockEntityWithoutLevelRenderer&amp;lt;/tt&amp;gt;]]&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;box&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;h3&amp;gt;Data Generation&amp;lt;/h3&amp;gt;&lt;br /&gt;
* [[Datageneration|Introduction]]&lt;br /&gt;
* [[Datageneration/Recipes|Recipes]]&lt;br /&gt;
* [[Datageneration/Tags|Tags]]&lt;br /&gt;
* [[Datageneration/Loot_Tables|Loot Tables]]&lt;br /&gt;
* [[Datageneration/I18n|Localization]]&lt;br /&gt;
* [[Datageneration/States and Models|&amp;lt;tt&amp;gt;BlockState&amp;lt;/tt&amp;gt;s and Models]]&lt;br /&gt;
* [[Datageneration/Datapack_Registries|Datapack Registries]]&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;box&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;h3&amp;gt;Block Entities&amp;lt;/h3&amp;gt;&lt;br /&gt;
* [[Block Entities|Introduction]]&lt;br /&gt;
* [[Block Entity Renderer|&amp;lt;tt&amp;gt;BlockEntityRenderer&amp;lt;/tt&amp;gt;]]&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;box&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;h3&amp;gt;Models&amp;lt;/h3&amp;gt;&lt;br /&gt;
* [[Introduction to Models|Introduction]]&lt;br /&gt;
* [[Model JSONs]]&lt;br /&gt;
* [[BlockState JSONs]]&lt;br /&gt;
* [[Coloring textures dynamically|Dynamically Colored Textures]]&lt;br /&gt;
* [[Item Properties]]&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;box&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;h3&amp;gt;Handling Information&amp;lt;/h3&amp;gt;&lt;br /&gt;
* [[Understanding Networking|Introduction]]&lt;br /&gt;
* [[Using NBT|Named Binary Tag (NBT)]]&lt;br /&gt;
* [[Using FriendlyByteBuf|Using &amp;lt;tt&amp;gt;FriendlyByteBuf&amp;lt;/tt&amp;gt;]]&lt;br /&gt;
* [[Sending Packets|Sending and Receiving Packets]]&lt;br /&gt;
* [[Using SimpleChannel|Using &amp;lt;tt&amp;gt;SimpleChannel&amp;lt;/tt&amp;gt;]]&lt;br /&gt;
* [[Networking with Entities]]&lt;br /&gt;
* [[DynamicOps|Using DynamicOps]]&lt;br /&gt;
* [[Codecs|Using Codecs]]&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;box&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;h3&amp;gt;Data Storage&amp;lt;/h3&amp;gt;&lt;br /&gt;
* [[Capabilities|Understanding Capabilities]] &lt;br /&gt;
* [[Capabilities/Attaching|Attaching Capabilities]]&lt;br /&gt;
* [[Saved Data]]&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;box&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;h3&amp;gt;Game Effects&amp;lt;/h3&amp;gt;&lt;br /&gt;
* [[Mob Effects]]&lt;br /&gt;
* [[Potions]]&lt;br /&gt;
* [[Particles]]&lt;br /&gt;
* [[Sounds]]&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;box&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;h3&amp;gt;Events&amp;lt;/h3&amp;gt;&lt;br /&gt;
* [[Events|Understanding Events]]&lt;br /&gt;
* [[Entity Events]]&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;box&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;h3&amp;gt;Others&amp;lt;/h3&amp;gt;&lt;br /&gt;
* [[Dependencies]]&lt;br /&gt;
* [[Dynamic Loot Modification]]&lt;br /&gt;
* [[Components|Components and Translation Keys]]&lt;br /&gt;
* [[Key Mappings]]&lt;br /&gt;
* [[Access Transformers]]&lt;br /&gt;
* [[Toolchain]]&lt;br /&gt;
* [[Game_Tests|Game Tests]]&lt;br /&gt;
* [[Biome_Modifiers|Biome Modifiers]]&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;box&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;h3&amp;gt;Recipes&amp;lt;/h3&amp;gt;&lt;br /&gt;
* [[Recipes]]&lt;br /&gt;
* [[Custom Recipes|Custom Recipe Types]]&lt;br /&gt;
* [[Datageneration/Recipes|Datageneration]]&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;/div&gt;</summary>
		<author><name>Commoble</name></author>
	</entry>
	<entry>
		<id>https://forge.gemwire.uk/index.php?title=Biome_Modifiers&amp;diff=3274</id>
		<title>Biome Modifiers</title>
		<link rel="alternate" type="text/html" href="https://forge.gemwire.uk/index.php?title=Biome_Modifiers&amp;diff=3274"/>
		<updated>2022-06-15T00:59:28Z</updated>

		<summary type="html">&lt;p&gt;Commoble: Add the four new stock biome modifiers and a datagen link&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Biome Modifiers are a data-driven system for modifying biomes. They have the ability to modify biomes in several ways:&lt;br /&gt;
&lt;br /&gt;
* Adding or removing worldgen features and carvers&lt;br /&gt;
* Adding or removing mob spawns and mob spawn costs&lt;br /&gt;
* Modifying the climate of a biome&lt;br /&gt;
* Modifying a biome's client effects, such as water color&lt;br /&gt;
&lt;br /&gt;
= Biome Modifier Types =&lt;br /&gt;
&lt;br /&gt;
To define a new type of biome modifier, begin by implementing a new class that extends &amp;lt;code&amp;gt;BiomeModifier&amp;lt;/code&amp;gt;. BiomeModifiers can usually be implemented as records, to reduce boilerplate.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
public record ExampleBiomeModifier() implements BiomeModifier&lt;br /&gt;
{&lt;br /&gt;
  public void modify(Holder&amp;lt;Biome&amp;gt; biome, Phase phase, Builder builder)&lt;br /&gt;
  {&lt;br /&gt;
    // This allows modifications to the given biome via the provided Builder.&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  public Codec&amp;lt;? extends BiomeModifier&amp;gt; codec()&lt;br /&gt;
  {&lt;br /&gt;
    // This must return a registered Codec, see Biome Modifier Serializers below.&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Beware! The modify method is called once per each phase per biome per biome modifier, so it's important to check which phase you're in and only make your changes in one phase.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
public void modify(Holder&amp;lt;Biome&amp;gt; biome, Phase phase, Builder builder)&lt;br /&gt;
{&lt;br /&gt;
  if (phase == Phase.ADD)&lt;br /&gt;
  {&lt;br /&gt;
    // add things to biomes&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Typically we also want to restrict biome modifiers to only apply to certain biomes. We can do that by accepting a HolderSet&amp;lt;Biome&amp;gt; in our constructor:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
public record ExampleBiomeModifier(HolderSet&amp;lt;Biome&amp;gt; biomes) implements BiomeModifier&lt;br /&gt;
{&lt;br /&gt;
  public void modify(Holder&amp;lt;Biome&amp;gt; biome, Phase phase, Builder builder)&lt;br /&gt;
  {&lt;br /&gt;
    if (phase == Phase.ADD &amp;amp;&amp;amp; biomes.contains(biome))&lt;br /&gt;
    {&lt;br /&gt;
      // add things to biomes&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We can also accept Holders or HolderSets for other [[Registration#Data_Driven_Entries|datapack registry elements]], such as PlacedFeatures, which allows our BiomeModifier to refer to those elements, which can then be defined in their own JSON files.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
public record ExampleBiomeModifier(HolderSet&amp;lt;Biome&amp;gt; biomes, Holder&amp;lt;PlacedFeature&amp;gt; feature) implements BiomeModifier&lt;br /&gt;
{&lt;br /&gt;
  public void modify(Holder&amp;lt;Biome&amp;gt; biome, Phase phase, Builder builder)&lt;br /&gt;
  {&lt;br /&gt;
    // add a feature to all specified biomes&lt;br /&gt;
    if (phase == Phase.ADD &amp;amp;&amp;amp; biomes.contains(biome))&lt;br /&gt;
    {&lt;br /&gt;
      builder.getGenerationSettings().addFeature(Decoration.UNDERGROUND_ORES, feature);&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Biome Modifier Serializers =&lt;br /&gt;
&lt;br /&gt;
Each type of biome modifier must have a [[Codecs|Codec]] registered for it; [[Registration#DeferredRegister|Deferred Registers]] are the recommended way to register biome modifier codecs.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
public class YourMod&lt;br /&gt;
{&lt;br /&gt;
  static DeferredRegister&amp;lt;Codec&amp;lt;? extends BiomeModifier&amp;gt;&amp;gt; BIOME_MODIFIER_SERIALIZERS =&lt;br /&gt;
    DeferredRegister.create(ForgeRegistries.Keys.BIOME_MODIFIER_SERIALIZERS, &amp;quot;yourmodid&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
  static RegistryObject&amp;lt;Codec&amp;lt;ExampleBiomeModifier&amp;gt;&amp;gt; EXAMPLE_CODEC = BIOME_MODIFIER_SERIALIZERS.register(&amp;quot;example&amp;quot;, () -&amp;gt;&lt;br /&gt;
    RecordCodecBuilder.create(builder -&amp;gt; builder.group(&lt;br /&gt;
        // declare fields&lt;br /&gt;
        Biome.LIST_CODEC.fieldOf(&amp;quot;biomes&amp;quot;).forGetter(ExampleBiomeModifier::biomes),&lt;br /&gt;
        PlacedFeature.CODEC.fieldOf(&amp;quot;feature&amp;quot;).forGetter(ExampleBiomeModifier::feature)&lt;br /&gt;
      // declare constructor&lt;br /&gt;
      ).apply(builder, ExampleBiomeModifier::new)));&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We can now implement the codec() method in our biome modifier class:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
public record ExampleBiomeModifier(HolderSet&amp;lt;Biome&amp;gt; biomes, Holder&amp;lt;PlacedFeature&amp;gt; feature) implements BiomeModifier&lt;br /&gt;
{&lt;br /&gt;
  public void modify(Holder&amp;lt;Biome&amp;gt; biome, Phase phase, Builder builder)&lt;br /&gt;
  {&lt;br /&gt;
    // add a feature to all specified biomes&lt;br /&gt;
    if (phase == Phase.ADD &amp;amp;&amp;amp; biomes.contains(biome))&lt;br /&gt;
    {&lt;br /&gt;
      builder.getGenerationSettings().addFeature(Decoration.UNDERGROUND_ORES, feature);&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  public Codec&amp;lt;? extends BiomeModifier&amp;gt; codec()&lt;br /&gt;
  {&lt;br /&gt;
    return YourMod.EXAMPLE_CODEC.get();&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Biome Modifier JSONs =&lt;br /&gt;
&lt;br /&gt;
Once we've registered a codec for our biome modifier type, we can define jsons for it. Biome modifier jsons must be defined in the directory &amp;lt;code&amp;gt;data/modid/forge/biome_modifier/&amp;lt;/code&amp;gt;; a biome modifier at &amp;lt;code&amp;gt;data/modid/forge/biome_modifier/your_biome_modifier.json&amp;lt;/code&amp;gt; has the namespaced id &amp;lt;code&amp;gt;modid:your_biome_modifier&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Our codec above defines the json format:&lt;br /&gt;
&lt;br /&gt;
* &amp;quot;biomes&amp;quot; is a special HolderSet field that accepts a single biome id, [list of biome ids], or #biome_tag.&lt;br /&gt;
* &amp;quot;feature&amp;quot; accepts a single placed feature id. [https://minecraft.fandom.com/wiki/Placed_feature These can be defined in jsons as well].&lt;br /&gt;
* We must also specify &amp;quot;type&amp;quot;: &amp;quot;yourmodid:example&amp;quot; to tell the data loader to use our registered codec to read our json.&lt;br /&gt;
&lt;br /&gt;
A json instance of our biome modifier that adds some feature to badlands biomes might look like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;json&amp;quot;&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;type&amp;quot;: &amp;quot;yourmodid:example&amp;quot;,&lt;br /&gt;
  &amp;quot;biomes&amp;quot;: &amp;quot;#minecraft:is_badlands&amp;quot;,&lt;br /&gt;
  &amp;quot;feature&amp;quot;: &amp;quot;yourmod:some_feature&amp;quot;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Side Note on HolderSets ==&lt;br /&gt;
&lt;br /&gt;
HolderSets are a vanilla feature that, when defined in JSON, can be specified as a single id, list of ids, or tag. Our example above uses a holderset of biomes, so all three of these are valid biome fields:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;json&amp;quot;&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;biomes&amp;quot;: &amp;quot;forest&amp;quot;,&lt;br /&gt;
  &amp;quot;biomes&amp;quot;: [&amp;quot;forest&amp;quot;, &amp;quot;birch_forest&amp;quot;],&lt;br /&gt;
  &amp;quot;biomes&amp;quot;: &amp;quot;#is_forest&amp;quot;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Datageneration =&lt;br /&gt;
&lt;br /&gt;
Biome Modifier jsons can be [[Datageneration|datagenerated via GatherDataEvent]]. As biome modifiers are datapack registry objects, this can be done by using JsonCodecProvider#forDatapackRegistry as the data provider. Refer to [[Datageneration/Datapack_Registries]] for additional information on datagenerating datapack registry elements.&lt;br /&gt;
&lt;br /&gt;
= Builtin Biome Modifier Types =&lt;br /&gt;
&lt;br /&gt;
Forge provides the following builtin biome modifier types:&lt;br /&gt;
&lt;br /&gt;
== None ==&lt;br /&gt;
&lt;br /&gt;
A no-op biome modifier type, whose jsons have the following format:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;json&amp;quot;&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;type&amp;quot;: &amp;quot;forge:none&amp;quot;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This allows pack devs or server operators to disable mods' biome modifiers by overriding their biome modifier jsons with the above.&lt;br /&gt;
&lt;br /&gt;
== Add Features ==&lt;br /&gt;
&lt;br /&gt;
This biome modifier type adds placed features to biomes.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;json&amp;quot;&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;type&amp;quot;: &amp;quot;forge:add_features&amp;quot;, // required&lt;br /&gt;
  &amp;quot;biomes&amp;quot;: &amp;quot;#namespace:your_biome_tag&amp;quot; // accepts a biome id, [list of biome ids], or #namespace:biome_tag&lt;br /&gt;
  &amp;quot;features&amp;quot;: &amp;quot;namespace:your_feature&amp;quot;, // accepts a placed feature id, [list of placed feature ids], or #namespace:feature_tag&lt;br /&gt;
  &amp;quot;step&amp;quot;: &amp;quot;underground_ores&amp;quot; // accepts a Decoration enum name&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Decoration steps in order of generation are:&lt;br /&gt;
* raw_generation&lt;br /&gt;
* lakes&lt;br /&gt;
* local_modifications&lt;br /&gt;
* underground_structures&lt;br /&gt;
* surface_structures&lt;br /&gt;
* underground_ores&lt;br /&gt;
* underground_decoration&lt;br /&gt;
* fluid_springs&lt;br /&gt;
* vegetal_decoration&lt;br /&gt;
* top_layer_modification&lt;br /&gt;
&lt;br /&gt;
== Remove Features ==&lt;br /&gt;
&lt;br /&gt;
This biome modifier type removes features from biomes.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;json&amp;quot;&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;type&amp;quot;: &amp;quot;forge:remove_features&amp;quot;, // required&lt;br /&gt;
  &amp;quot;biomes&amp;quot;: &amp;quot;#namespace:your_biome_tag&amp;quot; // accepts a biome id, [list of biome ids], or #namespace:biome_tag&lt;br /&gt;
  &amp;quot;features&amp;quot;: &amp;quot;namespace:your_feature&amp;quot;, // accepts a placed feature id, [list of placed feature ids], or #namespace:feature_tag&lt;br /&gt;
  &amp;quot;steps&amp;quot;: &amp;quot;underground_ores&amp;quot; // optional field specifying a Decoration or list of Decorations to remove features from, defaults to all if not specified&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Add Spawns ==&lt;br /&gt;
&lt;br /&gt;
This biome modifier type adds mob spawns to biomes.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;json&amp;quot;&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;type&amp;quot;: &amp;quot;forge:add_spawn&amp;quot;, // Required&lt;br /&gt;
  &amp;quot;biomes&amp;quot;: &amp;quot;#namespace:biome_tag&amp;quot;, // Accepts a biome id, [list of biome ids], or #namespace:biome_tag&lt;br /&gt;
  &amp;quot;spawner&amp;quot;:&lt;br /&gt;
  {&lt;br /&gt;
    &amp;quot;type&amp;quot;: &amp;quot;namespace:entity_type&amp;quot;, // Type of mob to spawn&lt;br /&gt;
    &amp;quot;weight&amp;quot;: 100, // int, spawn weighting&lt;br /&gt;
    &amp;quot;minCount&amp;quot;: 1, // int, minimum pack size&lt;br /&gt;
    &amp;quot;maxCount&amp;quot;: 4, // int, maximum pack size&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Remove Spawns ==&lt;br /&gt;
&lt;br /&gt;
This biome modifier type removes mob spawns from biomes.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;json&amp;quot;&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;type&amp;quot;: &amp;quot;forge:add_spawn&amp;quot;, // Required&lt;br /&gt;
  &amp;quot;biomes&amp;quot;: &amp;quot;#namespace:biome_tag&amp;quot;, // Accepts a biome id, [list of biome ids], or #namespace:biome_tag&lt;br /&gt;
  &amp;quot;entity_types&amp;quot;: &amp;quot;#namespace:entitytype_tag&amp;quot; // Accepts an entity type, list, or tag of entitytypes whose spawns are to be removed from the biomes&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Best Practices =&lt;br /&gt;
&lt;br /&gt;
* Avoid using biome modifiers to add vanilla placed features to biomes, as this may cause a feature cycle violation (the game will crash if two biomes have the same two features in their feature lists but in different orders). Placed features can be referenced in biome jsons or added via biome modifiers, but should not be used in both.&lt;/div&gt;</summary>
		<author><name>Commoble</name></author>
	</entry>
	<entry>
		<id>https://forge.gemwire.uk/index.php?title=Datapack_Registries&amp;diff=3273</id>
		<title>Datapack Registries</title>
		<link rel="alternate" type="text/html" href="https://forge.gemwire.uk/index.php?title=Datapack_Registries&amp;diff=3273"/>
		<updated>2022-06-15T00:49:41Z</updated>

		<summary type="html">&lt;p&gt;Commoble: Created page with &amp;quot;Datapack Registries (sometimes called dynamic registries or worldgen registries) are a set of registries that are able to load data from JSONS when a server starts. These incl...&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Datapack Registries (sometimes called dynamic registries or worldgen registries) are a set of registries that are able to load data from JSONS when a server starts. These include all vanilla registries enumerated in RegistryAccess.REGISTRIES (such as biomes, placed features, and dimensiontypes) as well as any [[Registration#Creating_Custom_Registries|custom forge registry]] marked with &amp;lt;code&amp;gt;datapackRegistry()&amp;lt;/code&amp;gt; in its registry builder (such as forge's [[Biome Modifiers]] and Structure Modifiers).&lt;br /&gt;
&lt;br /&gt;
These registries have the ability to have their objects registered in Java ''or'' defined in JSON.&lt;br /&gt;
&lt;br /&gt;
If a mod ships a JSON for a datapack registry element in its builtin datapack, then it is not necessary for that mod to register the object in java; however, it is also possible to create the object during GatherDataEvent and datagenerate the JSON.&lt;br /&gt;
&lt;br /&gt;
All datapack registries are automatically datagenerable; each registry has a [[Codecs|Codec]] registered to it, which defines the serialization, and each registry's registry id determines its json directory. Elements of vanilla registries are loaded from &amp;lt;code&amp;gt;data/{element-namespace}/{registry-path}/{element-path}.json&amp;lt;/code&amp;gt;, while elements of custom registries are loaded from &amp;lt;code&amp;gt;data/{element-namespace}/{registry-namespace}/{registry-path}/{element-path}.json&amp;lt;/code&amp;gt;, using the namespace and path of the registry and the element.&lt;br /&gt;
&lt;br /&gt;
= RegistryOps and RegistryAccess =&lt;br /&gt;
&lt;br /&gt;
RegistryOps is a special [[DynamicOps]] made specifically for de/serializing datapack registries; it provides additional registry context and enables the use of special codecs that can only be used with RegistryOps. Datageneration of datapack registry elements must always be done using RegistryOps to convert elements to JsonElements.&lt;br /&gt;
&lt;br /&gt;
RegistryOps can be created via &amp;lt;code&amp;gt;RegistryOps.create(JsonElement.INSTANCE, RegistryAccess.builtinCopy())&amp;lt;/code&amp;gt;. RegistryAccess.builtinCopy() creates a set of writable datapack registries, which is necessary for datagenerating unregistered objects. All datageneration done in a GatherDataEvent handler must use the same RegistryAccess/RegistryOps instances (trying to encode an object in one set of registries that refers to an object in another set of registries will fail with strange holder errors).&lt;br /&gt;
&lt;br /&gt;
== Holders ==&lt;br /&gt;
&lt;br /&gt;
A Holder vaguely resembles a Pair&amp;lt;Key, Value&amp;gt; that either starts with a key and has a value bound later, or starts with a value and may have a key bound later.&lt;br /&gt;
&lt;br /&gt;
Many datapack registry elements must be constructed with Holders that refer to elements of other registries; for example, PlacedFeatures are constructed with a Holder of a ConfiguredFeature. When datagenerating objects, we can use &amp;lt;code&amp;gt;RegistryOps#registry&amp;lt;/code&amp;gt; to get a registry and &amp;lt;code&amp;gt;Registry#getOrCreateHolderOrThrow&amp;lt;/code&amp;gt; to produce key-only reference holders (the key being the only part of the holder we need, as holder codecs encode only the key of the holder when using a RegistryOps).&lt;br /&gt;
&lt;br /&gt;
Holders referring to datapack registry elements must be retrieved from the RegistryAccess/RegistryOps that will be used for datageneration; holders referring to static registry elements (such as blocks) can come directly from a ForgeRegistry as e.g. there is only ever one registry for blocks.&lt;br /&gt;
&lt;br /&gt;
= JsonCodecProvider =&lt;br /&gt;
&lt;br /&gt;
Forge provides a dataprovider for datapack registry elements that, given a registry key and a map of objects to datagenerate, datagenerates all elements in the map to the locations determined by their keys.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
void onGatherData(GatherDataEvent event)&lt;br /&gt;
{&lt;br /&gt;
  DataGenerator generator = event.getDataGenerator();&lt;br /&gt;
  ExistingFileHelper existingFileHelper = event.getExistingFileHelper();&lt;br /&gt;
  RegistryAccess registryAccess = RegistryAccess.builtinCopy();&lt;br /&gt;
  RegistryOps&amp;lt;JsonElement&amp;gt; registryOps = RegistryOps.create(JsonOps.INSTANCE, registryAccess);&lt;br /&gt;
&lt;br /&gt;
  ResourceLocation placedFeatureRL = new ResourceLocation(&amp;quot;modid&amp;quot;, &amp;quot;sponge_everywhere&amp;quot;);&lt;br /&gt;
  PlacedFeature placedFeature = new PlacedFeature(//etc;)&lt;br /&gt;
  // All placed features to be datagenerated can be in the map&lt;br /&gt;
  Map&amp;lt;ResourceLocation, PlacedFeature&amp;gt; map = Map.of(placedFeatureRL, placedFeature);&lt;br /&gt;
&lt;br /&gt;
  JsonCodecProvider provider = JsonCodecProvider.forDatapackRegistry(&lt;br /&gt;
    dataGenerator, existingFileHelper, &amp;quot;modid&amp;quot;, registryOps, Registry.PLACED_FEATURE_REGISTRY, map);&lt;br /&gt;
&lt;br /&gt;
  event.addProvider(event.includeServer(), provider);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>Commoble</name></author>
	</entry>
	<entry>
		<id>https://forge.gemwire.uk/index.php?title=Biome_Modifiers&amp;diff=3272</id>
		<title>Biome Modifiers</title>
		<link rel="alternate" type="text/html" href="https://forge.gemwire.uk/index.php?title=Biome_Modifiers&amp;diff=3272"/>
		<updated>2022-06-14T23:27:18Z</updated>

		<summary type="html">&lt;p&gt;Commoble: /* Biome Modifier JSONs */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Biome Modifiers are a data-driven system for modifying biomes. They have the ability to modify biomes in several ways:&lt;br /&gt;
&lt;br /&gt;
* Adding or removing worldgen features and carvers&lt;br /&gt;
* Adding or removing mob spawns and mob spawn costs&lt;br /&gt;
* Modifying the climate of a biome&lt;br /&gt;
* Modifying a biome's client effects, such as water color&lt;br /&gt;
&lt;br /&gt;
= Biome Modifier Types =&lt;br /&gt;
&lt;br /&gt;
To define a new type of biome modifier, begin by implementing a new class that extends &amp;lt;code&amp;gt;BiomeModifier&amp;lt;/code&amp;gt;. BiomeModifiers can usually be implemented as records, to reduce boilerplate.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
public record ExampleBiomeModifier() implements BiomeModifier&lt;br /&gt;
{&lt;br /&gt;
  public void modify(Holder&amp;lt;Biome&amp;gt; biome, Phase phase, Builder builder)&lt;br /&gt;
  {&lt;br /&gt;
    // This allows modifications to the given biome via the provided Builder.&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  public Codec&amp;lt;? extends BiomeModifier&amp;gt; codec()&lt;br /&gt;
  {&lt;br /&gt;
    // This must return a registered Codec, see Biome Modifier Serializers below.&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Beware! The modify method is called once per each phase per biome per biome modifier, so it's important to check which phase you're in and only make your changes in one phase.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
public void modify(Holder&amp;lt;Biome&amp;gt; biome, Phase phase, Builder builder)&lt;br /&gt;
{&lt;br /&gt;
  if (phase == Phase.ADD)&lt;br /&gt;
  {&lt;br /&gt;
    // add things to biomes&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Typically we also want to restrict biome modifiers to only apply to certain biomes. We can do that by accepting a HolderSet&amp;lt;Biome&amp;gt; in our constructor:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
public record ExampleBiomeModifier(HolderSet&amp;lt;Biome&amp;gt; biomes) implements BiomeModifier&lt;br /&gt;
{&lt;br /&gt;
  public void modify(Holder&amp;lt;Biome&amp;gt; biome, Phase phase, Builder builder)&lt;br /&gt;
  {&lt;br /&gt;
    if (phase == Phase.ADD &amp;amp;&amp;amp; biomes.contains(biome))&lt;br /&gt;
    {&lt;br /&gt;
      // add things to biomes&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We can also accept Holders or HolderSets for other [[Registration#Data_Driven_Entries|datapack registry elements]], such as PlacedFeatures, which allows our BiomeModifier to refer to those elements, which can then be defined in their own JSON files.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
public record ExampleBiomeModifier(HolderSet&amp;lt;Biome&amp;gt; biomes, Holder&amp;lt;PlacedFeature&amp;gt; feature) implements BiomeModifier&lt;br /&gt;
{&lt;br /&gt;
  public void modify(Holder&amp;lt;Biome&amp;gt; biome, Phase phase, Builder builder)&lt;br /&gt;
  {&lt;br /&gt;
    // add a feature to all specified biomes&lt;br /&gt;
    if (phase == Phase.ADD &amp;amp;&amp;amp; biomes.contains(biome))&lt;br /&gt;
    {&lt;br /&gt;
      builder.getGenerationSettings().addFeature(Decoration.UNDERGROUND_ORES, feature);&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Biome Modifier Serializers =&lt;br /&gt;
&lt;br /&gt;
Each type of biome modifier must have a [[Codecs|Codec]] registered for it; [[Registration#DeferredRegister|Deferred Registers]] are the recommended way to register biome modifier codecs.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
public class YourMod&lt;br /&gt;
{&lt;br /&gt;
  static DeferredRegister&amp;lt;Codec&amp;lt;? extends BiomeModifier&amp;gt;&amp;gt; BIOME_MODIFIER_SERIALIZERS =&lt;br /&gt;
    DeferredRegister.create(ForgeRegistries.Keys.BIOME_MODIFIER_SERIALIZERS, &amp;quot;yourmodid&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
  static RegistryObject&amp;lt;Codec&amp;lt;ExampleBiomeModifier&amp;gt;&amp;gt; EXAMPLE_CODEC = BIOME_MODIFIER_SERIALIZERS.register(&amp;quot;example&amp;quot;, () -&amp;gt;&lt;br /&gt;
    RecordCodecBuilder.create(builder -&amp;gt; builder.group(&lt;br /&gt;
        // declare fields&lt;br /&gt;
        Biome.LIST_CODEC.fieldOf(&amp;quot;biomes&amp;quot;).forGetter(ExampleBiomeModifier::biomes),&lt;br /&gt;
        PlacedFeature.CODEC.fieldOf(&amp;quot;feature&amp;quot;).forGetter(ExampleBiomeModifier::feature)&lt;br /&gt;
      // declare constructor&lt;br /&gt;
      ).apply(builder, ExampleBiomeModifier::new)));&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We can now implement the codec() method in our biome modifier class:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
public record ExampleBiomeModifier(HolderSet&amp;lt;Biome&amp;gt; biomes, Holder&amp;lt;PlacedFeature&amp;gt; feature) implements BiomeModifier&lt;br /&gt;
{&lt;br /&gt;
  public void modify(Holder&amp;lt;Biome&amp;gt; biome, Phase phase, Builder builder)&lt;br /&gt;
  {&lt;br /&gt;
    // add a feature to all specified biomes&lt;br /&gt;
    if (phase == Phase.ADD &amp;amp;&amp;amp; biomes.contains(biome))&lt;br /&gt;
    {&lt;br /&gt;
      builder.getGenerationSettings().addFeature(Decoration.UNDERGROUND_ORES, feature);&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  public Codec&amp;lt;? extends BiomeModifier&amp;gt; codec()&lt;br /&gt;
  {&lt;br /&gt;
    return YourMod.EXAMPLE_CODEC.get();&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Biome Modifier JSONs =&lt;br /&gt;
&lt;br /&gt;
Once we've registered a codec for our biome modifier type, we can define jsons for it. Biome modifier jsons must be defined in the directory &amp;lt;code&amp;gt;data/modid/forge/biome_modifier/&amp;lt;/code&amp;gt;; a biome modifier at &amp;lt;code&amp;gt;data/modid/forge/biome_modifier/your_biome_modifier.json&amp;lt;/code&amp;gt; has the namespaced id &amp;lt;code&amp;gt;modid:your_biome_modifier&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Our codec above defines the json format:&lt;br /&gt;
&lt;br /&gt;
* &amp;quot;biomes&amp;quot; is a special HolderSet field that accepts a single biome id, [list of biome ids], or #biome_tag.&lt;br /&gt;
* &amp;quot;feature&amp;quot; accepts a single placed feature id. [https://minecraft.fandom.com/wiki/Placed_feature These can be defined in jsons as well].&lt;br /&gt;
* We must also specify &amp;quot;type&amp;quot;: &amp;quot;yourmodid:example&amp;quot; to tell the data loader to use our registered codec to read our json.&lt;br /&gt;
&lt;br /&gt;
A json instance of our biome modifier that adds some feature to badlands biomes might look like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;json&amp;quot;&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;type&amp;quot;: &amp;quot;yourmodid:example&amp;quot;,&lt;br /&gt;
  &amp;quot;biomes&amp;quot;: &amp;quot;#minecraft:is_badlands&amp;quot;,&lt;br /&gt;
  &amp;quot;feature&amp;quot;: &amp;quot;yourmod:some_feature&amp;quot;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Side Note on HolderSets ==&lt;br /&gt;
&lt;br /&gt;
HolderSets are a vanilla feature that, when defined in JSON, can be specified as a single id, list of ids, or tag. Our example above uses a holderset of biomes, so all three of these are valid biome fields:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;json&amp;quot;&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;biomes&amp;quot;: &amp;quot;forest&amp;quot;,&lt;br /&gt;
  &amp;quot;biomes&amp;quot;: [&amp;quot;forest&amp;quot;, &amp;quot;birch_forest&amp;quot;],&lt;br /&gt;
  &amp;quot;biomes&amp;quot;: &amp;quot;#is_forest&amp;quot;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Builtin Biome Modifier Types =&lt;br /&gt;
&lt;br /&gt;
== None ==&lt;br /&gt;
&lt;br /&gt;
Forge provides a no-op biome modifier type, whose jsons have the following format:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;json&amp;quot;&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;type&amp;quot;: &amp;quot;forge:none&amp;quot;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This allows pack devs or server operators to disable mods' biome modifiers by overriding their biome modifier jsons with the above.&lt;br /&gt;
&lt;br /&gt;
= Best Practices =&lt;br /&gt;
&lt;br /&gt;
* Avoid using biome modifiers to add vanilla placed features to biomes, as this may cause a feature cycle violation (the game will crash if two biomes have the same two features in their feature lists but in different orders). Placed features can be referenced in biome jsons or added via biome modifiers, but should not be used in both.&lt;/div&gt;</summary>
		<author><name>Commoble</name></author>
	</entry>
	<entry>
		<id>https://forge.gemwire.uk/index.php?title=Main_Page&amp;diff=3141</id>
		<title>Main Page</title>
		<link rel="alternate" type="text/html" href="https://forge.gemwire.uk/index.php?title=Main_Page&amp;diff=3141"/>
		<updated>2022-06-10T00:14:45Z</updated>

		<summary type="html">&lt;p&gt;Commoble: Link to biome modifiers&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__NOTOC__&lt;br /&gt;
&amp;lt;templatestyles src=&amp;quot;:Main_Page/styles.css&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;center title&amp;quot;&amp;gt;Forge Community Wiki&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The Forge Community Wiki exists so that the community can:&lt;br /&gt;
&lt;br /&gt;
* collectively keep track of major changes and updates to Forge and Vanilla code;&lt;br /&gt;
* create and edit articles with in-depth explanations about a variety of Forge-related subjects; and&lt;br /&gt;
* contribute example code and tutorials for both simple and difficult concepts.&lt;br /&gt;
&lt;br /&gt;
This wiki is editable by any registered user with an account. This is to allow tracking of harmful edits, but isn't imposing any annoying limits. We welcome any edit, however small. Join the [https://discord.gg/Nn42eAh Discord] to discuss changes and edits to the wiki with others and the staff.&lt;br /&gt;
&lt;br /&gt;
{{Supported versions}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;center round_warning&amp;quot;&amp;gt;&lt;br /&gt;
Please read the [[FCWMeta:Wiki Policy|wiki policy]] before editing!&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;center&amp;quot; style=&amp;quot;margin-bottom: 2em&amp;quot;&amp;gt;&lt;br /&gt;
{{Supported versions|text=1}}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;box_container center&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;box&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;h3&amp;gt;Beginner Topics&amp;lt;/h3&amp;gt;&lt;br /&gt;
* [[Getting Started]]&lt;br /&gt;
* [[Proper Mod Structuring]]&lt;br /&gt;
* [[Mods.toml file]]&lt;br /&gt;
* [[Debug Profiler|The Debug Profiler]]&lt;br /&gt;
* [[Version Checker]]&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;box&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;h3&amp;gt;Common Concepts&amp;lt;/h3&amp;gt;&lt;br /&gt;
* [[Sides|Understanding Sides]]&lt;br /&gt;
* [[Events|Understanding Events]]&lt;br /&gt;
* [[Registration]]&lt;br /&gt;
* [[Internationalization]]&lt;br /&gt;
* [[Configs]]&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;box&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;h3&amp;gt;Forge Conventions&amp;lt;/h3&amp;gt;&lt;br /&gt;
* [[Semantic Versioning]]&lt;br /&gt;
* [[Stages of Modloading]]&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;box&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;h3&amp;gt;Resources and Data&amp;lt;/h3&amp;gt;&lt;br /&gt;
* [[Using Resources|Introduction]]&lt;br /&gt;
* [[Recipes]]&lt;br /&gt;
* [[Tags]]&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;box&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;h3&amp;gt;Blocks&amp;lt;/h3&amp;gt;&lt;br /&gt;
* [[Making Blocks|Creating Blocks]]&lt;br /&gt;
* [[Understanding Blockstates]] &lt;br /&gt;
* [[Interacting With Blocks|Block Interactions]]&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;box&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;h3&amp;gt;Items&amp;lt;/h3&amp;gt;&lt;br /&gt;
* [[Making Items]]&lt;br /&gt;
* [[Making Tools]]&lt;br /&gt;
* [[BlockEntityWithoutLevelRenderer|&amp;lt;tt&amp;gt;BlockEntityWithoutLevelRenderer&amp;lt;/tt&amp;gt;]]&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;box&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;h3&amp;gt;Data Generation&amp;lt;/h3&amp;gt;&lt;br /&gt;
* [[Datageneration|Introduction]]&lt;br /&gt;
* [[Datageneration/Recipes|Recipes]]&lt;br /&gt;
* [[Datageneration/Tags|Tags]]&lt;br /&gt;
* [[Datageneration/Loot_Tables|Loot Tables]]&lt;br /&gt;
* [[Datageneration/I18n|Localization]]&lt;br /&gt;
* [[Datageneration/States and Models|&amp;lt;tt&amp;gt;BlockState&amp;lt;/tt&amp;gt;s and Models]]&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;box&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;h3&amp;gt;Block Entities&amp;lt;/h3&amp;gt;&lt;br /&gt;
* [[Block Entities|Introduction]]&lt;br /&gt;
* [[Block Entity Renderer|&amp;lt;tt&amp;gt;BlockEntityRenderer&amp;lt;/tt&amp;gt;]]&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;box&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;h3&amp;gt;Models&amp;lt;/h3&amp;gt;&lt;br /&gt;
* [[Introduction to Models|Introduction]]&lt;br /&gt;
* [[Model JSONs]]&lt;br /&gt;
* [[BlockState JSONs]]&lt;br /&gt;
* [[Coloring textures dynamically|Dynamically Colored Textures]]&lt;br /&gt;
* [[Item Properties]]&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;box&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;h3&amp;gt;Handling Information&amp;lt;/h3&amp;gt;&lt;br /&gt;
* [[Understanding Networking|Introduction]]&lt;br /&gt;
* [[Using NBT|Named Binary Tag (NBT)]]&lt;br /&gt;
* [[Using FriendlyByteBuf|Using &amp;lt;tt&amp;gt;FriendlyByteBuf&amp;lt;/tt&amp;gt;]]&lt;br /&gt;
* [[Sending Packets|Sending and Receiving Packets]]&lt;br /&gt;
* [[Using SimpleChannel|Using &amp;lt;tt&amp;gt;SimpleChannel&amp;lt;/tt&amp;gt;]]&lt;br /&gt;
* [[Networking with Entities]]&lt;br /&gt;
* [[DynamicOps|Using DynamicOps]]&lt;br /&gt;
* [[Codecs|Using Codecs]]&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;box&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;h3&amp;gt;Data Storage&amp;lt;/h3&amp;gt;&lt;br /&gt;
* [[Capabilities|Understanding Capabilities]] &lt;br /&gt;
* [[Capabilities/Attaching|Attaching Capabilities]]&lt;br /&gt;
* [[Saved Data]]&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;box&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;h3&amp;gt;Game Effects&amp;lt;/h3&amp;gt;&lt;br /&gt;
* [[Mob Effects]]&lt;br /&gt;
* [[Potions]]&lt;br /&gt;
* [[Particles]]&lt;br /&gt;
* [[Sounds]]&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;box&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;h3&amp;gt;Events&amp;lt;/h3&amp;gt;&lt;br /&gt;
* [[Events|Understanding Events]]&lt;br /&gt;
* [[Entity Events]]&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;box&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;h3&amp;gt;Others&amp;lt;/h3&amp;gt;&lt;br /&gt;
* [[Dependencies]]&lt;br /&gt;
* [[Dynamic Loot Modification]]&lt;br /&gt;
* [[Components|Components and Translation Keys]]&lt;br /&gt;
* [[Key Mappings]]&lt;br /&gt;
* [[Access Transformers]]&lt;br /&gt;
* [[Toolchain]]&lt;br /&gt;
* [[Game_Tests|Game Tests]]&lt;br /&gt;
* [[Biome_Modifiers|Biome Modifiers]]&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;box&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;h3&amp;gt;Recipes&amp;lt;/h3&amp;gt;&lt;br /&gt;
* [[Recipes]]&lt;br /&gt;
* [[Custom Recipes|Custom Recipe Types]]&lt;br /&gt;
* [[Datageneration/Recipes|Datageneration]]&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;/div&gt;</summary>
		<author><name>Commoble</name></author>
	</entry>
	<entry>
		<id>https://forge.gemwire.uk/index.php?title=Biome_Modifiers&amp;diff=3140</id>
		<title>Biome Modifiers</title>
		<link rel="alternate" type="text/html" href="https://forge.gemwire.uk/index.php?title=Biome_Modifiers&amp;diff=3140"/>
		<updated>2022-06-10T00:12:07Z</updated>

		<summary type="html">&lt;p&gt;Commoble: Biome modifiers documentation&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Biome Modifiers are a data-driven system for modifying biomes. They have the ability to modify biomes in several ways:&lt;br /&gt;
&lt;br /&gt;
* Adding or removing worldgen features and carvers&lt;br /&gt;
* Adding or removing mob spawns and mob spawn costs&lt;br /&gt;
* Modifying the climate of a biome&lt;br /&gt;
* Modifying a biome's client effects, such as water color&lt;br /&gt;
&lt;br /&gt;
= Biome Modifier Types =&lt;br /&gt;
&lt;br /&gt;
To define a new type of biome modifier, begin by implementing a new class that extends &amp;lt;code&amp;gt;BiomeModifier&amp;lt;/code&amp;gt;. BiomeModifiers can usually be implemented as records, to reduce boilerplate.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
public record ExampleBiomeModifier() implements BiomeModifier&lt;br /&gt;
{&lt;br /&gt;
  public void modify(Holder&amp;lt;Biome&amp;gt; biome, Phase phase, Builder builder)&lt;br /&gt;
  {&lt;br /&gt;
    // This allows modifications to the given biome via the provided Builder.&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  public Codec&amp;lt;? extends BiomeModifier&amp;gt; codec()&lt;br /&gt;
  {&lt;br /&gt;
    // This must return a registered Codec, see Biome Modifier Serializers below.&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Beware! The modify method is called once per each phase per biome per biome modifier, so it's important to check which phase you're in and only make your changes in one phase.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
public void modify(Holder&amp;lt;Biome&amp;gt; biome, Phase phase, Builder builder)&lt;br /&gt;
{&lt;br /&gt;
  if (phase == Phase.ADD)&lt;br /&gt;
  {&lt;br /&gt;
    // add things to biomes&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Typically we also want to restrict biome modifiers to only apply to certain biomes. We can do that by accepting a HolderSet&amp;lt;Biome&amp;gt; in our constructor:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
public record ExampleBiomeModifier(HolderSet&amp;lt;Biome&amp;gt; biomes) implements BiomeModifier&lt;br /&gt;
{&lt;br /&gt;
  public void modify(Holder&amp;lt;Biome&amp;gt; biome, Phase phase, Builder builder)&lt;br /&gt;
  {&lt;br /&gt;
    if (phase == Phase.ADD &amp;amp;&amp;amp; biomes.contains(biome))&lt;br /&gt;
    {&lt;br /&gt;
      // add things to biomes&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We can also accept Holders or HolderSets for other [[Registration#Data_Driven_Entries|datapack registry elements]], such as PlacedFeatures, which allows our BiomeModifier to refer to those elements, which can then be defined in their own JSON files.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
public record ExampleBiomeModifier(HolderSet&amp;lt;Biome&amp;gt; biomes, Holder&amp;lt;PlacedFeature&amp;gt; feature) implements BiomeModifier&lt;br /&gt;
{&lt;br /&gt;
  public void modify(Holder&amp;lt;Biome&amp;gt; biome, Phase phase, Builder builder)&lt;br /&gt;
  {&lt;br /&gt;
    // add a feature to all specified biomes&lt;br /&gt;
    if (phase == Phase.ADD &amp;amp;&amp;amp; biomes.contains(biome))&lt;br /&gt;
    {&lt;br /&gt;
      builder.getGenerationSettings().addFeature(Decoration.UNDERGROUND_ORES, feature);&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Biome Modifier Serializers =&lt;br /&gt;
&lt;br /&gt;
Each type of biome modifier must have a [[Codecs|Codec]] registered for it; [[Registration#DeferredRegister|Deferred Registers]] are the recommended way to register biome modifier codecs.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
public class YourMod&lt;br /&gt;
{&lt;br /&gt;
  static DeferredRegister&amp;lt;Codec&amp;lt;? extends BiomeModifier&amp;gt;&amp;gt; BIOME_MODIFIER_SERIALIZERS =&lt;br /&gt;
    DeferredRegister.create(ForgeRegistries.Keys.BIOME_MODIFIER_SERIALIZERS, &amp;quot;yourmodid&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
  static RegistryObject&amp;lt;Codec&amp;lt;ExampleBiomeModifier&amp;gt;&amp;gt; EXAMPLE_CODEC = BIOME_MODIFIER_SERIALIZERS.register(&amp;quot;example&amp;quot;, () -&amp;gt;&lt;br /&gt;
    RecordCodecBuilder.create(builder -&amp;gt; builder.group(&lt;br /&gt;
        // declare fields&lt;br /&gt;
        Biome.LIST_CODEC.fieldOf(&amp;quot;biomes&amp;quot;).forGetter(ExampleBiomeModifier::biomes),&lt;br /&gt;
        PlacedFeature.CODEC.fieldOf(&amp;quot;feature&amp;quot;).forGetter(ExampleBiomeModifier::feature)&lt;br /&gt;
      // declare constructor&lt;br /&gt;
      ).apply(builder, ExampleBiomeModifier::new)));&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We can now implement the codec() method in our biome modifier class:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
public record ExampleBiomeModifier(HolderSet&amp;lt;Biome&amp;gt; biomes, Holder&amp;lt;PlacedFeature&amp;gt; feature) implements BiomeModifier&lt;br /&gt;
{&lt;br /&gt;
  public void modify(Holder&amp;lt;Biome&amp;gt; biome, Phase phase, Builder builder)&lt;br /&gt;
  {&lt;br /&gt;
    // add a feature to all specified biomes&lt;br /&gt;
    if (phase == Phase.ADD &amp;amp;&amp;amp; biomes.contains(biome))&lt;br /&gt;
    {&lt;br /&gt;
      builder.getGenerationSettings().addFeature(Decoration.UNDERGROUND_ORES, feature);&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  public Codec&amp;lt;? extends BiomeModifier&amp;gt; codec()&lt;br /&gt;
  {&lt;br /&gt;
    return YourMod.EXAMPLE_CODEC.get();&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Biome Modifier JSONs =&lt;br /&gt;
&lt;br /&gt;
Once we've registered a codec for our biome modifier type, we can define jsons for it. Biome modifier jsons must be defined in the directory &amp;lt;code&amp;gt;data/modid/forge/biome_modifier/&amp;lt;/code&amp;gt;; a biome modifier at &amp;lt;code&amp;gt;data/modid/forge/biome_modifier/your_biome_modifier.json&amp;lt;/code&amp;gt; has the namespaced id &amp;lt;code&amp;gt;modid:your_biome_modifier&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Our codec above defines the json format:&lt;br /&gt;
&lt;br /&gt;
* &amp;quot;biomes&amp;quot; is a special HolderSet field that accepts a single biome id, [list of biome ids], or #biome_tag.&lt;br /&gt;
* &amp;quot;feature&amp;quot; accepts a single placed feature id. [https://minecraft.fandom.com/wiki/Placed_feature These can be defined in jsons as well].&lt;br /&gt;
* We must also specify &amp;quot;type&amp;quot;: &amp;quot;yourmodid:example&amp;quot; to tell the data loader to use our registered codec to read our json.&lt;br /&gt;
&lt;br /&gt;
A json instance of our biome modifier that adds some feature to badlands biomes might look like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;json&amp;quot;&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;type&amp;quot;: &amp;quot;yourmodid:example&amp;quot;,&lt;br /&gt;
  &amp;quot;biomes&amp;quot;: &amp;quot;#minecraft:is_badlands&amp;quot;,&lt;br /&gt;
  &amp;quot;feature&amp;quot;: &amp;quot;yourmod:some_feature&amp;quot;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Builtin Biome Modifier Types =&lt;br /&gt;
&lt;br /&gt;
== None ==&lt;br /&gt;
&lt;br /&gt;
Forge provides a no-op biome modifier type, whose jsons have the following format:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;json&amp;quot;&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;type&amp;quot;: &amp;quot;forge:none&amp;quot;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This allows pack devs or server operators to disable mods' biome modifiers by overriding their biome modifier jsons with the above.&lt;br /&gt;
&lt;br /&gt;
= Best Practices =&lt;br /&gt;
&lt;br /&gt;
* Avoid using biome modifiers to add vanilla placed features to biomes, as this may cause a feature cycle violation (the game will crash if two biomes have the same two features in their feature lists but in different orders). Placed features can be referenced in biome jsons or added via biome modifiers, but should not be used in both.&lt;/div&gt;</summary>
		<author><name>Commoble</name></author>
	</entry>
	<entry>
		<id>https://forge.gemwire.uk/index.php?title=Codecs&amp;diff=2904</id>
		<title>Codecs</title>
		<link rel="alternate" type="text/html" href="https://forge.gemwire.uk/index.php?title=Codecs&amp;diff=2904"/>
		<updated>2021-08-06T20:41:34Z</updated>

		<summary type="html">&lt;p&gt;Commoble: Fix incorrect name in pair codec example&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Codecs are a serialization tool from mojang's DataFixerUpper library. Codecs are used alongside [[DynamicOps|DynamicOps]] to allow objects to be serialized to different formats and back, such as JSON or [[Using_NBT|NBT]]. While the DynamicOps describes the format the object is to be serialized to, the Codec describes the manner in which the object is to be serialized; a single Codec can be used to serialize an object to any format for which a DynamicOps exists. Codecs and DynamicOps jointly form an abstraction layer over data serialization, simplifying the effort needed to serialize or deserialize data.&lt;br /&gt;
&lt;br /&gt;
= Using Codecs =&lt;br /&gt;
&lt;br /&gt;
== Serialization and Deserialization ==&lt;br /&gt;
&lt;br /&gt;
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 &amp;lt;code&amp;gt;Codec#encodeStart&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;Codec#parse&amp;lt;/code&amp;gt;, respectively. Given a Codec&amp;lt;SomeJavaType&amp;gt; and a DynamicOps&amp;lt;SomeSerializedType&amp;gt;, we can convert instances of SomeJavaType to instances of SomeSerializedType and back.&lt;br /&gt;
&lt;br /&gt;
Each of these methods take a [[DynamicOps]] instance and an instance of the object we are serializing or deserializing, and returns a DataResult:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
// let someCodec be a Codec&amp;lt;SomeJavaType&amp;gt;&lt;br /&gt;
// let someJavaObject be an instance of SomeJavaType&lt;br /&gt;
// let someTag and someJsonElement be instances of Tag and JsonElement, respectively&lt;br /&gt;
&lt;br /&gt;
// serialize some java object to Tag&lt;br /&gt;
DataResult&amp;lt;Tag&amp;gt; result = someCodec.encodeStart(NBTOps.INSTANCE, someJavaObject);&lt;br /&gt;
&lt;br /&gt;
// deserialize some Tag instance back to a proper java object&lt;br /&gt;
DataResult&amp;lt;SomeJavaType&amp;gt; result = someCodec.parse(NBTOps.INSTANCE, someTag );&lt;br /&gt;
&lt;br /&gt;
// serialize some java object to a JsonElement&lt;br /&gt;
DataResult&amp;lt;JsonElement&amp;gt; result = someCodec.encodeStart(JsonOps.INSTANCE, someJavaObject);&lt;br /&gt;
&lt;br /&gt;
// deserialize a JsonElement back to a proper java object&lt;br /&gt;
DataResult&amp;lt;SomeJavaType&amp;gt; result = someCodec.parse(JsonOps.INSTANCE, someJsonElement);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A DataResult either holds the converted instance, or it holds some error data, depending on whether the conversion was successful or not, respectively. There are several things we can do with this DataResult; &amp;lt;code&amp;gt;DataResult#result&amp;lt;/code&amp;gt; simply returns an Optional containing the converted object if the conversion was successful, while &amp;lt;code&amp;gt;DataResult#resultOrPartial&amp;lt;/code&amp;gt; also runs a given function if the conversion was unsuccessful (in addition to returning the Optional). #resultOrPartial is particularly useful for logging errors during datapack deserialization:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
// deserialize something from json&lt;br /&gt;
someCodec.parse(JsonOps.INSTANCE, someJsonElement)&lt;br /&gt;
	.resultOrPartial(errorMessage -&amp;gt; doSomethingIfBadData(errorMessage))&lt;br /&gt;
	.ifPresent(someJavaObject -&amp;gt; doSomethingIfGoodData(someJavaObject))&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Builtin Codecs ==&lt;br /&gt;
=== Primitive Codecs ===&lt;br /&gt;
The Codec class itself contains static instances of codecs for all supported primitive types, e.g. &amp;lt;code&amp;gt;Codec.STRING&amp;lt;/code&amp;gt; is the canonical &amp;lt;code&amp;gt;Codec&amp;lt;String&amp;gt;&amp;lt;/code&amp;gt; implementation. Primitive codecs include:&lt;br /&gt;
* BOOL, which serializes to a boolean value&lt;br /&gt;
* BYTE, SHORT, INT, LONG, FLOAT, and DOUBLE, which serialize to numeric values&lt;br /&gt;
* STRING, which serializes to a string&lt;br /&gt;
* BYTE_BUFFER, INT_STREAM, and LONG_STREAM, which serialize to lists of numbers&lt;br /&gt;
* EMPTY, which represents null objects&lt;br /&gt;
&lt;br /&gt;
=== Other Builtin Codecs ===&lt;br /&gt;
Vanilla minecraft has many builtin codecs for objects that it frequently serializes. These codecs are typically static instances in the class the codec is serializing; e.g. &amp;lt;code&amp;gt;ResourceLocation.CODEC&amp;lt;/code&amp;gt; is the canonical &amp;lt;code&amp;gt;Codec&amp;lt;ResourceLocation&amp;gt;&amp;lt;/code&amp;gt;, while &amp;lt;code&amp;gt;BlockPos.CODEC&amp;lt;/code&amp;gt; is the codec used for serializing a BlockPos.&lt;br /&gt;
&lt;br /&gt;
Each vanilla &amp;lt;code&amp;gt;Registry&amp;lt;/code&amp;gt; acts as the Codec for the type of object the registry contains; e.g. &amp;lt;code&amp;gt;Registry.BLOCK&amp;lt;/code&amp;gt; is itself a &amp;lt;code&amp;gt;Codec&amp;lt;Block&amp;gt;&amp;lt;/code&amp;gt;. Forge Registries, however, do not currently implement Codec and cannot yet be used in this way; custom codecs must be created for forge-specific registries that are not tied to specific vanilla registries.&lt;br /&gt;
&lt;br /&gt;
Of particular note here is the CompoundTag.CODEC, which can be used to e.g. serialize a CompoundTag into a json file. This has a notable limitation in that CompoundTag.CODEC *cannot* safely deserialize lists of numbers from json, due to the strong typing of ListTag and the way that the NBTOps deserializer reads numeric values.&lt;br /&gt;
&lt;br /&gt;
= Creating Codecs =&lt;br /&gt;
&lt;br /&gt;
Suppose we have the following class, and we want to deserialize json files to instances of this class:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
public class ExampleCodecClass {&lt;br /&gt;
&lt;br /&gt;
    private final int someInt;&lt;br /&gt;
    private final Item item;&lt;br /&gt;
    private final List&amp;lt;BlockPos&amp;gt; blockPositions;&lt;br /&gt;
&lt;br /&gt;
    public ExampleCodecClass(int someInt, Item item, List&amp;lt;BlockPos&amp;gt; blockPositions) {...}&lt;br /&gt;
&lt;br /&gt;
    public int getSomeInt() { return this.someInt; }&lt;br /&gt;
    public Item getItem() { return this.item; }&lt;br /&gt;
    public List&amp;lt;BlockPos&amp;gt; getBlockPositions() { return this.blockPositions; }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Where a json file for an instance of this class might look like:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;json&amp;quot;&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
	&amp;quot;some_int&amp;quot;: 42,&lt;br /&gt;
	&amp;quot;item&amp;quot;: &amp;quot;minecraft:gold_ingot&amp;quot;,&lt;br /&gt;
	&amp;quot;block_positions&amp;quot;:&lt;br /&gt;
	[&lt;br /&gt;
		[0,0,0],&lt;br /&gt;
		[10,20,-100]&lt;br /&gt;
	]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We can assemble a codec for this class by building a new codec out of smaller codecs. We'll need a codec for each of these fields:&lt;br /&gt;
* a &amp;lt;code&amp;gt;Codec&amp;lt;Integer&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
* a &amp;lt;code&amp;gt;Codec&amp;lt;Item&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
* a &amp;lt;code&amp;gt;Codec&amp;lt;List&amp;lt;BlockPos&amp;gt;&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
And then we'll need to assemble these into a &amp;lt;code&amp;gt;Codec&amp;lt;ExampleCodecClass&amp;gt;&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
As previously mentioned, we can use &amp;lt;code&amp;gt;Codec.INT&amp;lt;/code&amp;gt; for the integer codec, and &amp;lt;code&amp;gt;Registry.ITEM&amp;lt;/code&amp;gt; for the Item codec. We don't have a builtin codec for list-of-blockpos, but we can use BlockPos.CODEC to create one.&lt;br /&gt;
&lt;br /&gt;
== Lists ==&lt;br /&gt;
The &amp;lt;code&amp;gt;Codec#listOf&amp;lt;/code&amp;gt; instance method can be used to generate a codec for a List from an existing codec:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
// BlockPos.CODEC is a Codec&amp;lt;BlockPos&amp;gt;&lt;br /&gt;
Codec&amp;lt;List&amp;lt;BlockPos&amp;gt;&amp;gt; = BlockPos.CODEC.listOf();&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Codecs created via listOf() serialize things to listlike objects, such as [] json arrays or ListTags.&lt;br /&gt;
&lt;br /&gt;
Deserializing a list in this manner produces an ''immutable'' list. If a mutable list is needed, [[Codecs#Equivalent_Types_and_xmap|xmap]] can be used to convert the list after deserializing.&lt;br /&gt;
&lt;br /&gt;
== Records ==&lt;br /&gt;
RecordCodecBuilder is used to generate codecs that serialize instances of classes with explicitly named fields, like our example above. Codecs created via RecordCodecBuilder serialize things to maplike objects, such as {} json objects or CompoundTags.&lt;br /&gt;
&lt;br /&gt;
RecordCodecBuilder can be used in several ways, but the simplest form is as follows:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
public static final Codec&amp;lt;SomeJavaClass&amp;gt; = RecordCodecBuilder.create(instance -&amp;gt; instance.group(&lt;br /&gt;
		someFieldCodecA.fieldOf(&amp;quot;field_name_a&amp;quot;).forGetter(SomeJavaClass::getFieldA),&lt;br /&gt;
		someFieldCodecB.fieldOf(&amp;quot;field_name_b&amp;quot;).forGetter(SomeJavaClass::getFieldB),&lt;br /&gt;
		someFieldCodecC.fieldOf(&amp;quot;field_name_c&amp;quot;).forGetter(SomeJavaClass::getFieldC),&lt;br /&gt;
		// up to 16 fields can be declared here&lt;br /&gt;
	).apply(instance, SomeJavaClass::new));&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Where each line in the group specifies a codec instance for the type of that field, the field name in the serialized object, and the corresponding getter function in the java class. The builder is concluded by specifying a constructor or factory for the java class whose arguments are the previously defined fields in the same order.&lt;br /&gt;
&lt;br /&gt;
For example, using RecordCodecBuilder to create a codec for our example class above:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
public static final Codec&amp;lt;ExampleCodecClass&amp;gt; = RecordCodecBuilder.create(instance -&amp;gt; instance.group(&lt;br /&gt;
		Codec.INT.fieldOf(&amp;quot;some_int&amp;quot;).forGetter(ExampleCodecClass::getSomeInt),&lt;br /&gt;
		Registry.ITEM.fieldOf(&amp;quot;item&amp;quot;).forGetter(ExampleCodecClass::getItem),&lt;br /&gt;
		BlockPos.CODEC.listOf().fieldOf(&amp;quot;block_positions&amp;quot;).forGetter(ExampleCodecClass::getBlockPositions)&lt;br /&gt;
	).apply(instance, ExampleCodecClass::new));&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Optional and Default Values in Record Fields===&lt;br /&gt;
When RecordCodecBuilder is used as shown above, all of the fields are *required* to be in the serialized object (the JsonObject/CompoundTag/etc), or the entire thing will fail to parse when the codec tries to deserialize it. If we wish to have optional or default values, we have several alternatives of fieldOf() we can use.&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;someCodec.optionalFieldOf(&amp;quot;field_name&amp;quot;)&amp;lt;/code&amp;gt; creates a field for an Optional. If the field in the json/nbt is not present or invalid, it will deserialize as an empty optional. Empty optionals will not be serialized; the field will be omitted from the json or nbt.&lt;br /&gt;
* &amp;lt;code&amp;gt;someCodec.optionalFieldOf(&amp;quot;field_name&amp;quot;, someDefaultValue)&amp;lt;/code&amp;gt; creates an optional field that deserializes as the given default value if the field is not present in the json/nbt. When serializing, if the field in the java object equals the default value, the value will not be serialized and the field will be omitted from the json or nbt.&lt;br /&gt;
&lt;br /&gt;
When using optional fields, be wary that if the field contains bad data or otherwise fails to serialize, the error will be silently caught, and the field will serialize as the default value instead!&lt;br /&gt;
&lt;br /&gt;
===Boxing values as objects===&lt;br /&gt;
In some situations, we may need to serialize a single value as a single-field object. We can use fieldOf to box a single value in this way without needing the entire RecordCodecBuilder process:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
public static final Codec&amp;lt;Integer&amp;gt; BOXED_INT_CODEC = Codec.INT.fieldOf(&amp;quot;value&amp;quot;).codec();&lt;br /&gt;
&lt;br /&gt;
JsonElement value = BOXED_INT_CODEC.encodeStart(JsonOps.INSTANCE, 5).result().get();&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Which serializes the following output:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;json&amp;quot;&amp;gt;&lt;br /&gt;
{&amp;quot;value&amp;quot;:5}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Unit==&lt;br /&gt;
The &amp;lt;code&amp;gt;Codec.unit(defaultValue)&amp;lt;/code&amp;gt; codec creates a Codec that always deserializes a specified default value, regardless of input. When serializing, it serializes nothing.&lt;br /&gt;
&lt;br /&gt;
==Pair==&lt;br /&gt;
The &amp;lt;code&amp;gt;Codec.pair(codecA, codecB)&amp;lt;/code&amp;gt; static method takes two codecs and generates a Codec&amp;lt;Pair&amp;lt;A,B&amp;gt;&amp;gt; from them.&lt;br /&gt;
&lt;br /&gt;
The only valid arguments for this method are codecs that serialize to objects with explicit fields, such as codecs created using [[Codecs#Records|RecordCodecBuilder]] or [[Codecs#Boxing_values_as_objects|fieldOf]]. Codecs that serialize nothing (such as [[Codecs#Unit|unit codecs]]) are also valid as they act as objects-with-no-fields.&lt;br /&gt;
&lt;br /&gt;
The resulting Pair codec will serialize a single object that has all of the fields of the two original codecs. For example:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
public static final Codec&amp;lt;Pair&amp;lt;Integer,String&amp;gt;&amp;gt; PAIR_CODEC = Codec.pair(&lt;br /&gt;
	Codec.INT.fieldOf(&amp;quot;value&amp;quot;).codec(),&lt;br /&gt;
	Codec.STRING.fieldOf(&amp;quot;name&amp;quot;).codec());&lt;br /&gt;
&lt;br /&gt;
JsonElement encodedPair = PAIR_CODEC.encodeStart(JsonOps.INSTANCE, Pair.of(5, &amp;quot;cheese&amp;quot;).result().get();&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
This codec serializes the above value to:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;json&amp;quot;&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
	&amp;quot;value&amp;quot;: 5,&lt;br /&gt;
	&amp;quot;name&amp;quot;: &amp;quot;cheese&amp;quot;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Codecs that serialize to objects with undefined fields such as [[Codecs#Maps|unboundedMap]] may cause strange and unpredictable behaviour when used here; these objects should be boxed via fieldOf when used in a pair codec.&lt;br /&gt;
&lt;br /&gt;
==Either==&lt;br /&gt;
The &amp;lt;code&amp;gt;Codec.either(codecA, codecB)&amp;lt;/code&amp;gt; static method takes two codecs and generates a Codec&amp;lt;Either&amp;lt;A,B&amp;gt;&amp;gt; from them.&lt;br /&gt;
&lt;br /&gt;
When this codec is used to de/serialize an object, it first attempts to use the first codec; if and only if that conversion fails, it then attempts to use the second codec. If that conversion also fails, then the returned DataResult will contain the error data from the *second* codec's conversion attempt.&lt;br /&gt;
&lt;br /&gt;
==Numeric Ranges==&lt;br /&gt;
The &amp;lt;code&amp;gt;Codec.intRange(min,max)&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;Codec.floatRange(min,max)&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;Codec.doubleRange(min,max)&amp;lt;/code&amp;gt; static methods generate Codecs for Integers, Floats, or Doubles, respectively, for which only a specified inclusive range is valid, and values outside that range will fail to de/serialize.&lt;br /&gt;
&lt;br /&gt;
==Maps==&lt;br /&gt;
Suppose we want to serialize a HashMap or other Map type, where we could have indefinitely many key-value pairs and we don't know what the keys are ahead of time.&lt;br /&gt;
&lt;br /&gt;
We can create a &amp;lt;code&amp;gt;Codec&amp;lt;Map&amp;lt;KEY,VALUE&amp;gt;&amp;gt;&amp;lt;/code&amp;gt; using the &amp;lt;code&amp;gt;Codec.unboundedMap&amp;lt;/code&amp;gt; static method, which takes a key codec and a value codec and creates a codec for a map type:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
public static final Codec&amp;lt;Map&amp;lt;String, BlockPos&amp;gt;&amp;gt; = Codec.unboundedMap(Codec.STRING, BlockPos.CODEC);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The serialized form of maps serialized by this codec will be a JsonObject or CompoundTag, whose fields are the key-value pairs in the map; the map's keys will be used as the field names, and the map's values will be the values of those fields&lt;br /&gt;
&lt;br /&gt;
A limitation of using unboundedMap is that it only supports key codecs that serialize to Strings (including codecs for things like ResourceLocation that aren't Strings themselves but still serialize to strings). To create a codec for a Map whose keys are not fundamentally strings, the Map must be serialized as a list of key-value pairs instead of using unboundedMap.&lt;br /&gt;
&lt;br /&gt;
==Equivalent Types and xmap==&lt;br /&gt;
Suppose we have two java classes, Amalgam and Box; any Amalgam instance can be converted to a Box, and vice-versa. Now suppose we have a Codec&amp;lt;Amalgam&amp;gt;, but we'd also like to have a Codec&amp;lt;Box&amp;gt;. Rather than creating an entirely new codec for Box from scratch, we can simply xmap our Amalgam codec instead.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;Codec#xmap&amp;lt;/code&amp;gt; instance method is used to generate a second codec for a fundamentally equivalent type to the first codec's type. The method takes two function objects as arguments, which are used to convert the first type to the second when deserializing, and converting the second type to the first when serializing:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
public static final Codec&amp;lt;Box&amp;gt; = Amalgam.CODEC.xmap(Amalgam::toBox, Box::toAmalgam);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Codecs created in this manner will serialize objects in the same format as the starting codec.&lt;br /&gt;
&lt;br /&gt;
==Partially Equivalent Types, flatComapMap, comapFlatMap, and flatXMap==&lt;br /&gt;
Consider the ResourceLocation: Any ResourceLocation can be converted to a String, but not all Strings can be converted to a ResourceLocation; ResourceLocations have strict limits on their format and allowed characters.&lt;br /&gt;
&lt;br /&gt;
While we *could* use xmap to convert the Codec.STRING to a codec for ResourceLocations, this would cause attempts to parse an invalid string like &amp;lt;code&amp;gt;SHOUTY:MOD:Invalid$Characters&amp;lt;/code&amp;gt; to throw a runtime exception, when we really should be returning a failed DataResult to the parser instead -- which indeed is what the vanilla ResourceLocation codec does.&lt;br /&gt;
&lt;br /&gt;
Codecs have three additional instance methods for creating equivalent codecs for when we can *potentially* convert one type to another, but are not guaranteed to be able to do so. These take conversion function arguments that return DataResults, allowing validation to be performed during serialization and deserialization.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ Codec Conversion Methods&lt;br /&gt;
|-&lt;br /&gt;
! Can A always be converted to B? !! Can B always be converted to A? !! Which method of codecA should be used to create codecB?&lt;br /&gt;
|-&lt;br /&gt;
| yes || yes || codecA.xmap&lt;br /&gt;
|-&lt;br /&gt;
| yes || no || codecA.flatComapMap&lt;br /&gt;
|-&lt;br /&gt;
| no || yes || codecA.comapFlatMap&lt;br /&gt;
|-&lt;br /&gt;
| no || no || codecA.flatXmap&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Registry Dispatch ==&lt;br /&gt;
Registry Dispatch Codecs allow us to define a registry of codecs and delegate to a specific codec to deserialize a particular json based on a type field in that json. Dispatch codecs are used extensively when deserializing worldgen data.&lt;br /&gt;
&lt;br /&gt;
To create a dispatch codec for a Thing class, the following steps can be performed:&lt;br /&gt;
# Create a Thing abstract class class and ThingType interface. The ThingType interface should have a method that supplies a Codec&amp;lt;Thing&amp;gt;, while Thing subclasses must define a method that supplies a ThingType.&lt;br /&gt;
# Create a map or registry of ThingTypes, and register a ThingType for each sub-codec we want to have.&lt;br /&gt;
# Create a Codec&amp;lt;ThingType&amp;gt;, or have the ThingType registry implement Codec.&lt;br /&gt;
# Create our Codec&amp;lt;Thing&amp;gt; master codec by invoking &amp;lt;code&amp;gt;Codec#dispatch&amp;lt;/code&amp;gt; on our ThingType codec. This method's arguments are:&lt;br /&gt;
## A field name for the ID of the sub-codec (the example json below is using &amp;quot;type&amp;quot;)&lt;br /&gt;
## A function to retrieve a ThingType from a Thing&lt;br /&gt;
## A function to retrieve a Codec&amp;lt;Thing&amp;gt; from a ThingType&lt;br /&gt;
&lt;br /&gt;
We can then use our Codec&amp;lt;Thing&amp;gt; to create Thing fields in other codecs whose serialized format depends on the specific sub-codec used by a Thing instance.&lt;br /&gt;
&lt;br /&gt;
As an example of this, consider the ExampleCodecClass earlier. Suppose we make this class extend Thing and register our codec for it to a codec dispatch registry with the id &amp;quot;ourmod:exampleclass&amp;quot;. If we were to define an instance of this class in a Thing field in some json, it would look like&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;json&amp;quot;&amp;gt;&lt;br /&gt;
&amp;quot;some_thing&amp;quot;:&lt;br /&gt;
{&lt;br /&gt;
	&amp;quot;type&amp;quot;: &amp;quot;ourmod:exampleclass&amp;quot;,&lt;br /&gt;
	&amp;quot;some_int&amp;quot;: 42,&lt;br /&gt;
	&amp;quot;item&amp;quot;: &amp;quot;minecraft:gold_ingot&amp;quot;,&lt;br /&gt;
	&amp;quot;block_positions&amp;quot;:&lt;br /&gt;
	[&lt;br /&gt;
		[0,0,0],&lt;br /&gt;
		[10,20,-100]&lt;br /&gt;
	]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Other ThingTypes we register would have different fields in this json object, but would still be valid for the &amp;quot;some_thing&amp;quot; field.&lt;br /&gt;
&lt;br /&gt;
Several examples of vanilla classes that use dispatch codecs:&lt;br /&gt;
* RuleTest and RuleTestType&lt;br /&gt;
* BlockPlacer and BlockPlacerType&lt;br /&gt;
* ConfiguredDecorator and FeatureDecorator&lt;br /&gt;
&lt;br /&gt;
=External Links=&lt;br /&gt;
* [https://github.com/Mojang/DataFixerUpper/blob/master/src/main/java/com/mojang/serialization/Codec.java Codecs in Mojang's official public DataFixerUpper repository]&lt;br /&gt;
* [https://kvverti.github.io/Documented-DataFixerUpper/snapshot/com/mojang/serialization/Codec.html#flatXmap-java.util.function.Function-java.util.function.Function- Unofficial Codec Javadocs]&lt;/div&gt;</summary>
		<author><name>Commoble</name></author>
	</entry>
	<entry>
		<id>https://forge.gemwire.uk/index.php?title=Codecs&amp;diff=2361</id>
		<title>Codecs</title>
		<link rel="alternate" type="text/html" href="https://forge.gemwire.uk/index.php?title=Codecs&amp;diff=2361"/>
		<updated>2021-01-09T21:19:51Z</updated>

		<summary type="html">&lt;p&gt;Commoble: Add note that listOf codecs produce immutable Lists&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Codecs are a serialization tool from mojang's DataFixerUpper library. Codecs are used alongside [[DynamicOps|DynamicOps]] to allow objects to be serialized to different formats and back, such as JSON or [[Using_NBT|NBT]]. While the DynamicOps describes the format the object is to be serialized to, the Codec describes the manner in which the object is to be serialized; a single Codec can be used to serialize an object to any format for which a DynamicOps exists. Codecs and DynamicOps jointly form an abstraction layer over data serialization, simplifying the effort needed to serialize or deserialize data.&lt;br /&gt;
&lt;br /&gt;
= Using Codecs =&lt;br /&gt;
&lt;br /&gt;
== Serialization and Deserialization ==&lt;br /&gt;
&lt;br /&gt;
The primary use for Codecs is to serialize java objects to some serialized type, such as a JsonElement or an INBT, and to deserialize an serialized object back to its proper java type. This is accomplished with &amp;lt;code&amp;gt;Codec#encodeStart&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;Codec#parse&amp;lt;/code&amp;gt;, respectively. Given a Codec&amp;lt;SomeJavaType&amp;gt; and a DynamicOps&amp;lt;SomeSerializedType&amp;gt;, we can convert instances of SomeJavaType to instances of SomeSerializedType and back.&lt;br /&gt;
&lt;br /&gt;
Each of these methods take a [[DynamicOps]] instance and an instance of the object we are serializing or deserializing, and returns a DataResult:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
// let someCodec be a Codec&amp;lt;SomeJavaType&amp;gt;&lt;br /&gt;
// let someJavaObject be an instance of SomeJavaType&lt;br /&gt;
// let someNBT and someJsonElement be instances of INBT and JsonElement, respectively&lt;br /&gt;
&lt;br /&gt;
// serialize some java object to INBT&lt;br /&gt;
DataResult&amp;lt;INBT&amp;gt; result = someCodec.encodeStart(NBTDynamicOps.INSTANCE, someJavaObject);&lt;br /&gt;
&lt;br /&gt;
// deserialize some INBT instance back to a proper java object&lt;br /&gt;
DataResult&amp;lt;SomeJavaType&amp;gt; result = someCodec.parse(NBTDynamicOps.INSTANCE, someNBT);&lt;br /&gt;
&lt;br /&gt;
// serialize some java object to a JsonElement&lt;br /&gt;
DataResult&amp;lt;JsonElement&amp;gt; result = someCodec.encodeStart(JsonOps.INSTANCE, someJavaObject);&lt;br /&gt;
&lt;br /&gt;
// deserialize a JsonElement back to a proper java object&lt;br /&gt;
DataResult&amp;lt;SomeJavaType&amp;gt; result = someCodec.parse(JsonOps.INSTANCE, someJsonElement);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A DataResult either holds the converted instance, or it holds some error data, depending on whether the conversion was successful or not, respectively. There are several things we can do with this DataResult; &amp;lt;code&amp;gt;DataResult#result&amp;lt;/code&amp;gt; simply returns an Optional containing the converted object if the conversion was successful, while &amp;lt;code&amp;gt;DataResult#resultOrPartial&amp;lt;/code&amp;gt; also runs a given function if the conversion was unsuccessful (in addition to returning the Optional). #resultOrPartial is particularly useful for logging errors during datapack deserialization:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
// deserialize something from json&lt;br /&gt;
someCodec.parse(JsonOps.INSTANCE, someJsonElement)&lt;br /&gt;
	.resultOrPartial(errorMessage -&amp;gt; doSomethingIfBadData(errorMessage))&lt;br /&gt;
	.ifPresent(someJavaObject -&amp;gt; doSomethingIfGoodData(someJavaObject))&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Builtin Codecs ==&lt;br /&gt;
=== Primitive Codecs ===&lt;br /&gt;
The Codec class itself contains static instances of codecs for all supported primitive types, e.g. &amp;lt;code&amp;gt;Codec.STRING&amp;lt;/code&amp;gt; is the canonical &amp;lt;code&amp;gt;Codec&amp;lt;String&amp;gt;&amp;lt;/code&amp;gt; implementation. Primitive codecs include:&lt;br /&gt;
* BOOL, which serializes to a boolean value&lt;br /&gt;
* BYTE, SHORT, INT, LONG, FLOAT, and DOUBLE, which serialize to numeric values&lt;br /&gt;
* STRING, which serializes to a string&lt;br /&gt;
* BYTE_BUFFER, INT_STREAM, and LONG_STREAM, which serialize to lists of numbers&lt;br /&gt;
* EMPTY, which represents null objects&lt;br /&gt;
&lt;br /&gt;
=== Other Builtin Codecs ===&lt;br /&gt;
Vanilla minecraft has many builtin codecs for objects that it frequently serializes. These codecs are typically static instances in the class the codec is serializing; e.g. &amp;lt;code&amp;gt;ResourceLocation.CODEC&amp;lt;/code&amp;gt; is the canonical &amp;lt;code&amp;gt;Codec&amp;lt;ResourceLocation&amp;gt;&amp;lt;/code&amp;gt;, while &amp;lt;code&amp;gt;BlockPos.CODEC&amp;lt;/code&amp;gt; is the codec used for serializing a BlockPos.&lt;br /&gt;
&lt;br /&gt;
Each vanilla &amp;lt;code&amp;gt;Registry&amp;lt;/code&amp;gt; acts as the Codec for the type of object the registry contains; e.g. &amp;lt;code&amp;gt;Registry.BLOCK&amp;lt;/code&amp;gt; is itself a &amp;lt;code&amp;gt;Codec&amp;lt;Block&amp;gt;&amp;lt;/code&amp;gt;. Forge Registries, however, do not currently implement Codec and cannot yet be used in this way; custom codecs must be created for forge-specific registries that are not tied to specific vanilla registries.&lt;br /&gt;
&lt;br /&gt;
Of particular note here is the CompoundNBT.CODEC, which can be used to e.g. serialize a CompoundNBT into a json file. This has a notable limitation in that CompoundNBT.CODEC *cannot* safely deserialize lists of numbers from json, due to the strong typing of ListNBT and the way that the NBTDynamicOps deserializer reads numeric values.&lt;br /&gt;
&lt;br /&gt;
= Creating Codecs =&lt;br /&gt;
&lt;br /&gt;
Suppose we have the following class, and we want to deserialize json files to instances of this class:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
public class ExampleCodecClass {&lt;br /&gt;
&lt;br /&gt;
    private final int someInt;&lt;br /&gt;
    private final Item item;&lt;br /&gt;
    private final List&amp;lt;BlockPos&amp;gt; blockPositions;&lt;br /&gt;
&lt;br /&gt;
    public ExampleCodecClass(int someInt, Item item, List&amp;lt;BlockPos&amp;gt; blockPositions) {...}&lt;br /&gt;
&lt;br /&gt;
    public int getSomeInt() { return this.someInt; }&lt;br /&gt;
    public Item getItem() { return this.someItem; }&lt;br /&gt;
    public List&amp;lt;BlockPos&amp;gt; getBlockPositions() { return this.blockPositions; }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Where a json file for an instance of this class might look like:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;json&amp;quot;&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
	&amp;quot;some_int&amp;quot;: 42,&lt;br /&gt;
	&amp;quot;item&amp;quot;: &amp;quot;minecraft:gold_ingot&amp;quot;,&lt;br /&gt;
	&amp;quot;block_positions&amp;quot;:&lt;br /&gt;
	[&lt;br /&gt;
		[0,0,0],&lt;br /&gt;
		[10,20,-100]&lt;br /&gt;
	]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We can assemble a codec for this class by building a new codec out of smaller codecs. We'll need a codec for each of these fields:&lt;br /&gt;
* a &amp;lt;code&amp;gt;Codec&amp;lt;Integer&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
* a &amp;lt;code&amp;gt;Codec&amp;lt;Item&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
* a &amp;lt;code&amp;gt;Codec&amp;lt;List&amp;lt;BlockPos&amp;gt;&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
And then we'll need to assemble these into a &amp;lt;code&amp;gt;Codec&amp;lt;ExampleCodecClass&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
As previously mentioned, we can use &amp;lt;code&amp;gt;Codec.INT&amp;lt;/code&amp;gt; for the integer codec, and &amp;lt;code&amp;gt;Registry.ITEM&amp;lt;/code&amp;gt; for the Item codec. We don't have a builtin codec for list-of-blockpos, but we can use BlockPos.CODEC to create one.&lt;br /&gt;
&lt;br /&gt;
== Lists ==&lt;br /&gt;
The &amp;lt;code&amp;gt;Codec#listOf&amp;lt;/code&amp;gt; instance method can be used to generate a codec for a List from an existing codec:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
// BlockPos.CODEC is a Codec&amp;lt;BlockPos&amp;gt;&lt;br /&gt;
Codec&amp;lt;List&amp;lt;BlockPos&amp;gt;&amp;gt; = BlockPos.CODEC.listOf();&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Codecs created via listOf() serialize things to listlike objects, such as [] json arrays or ListNBTs.&lt;br /&gt;
&lt;br /&gt;
Deserializing a list in this manner produces an ''immutable'' list. If a mutable list is needed, [[Codecs#Equivalent_Types_and_xmap|xmap]] can be used to convert the list after deserializing.&lt;br /&gt;
&lt;br /&gt;
== Records ==&lt;br /&gt;
RecordCodecBuilder is used to generate codecs that serialize instances of classes with explicitly named fields, like our example above. Codecs created via RecordCodecBuilder serialize things to maplike objects, such as {} json objects or CompoundNBTs.&lt;br /&gt;
&lt;br /&gt;
RecordCodecBuilder can be used in several ways, but the simplest form is as follows:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
public static final Codec&amp;lt;SomeJavaClass&amp;gt; = RecordCodecBuilder.create(instance -&amp;gt; instance.group(&lt;br /&gt;
		someFieldCodecA.fieldOf(&amp;quot;field_name_a&amp;quot;).forGetter(SomeJavaClass::getFieldA),&lt;br /&gt;
		someFieldCodecB.fieldOf(&amp;quot;field_name_b&amp;quot;).forGetter(SomeJavaClass::getFieldB),&lt;br /&gt;
		someFieldCodecC.fieldOf(&amp;quot;field_name_c&amp;quot;).forGetter(SomeJavaClass::getFieldC),&lt;br /&gt;
		// up to 16 fields can be declared here&lt;br /&gt;
	).apply(instance, SomeJavaClass::new));&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Where each line in the group specifies a codec instance for the type of that field, the field name in the serialized object, and the corresponding getter function in the java class. The builder is concluded by specifying a constructor or factory for the java class whose arguments are the previously defined fields in the same order.&lt;br /&gt;
&lt;br /&gt;
For example, using RecordCodecBuilder to create a codec for our example class above:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
public static final Codec&amp;lt;ExampleCodecClass&amp;gt; = RecordCodecBuilder.create(instance -&amp;gt; instance.group(&lt;br /&gt;
		Codec.INT.fieldOf(&amp;quot;some_int&amp;quot;).forGetter(ExampleCodecClass::getSomeInt),&lt;br /&gt;
		Registry.ITEM.fieldOf(&amp;quot;item&amp;quot;).forGetter(ExampleCodecClass::getItem),&lt;br /&gt;
		BlockPos.CODEC.listOf().fieldOf(&amp;quot;block_positions&amp;quot;).forGetter(ExampleCodecClass::getBlockPositions)&lt;br /&gt;
	).apply(instance, ExampleCodecClass::new));&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Optional and Default Values in Record Fields===&lt;br /&gt;
When RecordCodecBuilder is used as shown above, all of the fields are *required* to be in the serialized object (the JsonObject/CompoundNBT/etc), or the entire thing will fail to parse when the codec tries to deserialize it. If we wish to have optional or default values, we have several alternatives of fieldOf() we can use.&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;someCodec.optionalFieldOf(&amp;quot;field_name&amp;quot;)&amp;lt;/code&amp;gt; creates a field for an Optional. If the field in the json/nbt is not present or invalid, it will deserialize as an empty optional. Empty optionals will not be serialized; the field will be omitted from the json or nbt.&lt;br /&gt;
* &amp;lt;code&amp;gt;someCodec.optionalFieldOf(&amp;quot;field_name&amp;quot;, someDefaultValue)&amp;lt;/code&amp;gt; creates an optional field that deserializes as the given default value if the field is not present in the json/nbt. When serializing, if the field in the java object equals the default value, the value will not be serialized and the field will be omitted from the json or nbt.&lt;br /&gt;
&lt;br /&gt;
When using optional fields, be wary that if the field contains bad data or otherwise fails to serialize, the error will be silently caught, and the field will serialize as the default value instead!&lt;br /&gt;
&lt;br /&gt;
===Boxing values as objects===&lt;br /&gt;
In some situations, we may need to serialize a single value as a single-field object. We can use fieldOf to box a single value in this way without needing the entire RecordCodecBuilder process:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
public static final Codec&amp;lt;Integer&amp;gt; BOXED_INT_CODEC = Codec.INT.fieldOf(&amp;quot;value&amp;quot;).codec();&lt;br /&gt;
&lt;br /&gt;
JsonElement value = BOXED_INT_CODEC.encodeStart(JsonOps.INSTANCE, 5).result().get();&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Which serializes the following output:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;json&amp;quot;&amp;gt;&lt;br /&gt;
{&amp;quot;value&amp;quot;:5}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Unit==&lt;br /&gt;
The &amp;lt;code&amp;gt;Codec.unit(defaultValue)&amp;lt;/code&amp;gt; codec creates a Codec that always deserializes a specified default value, regardless of input. When serializing, it serializes nothing.&lt;br /&gt;
&lt;br /&gt;
==Pair==&lt;br /&gt;
The &amp;lt;code&amp;gt;Codec.pair(codecA, codecB)&amp;lt;/code&amp;gt; static method takes two codecs and generates a Codec&amp;lt;Pair&amp;lt;A,B&amp;gt;&amp;gt; from them.&lt;br /&gt;
&lt;br /&gt;
The only valid arguments for this method are codecs that serialize to objects with explicit fields, such as codecs created using [[Codecs#Records|RecordCodecBuilder]] or [[Codecs#Boxing_values_as_objects|fieldOf]]. Codecs that serialize nothing (such as [[Codecs#Unit|unit codecs]]) are also valid as they act as objects-with-no-fields.&lt;br /&gt;
&lt;br /&gt;
The resulting Pair codec will serialize a single object that has all of the fields of the two original codecs. For example:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
public static final Codec&amp;lt;Pair&amp;lt;Integer,String&amp;gt;&amp;gt; PAIR_CODEC = Codec.pair(&lt;br /&gt;
	Codec.INT.fieldOf(&amp;quot;value&amp;quot;).codec(),&lt;br /&gt;
	Codec.STRING.fieldOf(&amp;quot;name&amp;quot;).codec());&lt;br /&gt;
&lt;br /&gt;
JsonElement encodedPair = BOXED_INT_CODEC.encodeStart(JsonOps.INSTANCE, Pair.of(5, &amp;quot;cheese&amp;quot;).result().get();&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
This codec serializes the above value to:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;json&amp;quot;&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
	&amp;quot;value&amp;quot;: 5,&lt;br /&gt;
	&amp;quot;name&amp;quot;: &amp;quot;cheese&amp;quot;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Codecs that serialize to objects with undefined fields such as [[Codecs#Maps|unboundedMap]] may cause strange and unpredictable behaviour when used here; these objects should be boxed via fieldOf when used in a pair codec.&lt;br /&gt;
&lt;br /&gt;
==Either==&lt;br /&gt;
The &amp;lt;code&amp;gt;Codec.either(codecA, codecB)&amp;lt;/code&amp;gt; static method takes two codecs and generates a Codec&amp;lt;Either&amp;lt;A,B&amp;gt;&amp;gt; from them.&lt;br /&gt;
&lt;br /&gt;
When this codec is used to de/serialize an object, it first attempts to use the first codec; if and only if that conversion fails, it then attempts to use the second codec. If that conversion also fails, then the returned DataResult will contain the error data from the *second* codec's conversion attempt.&lt;br /&gt;
&lt;br /&gt;
==Numeric Ranges==&lt;br /&gt;
The &amp;lt;code&amp;gt;Codec.intRange(min,max)&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;Codec.floatRange(min,max)&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;Codec.doubleRange(min,max)&amp;lt;/code&amp;gt; static methods generate Codecs for Integers, Floats, or Doubles, respectively, for which only a specified inclusive range is valid, and values outside that range will fail to de/serialize.&lt;br /&gt;
&lt;br /&gt;
==Maps==&lt;br /&gt;
Suppose we want to serialize a HashMap or other Map type, where we could have indefinitely many key-value pairs and we don't know what the keys are ahead of time.&lt;br /&gt;
&lt;br /&gt;
We can create a &amp;lt;code&amp;gt;Codec&amp;lt;Map&amp;lt;KEY,VALUE&amp;gt;&amp;gt;&amp;lt;/code&amp;gt; using the &amp;lt;code&amp;gt;Codec.unboundedMap&amp;lt;/code&amp;gt; static method, which takes a key codec and a value codec and creates a codec for a map type:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
public static final Codec&amp;lt;Map&amp;lt;String, BlockPos&amp;gt;&amp;gt; = Codec.unboundedMap(Codec.STRING, BlockPos.CODEC);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The serialized form of maps serialized by this codec will be a JsonObject or CompoundNBT, whose fields are the key-value pairs in the map; the map's keys will be used as the field names, and the map's values will be the values of those fields&lt;br /&gt;
&lt;br /&gt;
A limitation of using unboundedMap is that it only supports key codecs that serialize to Strings (including codecs for things like ResourceLocation that aren't Strings themselves but still serialize to strings). To create a codec for a Map whose keys are not fundamentally strings, the Map must be serialized as a list of key-value pairs instead of using unboundedMap.&lt;br /&gt;
&lt;br /&gt;
==Equivalent Types and xmap==&lt;br /&gt;
Suppose we have two java classes, Amalgam and Box; any Amalgam instance can be converted to a Box, and vice-versa. Now suppose we have a Codec&amp;lt;Amalgam&amp;gt;, but we'd also like to have a Codec&amp;lt;Box&amp;gt;. Rather than creating an entirely new codec for Box from scratch, we can simply xmap our Amalgam codec instead.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;Codec#xmap&amp;lt;/code&amp;gt; instance method is used to generate a second codec for a fundamentally equivalent type to the first codec's type. The method takes two function objects as arguments, which are used to convert the first type to the second when deserializing, and converting the second type to the first when serializing:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
public static final Codec&amp;lt;Box&amp;gt; = Amalgam.CODEC.xmap(Amalgam::toBox, Box::toAmalgam);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Codecs created in this manner will serialize objects in the same format as the starting codec.&lt;br /&gt;
&lt;br /&gt;
==Partially Equivalent Types, flatComapMap, comapFlatMap, and flatXMap==&lt;br /&gt;
Consider the ResourceLocation: Any ResourceLocation can be converted to a String, but not all Strings can be converted to a ResourceLocation; ResourceLocations have strict limits on their format and allowed characters.&lt;br /&gt;
&lt;br /&gt;
While we *could* use xmap to convert the Codec.STRING to a codec for ResourceLocations, this would cause attempts to parse an invalid string like &amp;lt;code&amp;gt;SHOUTY:MOD:Invalid$Characters&amp;lt;/code&amp;gt; to throw a runtime exception, when we really should be returning a failed DataResult to the parser instead -- which indeed is what the vanilla ResourceLocation codec does.&lt;br /&gt;
&lt;br /&gt;
Codecs have three additional instance methods for creating equivalent codecs for when we can *potentially* convert one type to another, but are not guaranteed to be able to do so. These take conversion function arguments that return DataResults, allowing validation to be performed during serialization and deserialization.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ Codec Conversion Methods&lt;br /&gt;
|-&lt;br /&gt;
! Can A always be converted to B? !! Can B always be converted to A? !! Which method of codecA should be used to create codecB?&lt;br /&gt;
|-&lt;br /&gt;
| yes || yes || codecA.xmap&lt;br /&gt;
|-&lt;br /&gt;
| yes || no || codecA.flatComapMap&lt;br /&gt;
|-&lt;br /&gt;
| no || yes || codecA.comapFlatMap&lt;br /&gt;
|-&lt;br /&gt;
| no || no || codecA.flatXmap&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Registry Dispatch ==&lt;br /&gt;
Registry Dispatch Codecs allow us to define a registry of codecs and delegate to a specific codec to deserialize a particular json based on a type field in that json. Dispatch codecs are used extensively when deserializing worldgen data.&lt;br /&gt;
&lt;br /&gt;
To create a dispatch codec for a Thing class, the following steps can be performed:&lt;br /&gt;
# Create a Thing abstract class class and ThingType interface. The ThingType interface should have a method that supplies a Codec&amp;lt;Thing&amp;gt;, while Thing subclasses must define a method that supplies a ThingType.&lt;br /&gt;
# Create a map or registry of ThingTypes, and register a ThingType for each sub-codec we want to have.&lt;br /&gt;
# Create a Codec&amp;lt;ThingType&amp;gt;, or have the ThingType registry implement Codec.&lt;br /&gt;
# Create our Codec&amp;lt;Thing&amp;gt; master codec by invoking &amp;lt;code&amp;gt;Codec#dispatch&amp;lt;/code&amp;gt; on our ThingType codec. This method's arguments are:&lt;br /&gt;
## A field name for the ID of the sub-codec (the example json below is using &amp;quot;type&amp;quot;)&lt;br /&gt;
## A function to retrieve a ThingType from a Thing&lt;br /&gt;
## A function to retrieve a Codec&amp;lt;Thing&amp;gt; from a ThingType&lt;br /&gt;
&lt;br /&gt;
We can then use our Codec&amp;lt;Thing&amp;gt; to create Thing fields in other codecs whose serialized format depends on the specific sub-codec used by a Thing instance.&lt;br /&gt;
&lt;br /&gt;
As an example of this, consider the ExampleCodecClass earlier. Suppose we make this class extend Thing and register our codec for it to a codec dispatch registry with the id &amp;quot;ourmod:exampleclass&amp;quot;. If we were to define an instance of this class in a Thing field in some json, it would look like&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;json&amp;quot;&amp;gt;&lt;br /&gt;
&amp;quot;some_thing&amp;quot;:&lt;br /&gt;
{&lt;br /&gt;
	&amp;quot;type&amp;quot;: &amp;quot;ourmod:exampleclass&amp;quot;,&lt;br /&gt;
	&amp;quot;some_int&amp;quot;: 42,&lt;br /&gt;
	&amp;quot;item&amp;quot;: &amp;quot;minecraft:gold_ingot&amp;quot;,&lt;br /&gt;
	&amp;quot;block_positions&amp;quot;:&lt;br /&gt;
	[&lt;br /&gt;
		[0,0,0],&lt;br /&gt;
		[10,20,-100]&lt;br /&gt;
	]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Other ThingTypes we register would have different fields in this json object, but would still be valid for the &amp;quot;some_thing&amp;quot; field.&lt;br /&gt;
&lt;br /&gt;
Several examples of vanilla classes that use dispatch codecs:&lt;br /&gt;
* RuleTest and IRuleTestType&lt;br /&gt;
* IParticleData and ParticleType&lt;br /&gt;
* ConfiguredPlacement and Placement&lt;br /&gt;
&lt;br /&gt;
=External Links=&lt;br /&gt;
* [https://github.com/Mojang/DataFixerUpper/blob/master/src/main/java/com/mojang/serialization/Codec.java Codecs in Mojang's official public DataFixerUpper repository]&lt;br /&gt;
* [https://kvverti.github.io/Documented-DataFixerUpper/snapshot/com/mojang/serialization/Codec.html#flatXmap-java.util.function.Function-java.util.function.Function- Unofficial Codec Javadocs]&lt;/div&gt;</summary>
		<author><name>Commoble</name></author>
	</entry>
	<entry>
		<id>https://forge.gemwire.uk/index.php?title=Codecs&amp;diff=2329</id>
		<title>Codecs</title>
		<link rel="alternate" type="text/html" href="https://forge.gemwire.uk/index.php?title=Codecs&amp;diff=2329"/>
		<updated>2021-01-06T00:41:46Z</updated>

		<summary type="html">&lt;p&gt;Commoble: Remove incorrect statement re: pairs and strings from Maps section, clarify relationship between map keys and object fields&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Codecs are a serialization tool from mojang's DataFixerUpper library. Codecs are used alongside [[DynamicOps|DynamicOps]] to allow objects to be serialized to different formats and back, such as JSON or [[Using_NBT|NBT]]. While the DynamicOps describes the format the object is to be serialized to, the Codec describes the manner in which the object is to be serialized; a single Codec can be used to serialize an object to any format for which a DynamicOps exists. Codecs and DynamicOps jointly form an abstraction layer over data serialization, simplifying the effort needed to serialize or deserialize data.&lt;br /&gt;
&lt;br /&gt;
= Using Codecs =&lt;br /&gt;
&lt;br /&gt;
== Serialization and Deserialization ==&lt;br /&gt;
&lt;br /&gt;
The primary use for Codecs is to serialize java objects to some serialized type, such as a JsonElement or an INBT, and to deserialize an serialized object back to its proper java type. This is accomplished with &amp;lt;code&amp;gt;Codec#encodeStart&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;Codec#parse&amp;lt;/code&amp;gt;, respectively. Given a Codec&amp;lt;SomeJavaType&amp;gt; and a DynamicOps&amp;lt;SomeSerializedType&amp;gt;, we can convert instances of SomeJavaType to instances of SomeSerializedType and back.&lt;br /&gt;
&lt;br /&gt;
Each of these methods take a [[DynamicOps]] instance and an instance of the object we are serializing or deserializing, and returns a DataResult:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
// let someCodec be a Codec&amp;lt;SomeJavaType&amp;gt;&lt;br /&gt;
// let someJavaObject be an instance of SomeJavaType&lt;br /&gt;
// let someNBT and someJsonElement be instances of INBT and JsonElement, respectively&lt;br /&gt;
&lt;br /&gt;
// serialize some java object to INBT&lt;br /&gt;
DataResult&amp;lt;INBT&amp;gt; result = someCodec.encodeStart(NBTDynamicOps.INSTANCE, someJavaObject);&lt;br /&gt;
&lt;br /&gt;
// deserialize some INBT instance back to a proper java object&lt;br /&gt;
DataResult&amp;lt;SomeJavaType&amp;gt; result = someCodec.parse(NBTDynamicOps.INSTANCE, someNBT);&lt;br /&gt;
&lt;br /&gt;
// serialize some java object to a JsonElement&lt;br /&gt;
DataResult&amp;lt;JsonElement&amp;gt; result = someCodec.encodeStart(JsonOps.INSTANCE, someJavaObject);&lt;br /&gt;
&lt;br /&gt;
// deserialize a JsonElement back to a proper java object&lt;br /&gt;
DataResult&amp;lt;SomeJavaType&amp;gt; result = someCodec.parse(JsonOps.INSTANCE, someJsonElement);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A DataResult either holds the converted instance, or it holds some error data, depending on whether the conversion was successful or not, respectively. There are several things we can do with this DataResult; &amp;lt;code&amp;gt;DataResult#result&amp;lt;/code&amp;gt; simply returns an Optional containing the converted object if the conversion was successful, while &amp;lt;code&amp;gt;DataResult#resultOrPartial&amp;lt;/code&amp;gt; also runs a given function if the conversion was unsuccessful (in addition to returning the Optional). #resultOrPartial is particularly useful for logging errors during datapack deserialization:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
// deserialize something from json&lt;br /&gt;
someCodec.parse(JsonOps.INSTANCE, someJsonElement)&lt;br /&gt;
	.resultOrPartial(errorMessage -&amp;gt; doSomethingIfBadData(errorMessage))&lt;br /&gt;
	.ifPresent(someJavaObject -&amp;gt; doSomethingIfGoodData(someJavaObject))&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Builtin Codecs ==&lt;br /&gt;
=== Primitive Codecs ===&lt;br /&gt;
The Codec class itself contains static instances of codecs for all supported primitive types, e.g. &amp;lt;code&amp;gt;Codec.STRING&amp;lt;/code&amp;gt; is the canonical &amp;lt;code&amp;gt;Codec&amp;lt;String&amp;gt;&amp;lt;/code&amp;gt; implementation. Primitive codecs include:&lt;br /&gt;
* BOOL, which serializes to a boolean value&lt;br /&gt;
* BYTE, SHORT, INT, LONG, FLOAT, and DOUBLE, which serialize to numeric values&lt;br /&gt;
* STRING, which serializes to a string&lt;br /&gt;
* BYTE_BUFFER, INT_STREAM, and LONG_STREAM, which serialize to lists of numbers&lt;br /&gt;
* EMPTY, which represents null objects&lt;br /&gt;
&lt;br /&gt;
=== Other Builtin Codecs ===&lt;br /&gt;
Vanilla minecraft has many builtin codecs for objects that it frequently serializes. These codecs are typically static instances in the class the codec is serializing; e.g. &amp;lt;code&amp;gt;ResourceLocation.CODEC&amp;lt;/code&amp;gt; is the canonical &amp;lt;code&amp;gt;Codec&amp;lt;ResourceLocation&amp;gt;&amp;lt;/code&amp;gt;, while &amp;lt;code&amp;gt;BlockPos.CODEC&amp;lt;/code&amp;gt; is the codec used for serializing a BlockPos.&lt;br /&gt;
&lt;br /&gt;
Each vanilla &amp;lt;code&amp;gt;Registry&amp;lt;/code&amp;gt; acts as the Codec for the type of object the registry contains; e.g. &amp;lt;code&amp;gt;Registry.BLOCK&amp;lt;/code&amp;gt; is itself a &amp;lt;code&amp;gt;Codec&amp;lt;Block&amp;gt;&amp;lt;/code&amp;gt;. Forge Registries, however, do not currently implement Codec and cannot yet be used in this way; custom codecs must be created for forge-specific registries that are not tied to specific vanilla registries.&lt;br /&gt;
&lt;br /&gt;
Of particular note here is the CompoundNBT.CODEC, which can be used to e.g. serialize a CompoundNBT into a json file. This has a notable limitation in that CompoundNBT.CODEC *cannot* safely deserialize lists of numbers from json, due to the strong typing of ListNBT and the way that the NBTDynamicOps deserializer reads numeric values.&lt;br /&gt;
&lt;br /&gt;
= Creating Codecs =&lt;br /&gt;
&lt;br /&gt;
Suppose we have the following class, and we want to deserialize json files to instances of this class:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
public class ExampleCodecClass {&lt;br /&gt;
&lt;br /&gt;
    private final int someInt;&lt;br /&gt;
    private final Item item;&lt;br /&gt;
    private final List&amp;lt;BlockPos&amp;gt; blockPositions;&lt;br /&gt;
&lt;br /&gt;
    public ExampleCodecClass(int someInt, Item item, List&amp;lt;BlockPos&amp;gt; blockPositions) {...}&lt;br /&gt;
&lt;br /&gt;
    public int getSomeInt() { return this.someInt; }&lt;br /&gt;
    public Item getItem() { return this.someItem; }&lt;br /&gt;
    public List&amp;lt;BlockPos&amp;gt; getBlockPositions() { return this.blockPositions; }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Where a json file for an instance of this class might look like:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;json&amp;quot;&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
	&amp;quot;some_int&amp;quot;: 42,&lt;br /&gt;
	&amp;quot;item&amp;quot;: &amp;quot;minecraft:gold_ingot&amp;quot;,&lt;br /&gt;
	&amp;quot;block_positions&amp;quot;:&lt;br /&gt;
	[&lt;br /&gt;
		[0,0,0],&lt;br /&gt;
		[10,20,-100]&lt;br /&gt;
	]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We can assemble a codec for this class by building a new codec out of smaller codecs. We'll need a codec for each of these fields:&lt;br /&gt;
* a &amp;lt;code&amp;gt;Codec&amp;lt;Integer&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
* a &amp;lt;code&amp;gt;Codec&amp;lt;Item&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
* a &amp;lt;code&amp;gt;Codec&amp;lt;List&amp;lt;BlockPos&amp;gt;&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
And then we'll need to assemble these into a &amp;lt;code&amp;gt;Codec&amp;lt;ExampleCodecClass&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
As previously mentioned, we can use &amp;lt;code&amp;gt;Codec.INT&amp;lt;/code&amp;gt; for the integer codec, and &amp;lt;code&amp;gt;Registry.ITEM&amp;lt;/code&amp;gt; for the Item codec. We don't have a builtin codec for list-of-blockpos, but we can use BlockPos.CODEC to create one.&lt;br /&gt;
&lt;br /&gt;
== Lists ==&lt;br /&gt;
The &amp;lt;code&amp;gt;Codec#listOf&amp;lt;/code&amp;gt; instance method can be used to generate a codec for a List from an existing codec:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
// BlockPos.CODEC is a Codec&amp;lt;BlockPos&amp;gt;&lt;br /&gt;
Codec&amp;lt;List&amp;lt;BlockPos&amp;gt;&amp;gt; = BlockPos.CODEC.listOf();&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Codecs created via listOf() serialize things to listlike objects, such as [] json arrays or ListNBTs.&lt;br /&gt;
&lt;br /&gt;
== Records ==&lt;br /&gt;
RecordCodecBuilder is used to generate codecs that serialize instances of classes with explicitly named fields, like our example above. Codecs created via RecordCodecBuilder serialize things to maplike objects, such as {} json objects or CompoundNBTs.&lt;br /&gt;
&lt;br /&gt;
RecordCodecBuilder can be used in several ways, but the simplest form is as follows:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
public static final Codec&amp;lt;SomeJavaClass&amp;gt; = RecordCodecBuilder.create(instance -&amp;gt; instance.group(&lt;br /&gt;
		someFieldCodecA.fieldOf(&amp;quot;field_name_a&amp;quot;).forGetter(SomeJavaClass::getFieldA),&lt;br /&gt;
		someFieldCodecB.fieldOf(&amp;quot;field_name_b&amp;quot;).forGetter(SomeJavaClass::getFieldB),&lt;br /&gt;
		someFieldCodecC.fieldOf(&amp;quot;field_name_c&amp;quot;).forGetter(SomeJavaClass::getFieldC),&lt;br /&gt;
		// up to 16 fields can be declared here&lt;br /&gt;
	).apply(instance, SomeJavaClass::new));&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Where each line in the group specifies a codec instance for the type of that field, the field name in the serialized object, and the corresponding getter function in the java class. The builder is concluded by specifying a constructor or factory for the java class whose arguments are the previously defined fields in the same order.&lt;br /&gt;
&lt;br /&gt;
For example, using RecordCodecBuilder to create a codec for our example class above:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
public static final Codec&amp;lt;ExampleCodecClass&amp;gt; = RecordCodecBuilder.create(instance -&amp;gt; instance.group(&lt;br /&gt;
		Codec.INT.fieldOf(&amp;quot;some_int&amp;quot;).forGetter(ExampleCodecClass::getSomeInt),&lt;br /&gt;
		Registry.ITEM.fieldOf(&amp;quot;item&amp;quot;).forGetter(ExampleCodecClass::getItem),&lt;br /&gt;
		BlockPos.CODEC.listOf().fieldOf(&amp;quot;block_positions&amp;quot;).forGetter(ExampleCodecClass::getBlockPositions)&lt;br /&gt;
	).apply(instance, ExampleCodecClass::new));&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Optional and Default Values in Record Fields===&lt;br /&gt;
When RecordCodecBuilder is used as shown above, all of the fields are *required* to be in the serialized object (the JsonObject/CompoundNBT/etc), or the entire thing will fail to parse when the codec tries to deserialize it. If we wish to have optional or default values, we have several alternatives of fieldOf() we can use.&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;someCodec.optionalFieldOf(&amp;quot;field_name&amp;quot;)&amp;lt;/code&amp;gt; creates a field for an Optional. If the field in the json/nbt is not present or invalid, it will deserialize as an empty optional. Empty optionals will not be serialized; the field will be omitted from the json or nbt.&lt;br /&gt;
* &amp;lt;code&amp;gt;someCodec.optionalFieldOf(&amp;quot;field_name&amp;quot;, someDefaultValue)&amp;lt;/code&amp;gt; creates an optional field that deserializes as the given default value if the field is not present in the json/nbt. When serializing, if the field in the java object equals the default value, the value will not be serialized and the field will be omitted from the json or nbt.&lt;br /&gt;
&lt;br /&gt;
When using optional fields, be wary that if the field contains bad data or otherwise fails to serialize, the error will be silently caught, and the field will serialize as the default value instead!&lt;br /&gt;
&lt;br /&gt;
===Boxing values as objects===&lt;br /&gt;
In some situations, we may need to serialize a single value as a single-field object. We can use fieldOf to box a single value in this way without needing the entire RecordCodecBuilder process:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
public static final Codec&amp;lt;Integer&amp;gt; BOXED_INT_CODEC = Codec.INT.fieldOf(&amp;quot;value&amp;quot;).codec();&lt;br /&gt;
&lt;br /&gt;
JsonElement value = BOXED_INT_CODEC.encodeStart(JsonOps.INSTANCE, 5).result().get();&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Which serializes the following output:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;json&amp;quot;&amp;gt;&lt;br /&gt;
{&amp;quot;value&amp;quot;:5}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Unit==&lt;br /&gt;
The &amp;lt;code&amp;gt;Codec.unit(defaultValue)&amp;lt;/code&amp;gt; codec creates a Codec that always deserializes a specified default value, regardless of input. When serializing, it serializes nothing.&lt;br /&gt;
&lt;br /&gt;
==Pair==&lt;br /&gt;
The &amp;lt;code&amp;gt;Codec.pair(codecA, codecB)&amp;lt;/code&amp;gt; static method takes two codecs and generates a Codec&amp;lt;Pair&amp;lt;A,B&amp;gt;&amp;gt; from them.&lt;br /&gt;
&lt;br /&gt;
The only valid arguments for this method are codecs that serialize to objects with explicit fields, such as codecs created using [[Codecs#Records|RecordCodecBuilder]] or [[Codecs#Boxing_values_as_objects|fieldOf]]. Codecs that serialize nothing (such as [[Codecs#Unit|unit codecs]]) are also valid as they act as objects-with-no-fields.&lt;br /&gt;
&lt;br /&gt;
The resulting Pair codec will serialize a single object that has all of the fields of the two original codecs. For example:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
public static final Codec&amp;lt;Pair&amp;lt;Integer,String&amp;gt;&amp;gt; PAIR_CODEC = Codec.pair(&lt;br /&gt;
	Codec.INT.fieldOf(&amp;quot;value&amp;quot;).codec(),&lt;br /&gt;
	Codec.STRING.fieldOf(&amp;quot;name&amp;quot;).codec());&lt;br /&gt;
&lt;br /&gt;
JsonElement encodedPair = BOXED_INT_CODEC.encodeStart(JsonOps.INSTANCE, Pair.of(5, &amp;quot;cheese&amp;quot;).result().get();&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
This codec serializes the above value to:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;json&amp;quot;&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
	&amp;quot;value&amp;quot;: 5,&lt;br /&gt;
	&amp;quot;name&amp;quot;: &amp;quot;cheese&amp;quot;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Codecs that serialize to objects with undefined fields such as [[Codecs#Maps|unboundedMap]] may cause strange and unpredictable behaviour when used here; these objects should be boxed via fieldOf when used in a pair codec.&lt;br /&gt;
&lt;br /&gt;
==Either==&lt;br /&gt;
The &amp;lt;code&amp;gt;Codec.either(codecA, codecB)&amp;lt;/code&amp;gt; static method takes two codecs and generates a Codec&amp;lt;Either&amp;lt;A,B&amp;gt;&amp;gt; from them.&lt;br /&gt;
&lt;br /&gt;
When this codec is used to de/serialize an object, it first attempts to use the first codec; if and only if that conversion fails, it then attempts to use the second codec. If that conversion also fails, then the returned DataResult will contain the error data from the *second* codec's conversion attempt.&lt;br /&gt;
&lt;br /&gt;
==Numeric Ranges==&lt;br /&gt;
The &amp;lt;code&amp;gt;Codec.intRange(min,max)&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;Codec.floatRange(min,max)&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;Codec.doubleRange(min,max)&amp;lt;/code&amp;gt; static methods generate Codecs for Integers, Floats, or Doubles, respectively, for which only a specified inclusive range is valid, and values outside that range will fail to de/serialize.&lt;br /&gt;
&lt;br /&gt;
==Maps==&lt;br /&gt;
Suppose we want to serialize a HashMap or other Map type, where we could have indefinitely many key-value pairs and we don't know what the keys are ahead of time.&lt;br /&gt;
&lt;br /&gt;
We can create a &amp;lt;code&amp;gt;Codec&amp;lt;Map&amp;lt;KEY,VALUE&amp;gt;&amp;gt;&amp;lt;/code&amp;gt; using the &amp;lt;code&amp;gt;Codec.unboundedMap&amp;lt;/code&amp;gt; static method, which takes a key codec and a value codec and creates a codec for a map type:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
public static final Codec&amp;lt;Map&amp;lt;String, BlockPos&amp;gt;&amp;gt; = Codec.unboundedMap(Codec.STRING, BlockPos.CODEC);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The serialized form of maps serialized by this codec will be a JsonObject or CompoundNBT, whose fields are the key-value pairs in the map; the map's keys will be used as the field names, and the map's values will be the values of those fields&lt;br /&gt;
&lt;br /&gt;
A limitation of using unboundedMap is that it only supports key codecs that serialize to Strings (including codecs for things like ResourceLocation that aren't Strings themselves but still serialize to strings). To create a codec for a Map whose keys are not fundamentally strings, the Map must be serialized as a list of key-value pairs instead of using unboundedMap.&lt;br /&gt;
&lt;br /&gt;
==Equivalent Types and xmap==&lt;br /&gt;
Suppose we have two java classes, Amalgam and Box; any Amalgam instance can be converted to a Box, and vice-versa. Now suppose we have a Codec&amp;lt;Amalgam&amp;gt;, but we'd also like to have a Codec&amp;lt;Box&amp;gt;. Rather than creating an entirely new codec for Box from scratch, we can simply xmap our Amalgam codec instead.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;Codec#xmap&amp;lt;/code&amp;gt; instance method is used to generate a second codec for a fundamentally equivalent type to the first codec's type. The method takes two function objects as arguments, which are used to convert the first type to the second when deserializing, and converting the second type to the first when serializing:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
public static final Codec&amp;lt;Box&amp;gt; = Amalgam.CODEC.xmap(Amalgam::toBox, Box::toAmalgam);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Codecs created in this manner will serialize objects in the same format as the starting codec.&lt;br /&gt;
&lt;br /&gt;
==Partially Equivalent Types, flatComapMap, comapFlatMap, and flatXMap==&lt;br /&gt;
Consider the ResourceLocation: Any ResourceLocation can be converted to a String, but not all Strings can be converted to a ResourceLocation; ResourceLocations have strict limits on their format and allowed characters.&lt;br /&gt;
&lt;br /&gt;
While we *could* use xmap to convert the Codec.STRING to a codec for ResourceLocations, this would cause attempts to parse an invalid string like &amp;lt;code&amp;gt;SHOUTY:MOD:Invalid$Characters&amp;lt;/code&amp;gt; to throw a runtime exception, when we really should be returning a failed DataResult to the parser instead -- which indeed is what the vanilla ResourceLocation codec does.&lt;br /&gt;
&lt;br /&gt;
Codecs have three additional instance methods for creating equivalent codecs for when we can *potentially* convert one type to another, but are not guaranteed to be able to do so. These take conversion function arguments that return DataResults, allowing validation to be performed during serialization and deserialization.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ Codec Conversion Methods&lt;br /&gt;
|-&lt;br /&gt;
! Can A always be converted to B? !! Can B always be converted to A? !! Which method of codecA should be used to create codecB?&lt;br /&gt;
|-&lt;br /&gt;
| yes || yes || codecA.xmap&lt;br /&gt;
|-&lt;br /&gt;
| yes || no || codecA.flatComapMap&lt;br /&gt;
|-&lt;br /&gt;
| no || yes || codecA.comapFlatMap&lt;br /&gt;
|-&lt;br /&gt;
| no || no || codecA.flatXmap&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Registry Dispatch ==&lt;br /&gt;
Registry Dispatch Codecs allow us to define a registry of codecs and delegate to a specific codec to deserialize a particular json based on a type field in that json. Dispatch codecs are used extensively when deserializing worldgen data.&lt;br /&gt;
&lt;br /&gt;
To create a dispatch codec for a Thing class, the following steps can be performed:&lt;br /&gt;
# Create a Thing abstract class class and ThingType interface. The ThingType interface should have a method that supplies a Codec&amp;lt;Thing&amp;gt;, while Thing subclasses must define a method that supplies a ThingType.&lt;br /&gt;
# Create a map or registry of ThingTypes, and register a ThingType for each sub-codec we want to have.&lt;br /&gt;
# Create a Codec&amp;lt;ThingType&amp;gt;, or have the ThingType registry implement Codec.&lt;br /&gt;
# Create our Codec&amp;lt;Thing&amp;gt; master codec by invoking &amp;lt;code&amp;gt;Codec#dispatch&amp;lt;/code&amp;gt; on our ThingType codec. This method's arguments are:&lt;br /&gt;
## A field name for the ID of the sub-codec (the example json below is using &amp;quot;type&amp;quot;)&lt;br /&gt;
## A function to retrieve a ThingType from a Thing&lt;br /&gt;
## A function to retrieve a Codec&amp;lt;Thing&amp;gt; from a ThingType&lt;br /&gt;
&lt;br /&gt;
We can then use our Codec&amp;lt;Thing&amp;gt; to create Thing fields in other codecs whose serialized format depends on the specific sub-codec used by a Thing instance.&lt;br /&gt;
&lt;br /&gt;
As an example of this, consider the ExampleCodecClass earlier. Suppose we make this class extend Thing and register our codec for it to a codec dispatch registry with the id &amp;quot;ourmod:exampleclass&amp;quot;. If we were to define an instance of this class in a Thing field in some json, it would look like&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;json&amp;quot;&amp;gt;&lt;br /&gt;
&amp;quot;some_thing&amp;quot;:&lt;br /&gt;
{&lt;br /&gt;
	&amp;quot;type&amp;quot;: &amp;quot;ourmod:exampleclass&amp;quot;,&lt;br /&gt;
	&amp;quot;some_int&amp;quot;: 42,&lt;br /&gt;
	&amp;quot;item&amp;quot;: &amp;quot;minecraft:gold_ingot&amp;quot;,&lt;br /&gt;
	&amp;quot;block_positions&amp;quot;:&lt;br /&gt;
	[&lt;br /&gt;
		[0,0,0],&lt;br /&gt;
		[10,20,-100]&lt;br /&gt;
	]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Other ThingTypes we register would have different fields in this json object, but would still be valid for the &amp;quot;some_thing&amp;quot; field.&lt;br /&gt;
&lt;br /&gt;
Several examples of vanilla classes that use dispatch codecs:&lt;br /&gt;
* RuleTest and IRuleTestType&lt;br /&gt;
* IParticleData and ParticleType&lt;br /&gt;
* ConfiguredPlacement and Placement&lt;br /&gt;
&lt;br /&gt;
=External Links=&lt;br /&gt;
* [https://github.com/Mojang/DataFixerUpper/blob/master/src/main/java/com/mojang/serialization/Codec.java Codecs in Mojang's official public DataFixerUpper repository]&lt;br /&gt;
* [https://kvverti.github.io/Documented-DataFixerUpper/snapshot/com/mojang/serialization/Codec.html#flatXmap-java.util.function.Function-java.util.function.Function- Unofficial Codec Javadocs]&lt;/div&gt;</summary>
		<author><name>Commoble</name></author>
	</entry>
	<entry>
		<id>https://forge.gemwire.uk/index.php?title=Codecs&amp;diff=2328</id>
		<title>Codecs</title>
		<link rel="alternate" type="text/html" href="https://forge.gemwire.uk/index.php?title=Codecs&amp;diff=2328"/>
		<updated>2021-01-06T00:38:37Z</updated>

		<summary type="html">&lt;p&gt;Commoble: Add boxing/fieldOf link to Pair section, add warning for unbounded maps, add Pair example&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Codecs are a serialization tool from mojang's DataFixerUpper library. Codecs are used alongside [[DynamicOps|DynamicOps]] to allow objects to be serialized to different formats and back, such as JSON or [[Using_NBT|NBT]]. While the DynamicOps describes the format the object is to be serialized to, the Codec describes the manner in which the object is to be serialized; a single Codec can be used to serialize an object to any format for which a DynamicOps exists. Codecs and DynamicOps jointly form an abstraction layer over data serialization, simplifying the effort needed to serialize or deserialize data.&lt;br /&gt;
&lt;br /&gt;
= Using Codecs =&lt;br /&gt;
&lt;br /&gt;
== Serialization and Deserialization ==&lt;br /&gt;
&lt;br /&gt;
The primary use for Codecs is to serialize java objects to some serialized type, such as a JsonElement or an INBT, and to deserialize an serialized object back to its proper java type. This is accomplished with &amp;lt;code&amp;gt;Codec#encodeStart&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;Codec#parse&amp;lt;/code&amp;gt;, respectively. Given a Codec&amp;lt;SomeJavaType&amp;gt; and a DynamicOps&amp;lt;SomeSerializedType&amp;gt;, we can convert instances of SomeJavaType to instances of SomeSerializedType and back.&lt;br /&gt;
&lt;br /&gt;
Each of these methods take a [[DynamicOps]] instance and an instance of the object we are serializing or deserializing, and returns a DataResult:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
// let someCodec be a Codec&amp;lt;SomeJavaType&amp;gt;&lt;br /&gt;
// let someJavaObject be an instance of SomeJavaType&lt;br /&gt;
// let someNBT and someJsonElement be instances of INBT and JsonElement, respectively&lt;br /&gt;
&lt;br /&gt;
// serialize some java object to INBT&lt;br /&gt;
DataResult&amp;lt;INBT&amp;gt; result = someCodec.encodeStart(NBTDynamicOps.INSTANCE, someJavaObject);&lt;br /&gt;
&lt;br /&gt;
// deserialize some INBT instance back to a proper java object&lt;br /&gt;
DataResult&amp;lt;SomeJavaType&amp;gt; result = someCodec.parse(NBTDynamicOps.INSTANCE, someNBT);&lt;br /&gt;
&lt;br /&gt;
// serialize some java object to a JsonElement&lt;br /&gt;
DataResult&amp;lt;JsonElement&amp;gt; result = someCodec.encodeStart(JsonOps.INSTANCE, someJavaObject);&lt;br /&gt;
&lt;br /&gt;
// deserialize a JsonElement back to a proper java object&lt;br /&gt;
DataResult&amp;lt;SomeJavaType&amp;gt; result = someCodec.parse(JsonOps.INSTANCE, someJsonElement);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A DataResult either holds the converted instance, or it holds some error data, depending on whether the conversion was successful or not, respectively. There are several things we can do with this DataResult; &amp;lt;code&amp;gt;DataResult#result&amp;lt;/code&amp;gt; simply returns an Optional containing the converted object if the conversion was successful, while &amp;lt;code&amp;gt;DataResult#resultOrPartial&amp;lt;/code&amp;gt; also runs a given function if the conversion was unsuccessful (in addition to returning the Optional). #resultOrPartial is particularly useful for logging errors during datapack deserialization:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
// deserialize something from json&lt;br /&gt;
someCodec.parse(JsonOps.INSTANCE, someJsonElement)&lt;br /&gt;
	.resultOrPartial(errorMessage -&amp;gt; doSomethingIfBadData(errorMessage))&lt;br /&gt;
	.ifPresent(someJavaObject -&amp;gt; doSomethingIfGoodData(someJavaObject))&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Builtin Codecs ==&lt;br /&gt;
=== Primitive Codecs ===&lt;br /&gt;
The Codec class itself contains static instances of codecs for all supported primitive types, e.g. &amp;lt;code&amp;gt;Codec.STRING&amp;lt;/code&amp;gt; is the canonical &amp;lt;code&amp;gt;Codec&amp;lt;String&amp;gt;&amp;lt;/code&amp;gt; implementation. Primitive codecs include:&lt;br /&gt;
* BOOL, which serializes to a boolean value&lt;br /&gt;
* BYTE, SHORT, INT, LONG, FLOAT, and DOUBLE, which serialize to numeric values&lt;br /&gt;
* STRING, which serializes to a string&lt;br /&gt;
* BYTE_BUFFER, INT_STREAM, and LONG_STREAM, which serialize to lists of numbers&lt;br /&gt;
* EMPTY, which represents null objects&lt;br /&gt;
&lt;br /&gt;
=== Other Builtin Codecs ===&lt;br /&gt;
Vanilla minecraft has many builtin codecs for objects that it frequently serializes. These codecs are typically static instances in the class the codec is serializing; e.g. &amp;lt;code&amp;gt;ResourceLocation.CODEC&amp;lt;/code&amp;gt; is the canonical &amp;lt;code&amp;gt;Codec&amp;lt;ResourceLocation&amp;gt;&amp;lt;/code&amp;gt;, while &amp;lt;code&amp;gt;BlockPos.CODEC&amp;lt;/code&amp;gt; is the codec used for serializing a BlockPos.&lt;br /&gt;
&lt;br /&gt;
Each vanilla &amp;lt;code&amp;gt;Registry&amp;lt;/code&amp;gt; acts as the Codec for the type of object the registry contains; e.g. &amp;lt;code&amp;gt;Registry.BLOCK&amp;lt;/code&amp;gt; is itself a &amp;lt;code&amp;gt;Codec&amp;lt;Block&amp;gt;&amp;lt;/code&amp;gt;. Forge Registries, however, do not currently implement Codec and cannot yet be used in this way; custom codecs must be created for forge-specific registries that are not tied to specific vanilla registries.&lt;br /&gt;
&lt;br /&gt;
Of particular note here is the CompoundNBT.CODEC, which can be used to e.g. serialize a CompoundNBT into a json file. This has a notable limitation in that CompoundNBT.CODEC *cannot* safely deserialize lists of numbers from json, due to the strong typing of ListNBT and the way that the NBTDynamicOps deserializer reads numeric values.&lt;br /&gt;
&lt;br /&gt;
= Creating Codecs =&lt;br /&gt;
&lt;br /&gt;
Suppose we have the following class, and we want to deserialize json files to instances of this class:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
public class ExampleCodecClass {&lt;br /&gt;
&lt;br /&gt;
    private final int someInt;&lt;br /&gt;
    private final Item item;&lt;br /&gt;
    private final List&amp;lt;BlockPos&amp;gt; blockPositions;&lt;br /&gt;
&lt;br /&gt;
    public ExampleCodecClass(int someInt, Item item, List&amp;lt;BlockPos&amp;gt; blockPositions) {...}&lt;br /&gt;
&lt;br /&gt;
    public int getSomeInt() { return this.someInt; }&lt;br /&gt;
    public Item getItem() { return this.someItem; }&lt;br /&gt;
    public List&amp;lt;BlockPos&amp;gt; getBlockPositions() { return this.blockPositions; }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Where a json file for an instance of this class might look like:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;json&amp;quot;&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
	&amp;quot;some_int&amp;quot;: 42,&lt;br /&gt;
	&amp;quot;item&amp;quot;: &amp;quot;minecraft:gold_ingot&amp;quot;,&lt;br /&gt;
	&amp;quot;block_positions&amp;quot;:&lt;br /&gt;
	[&lt;br /&gt;
		[0,0,0],&lt;br /&gt;
		[10,20,-100]&lt;br /&gt;
	]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We can assemble a codec for this class by building a new codec out of smaller codecs. We'll need a codec for each of these fields:&lt;br /&gt;
* a &amp;lt;code&amp;gt;Codec&amp;lt;Integer&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
* a &amp;lt;code&amp;gt;Codec&amp;lt;Item&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
* a &amp;lt;code&amp;gt;Codec&amp;lt;List&amp;lt;BlockPos&amp;gt;&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
And then we'll need to assemble these into a &amp;lt;code&amp;gt;Codec&amp;lt;ExampleCodecClass&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
As previously mentioned, we can use &amp;lt;code&amp;gt;Codec.INT&amp;lt;/code&amp;gt; for the integer codec, and &amp;lt;code&amp;gt;Registry.ITEM&amp;lt;/code&amp;gt; for the Item codec. We don't have a builtin codec for list-of-blockpos, but we can use BlockPos.CODEC to create one.&lt;br /&gt;
&lt;br /&gt;
== Lists ==&lt;br /&gt;
The &amp;lt;code&amp;gt;Codec#listOf&amp;lt;/code&amp;gt; instance method can be used to generate a codec for a List from an existing codec:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
// BlockPos.CODEC is a Codec&amp;lt;BlockPos&amp;gt;&lt;br /&gt;
Codec&amp;lt;List&amp;lt;BlockPos&amp;gt;&amp;gt; = BlockPos.CODEC.listOf();&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Codecs created via listOf() serialize things to listlike objects, such as [] json arrays or ListNBTs.&lt;br /&gt;
&lt;br /&gt;
== Records ==&lt;br /&gt;
RecordCodecBuilder is used to generate codecs that serialize instances of classes with explicitly named fields, like our example above. Codecs created via RecordCodecBuilder serialize things to maplike objects, such as {} json objects or CompoundNBTs.&lt;br /&gt;
&lt;br /&gt;
RecordCodecBuilder can be used in several ways, but the simplest form is as follows:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
public static final Codec&amp;lt;SomeJavaClass&amp;gt; = RecordCodecBuilder.create(instance -&amp;gt; instance.group(&lt;br /&gt;
		someFieldCodecA.fieldOf(&amp;quot;field_name_a&amp;quot;).forGetter(SomeJavaClass::getFieldA),&lt;br /&gt;
		someFieldCodecB.fieldOf(&amp;quot;field_name_b&amp;quot;).forGetter(SomeJavaClass::getFieldB),&lt;br /&gt;
		someFieldCodecC.fieldOf(&amp;quot;field_name_c&amp;quot;).forGetter(SomeJavaClass::getFieldC),&lt;br /&gt;
		// up to 16 fields can be declared here&lt;br /&gt;
	).apply(instance, SomeJavaClass::new));&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Where each line in the group specifies a codec instance for the type of that field, the field name in the serialized object, and the corresponding getter function in the java class. The builder is concluded by specifying a constructor or factory for the java class whose arguments are the previously defined fields in the same order.&lt;br /&gt;
&lt;br /&gt;
For example, using RecordCodecBuilder to create a codec for our example class above:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
public static final Codec&amp;lt;ExampleCodecClass&amp;gt; = RecordCodecBuilder.create(instance -&amp;gt; instance.group(&lt;br /&gt;
		Codec.INT.fieldOf(&amp;quot;some_int&amp;quot;).forGetter(ExampleCodecClass::getSomeInt),&lt;br /&gt;
		Registry.ITEM.fieldOf(&amp;quot;item&amp;quot;).forGetter(ExampleCodecClass::getItem),&lt;br /&gt;
		BlockPos.CODEC.listOf().fieldOf(&amp;quot;block_positions&amp;quot;).forGetter(ExampleCodecClass::getBlockPositions)&lt;br /&gt;
	).apply(instance, ExampleCodecClass::new));&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Optional and Default Values in Record Fields===&lt;br /&gt;
When RecordCodecBuilder is used as shown above, all of the fields are *required* to be in the serialized object (the JsonObject/CompoundNBT/etc), or the entire thing will fail to parse when the codec tries to deserialize it. If we wish to have optional or default values, we have several alternatives of fieldOf() we can use.&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;someCodec.optionalFieldOf(&amp;quot;field_name&amp;quot;)&amp;lt;/code&amp;gt; creates a field for an Optional. If the field in the json/nbt is not present or invalid, it will deserialize as an empty optional. Empty optionals will not be serialized; the field will be omitted from the json or nbt.&lt;br /&gt;
* &amp;lt;code&amp;gt;someCodec.optionalFieldOf(&amp;quot;field_name&amp;quot;, someDefaultValue)&amp;lt;/code&amp;gt; creates an optional field that deserializes as the given default value if the field is not present in the json/nbt. When serializing, if the field in the java object equals the default value, the value will not be serialized and the field will be omitted from the json or nbt.&lt;br /&gt;
&lt;br /&gt;
When using optional fields, be wary that if the field contains bad data or otherwise fails to serialize, the error will be silently caught, and the field will serialize as the default value instead!&lt;br /&gt;
&lt;br /&gt;
===Boxing values as objects===&lt;br /&gt;
In some situations, we may need to serialize a single value as a single-field object. We can use fieldOf to box a single value in this way without needing the entire RecordCodecBuilder process:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
public static final Codec&amp;lt;Integer&amp;gt; BOXED_INT_CODEC = Codec.INT.fieldOf(&amp;quot;value&amp;quot;).codec();&lt;br /&gt;
&lt;br /&gt;
JsonElement value = BOXED_INT_CODEC.encodeStart(JsonOps.INSTANCE, 5).result().get();&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Which serializes the following output:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;json&amp;quot;&amp;gt;&lt;br /&gt;
{&amp;quot;value&amp;quot;:5}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Unit==&lt;br /&gt;
The &amp;lt;code&amp;gt;Codec.unit(defaultValue)&amp;lt;/code&amp;gt; codec creates a Codec that always deserializes a specified default value, regardless of input. When serializing, it serializes nothing.&lt;br /&gt;
&lt;br /&gt;
==Pair==&lt;br /&gt;
The &amp;lt;code&amp;gt;Codec.pair(codecA, codecB)&amp;lt;/code&amp;gt; static method takes two codecs and generates a Codec&amp;lt;Pair&amp;lt;A,B&amp;gt;&amp;gt; from them.&lt;br /&gt;
&lt;br /&gt;
The only valid arguments for this method are codecs that serialize to objects with explicit fields, such as codecs created using [[Codecs#Records|RecordCodecBuilder]] or [[Codecs#Boxing_values_as_objects|fieldOf]]. Codecs that serialize nothing (such as [[Codecs#Unit|unit codecs]]) are also valid as they act as objects-with-no-fields.&lt;br /&gt;
&lt;br /&gt;
The resulting Pair codec will serialize a single object that has all of the fields of the two original codecs. For example:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
public static final Codec&amp;lt;Pair&amp;lt;Integer,String&amp;gt;&amp;gt; PAIR_CODEC = Codec.pair(&lt;br /&gt;
	Codec.INT.fieldOf(&amp;quot;value&amp;quot;).codec(),&lt;br /&gt;
	Codec.STRING.fieldOf(&amp;quot;name&amp;quot;).codec());&lt;br /&gt;
&lt;br /&gt;
JsonElement encodedPair = BOXED_INT_CODEC.encodeStart(JsonOps.INSTANCE, Pair.of(5, &amp;quot;cheese&amp;quot;).result().get();&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
This codec serializes the above value to:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;json&amp;quot;&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
	&amp;quot;value&amp;quot;: 5,&lt;br /&gt;
	&amp;quot;name&amp;quot;: &amp;quot;cheese&amp;quot;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Codecs that serialize to objects with undefined fields such as [[Codecs#Maps|unboundedMap]] may cause strange and unpredictable behaviour when used here; these objects should be boxed via fieldOf when used in a pair codec.&lt;br /&gt;
&lt;br /&gt;
==Either==&lt;br /&gt;
The &amp;lt;code&amp;gt;Codec.either(codecA, codecB)&amp;lt;/code&amp;gt; static method takes two codecs and generates a Codec&amp;lt;Either&amp;lt;A,B&amp;gt;&amp;gt; from them.&lt;br /&gt;
&lt;br /&gt;
When this codec is used to de/serialize an object, it first attempts to use the first codec; if and only if that conversion fails, it then attempts to use the second codec. If that conversion also fails, then the returned DataResult will contain the error data from the *second* codec's conversion attempt.&lt;br /&gt;
&lt;br /&gt;
==Numeric Ranges==&lt;br /&gt;
The &amp;lt;code&amp;gt;Codec.intRange(min,max)&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;Codec.floatRange(min,max)&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;Codec.doubleRange(min,max)&amp;lt;/code&amp;gt; static methods generate Codecs for Integers, Floats, or Doubles, respectively, for which only a specified inclusive range is valid, and values outside that range will fail to de/serialize.&lt;br /&gt;
&lt;br /&gt;
==Maps==&lt;br /&gt;
Suppose we want to serialize a HashMap or other Map type, where we could have indefinitely many key-value pairs and we don't know what the keys are ahead of time.&lt;br /&gt;
&lt;br /&gt;
We can create a &amp;lt;code&amp;gt;Codec&amp;lt;Map&amp;lt;KEY,VALUE&amp;gt;&amp;gt;&amp;lt;/code&amp;gt; using the &amp;lt;code&amp;gt;Codec.unboundedMap&amp;lt;/code&amp;gt; static method, which takes a key codec and a value codec and creates a codec for a map type:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
public static final Codec&amp;lt;Map&amp;lt;String, BlockPos&amp;gt;&amp;gt; = Codec.unboundedMap(Codec.STRING, BlockPos.CODEC);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The serialized form of maps serialized by this codec will be a JsonObject or CompoundNBT, whose fields are the key-value pairs in the map.&lt;br /&gt;
&lt;br /&gt;
A limitation of using unboundedMap is that it only supports key codecs that serialize to Strings (including codecs for things like ResourceLocation that aren't Strings themselves but still serialize to strings). To create a codec for a Map whose keys are not fundamentally strings, the Map must be serialized as a list of key-value entries instead of using unboundedMap. As Codec.pair() also requires that the first codec serialize to a string, the pair function cannot be used for this purpose either.&lt;br /&gt;
&lt;br /&gt;
==Equivalent Types and xmap==&lt;br /&gt;
Suppose we have two java classes, Amalgam and Box; any Amalgam instance can be converted to a Box, and vice-versa. Now suppose we have a Codec&amp;lt;Amalgam&amp;gt;, but we'd also like to have a Codec&amp;lt;Box&amp;gt;. Rather than creating an entirely new codec for Box from scratch, we can simply xmap our Amalgam codec instead.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;Codec#xmap&amp;lt;/code&amp;gt; instance method is used to generate a second codec for a fundamentally equivalent type to the first codec's type. The method takes two function objects as arguments, which are used to convert the first type to the second when deserializing, and converting the second type to the first when serializing:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
public static final Codec&amp;lt;Box&amp;gt; = Amalgam.CODEC.xmap(Amalgam::toBox, Box::toAmalgam);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Codecs created in this manner will serialize objects in the same format as the starting codec.&lt;br /&gt;
&lt;br /&gt;
==Partially Equivalent Types, flatComapMap, comapFlatMap, and flatXMap==&lt;br /&gt;
Consider the ResourceLocation: Any ResourceLocation can be converted to a String, but not all Strings can be converted to a ResourceLocation; ResourceLocations have strict limits on their format and allowed characters.&lt;br /&gt;
&lt;br /&gt;
While we *could* use xmap to convert the Codec.STRING to a codec for ResourceLocations, this would cause attempts to parse an invalid string like &amp;lt;code&amp;gt;SHOUTY:MOD:Invalid$Characters&amp;lt;/code&amp;gt; to throw a runtime exception, when we really should be returning a failed DataResult to the parser instead -- which indeed is what the vanilla ResourceLocation codec does.&lt;br /&gt;
&lt;br /&gt;
Codecs have three additional instance methods for creating equivalent codecs for when we can *potentially* convert one type to another, but are not guaranteed to be able to do so. These take conversion function arguments that return DataResults, allowing validation to be performed during serialization and deserialization.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ Codec Conversion Methods&lt;br /&gt;
|-&lt;br /&gt;
! Can A always be converted to B? !! Can B always be converted to A? !! Which method of codecA should be used to create codecB?&lt;br /&gt;
|-&lt;br /&gt;
| yes || yes || codecA.xmap&lt;br /&gt;
|-&lt;br /&gt;
| yes || no || codecA.flatComapMap&lt;br /&gt;
|-&lt;br /&gt;
| no || yes || codecA.comapFlatMap&lt;br /&gt;
|-&lt;br /&gt;
| no || no || codecA.flatXmap&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Registry Dispatch ==&lt;br /&gt;
Registry Dispatch Codecs allow us to define a registry of codecs and delegate to a specific codec to deserialize a particular json based on a type field in that json. Dispatch codecs are used extensively when deserializing worldgen data.&lt;br /&gt;
&lt;br /&gt;
To create a dispatch codec for a Thing class, the following steps can be performed:&lt;br /&gt;
# Create a Thing abstract class class and ThingType interface. The ThingType interface should have a method that supplies a Codec&amp;lt;Thing&amp;gt;, while Thing subclasses must define a method that supplies a ThingType.&lt;br /&gt;
# Create a map or registry of ThingTypes, and register a ThingType for each sub-codec we want to have.&lt;br /&gt;
# Create a Codec&amp;lt;ThingType&amp;gt;, or have the ThingType registry implement Codec.&lt;br /&gt;
# Create our Codec&amp;lt;Thing&amp;gt; master codec by invoking &amp;lt;code&amp;gt;Codec#dispatch&amp;lt;/code&amp;gt; on our ThingType codec. This method's arguments are:&lt;br /&gt;
## A field name for the ID of the sub-codec (the example json below is using &amp;quot;type&amp;quot;)&lt;br /&gt;
## A function to retrieve a ThingType from a Thing&lt;br /&gt;
## A function to retrieve a Codec&amp;lt;Thing&amp;gt; from a ThingType&lt;br /&gt;
&lt;br /&gt;
We can then use our Codec&amp;lt;Thing&amp;gt; to create Thing fields in other codecs whose serialized format depends on the specific sub-codec used by a Thing instance.&lt;br /&gt;
&lt;br /&gt;
As an example of this, consider the ExampleCodecClass earlier. Suppose we make this class extend Thing and register our codec for it to a codec dispatch registry with the id &amp;quot;ourmod:exampleclass&amp;quot;. If we were to define an instance of this class in a Thing field in some json, it would look like&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;json&amp;quot;&amp;gt;&lt;br /&gt;
&amp;quot;some_thing&amp;quot;:&lt;br /&gt;
{&lt;br /&gt;
	&amp;quot;type&amp;quot;: &amp;quot;ourmod:exampleclass&amp;quot;,&lt;br /&gt;
	&amp;quot;some_int&amp;quot;: 42,&lt;br /&gt;
	&amp;quot;item&amp;quot;: &amp;quot;minecraft:gold_ingot&amp;quot;,&lt;br /&gt;
	&amp;quot;block_positions&amp;quot;:&lt;br /&gt;
	[&lt;br /&gt;
		[0,0,0],&lt;br /&gt;
		[10,20,-100]&lt;br /&gt;
	]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Other ThingTypes we register would have different fields in this json object, but would still be valid for the &amp;quot;some_thing&amp;quot; field.&lt;br /&gt;
&lt;br /&gt;
Several examples of vanilla classes that use dispatch codecs:&lt;br /&gt;
* RuleTest and IRuleTestType&lt;br /&gt;
* IParticleData and ParticleType&lt;br /&gt;
* ConfiguredPlacement and Placement&lt;br /&gt;
&lt;br /&gt;
=External Links=&lt;br /&gt;
* [https://github.com/Mojang/DataFixerUpper/blob/master/src/main/java/com/mojang/serialization/Codec.java Codecs in Mojang's official public DataFixerUpper repository]&lt;br /&gt;
* [https://kvverti.github.io/Documented-DataFixerUpper/snapshot/com/mojang/serialization/Codec.html#flatXmap-java.util.function.Function-java.util.function.Function- Unofficial Codec Javadocs]&lt;/div&gt;</summary>
		<author><name>Commoble</name></author>
	</entry>
	<entry>
		<id>https://forge.gemwire.uk/index.php?title=Codecs&amp;diff=2327</id>
		<title>Codecs</title>
		<link rel="alternate" type="text/html" href="https://forge.gemwire.uk/index.php?title=Codecs&amp;diff=2327"/>
		<updated>2021-01-06T00:23:32Z</updated>

		<summary type="html">&lt;p&gt;Commoble: Add section on boxing single values as objects&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Codecs are a serialization tool from mojang's DataFixerUpper library. Codecs are used alongside [[DynamicOps|DynamicOps]] to allow objects to be serialized to different formats and back, such as JSON or [[Using_NBT|NBT]]. While the DynamicOps describes the format the object is to be serialized to, the Codec describes the manner in which the object is to be serialized; a single Codec can be used to serialize an object to any format for which a DynamicOps exists. Codecs and DynamicOps jointly form an abstraction layer over data serialization, simplifying the effort needed to serialize or deserialize data.&lt;br /&gt;
&lt;br /&gt;
= Using Codecs =&lt;br /&gt;
&lt;br /&gt;
== Serialization and Deserialization ==&lt;br /&gt;
&lt;br /&gt;
The primary use for Codecs is to serialize java objects to some serialized type, such as a JsonElement or an INBT, and to deserialize an serialized object back to its proper java type. This is accomplished with &amp;lt;code&amp;gt;Codec#encodeStart&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;Codec#parse&amp;lt;/code&amp;gt;, respectively. Given a Codec&amp;lt;SomeJavaType&amp;gt; and a DynamicOps&amp;lt;SomeSerializedType&amp;gt;, we can convert instances of SomeJavaType to instances of SomeSerializedType and back.&lt;br /&gt;
&lt;br /&gt;
Each of these methods take a [[DynamicOps]] instance and an instance of the object we are serializing or deserializing, and returns a DataResult:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
// let someCodec be a Codec&amp;lt;SomeJavaType&amp;gt;&lt;br /&gt;
// let someJavaObject be an instance of SomeJavaType&lt;br /&gt;
// let someNBT and someJsonElement be instances of INBT and JsonElement, respectively&lt;br /&gt;
&lt;br /&gt;
// serialize some java object to INBT&lt;br /&gt;
DataResult&amp;lt;INBT&amp;gt; result = someCodec.encodeStart(NBTDynamicOps.INSTANCE, someJavaObject);&lt;br /&gt;
&lt;br /&gt;
// deserialize some INBT instance back to a proper java object&lt;br /&gt;
DataResult&amp;lt;SomeJavaType&amp;gt; result = someCodec.parse(NBTDynamicOps.INSTANCE, someNBT);&lt;br /&gt;
&lt;br /&gt;
// serialize some java object to a JsonElement&lt;br /&gt;
DataResult&amp;lt;JsonElement&amp;gt; result = someCodec.encodeStart(JsonOps.INSTANCE, someJavaObject);&lt;br /&gt;
&lt;br /&gt;
// deserialize a JsonElement back to a proper java object&lt;br /&gt;
DataResult&amp;lt;SomeJavaType&amp;gt; result = someCodec.parse(JsonOps.INSTANCE, someJsonElement);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A DataResult either holds the converted instance, or it holds some error data, depending on whether the conversion was successful or not, respectively. There are several things we can do with this DataResult; &amp;lt;code&amp;gt;DataResult#result&amp;lt;/code&amp;gt; simply returns an Optional containing the converted object if the conversion was successful, while &amp;lt;code&amp;gt;DataResult#resultOrPartial&amp;lt;/code&amp;gt; also runs a given function if the conversion was unsuccessful (in addition to returning the Optional). #resultOrPartial is particularly useful for logging errors during datapack deserialization:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
// deserialize something from json&lt;br /&gt;
someCodec.parse(JsonOps.INSTANCE, someJsonElement)&lt;br /&gt;
	.resultOrPartial(errorMessage -&amp;gt; doSomethingIfBadData(errorMessage))&lt;br /&gt;
	.ifPresent(someJavaObject -&amp;gt; doSomethingIfGoodData(someJavaObject))&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Builtin Codecs ==&lt;br /&gt;
=== Primitive Codecs ===&lt;br /&gt;
The Codec class itself contains static instances of codecs for all supported primitive types, e.g. &amp;lt;code&amp;gt;Codec.STRING&amp;lt;/code&amp;gt; is the canonical &amp;lt;code&amp;gt;Codec&amp;lt;String&amp;gt;&amp;lt;/code&amp;gt; implementation. Primitive codecs include:&lt;br /&gt;
* BOOL, which serializes to a boolean value&lt;br /&gt;
* BYTE, SHORT, INT, LONG, FLOAT, and DOUBLE, which serialize to numeric values&lt;br /&gt;
* STRING, which serializes to a string&lt;br /&gt;
* BYTE_BUFFER, INT_STREAM, and LONG_STREAM, which serialize to lists of numbers&lt;br /&gt;
* EMPTY, which represents null objects&lt;br /&gt;
&lt;br /&gt;
=== Other Builtin Codecs ===&lt;br /&gt;
Vanilla minecraft has many builtin codecs for objects that it frequently serializes. These codecs are typically static instances in the class the codec is serializing; e.g. &amp;lt;code&amp;gt;ResourceLocation.CODEC&amp;lt;/code&amp;gt; is the canonical &amp;lt;code&amp;gt;Codec&amp;lt;ResourceLocation&amp;gt;&amp;lt;/code&amp;gt;, while &amp;lt;code&amp;gt;BlockPos.CODEC&amp;lt;/code&amp;gt; is the codec used for serializing a BlockPos.&lt;br /&gt;
&lt;br /&gt;
Each vanilla &amp;lt;code&amp;gt;Registry&amp;lt;/code&amp;gt; acts as the Codec for the type of object the registry contains; e.g. &amp;lt;code&amp;gt;Registry.BLOCK&amp;lt;/code&amp;gt; is itself a &amp;lt;code&amp;gt;Codec&amp;lt;Block&amp;gt;&amp;lt;/code&amp;gt;. Forge Registries, however, do not currently implement Codec and cannot yet be used in this way; custom codecs must be created for forge-specific registries that are not tied to specific vanilla registries.&lt;br /&gt;
&lt;br /&gt;
Of particular note here is the CompoundNBT.CODEC, which can be used to e.g. serialize a CompoundNBT into a json file. This has a notable limitation in that CompoundNBT.CODEC *cannot* safely deserialize lists of numbers from json, due to the strong typing of ListNBT and the way that the NBTDynamicOps deserializer reads numeric values.&lt;br /&gt;
&lt;br /&gt;
= Creating Codecs =&lt;br /&gt;
&lt;br /&gt;
Suppose we have the following class, and we want to deserialize json files to instances of this class:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
public class ExampleCodecClass {&lt;br /&gt;
&lt;br /&gt;
    private final int someInt;&lt;br /&gt;
    private final Item item;&lt;br /&gt;
    private final List&amp;lt;BlockPos&amp;gt; blockPositions;&lt;br /&gt;
&lt;br /&gt;
    public ExampleCodecClass(int someInt, Item item, List&amp;lt;BlockPos&amp;gt; blockPositions) {...}&lt;br /&gt;
&lt;br /&gt;
    public int getSomeInt() { return this.someInt; }&lt;br /&gt;
    public Item getItem() { return this.someItem; }&lt;br /&gt;
    public List&amp;lt;BlockPos&amp;gt; getBlockPositions() { return this.blockPositions; }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Where a json file for an instance of this class might look like:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;json&amp;quot;&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
	&amp;quot;some_int&amp;quot;: 42,&lt;br /&gt;
	&amp;quot;item&amp;quot;: &amp;quot;minecraft:gold_ingot&amp;quot;,&lt;br /&gt;
	&amp;quot;block_positions&amp;quot;:&lt;br /&gt;
	[&lt;br /&gt;
		[0,0,0],&lt;br /&gt;
		[10,20,-100]&lt;br /&gt;
	]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We can assemble a codec for this class by building a new codec out of smaller codecs. We'll need a codec for each of these fields:&lt;br /&gt;
* a &amp;lt;code&amp;gt;Codec&amp;lt;Integer&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
* a &amp;lt;code&amp;gt;Codec&amp;lt;Item&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
* a &amp;lt;code&amp;gt;Codec&amp;lt;List&amp;lt;BlockPos&amp;gt;&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
And then we'll need to assemble these into a &amp;lt;code&amp;gt;Codec&amp;lt;ExampleCodecClass&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
As previously mentioned, we can use &amp;lt;code&amp;gt;Codec.INT&amp;lt;/code&amp;gt; for the integer codec, and &amp;lt;code&amp;gt;Registry.ITEM&amp;lt;/code&amp;gt; for the Item codec. We don't have a builtin codec for list-of-blockpos, but we can use BlockPos.CODEC to create one.&lt;br /&gt;
&lt;br /&gt;
== Lists ==&lt;br /&gt;
The &amp;lt;code&amp;gt;Codec#listOf&amp;lt;/code&amp;gt; instance method can be used to generate a codec for a List from an existing codec:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
// BlockPos.CODEC is a Codec&amp;lt;BlockPos&amp;gt;&lt;br /&gt;
Codec&amp;lt;List&amp;lt;BlockPos&amp;gt;&amp;gt; = BlockPos.CODEC.listOf();&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Codecs created via listOf() serialize things to listlike objects, such as [] json arrays or ListNBTs.&lt;br /&gt;
&lt;br /&gt;
== Records ==&lt;br /&gt;
RecordCodecBuilder is used to generate codecs that serialize instances of classes with explicitly named fields, like our example above. Codecs created via RecordCodecBuilder serialize things to maplike objects, such as {} json objects or CompoundNBTs.&lt;br /&gt;
&lt;br /&gt;
RecordCodecBuilder can be used in several ways, but the simplest form is as follows:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
public static final Codec&amp;lt;SomeJavaClass&amp;gt; = RecordCodecBuilder.create(instance -&amp;gt; instance.group(&lt;br /&gt;
		someFieldCodecA.fieldOf(&amp;quot;field_name_a&amp;quot;).forGetter(SomeJavaClass::getFieldA),&lt;br /&gt;
		someFieldCodecB.fieldOf(&amp;quot;field_name_b&amp;quot;).forGetter(SomeJavaClass::getFieldB),&lt;br /&gt;
		someFieldCodecC.fieldOf(&amp;quot;field_name_c&amp;quot;).forGetter(SomeJavaClass::getFieldC),&lt;br /&gt;
		// up to 16 fields can be declared here&lt;br /&gt;
	).apply(instance, SomeJavaClass::new));&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Where each line in the group specifies a codec instance for the type of that field, the field name in the serialized object, and the corresponding getter function in the java class. The builder is concluded by specifying a constructor or factory for the java class whose arguments are the previously defined fields in the same order.&lt;br /&gt;
&lt;br /&gt;
For example, using RecordCodecBuilder to create a codec for our example class above:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
public static final Codec&amp;lt;ExampleCodecClass&amp;gt; = RecordCodecBuilder.create(instance -&amp;gt; instance.group(&lt;br /&gt;
		Codec.INT.fieldOf(&amp;quot;some_int&amp;quot;).forGetter(ExampleCodecClass::getSomeInt),&lt;br /&gt;
		Registry.ITEM.fieldOf(&amp;quot;item&amp;quot;).forGetter(ExampleCodecClass::getItem),&lt;br /&gt;
		BlockPos.CODEC.listOf().fieldOf(&amp;quot;block_positions&amp;quot;).forGetter(ExampleCodecClass::getBlockPositions)&lt;br /&gt;
	).apply(instance, ExampleCodecClass::new));&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Optional and Default Values in Record Fields===&lt;br /&gt;
When RecordCodecBuilder is used as shown above, all of the fields are *required* to be in the serialized object (the JsonObject/CompoundNBT/etc), or the entire thing will fail to parse when the codec tries to deserialize it. If we wish to have optional or default values, we have several alternatives of fieldOf() we can use.&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;someCodec.optionalFieldOf(&amp;quot;field_name&amp;quot;)&amp;lt;/code&amp;gt; creates a field for an Optional. If the field in the json/nbt is not present or invalid, it will deserialize as an empty optional. Empty optionals will not be serialized; the field will be omitted from the json or nbt.&lt;br /&gt;
* &amp;lt;code&amp;gt;someCodec.optionalFieldOf(&amp;quot;field_name&amp;quot;, someDefaultValue)&amp;lt;/code&amp;gt; creates an optional field that deserializes as the given default value if the field is not present in the json/nbt. When serializing, if the field in the java object equals the default value, the value will not be serialized and the field will be omitted from the json or nbt.&lt;br /&gt;
&lt;br /&gt;
When using optional fields, be wary that if the field contains bad data or otherwise fails to serialize, the error will be silently caught, and the field will serialize as the default value instead!&lt;br /&gt;
&lt;br /&gt;
===Boxing values as objects===&lt;br /&gt;
In some situations, we may need to serialize a single value as a single-field object. We can use fieldOf to box a single value in this way without needing the entire RecordCodecBuilder process:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
public static final Codec&amp;lt;Integer&amp;gt; BOXED_INT_CODEC = Codec.INT.fieldOf(&amp;quot;value&amp;quot;).codec();&lt;br /&gt;
&lt;br /&gt;
JsonElement value = BOXED_INT_CODEC.encodeStart(JsonOps.INSTANCE, 5).result().get();&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Which serializes the following output:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;json&amp;quot;&amp;gt;&lt;br /&gt;
{&amp;quot;value&amp;quot;:5}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Unit==&lt;br /&gt;
The &amp;lt;code&amp;gt;Codec.unit(defaultValue)&amp;lt;/code&amp;gt; codec creates a Codec that always deserializes a specified default value, regardless of input. When serializing, it serializes nothing.&lt;br /&gt;
&lt;br /&gt;
==Pair==&lt;br /&gt;
The &amp;lt;code&amp;gt;Codec.pair(codecA, codecB)&amp;lt;/code&amp;gt; static method takes two codecs and generates a Codec&amp;lt;Pair&amp;lt;A,B&amp;gt;&amp;gt; from them.&lt;br /&gt;
&lt;br /&gt;
The only valid arguments for this method are codecs that serialize to objects, such as codecs created using [[Codecs#Records|RecordCodecBuilder]], [[Codecs#Maps|unboundedMap]], or fieldOf. Codecs that serialize nothing (such as [[Codecs#Unit|unit codecs]]) are also valid as they act as objects-with-no-fields.&lt;br /&gt;
&lt;br /&gt;
The resulting Pair codec will serialize a single object that has all of the fields of the two original codecs.&lt;br /&gt;
&lt;br /&gt;
==Either==&lt;br /&gt;
The &amp;lt;code&amp;gt;Codec.either(codecA, codecB)&amp;lt;/code&amp;gt; static method takes two codecs and generates a Codec&amp;lt;Either&amp;lt;A,B&amp;gt;&amp;gt; from them.&lt;br /&gt;
&lt;br /&gt;
When this codec is used to de/serialize an object, it first attempts to use the first codec; if and only if that conversion fails, it then attempts to use the second codec. If that conversion also fails, then the returned DataResult will contain the error data from the *second* codec's conversion attempt.&lt;br /&gt;
&lt;br /&gt;
==Numeric Ranges==&lt;br /&gt;
The &amp;lt;code&amp;gt;Codec.intRange(min,max)&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;Codec.floatRange(min,max)&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;Codec.doubleRange(min,max)&amp;lt;/code&amp;gt; static methods generate Codecs for Integers, Floats, or Doubles, respectively, for which only a specified inclusive range is valid, and values outside that range will fail to de/serialize.&lt;br /&gt;
&lt;br /&gt;
==Maps==&lt;br /&gt;
Suppose we want to serialize a HashMap or other Map type, where we could have indefinitely many key-value pairs and we don't know what the keys are ahead of time.&lt;br /&gt;
&lt;br /&gt;
We can create a &amp;lt;code&amp;gt;Codec&amp;lt;Map&amp;lt;KEY,VALUE&amp;gt;&amp;gt;&amp;lt;/code&amp;gt; using the &amp;lt;code&amp;gt;Codec.unboundedMap&amp;lt;/code&amp;gt; static method, which takes a key codec and a value codec and creates a codec for a map type:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
public static final Codec&amp;lt;Map&amp;lt;String, BlockPos&amp;gt;&amp;gt; = Codec.unboundedMap(Codec.STRING, BlockPos.CODEC);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The serialized form of maps serialized by this codec will be a JsonObject or CompoundNBT, whose fields are the key-value pairs in the map.&lt;br /&gt;
&lt;br /&gt;
A limitation of using unboundedMap is that it only supports key codecs that serialize to Strings (including codecs for things like ResourceLocation that aren't Strings themselves but still serialize to strings). To create a codec for a Map whose keys are not fundamentally strings, the Map must be serialized as a list of key-value entries instead of using unboundedMap. As Codec.pair() also requires that the first codec serialize to a string, the pair function cannot be used for this purpose either.&lt;br /&gt;
&lt;br /&gt;
==Equivalent Types and xmap==&lt;br /&gt;
Suppose we have two java classes, Amalgam and Box; any Amalgam instance can be converted to a Box, and vice-versa. Now suppose we have a Codec&amp;lt;Amalgam&amp;gt;, but we'd also like to have a Codec&amp;lt;Box&amp;gt;. Rather than creating an entirely new codec for Box from scratch, we can simply xmap our Amalgam codec instead.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;Codec#xmap&amp;lt;/code&amp;gt; instance method is used to generate a second codec for a fundamentally equivalent type to the first codec's type. The method takes two function objects as arguments, which are used to convert the first type to the second when deserializing, and converting the second type to the first when serializing:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
public static final Codec&amp;lt;Box&amp;gt; = Amalgam.CODEC.xmap(Amalgam::toBox, Box::toAmalgam);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Codecs created in this manner will serialize objects in the same format as the starting codec.&lt;br /&gt;
&lt;br /&gt;
==Partially Equivalent Types, flatComapMap, comapFlatMap, and flatXMap==&lt;br /&gt;
Consider the ResourceLocation: Any ResourceLocation can be converted to a String, but not all Strings can be converted to a ResourceLocation; ResourceLocations have strict limits on their format and allowed characters.&lt;br /&gt;
&lt;br /&gt;
While we *could* use xmap to convert the Codec.STRING to a codec for ResourceLocations, this would cause attempts to parse an invalid string like &amp;lt;code&amp;gt;SHOUTY:MOD:Invalid$Characters&amp;lt;/code&amp;gt; to throw a runtime exception, when we really should be returning a failed DataResult to the parser instead -- which indeed is what the vanilla ResourceLocation codec does.&lt;br /&gt;
&lt;br /&gt;
Codecs have three additional instance methods for creating equivalent codecs for when we can *potentially* convert one type to another, but are not guaranteed to be able to do so. These take conversion function arguments that return DataResults, allowing validation to be performed during serialization and deserialization.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ Codec Conversion Methods&lt;br /&gt;
|-&lt;br /&gt;
! Can A always be converted to B? !! Can B always be converted to A? !! Which method of codecA should be used to create codecB?&lt;br /&gt;
|-&lt;br /&gt;
| yes || yes || codecA.xmap&lt;br /&gt;
|-&lt;br /&gt;
| yes || no || codecA.flatComapMap&lt;br /&gt;
|-&lt;br /&gt;
| no || yes || codecA.comapFlatMap&lt;br /&gt;
|-&lt;br /&gt;
| no || no || codecA.flatXmap&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Registry Dispatch ==&lt;br /&gt;
Registry Dispatch Codecs allow us to define a registry of codecs and delegate to a specific codec to deserialize a particular json based on a type field in that json. Dispatch codecs are used extensively when deserializing worldgen data.&lt;br /&gt;
&lt;br /&gt;
To create a dispatch codec for a Thing class, the following steps can be performed:&lt;br /&gt;
# Create a Thing abstract class class and ThingType interface. The ThingType interface should have a method that supplies a Codec&amp;lt;Thing&amp;gt;, while Thing subclasses must define a method that supplies a ThingType.&lt;br /&gt;
# Create a map or registry of ThingTypes, and register a ThingType for each sub-codec we want to have.&lt;br /&gt;
# Create a Codec&amp;lt;ThingType&amp;gt;, or have the ThingType registry implement Codec.&lt;br /&gt;
# Create our Codec&amp;lt;Thing&amp;gt; master codec by invoking &amp;lt;code&amp;gt;Codec#dispatch&amp;lt;/code&amp;gt; on our ThingType codec. This method's arguments are:&lt;br /&gt;
## A field name for the ID of the sub-codec (the example json below is using &amp;quot;type&amp;quot;)&lt;br /&gt;
## A function to retrieve a ThingType from a Thing&lt;br /&gt;
## A function to retrieve a Codec&amp;lt;Thing&amp;gt; from a ThingType&lt;br /&gt;
&lt;br /&gt;
We can then use our Codec&amp;lt;Thing&amp;gt; to create Thing fields in other codecs whose serialized format depends on the specific sub-codec used by a Thing instance.&lt;br /&gt;
&lt;br /&gt;
As an example of this, consider the ExampleCodecClass earlier. Suppose we make this class extend Thing and register our codec for it to a codec dispatch registry with the id &amp;quot;ourmod:exampleclass&amp;quot;. If we were to define an instance of this class in a Thing field in some json, it would look like&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;json&amp;quot;&amp;gt;&lt;br /&gt;
&amp;quot;some_thing&amp;quot;:&lt;br /&gt;
{&lt;br /&gt;
	&amp;quot;type&amp;quot;: &amp;quot;ourmod:exampleclass&amp;quot;,&lt;br /&gt;
	&amp;quot;some_int&amp;quot;: 42,&lt;br /&gt;
	&amp;quot;item&amp;quot;: &amp;quot;minecraft:gold_ingot&amp;quot;,&lt;br /&gt;
	&amp;quot;block_positions&amp;quot;:&lt;br /&gt;
	[&lt;br /&gt;
		[0,0,0],&lt;br /&gt;
		[10,20,-100]&lt;br /&gt;
	]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Other ThingTypes we register would have different fields in this json object, but would still be valid for the &amp;quot;some_thing&amp;quot; field.&lt;br /&gt;
&lt;br /&gt;
Several examples of vanilla classes that use dispatch codecs:&lt;br /&gt;
* RuleTest and IRuleTestType&lt;br /&gt;
* IParticleData and ParticleType&lt;br /&gt;
* ConfiguredPlacement and Placement&lt;br /&gt;
&lt;br /&gt;
=External Links=&lt;br /&gt;
* [https://github.com/Mojang/DataFixerUpper/blob/master/src/main/java/com/mojang/serialization/Codec.java Codecs in Mojang's official public DataFixerUpper repository]&lt;br /&gt;
* [https://kvverti.github.io/Documented-DataFixerUpper/snapshot/com/mojang/serialization/Codec.html#flatXmap-java.util.function.Function-java.util.function.Function- Unofficial Codec Javadocs]&lt;/div&gt;</summary>
		<author><name>Commoble</name></author>
	</entry>
	<entry>
		<id>https://forge.gemwire.uk/index.php?title=Codecs&amp;diff=2326</id>
		<title>Codecs</title>
		<link rel="alternate" type="text/html" href="https://forge.gemwire.uk/index.php?title=Codecs&amp;diff=2326"/>
		<updated>2021-01-06T00:09:10Z</updated>

		<summary type="html">&lt;p&gt;Commoble: Corrected valid arguments for pair codecs&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Codecs are a serialization tool from mojang's DataFixerUpper library. Codecs are used alongside [[DynamicOps|DynamicOps]] to allow objects to be serialized to different formats and back, such as JSON or [[Using_NBT|NBT]]. While the DynamicOps describes the format the object is to be serialized to, the Codec describes the manner in which the object is to be serialized; a single Codec can be used to serialize an object to any format for which a DynamicOps exists. Codecs and DynamicOps jointly form an abstraction layer over data serialization, simplifying the effort needed to serialize or deserialize data.&lt;br /&gt;
&lt;br /&gt;
= Using Codecs =&lt;br /&gt;
&lt;br /&gt;
== Serialization and Deserialization ==&lt;br /&gt;
&lt;br /&gt;
The primary use for Codecs is to serialize java objects to some serialized type, such as a JsonElement or an INBT, and to deserialize an serialized object back to its proper java type. This is accomplished with &amp;lt;code&amp;gt;Codec#encodeStart&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;Codec#parse&amp;lt;/code&amp;gt;, respectively. Given a Codec&amp;lt;SomeJavaType&amp;gt; and a DynamicOps&amp;lt;SomeSerializedType&amp;gt;, we can convert instances of SomeJavaType to instances of SomeSerializedType and back.&lt;br /&gt;
&lt;br /&gt;
Each of these methods take a [[DynamicOps]] instance and an instance of the object we are serializing or deserializing, and returns a DataResult:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
// let someCodec be a Codec&amp;lt;SomeJavaType&amp;gt;&lt;br /&gt;
// let someJavaObject be an instance of SomeJavaType&lt;br /&gt;
// let someNBT and someJsonElement be instances of INBT and JsonElement, respectively&lt;br /&gt;
&lt;br /&gt;
// serialize some java object to INBT&lt;br /&gt;
DataResult&amp;lt;INBT&amp;gt; result = someCodec.encodeStart(NBTDynamicOps.INSTANCE, someJavaObject);&lt;br /&gt;
&lt;br /&gt;
// deserialize some INBT instance back to a proper java object&lt;br /&gt;
DataResult&amp;lt;SomeJavaType&amp;gt; result = someCodec.parse(NBTDynamicOps.INSTANCE, someNBT);&lt;br /&gt;
&lt;br /&gt;
// serialize some java object to a JsonElement&lt;br /&gt;
DataResult&amp;lt;JsonElement&amp;gt; result = someCodec.encodeStart(JsonOps.INSTANCE, someJavaObject);&lt;br /&gt;
&lt;br /&gt;
// deserialize a JsonElement back to a proper java object&lt;br /&gt;
DataResult&amp;lt;SomeJavaType&amp;gt; result = someCodec.parse(JsonOps.INSTANCE, someJsonElement);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A DataResult either holds the converted instance, or it holds some error data, depending on whether the conversion was successful or not, respectively. There are several things we can do with this DataResult; &amp;lt;code&amp;gt;DataResult#result&amp;lt;/code&amp;gt; simply returns an Optional containing the converted object if the conversion was successful, while &amp;lt;code&amp;gt;DataResult#resultOrPartial&amp;lt;/code&amp;gt; also runs a given function if the conversion was unsuccessful (in addition to returning the Optional). #resultOrPartial is particularly useful for logging errors during datapack deserialization:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
// deserialize something from json&lt;br /&gt;
someCodec.parse(JsonOps.INSTANCE, someJsonElement)&lt;br /&gt;
	.resultOrPartial(errorMessage -&amp;gt; doSomethingIfBadData(errorMessage))&lt;br /&gt;
	.ifPresent(someJavaObject -&amp;gt; doSomethingIfGoodData(someJavaObject))&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Builtin Codecs ==&lt;br /&gt;
=== Primitive Codecs ===&lt;br /&gt;
The Codec class itself contains static instances of codecs for all supported primitive types, e.g. &amp;lt;code&amp;gt;Codec.STRING&amp;lt;/code&amp;gt; is the canonical &amp;lt;code&amp;gt;Codec&amp;lt;String&amp;gt;&amp;lt;/code&amp;gt; implementation. Primitive codecs include:&lt;br /&gt;
* BOOL, which serializes to a boolean value&lt;br /&gt;
* BYTE, SHORT, INT, LONG, FLOAT, and DOUBLE, which serialize to numeric values&lt;br /&gt;
* STRING, which serializes to a string&lt;br /&gt;
* BYTE_BUFFER, INT_STREAM, and LONG_STREAM, which serialize to lists of numbers&lt;br /&gt;
* EMPTY, which represents null objects&lt;br /&gt;
&lt;br /&gt;
=== Other Builtin Codecs ===&lt;br /&gt;
Vanilla minecraft has many builtin codecs for objects that it frequently serializes. These codecs are typically static instances in the class the codec is serializing; e.g. &amp;lt;code&amp;gt;ResourceLocation.CODEC&amp;lt;/code&amp;gt; is the canonical &amp;lt;code&amp;gt;Codec&amp;lt;ResourceLocation&amp;gt;&amp;lt;/code&amp;gt;, while &amp;lt;code&amp;gt;BlockPos.CODEC&amp;lt;/code&amp;gt; is the codec used for serializing a BlockPos.&lt;br /&gt;
&lt;br /&gt;
Each vanilla &amp;lt;code&amp;gt;Registry&amp;lt;/code&amp;gt; acts as the Codec for the type of object the registry contains; e.g. &amp;lt;code&amp;gt;Registry.BLOCK&amp;lt;/code&amp;gt; is itself a &amp;lt;code&amp;gt;Codec&amp;lt;Block&amp;gt;&amp;lt;/code&amp;gt;. Forge Registries, however, do not currently implement Codec and cannot yet be used in this way; custom codecs must be created for forge-specific registries that are not tied to specific vanilla registries.&lt;br /&gt;
&lt;br /&gt;
Of particular note here is the CompoundNBT.CODEC, which can be used to e.g. serialize a CompoundNBT into a json file. This has a notable limitation in that CompoundNBT.CODEC *cannot* safely deserialize lists of numbers from json, due to the strong typing of ListNBT and the way that the NBTDynamicOps deserializer reads numeric values.&lt;br /&gt;
&lt;br /&gt;
= Creating Codecs =&lt;br /&gt;
&lt;br /&gt;
Suppose we have the following class, and we want to deserialize json files to instances of this class:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
public class ExampleCodecClass {&lt;br /&gt;
&lt;br /&gt;
    private final int someInt;&lt;br /&gt;
    private final Item item;&lt;br /&gt;
    private final List&amp;lt;BlockPos&amp;gt; blockPositions;&lt;br /&gt;
&lt;br /&gt;
    public ExampleCodecClass(int someInt, Item item, List&amp;lt;BlockPos&amp;gt; blockPositions) {...}&lt;br /&gt;
&lt;br /&gt;
    public int getSomeInt() { return this.someInt; }&lt;br /&gt;
    public Item getItem() { return this.someItem; }&lt;br /&gt;
    public List&amp;lt;BlockPos&amp;gt; getBlockPositions() { return this.blockPositions; }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Where a json file for an instance of this class might look like:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;json&amp;quot;&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
	&amp;quot;some_int&amp;quot;: 42,&lt;br /&gt;
	&amp;quot;item&amp;quot;: &amp;quot;minecraft:gold_ingot&amp;quot;,&lt;br /&gt;
	&amp;quot;block_positions&amp;quot;:&lt;br /&gt;
	[&lt;br /&gt;
		[0,0,0],&lt;br /&gt;
		[10,20,-100]&lt;br /&gt;
	]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We can assemble a codec for this class by building a new codec out of smaller codecs. We'll need a codec for each of these fields:&lt;br /&gt;
* a &amp;lt;code&amp;gt;Codec&amp;lt;Integer&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
* a &amp;lt;code&amp;gt;Codec&amp;lt;Item&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
* a &amp;lt;code&amp;gt;Codec&amp;lt;List&amp;lt;BlockPos&amp;gt;&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
And then we'll need to assemble these into a &amp;lt;code&amp;gt;Codec&amp;lt;ExampleCodecClass&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
As previously mentioned, we can use &amp;lt;code&amp;gt;Codec.INT&amp;lt;/code&amp;gt; for the integer codec, and &amp;lt;code&amp;gt;Registry.ITEM&amp;lt;/code&amp;gt; for the Item codec. We don't have a builtin codec for list-of-blockpos, but we can use BlockPos.CODEC to create one.&lt;br /&gt;
&lt;br /&gt;
== Lists ==&lt;br /&gt;
The &amp;lt;code&amp;gt;Codec#listOf&amp;lt;/code&amp;gt; instance method can be used to generate a codec for a List from an existing codec:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
// BlockPos.CODEC is a Codec&amp;lt;BlockPos&amp;gt;&lt;br /&gt;
Codec&amp;lt;List&amp;lt;BlockPos&amp;gt;&amp;gt; = BlockPos.CODEC.listOf();&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Codecs created via listOf() serialize things to listlike objects, such as [] json arrays or ListNBTs.&lt;br /&gt;
&lt;br /&gt;
== Records ==&lt;br /&gt;
RecordCodecBuilder is used to generate codecs that serialize instances of classes with explicitly named fields, like our example above. Codecs created via RecordCodecBuilder serialize things to maplike objects, such as {} json objects or CompoundNBTs.&lt;br /&gt;
&lt;br /&gt;
RecordCodecBuilder can be used in several ways, but the simplest form is as follows:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
public static final Codec&amp;lt;SomeJavaClass&amp;gt; = RecordCodecBuilder.create(instance -&amp;gt; instance.group(&lt;br /&gt;
		someFieldCodecA.fieldOf(&amp;quot;field_name_a&amp;quot;).forGetter(SomeJavaClass::getFieldA),&lt;br /&gt;
		someFieldCodecB.fieldOf(&amp;quot;field_name_b&amp;quot;).forGetter(SomeJavaClass::getFieldB),&lt;br /&gt;
		someFieldCodecC.fieldOf(&amp;quot;field_name_c&amp;quot;).forGetter(SomeJavaClass::getFieldC),&lt;br /&gt;
		// up to 16 fields can be declared here&lt;br /&gt;
	).apply(instance, SomeJavaClass::new));&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Where each line in the group specifies a codec instance for the type of that field, the field name in the serialized object, and the corresponding getter function in the java class. The builder is concluded by specifying a constructor or factory for the java class whose arguments are the previously defined fields in the same order.&lt;br /&gt;
&lt;br /&gt;
For example, using RecordCodecBuilder to create a codec for our example class above:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
public static final Codec&amp;lt;ExampleCodecClass&amp;gt; = RecordCodecBuilder.create(instance -&amp;gt; instance.group(&lt;br /&gt;
		Codec.INT.fieldOf(&amp;quot;some_int&amp;quot;).forGetter(ExampleCodecClass::getSomeInt),&lt;br /&gt;
		Registry.ITEM.fieldOf(&amp;quot;item&amp;quot;).forGetter(ExampleCodecClass::getItem),&lt;br /&gt;
		BlockPos.CODEC.listOf().fieldOf(&amp;quot;block_positions&amp;quot;).forGetter(ExampleCodecClass::getBlockPositions)&lt;br /&gt;
	).apply(instance, ExampleCodecClass::new));&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Optional and Default Values in Record Fields===&lt;br /&gt;
When RecordCodecBuilder is used as shown above, all of the fields are *required* to be in the serialized object (the JsonObject/CompoundNBT/etc), or the entire thing will fail to parse when the codec tries to deserialize it. If we wish to have optional or default values, we have several alternatives of fieldOf() we can use.&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;someCodec.optionalFieldOf(&amp;quot;field_name&amp;quot;)&amp;lt;/code&amp;gt; creates a field for an Optional. If the field in the json/nbt is not present or invalid, it will deserialize as an empty optional. Empty optionals will not be serialized; the field will be omitted from the json or nbt.&lt;br /&gt;
* &amp;lt;code&amp;gt;someCodec.optionalFieldOf(&amp;quot;field_name&amp;quot;, someDefaultValue)&amp;lt;/code&amp;gt; creates an optional field that deserializes as the given default value if the field is not present in the json/nbt. When serializing, if the field in the java object equals the default value, the value will not be serialized and the field will be omitted from the json or nbt.&lt;br /&gt;
&lt;br /&gt;
When using optional fields, be wary that if the field contains bad data or otherwise fails to serialize, the error will be silently caught, and the field will serialize as the default value instead!&lt;br /&gt;
&lt;br /&gt;
==Unit==&lt;br /&gt;
The &amp;lt;code&amp;gt;Codec.unit(defaultValue)&amp;lt;/code&amp;gt; codec creates a Codec that always deserializes a specified default value, regardless of input. When serializing, it serializes nothing.&lt;br /&gt;
&lt;br /&gt;
==Pair==&lt;br /&gt;
The &amp;lt;code&amp;gt;Codec.pair(codecA, codecB)&amp;lt;/code&amp;gt; static method takes two codecs and generates a Codec&amp;lt;Pair&amp;lt;A,B&amp;gt;&amp;gt; from them.&lt;br /&gt;
&lt;br /&gt;
The only valid arguments for this method are codecs that serialize to objects, such as codecs created using [[Codecs#Records|RecordCodecBuilder]], [[Codecs#Maps|unboundedMap]], or fieldOf. Codecs that serialize nothing (such as [[Codecs#Unit|unit codecs]]) are also valid as they act as objects-with-no-fields.&lt;br /&gt;
&lt;br /&gt;
The resulting Pair codec will serialize a single object that has all of the fields of the two original codecs.&lt;br /&gt;
&lt;br /&gt;
==Either==&lt;br /&gt;
The &amp;lt;code&amp;gt;Codec.either(codecA, codecB)&amp;lt;/code&amp;gt; static method takes two codecs and generates a Codec&amp;lt;Either&amp;lt;A,B&amp;gt;&amp;gt; from them.&lt;br /&gt;
&lt;br /&gt;
When this codec is used to de/serialize an object, it first attempts to use the first codec; if and only if that conversion fails, it then attempts to use the second codec. If that conversion also fails, then the returned DataResult will contain the error data from the *second* codec's conversion attempt.&lt;br /&gt;
&lt;br /&gt;
==Numeric Ranges==&lt;br /&gt;
The &amp;lt;code&amp;gt;Codec.intRange(min,max)&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;Codec.floatRange(min,max)&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;Codec.doubleRange(min,max)&amp;lt;/code&amp;gt; static methods generate Codecs for Integers, Floats, or Doubles, respectively, for which only a specified inclusive range is valid, and values outside that range will fail to de/serialize.&lt;br /&gt;
&lt;br /&gt;
==Maps==&lt;br /&gt;
Suppose we want to serialize a HashMap or other Map type, where we could have indefinitely many key-value pairs and we don't know what the keys are ahead of time.&lt;br /&gt;
&lt;br /&gt;
We can create a &amp;lt;code&amp;gt;Codec&amp;lt;Map&amp;lt;KEY,VALUE&amp;gt;&amp;gt;&amp;lt;/code&amp;gt; using the &amp;lt;code&amp;gt;Codec.unboundedMap&amp;lt;/code&amp;gt; static method, which takes a key codec and a value codec and creates a codec for a map type:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
public static final Codec&amp;lt;Map&amp;lt;String, BlockPos&amp;gt;&amp;gt; = Codec.unboundedMap(Codec.STRING, BlockPos.CODEC);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The serialized form of maps serialized by this codec will be a JsonObject or CompoundNBT, whose fields are the key-value pairs in the map.&lt;br /&gt;
&lt;br /&gt;
A limitation of using unboundedMap is that it only supports key codecs that serialize to Strings (including codecs for things like ResourceLocation that aren't Strings themselves but still serialize to strings). To create a codec for a Map whose keys are not fundamentally strings, the Map must be serialized as a list of key-value entries instead of using unboundedMap. As Codec.pair() also requires that the first codec serialize to a string, the pair function cannot be used for this purpose either.&lt;br /&gt;
&lt;br /&gt;
==Equivalent Types and xmap==&lt;br /&gt;
Suppose we have two java classes, Amalgam and Box; any Amalgam instance can be converted to a Box, and vice-versa. Now suppose we have a Codec&amp;lt;Amalgam&amp;gt;, but we'd also like to have a Codec&amp;lt;Box&amp;gt;. Rather than creating an entirely new codec for Box from scratch, we can simply xmap our Amalgam codec instead.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;Codec#xmap&amp;lt;/code&amp;gt; instance method is used to generate a second codec for a fundamentally equivalent type to the first codec's type. The method takes two function objects as arguments, which are used to convert the first type to the second when deserializing, and converting the second type to the first when serializing:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
public static final Codec&amp;lt;Box&amp;gt; = Amalgam.CODEC.xmap(Amalgam::toBox, Box::toAmalgam);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Codecs created in this manner will serialize objects in the same format as the starting codec.&lt;br /&gt;
&lt;br /&gt;
==Partially Equivalent Types, flatComapMap, comapFlatMap, and flatXMap==&lt;br /&gt;
Consider the ResourceLocation: Any ResourceLocation can be converted to a String, but not all Strings can be converted to a ResourceLocation; ResourceLocations have strict limits on their format and allowed characters.&lt;br /&gt;
&lt;br /&gt;
While we *could* use xmap to convert the Codec.STRING to a codec for ResourceLocations, this would cause attempts to parse an invalid string like &amp;lt;code&amp;gt;SHOUTY:MOD:Invalid$Characters&amp;lt;/code&amp;gt; to throw a runtime exception, when we really should be returning a failed DataResult to the parser instead -- which indeed is what the vanilla ResourceLocation codec does.&lt;br /&gt;
&lt;br /&gt;
Codecs have three additional instance methods for creating equivalent codecs for when we can *potentially* convert one type to another, but are not guaranteed to be able to do so. These take conversion function arguments that return DataResults, allowing validation to be performed during serialization and deserialization.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ Codec Conversion Methods&lt;br /&gt;
|-&lt;br /&gt;
! Can A always be converted to B? !! Can B always be converted to A? !! Which method of codecA should be used to create codecB?&lt;br /&gt;
|-&lt;br /&gt;
| yes || yes || codecA.xmap&lt;br /&gt;
|-&lt;br /&gt;
| yes || no || codecA.flatComapMap&lt;br /&gt;
|-&lt;br /&gt;
| no || yes || codecA.comapFlatMap&lt;br /&gt;
|-&lt;br /&gt;
| no || no || codecA.flatXmap&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Registry Dispatch ==&lt;br /&gt;
Registry Dispatch Codecs allow us to define a registry of codecs and delegate to a specific codec to deserialize a particular json based on a type field in that json. Dispatch codecs are used extensively when deserializing worldgen data.&lt;br /&gt;
&lt;br /&gt;
To create a dispatch codec for a Thing class, the following steps can be performed:&lt;br /&gt;
# Create a Thing abstract class class and ThingType interface. The ThingType interface should have a method that supplies a Codec&amp;lt;Thing&amp;gt;, while Thing subclasses must define a method that supplies a ThingType.&lt;br /&gt;
# Create a map or registry of ThingTypes, and register a ThingType for each sub-codec we want to have.&lt;br /&gt;
# Create a Codec&amp;lt;ThingType&amp;gt;, or have the ThingType registry implement Codec.&lt;br /&gt;
# Create our Codec&amp;lt;Thing&amp;gt; master codec by invoking &amp;lt;code&amp;gt;Codec#dispatch&amp;lt;/code&amp;gt; on our ThingType codec. This method's arguments are:&lt;br /&gt;
## A field name for the ID of the sub-codec (the example json below is using &amp;quot;type&amp;quot;)&lt;br /&gt;
## A function to retrieve a ThingType from a Thing&lt;br /&gt;
## A function to retrieve a Codec&amp;lt;Thing&amp;gt; from a ThingType&lt;br /&gt;
&lt;br /&gt;
We can then use our Codec&amp;lt;Thing&amp;gt; to create Thing fields in other codecs whose serialized format depends on the specific sub-codec used by a Thing instance.&lt;br /&gt;
&lt;br /&gt;
As an example of this, consider the ExampleCodecClass earlier. Suppose we make this class extend Thing and register our codec for it to a codec dispatch registry with the id &amp;quot;ourmod:exampleclass&amp;quot;. If we were to define an instance of this class in a Thing field in some json, it would look like&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;json&amp;quot;&amp;gt;&lt;br /&gt;
&amp;quot;some_thing&amp;quot;:&lt;br /&gt;
{&lt;br /&gt;
	&amp;quot;type&amp;quot;: &amp;quot;ourmod:exampleclass&amp;quot;,&lt;br /&gt;
	&amp;quot;some_int&amp;quot;: 42,&lt;br /&gt;
	&amp;quot;item&amp;quot;: &amp;quot;minecraft:gold_ingot&amp;quot;,&lt;br /&gt;
	&amp;quot;block_positions&amp;quot;:&lt;br /&gt;
	[&lt;br /&gt;
		[0,0,0],&lt;br /&gt;
		[10,20,-100]&lt;br /&gt;
	]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Other ThingTypes we register would have different fields in this json object, but would still be valid for the &amp;quot;some_thing&amp;quot; field.&lt;br /&gt;
&lt;br /&gt;
Several examples of vanilla classes that use dispatch codecs:&lt;br /&gt;
* RuleTest and IRuleTestType&lt;br /&gt;
* IParticleData and ParticleType&lt;br /&gt;
* ConfiguredPlacement and Placement&lt;br /&gt;
&lt;br /&gt;
=External Links=&lt;br /&gt;
* [https://github.com/Mojang/DataFixerUpper/blob/master/src/main/java/com/mojang/serialization/Codec.java Codecs in Mojang's official public DataFixerUpper repository]&lt;br /&gt;
* [https://kvverti.github.io/Documented-DataFixerUpper/snapshot/com/mojang/serialization/Codec.html#flatXmap-java.util.function.Function-java.util.function.Function- Unofficial Codec Javadocs]&lt;/div&gt;</summary>
		<author><name>Commoble</name></author>
	</entry>
	<entry>
		<id>https://forge.gemwire.uk/index.php?title=Codecs&amp;diff=2325</id>
		<title>Codecs</title>
		<link rel="alternate" type="text/html" href="https://forge.gemwire.uk/index.php?title=Codecs&amp;diff=2325"/>
		<updated>2021-01-04T23:14:33Z</updated>

		<summary type="html">&lt;p&gt;Commoble: Add link to NBT page&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Codecs are a serialization tool from mojang's DataFixerUpper library. Codecs are used alongside [[DynamicOps|DynamicOps]] to allow objects to be serialized to different formats and back, such as JSON or [[Using_NBT|NBT]]. While the DynamicOps describes the format the object is to be serialized to, the Codec describes the manner in which the object is to be serialized; a single Codec can be used to serialize an object to any format for which a DynamicOps exists. Codecs and DynamicOps jointly form an abstraction layer over data serialization, simplifying the effort needed to serialize or deserialize data.&lt;br /&gt;
&lt;br /&gt;
= Using Codecs =&lt;br /&gt;
&lt;br /&gt;
== Serialization and Deserialization ==&lt;br /&gt;
&lt;br /&gt;
The primary use for Codecs is to serialize java objects to some serialized type, such as a JsonElement or an INBT, and to deserialize an serialized object back to its proper java type. This is accomplished with &amp;lt;code&amp;gt;Codec#encodeStart&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;Codec#parse&amp;lt;/code&amp;gt;, respectively. Given a Codec&amp;lt;SomeJavaType&amp;gt; and a DynamicOps&amp;lt;SomeSerializedType&amp;gt;, we can convert instances of SomeJavaType to instances of SomeSerializedType and back.&lt;br /&gt;
&lt;br /&gt;
Each of these methods take a [[DynamicOps]] instance and an instance of the object we are serializing or deserializing, and returns a DataResult:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
// let someCodec be a Codec&amp;lt;SomeJavaType&amp;gt;&lt;br /&gt;
// let someJavaObject be an instance of SomeJavaType&lt;br /&gt;
// let someNBT and someJsonElement be instances of INBT and JsonElement, respectively&lt;br /&gt;
&lt;br /&gt;
// serialize some java object to INBT&lt;br /&gt;
DataResult&amp;lt;INBT&amp;gt; result = someCodec.encodeStart(NBTDynamicOps.INSTANCE, someJavaObject);&lt;br /&gt;
&lt;br /&gt;
// deserialize some INBT instance back to a proper java object&lt;br /&gt;
DataResult&amp;lt;SomeJavaType&amp;gt; result = someCodec.parse(NBTDynamicOps.INSTANCE, someNBT);&lt;br /&gt;
&lt;br /&gt;
// serialize some java object to a JsonElement&lt;br /&gt;
DataResult&amp;lt;JsonElement&amp;gt; result = someCodec.encodeStart(JsonOps.INSTANCE, someJavaObject);&lt;br /&gt;
&lt;br /&gt;
// deserialize a JsonElement back to a proper java object&lt;br /&gt;
DataResult&amp;lt;SomeJavaType&amp;gt; result = someCodec.parse(JsonOps.INSTANCE, someJsonElement);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A DataResult either holds the converted instance, or it holds some error data, depending on whether the conversion was successful or not, respectively. There are several things we can do with this DataResult; &amp;lt;code&amp;gt;DataResult#result&amp;lt;/code&amp;gt; simply returns an Optional containing the converted object if the conversion was successful, while &amp;lt;code&amp;gt;DataResult#resultOrPartial&amp;lt;/code&amp;gt; also runs a given function if the conversion was unsuccessful (in addition to returning the Optional). #resultOrPartial is particularly useful for logging errors during datapack deserialization:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
// deserialize something from json&lt;br /&gt;
someCodec.parse(JsonOps.INSTANCE, someJsonElement)&lt;br /&gt;
	.resultOrPartial(errorMessage -&amp;gt; doSomethingIfBadData(errorMessage))&lt;br /&gt;
	.ifPresent(someJavaObject -&amp;gt; doSomethingIfGoodData(someJavaObject))&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Builtin Codecs ==&lt;br /&gt;
=== Primitive Codecs ===&lt;br /&gt;
The Codec class itself contains static instances of codecs for all supported primitive types, e.g. &amp;lt;code&amp;gt;Codec.STRING&amp;lt;/code&amp;gt; is the canonical &amp;lt;code&amp;gt;Codec&amp;lt;String&amp;gt;&amp;lt;/code&amp;gt; implementation. Primitive codecs include:&lt;br /&gt;
* BOOL, which serializes to a boolean value&lt;br /&gt;
* BYTE, SHORT, INT, LONG, FLOAT, and DOUBLE, which serialize to numeric values&lt;br /&gt;
* STRING, which serializes to a string&lt;br /&gt;
* BYTE_BUFFER, INT_STREAM, and LONG_STREAM, which serialize to lists of numbers&lt;br /&gt;
* EMPTY, which represents null objects&lt;br /&gt;
&lt;br /&gt;
=== Other Builtin Codecs ===&lt;br /&gt;
Vanilla minecraft has many builtin codecs for objects that it frequently serializes. These codecs are typically static instances in the class the codec is serializing; e.g. &amp;lt;code&amp;gt;ResourceLocation.CODEC&amp;lt;/code&amp;gt; is the canonical &amp;lt;code&amp;gt;Codec&amp;lt;ResourceLocation&amp;gt;&amp;lt;/code&amp;gt;, while &amp;lt;code&amp;gt;BlockPos.CODEC&amp;lt;/code&amp;gt; is the codec used for serializing a BlockPos.&lt;br /&gt;
&lt;br /&gt;
Each vanilla &amp;lt;code&amp;gt;Registry&amp;lt;/code&amp;gt; acts as the Codec for the type of object the registry contains; e.g. &amp;lt;code&amp;gt;Registry.BLOCK&amp;lt;/code&amp;gt; is itself a &amp;lt;code&amp;gt;Codec&amp;lt;Block&amp;gt;&amp;lt;/code&amp;gt;. Forge Registries, however, do not currently implement Codec and cannot yet be used in this way; custom codecs must be created for forge-specific registries that are not tied to specific vanilla registries.&lt;br /&gt;
&lt;br /&gt;
Of particular note here is the CompoundNBT.CODEC, which can be used to e.g. serialize a CompoundNBT into a json file. This has a notable limitation in that CompoundNBT.CODEC *cannot* safely deserialize lists of numbers from json, due to the strong typing of ListNBT and the way that the NBTDynamicOps deserializer reads numeric values.&lt;br /&gt;
&lt;br /&gt;
= Creating Codecs =&lt;br /&gt;
&lt;br /&gt;
Suppose we have the following class, and we want to deserialize json files to instances of this class:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
public class ExampleCodecClass {&lt;br /&gt;
&lt;br /&gt;
    private final int someInt;&lt;br /&gt;
    private final Item item;&lt;br /&gt;
    private final List&amp;lt;BlockPos&amp;gt; blockPositions;&lt;br /&gt;
&lt;br /&gt;
    public ExampleCodecClass(int someInt, Item item, List&amp;lt;BlockPos&amp;gt; blockPositions) {...}&lt;br /&gt;
&lt;br /&gt;
    public int getSomeInt() { return this.someInt; }&lt;br /&gt;
    public Item getItem() { return this.someItem; }&lt;br /&gt;
    public List&amp;lt;BlockPos&amp;gt; getBlockPositions() { return this.blockPositions; }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Where a json file for an instance of this class might look like:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;json&amp;quot;&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
	&amp;quot;some_int&amp;quot;: 42,&lt;br /&gt;
	&amp;quot;item&amp;quot;: &amp;quot;minecraft:gold_ingot&amp;quot;,&lt;br /&gt;
	&amp;quot;block_positions&amp;quot;:&lt;br /&gt;
	[&lt;br /&gt;
		[0,0,0],&lt;br /&gt;
		[10,20,-100]&lt;br /&gt;
	]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We can assemble a codec for this class by building a new codec out of smaller codecs. We'll need a codec for each of these fields:&lt;br /&gt;
* a &amp;lt;code&amp;gt;Codec&amp;lt;Integer&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
* a &amp;lt;code&amp;gt;Codec&amp;lt;Item&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
* a &amp;lt;code&amp;gt;Codec&amp;lt;List&amp;lt;BlockPos&amp;gt;&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
And then we'll need to assemble these into a &amp;lt;code&amp;gt;Codec&amp;lt;ExampleCodecClass&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
As previously mentioned, we can use &amp;lt;code&amp;gt;Codec.INT&amp;lt;/code&amp;gt; for the integer codec, and &amp;lt;code&amp;gt;Registry.ITEM&amp;lt;/code&amp;gt; for the Item codec. We don't have a builtin codec for list-of-blockpos, but we can use BlockPos.CODEC to create one.&lt;br /&gt;
&lt;br /&gt;
== Lists ==&lt;br /&gt;
The &amp;lt;code&amp;gt;Codec#listOf&amp;lt;/code&amp;gt; instance method can be used to generate a codec for a List from an existing codec:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
// BlockPos.CODEC is a Codec&amp;lt;BlockPos&amp;gt;&lt;br /&gt;
Codec&amp;lt;List&amp;lt;BlockPos&amp;gt;&amp;gt; = BlockPos.CODEC.listOf();&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Codecs created via listOf() serialize things to listlike objects, such as [] json arrays or ListNBTs.&lt;br /&gt;
&lt;br /&gt;
== Records ==&lt;br /&gt;
RecordCodecBuilder is used to generate codecs that serialize instances of classes with explicitly named fields, like our example above. Codecs created via RecordCodecBuilder serialize things to maplike objects, such as {} json objects or CompoundNBTs.&lt;br /&gt;
&lt;br /&gt;
RecordCodecBuilder can be used in several ways, but the simplest form is as follows:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
public static final Codec&amp;lt;SomeJavaClass&amp;gt; = RecordCodecBuilder.create(instance -&amp;gt; instance.group(&lt;br /&gt;
		someFieldCodecA.fieldOf(&amp;quot;field_name_a&amp;quot;).forGetter(SomeJavaClass::getFieldA),&lt;br /&gt;
		someFieldCodecB.fieldOf(&amp;quot;field_name_b&amp;quot;).forGetter(SomeJavaClass::getFieldB),&lt;br /&gt;
		someFieldCodecC.fieldOf(&amp;quot;field_name_c&amp;quot;).forGetter(SomeJavaClass::getFieldC),&lt;br /&gt;
		// up to 16 fields can be declared here&lt;br /&gt;
	).apply(instance, SomeJavaClass::new));&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Where each line in the group specifies a codec instance for the type of that field, the field name in the serialized object, and the corresponding getter function in the java class. The builder is concluded by specifying a constructor or factory for the java class whose arguments are the previously defined fields in the same order.&lt;br /&gt;
&lt;br /&gt;
For example, using RecordCodecBuilder to create a codec for our example class above:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
public static final Codec&amp;lt;ExampleCodecClass&amp;gt; = RecordCodecBuilder.create(instance -&amp;gt; instance.group(&lt;br /&gt;
		Codec.INT.fieldOf(&amp;quot;some_int&amp;quot;).forGetter(ExampleCodecClass::getSomeInt),&lt;br /&gt;
		Registry.ITEM.fieldOf(&amp;quot;item&amp;quot;).forGetter(ExampleCodecClass::getItem),&lt;br /&gt;
		BlockPos.CODEC.listOf().fieldOf(&amp;quot;block_positions&amp;quot;).forGetter(ExampleCodecClass::getBlockPositions)&lt;br /&gt;
	).apply(instance, ExampleCodecClass::new));&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Optional and Default Values in Record Fields===&lt;br /&gt;
When RecordCodecBuilder is used as shown above, all of the fields are *required* to be in the serialized object (the JsonObject/CompoundNBT/etc), or the entire thing will fail to parse when the codec tries to deserialize it. If we wish to have optional or default values, we have several alternatives of fieldOf() we can use.&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;someCodec.optionalFieldOf(&amp;quot;field_name&amp;quot;)&amp;lt;/code&amp;gt; creates a field for an Optional. If the field in the json/nbt is not present or invalid, it will deserialize as an empty optional. Empty optionals will not be serialized; the field will be omitted from the json or nbt.&lt;br /&gt;
* &amp;lt;code&amp;gt;someCodec.optionalFieldOf(&amp;quot;field_name&amp;quot;, someDefaultValue)&amp;lt;/code&amp;gt; creates an optional field that deserializes as the given default value if the field is not present in the json/nbt. When serializing, if the field in the java object equals the default value, the value will not be serialized and the field will be omitted from the json or nbt.&lt;br /&gt;
&lt;br /&gt;
When using optional fields, be wary that if the field contains bad data or otherwise fails to serialize, the error will be silently caught, and the field will serialize as the default value instead!&lt;br /&gt;
&lt;br /&gt;
==Unit==&lt;br /&gt;
The &amp;lt;code&amp;gt;Codec.unit(defaultValue)&amp;lt;/code&amp;gt; codec creates a Codec that always deserializes a specified default value, regardless of input. When serializing, it serializes nothing.&lt;br /&gt;
&lt;br /&gt;
==Pair==&lt;br /&gt;
The &amp;lt;code&amp;gt;Codec.pair(codecA, codecB)&amp;lt;/code&amp;gt; static method takes two codecs and generates a Codec&amp;lt;Pair&amp;lt;A,B&amp;gt;&amp;gt; from them.&lt;br /&gt;
&lt;br /&gt;
Using this function requires that codecA be a codec that serializes to a string.&lt;br /&gt;
&lt;br /&gt;
==Either==&lt;br /&gt;
The &amp;lt;code&amp;gt;Codec.either(codecA, codecB)&amp;lt;/code&amp;gt; static method takes two codecs and generates a Codec&amp;lt;Either&amp;lt;A,B&amp;gt;&amp;gt; from them.&lt;br /&gt;
&lt;br /&gt;
When this codec is used to de/serialize an object, it first attempts to use the first codec; if and only if that conversion fails, it then attempts to use the second codec. If that conversion also fails, then the returned DataResult will contain the error data from the *second* codec's conversion attempt.&lt;br /&gt;
&lt;br /&gt;
==Numeric Ranges==&lt;br /&gt;
The &amp;lt;code&amp;gt;Codec.intRange(min,max)&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;Codec.floatRange(min,max)&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;Codec.doubleRange(min,max)&amp;lt;/code&amp;gt; static methods generate Codecs for Integers, Floats, or Doubles, respectively, for which only a specified inclusive range is valid, and values outside that range will fail to de/serialize.&lt;br /&gt;
&lt;br /&gt;
==Maps==&lt;br /&gt;
Suppose we want to serialize a HashMap or other Map type, where we could have indefinitely many key-value pairs and we don't know what the keys are ahead of time.&lt;br /&gt;
&lt;br /&gt;
We can create a &amp;lt;code&amp;gt;Codec&amp;lt;Map&amp;lt;KEY,VALUE&amp;gt;&amp;gt;&amp;lt;/code&amp;gt; using the &amp;lt;code&amp;gt;Codec.unboundedMap&amp;lt;/code&amp;gt; static method, which takes a key codec and a value codec and creates a codec for a map type:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
public static final Codec&amp;lt;Map&amp;lt;String, BlockPos&amp;gt;&amp;gt; = Codec.unboundedMap(Codec.STRING, BlockPos.CODEC);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The serialized form of maps serialized by this codec will be a JsonObject or CompoundNBT, whose fields are the key-value pairs in the map.&lt;br /&gt;
&lt;br /&gt;
A limitation of using unboundedMap is that it only supports key codecs that serialize to Strings (including codecs for things like ResourceLocation that aren't Strings themselves but still serialize to strings). To create a codec for a Map whose keys are not fundamentally strings, the Map must be serialized as a list of key-value entries instead of using unboundedMap. As Codec.pair() also requires that the first codec serialize to a string, the pair function cannot be used for this purpose either.&lt;br /&gt;
&lt;br /&gt;
==Equivalent Types and xmap==&lt;br /&gt;
Suppose we have two java classes, Amalgam and Box; any Amalgam instance can be converted to a Box, and vice-versa. Now suppose we have a Codec&amp;lt;Amalgam&amp;gt;, but we'd also like to have a Codec&amp;lt;Box&amp;gt;. Rather than creating an entirely new codec for Box from scratch, we can simply xmap our Amalgam codec instead.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;Codec#xmap&amp;lt;/code&amp;gt; instance method is used to generate a second codec for a fundamentally equivalent type to the first codec's type. The method takes two function objects as arguments, which are used to convert the first type to the second when deserializing, and converting the second type to the first when serializing:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
public static final Codec&amp;lt;Box&amp;gt; = Amalgam.CODEC.xmap(Amalgam::toBox, Box::toAmalgam);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Codecs created in this manner will serialize objects in the same format as the starting codec.&lt;br /&gt;
&lt;br /&gt;
==Partially Equivalent Types, flatComapMap, comapFlatMap, and flatXMap==&lt;br /&gt;
Consider the ResourceLocation: Any ResourceLocation can be converted to a String, but not all Strings can be converted to a ResourceLocation; ResourceLocations have strict limits on their format and allowed characters.&lt;br /&gt;
&lt;br /&gt;
While we *could* use xmap to convert the Codec.STRING to a codec for ResourceLocations, this would cause attempts to parse an invalid string like &amp;lt;code&amp;gt;SHOUTY:MOD:Invalid$Characters&amp;lt;/code&amp;gt; to throw a runtime exception, when we really should be returning a failed DataResult to the parser instead -- which indeed is what the vanilla ResourceLocation codec does.&lt;br /&gt;
&lt;br /&gt;
Codecs have three additional instance methods for creating equivalent codecs for when we can *potentially* convert one type to another, but are not guaranteed to be able to do so. These take conversion function arguments that return DataResults, allowing validation to be performed during serialization and deserialization.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ Codec Conversion Methods&lt;br /&gt;
|-&lt;br /&gt;
! Can A always be converted to B? !! Can B always be converted to A? !! Which method of codecA should be used to create codecB?&lt;br /&gt;
|-&lt;br /&gt;
| yes || yes || codecA.xmap&lt;br /&gt;
|-&lt;br /&gt;
| yes || no || codecA.flatComapMap&lt;br /&gt;
|-&lt;br /&gt;
| no || yes || codecA.comapFlatMap&lt;br /&gt;
|-&lt;br /&gt;
| no || no || codecA.flatXmap&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Registry Dispatch ==&lt;br /&gt;
Registry Dispatch Codecs allow us to define a registry of codecs and delegate to a specific codec to deserialize a particular json based on a type field in that json. Dispatch codecs are used extensively when deserializing worldgen data.&lt;br /&gt;
&lt;br /&gt;
To create a dispatch codec for a Thing class, the following steps can be performed:&lt;br /&gt;
# Create a Thing abstract class class and ThingType interface. The ThingType interface should have a method that supplies a Codec&amp;lt;Thing&amp;gt;, while Thing subclasses must define a method that supplies a ThingType.&lt;br /&gt;
# Create a map or registry of ThingTypes, and register a ThingType for each sub-codec we want to have.&lt;br /&gt;
# Create a Codec&amp;lt;ThingType&amp;gt;, or have the ThingType registry implement Codec.&lt;br /&gt;
# Create our Codec&amp;lt;Thing&amp;gt; master codec by invoking &amp;lt;code&amp;gt;Codec#dispatch&amp;lt;/code&amp;gt; on our ThingType codec. This method's arguments are:&lt;br /&gt;
## A field name for the ID of the sub-codec (the example json below is using &amp;quot;type&amp;quot;)&lt;br /&gt;
## A function to retrieve a ThingType from a Thing&lt;br /&gt;
## A function to retrieve a Codec&amp;lt;Thing&amp;gt; from a ThingType&lt;br /&gt;
&lt;br /&gt;
We can then use our Codec&amp;lt;Thing&amp;gt; to create Thing fields in other codecs whose serialized format depends on the specific sub-codec used by a Thing instance.&lt;br /&gt;
&lt;br /&gt;
As an example of this, consider the ExampleCodecClass earlier. Suppose we make this class extend Thing and register our codec for it to a codec dispatch registry with the id &amp;quot;ourmod:exampleclass&amp;quot;. If we were to define an instance of this class in a Thing field in some json, it would look like&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;json&amp;quot;&amp;gt;&lt;br /&gt;
&amp;quot;some_thing&amp;quot;:&lt;br /&gt;
{&lt;br /&gt;
	&amp;quot;type&amp;quot;: &amp;quot;ourmod:exampleclass&amp;quot;,&lt;br /&gt;
	&amp;quot;some_int&amp;quot;: 42,&lt;br /&gt;
	&amp;quot;item&amp;quot;: &amp;quot;minecraft:gold_ingot&amp;quot;,&lt;br /&gt;
	&amp;quot;block_positions&amp;quot;:&lt;br /&gt;
	[&lt;br /&gt;
		[0,0,0],&lt;br /&gt;
		[10,20,-100]&lt;br /&gt;
	]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Other ThingTypes we register would have different fields in this json object, but would still be valid for the &amp;quot;some_thing&amp;quot; field.&lt;br /&gt;
&lt;br /&gt;
Several examples of vanilla classes that use dispatch codecs:&lt;br /&gt;
* RuleTest and IRuleTestType&lt;br /&gt;
* IParticleData and ParticleType&lt;br /&gt;
* ConfiguredPlacement and Placement&lt;br /&gt;
&lt;br /&gt;
=External Links=&lt;br /&gt;
* [https://github.com/Mojang/DataFixerUpper/blob/master/src/main/java/com/mojang/serialization/Codec.java Codecs in Mojang's official public DataFixerUpper repository]&lt;br /&gt;
* [https://kvverti.github.io/Documented-DataFixerUpper/snapshot/com/mojang/serialization/Codec.html#flatXmap-java.util.function.Function-java.util.function.Function- Unofficial Codec Javadocs]&lt;/div&gt;</summary>
		<author><name>Commoble</name></author>
	</entry>
	<entry>
		<id>https://forge.gemwire.uk/index.php?title=Codecs&amp;diff=2324</id>
		<title>Codecs</title>
		<link rel="alternate" type="text/html" href="https://forge.gemwire.uk/index.php?title=Codecs&amp;diff=2324"/>
		<updated>2021-01-04T23:10:02Z</updated>

		<summary type="html">&lt;p&gt;Commoble: Clarify numeric range methods&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Codecs are a serialization tool from mojang's DataFixerUpper library. Codecs are used alongside [[DynamicOps|DynamicOps]] to allow objects to be serialized to different formats and back, such as JSON or NBT. While the DynamicOps describes the format the object is to be serialized to, the Codec describes the manner in which the object is to be serialized; a single Codec can be used to serialize an object to any format for which a DynamicOps exists. Codecs and DynamicOps jointly form an abstraction layer over data serialization, simplifying the effort needed to serialize or deserialize data.&lt;br /&gt;
&lt;br /&gt;
= Using Codecs =&lt;br /&gt;
&lt;br /&gt;
== Serialization and Deserialization ==&lt;br /&gt;
&lt;br /&gt;
The primary use for Codecs is to serialize java objects to some serialized type, such as a JsonElement or an INBT, and to deserialize an serialized object back to its proper java type. This is accomplished with &amp;lt;code&amp;gt;Codec#encodeStart&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;Codec#parse&amp;lt;/code&amp;gt;, respectively. Given a Codec&amp;lt;SomeJavaType&amp;gt; and a DynamicOps&amp;lt;SomeSerializedType&amp;gt;, we can convert instances of SomeJavaType to instances of SomeSerializedType and back.&lt;br /&gt;
&lt;br /&gt;
Each of these methods take a [[DynamicOps]] instance and an instance of the object we are serializing or deserializing, and returns a DataResult:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
// let someCodec be a Codec&amp;lt;SomeJavaType&amp;gt;&lt;br /&gt;
// let someJavaObject be an instance of SomeJavaType&lt;br /&gt;
// let someNBT and someJsonElement be instances of INBT and JsonElement, respectively&lt;br /&gt;
&lt;br /&gt;
// serialize some java object to INBT&lt;br /&gt;
DataResult&amp;lt;INBT&amp;gt; result = someCodec.encodeStart(NBTDynamicOps.INSTANCE, someJavaObject);&lt;br /&gt;
&lt;br /&gt;
// deserialize some INBT instance back to a proper java object&lt;br /&gt;
DataResult&amp;lt;SomeJavaType&amp;gt; result = someCodec.parse(NBTDynamicOps.INSTANCE, someNBT);&lt;br /&gt;
&lt;br /&gt;
// serialize some java object to a JsonElement&lt;br /&gt;
DataResult&amp;lt;JsonElement&amp;gt; result = someCodec.encodeStart(JsonOps.INSTANCE, someJavaObject);&lt;br /&gt;
&lt;br /&gt;
// deserialize a JsonElement back to a proper java object&lt;br /&gt;
DataResult&amp;lt;SomeJavaType&amp;gt; result = someCodec.parse(JsonOps.INSTANCE, someJsonElement);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A DataResult either holds the converted instance, or it holds some error data, depending on whether the conversion was successful or not, respectively. There are several things we can do with this DataResult; &amp;lt;code&amp;gt;DataResult#result&amp;lt;/code&amp;gt; simply returns an Optional containing the converted object if the conversion was successful, while &amp;lt;code&amp;gt;DataResult#resultOrPartial&amp;lt;/code&amp;gt; also runs a given function if the conversion was unsuccessful (in addition to returning the Optional). #resultOrPartial is particularly useful for logging errors during datapack deserialization:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
// deserialize something from json&lt;br /&gt;
someCodec.parse(JsonOps.INSTANCE, someJsonElement)&lt;br /&gt;
	.resultOrPartial(errorMessage -&amp;gt; doSomethingIfBadData(errorMessage))&lt;br /&gt;
	.ifPresent(someJavaObject -&amp;gt; doSomethingIfGoodData(someJavaObject))&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Builtin Codecs ==&lt;br /&gt;
=== Primitive Codecs ===&lt;br /&gt;
The Codec class itself contains static instances of codecs for all supported primitive types, e.g. &amp;lt;code&amp;gt;Codec.STRING&amp;lt;/code&amp;gt; is the canonical &amp;lt;code&amp;gt;Codec&amp;lt;String&amp;gt;&amp;lt;/code&amp;gt; implementation. Primitive codecs include:&lt;br /&gt;
* BOOL, which serializes to a boolean value&lt;br /&gt;
* BYTE, SHORT, INT, LONG, FLOAT, and DOUBLE, which serialize to numeric values&lt;br /&gt;
* STRING, which serializes to a string&lt;br /&gt;
* BYTE_BUFFER, INT_STREAM, and LONG_STREAM, which serialize to lists of numbers&lt;br /&gt;
* EMPTY, which represents null objects&lt;br /&gt;
&lt;br /&gt;
=== Other Builtin Codecs ===&lt;br /&gt;
Vanilla minecraft has many builtin codecs for objects that it frequently serializes. These codecs are typically static instances in the class the codec is serializing; e.g. &amp;lt;code&amp;gt;ResourceLocation.CODEC&amp;lt;/code&amp;gt; is the canonical &amp;lt;code&amp;gt;Codec&amp;lt;ResourceLocation&amp;gt;&amp;lt;/code&amp;gt;, while &amp;lt;code&amp;gt;BlockPos.CODEC&amp;lt;/code&amp;gt; is the codec used for serializing a BlockPos.&lt;br /&gt;
&lt;br /&gt;
Each vanilla &amp;lt;code&amp;gt;Registry&amp;lt;/code&amp;gt; acts as the Codec for the type of object the registry contains; e.g. &amp;lt;code&amp;gt;Registry.BLOCK&amp;lt;/code&amp;gt; is itself a &amp;lt;code&amp;gt;Codec&amp;lt;Block&amp;gt;&amp;lt;/code&amp;gt;. Forge Registries, however, do not currently implement Codec and cannot yet be used in this way; custom codecs must be created for forge-specific registries that are not tied to specific vanilla registries.&lt;br /&gt;
&lt;br /&gt;
Of particular note here is the CompoundNBT.CODEC, which can be used to e.g. serialize a CompoundNBT into a json file. This has a notable limitation in that CompoundNBT.CODEC *cannot* safely deserialize lists of numbers from json, due to the strong typing of ListNBT and the way that the NBTDynamicOps deserializer reads numeric values.&lt;br /&gt;
&lt;br /&gt;
= Creating Codecs =&lt;br /&gt;
&lt;br /&gt;
Suppose we have the following class, and we want to deserialize json files to instances of this class:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
public class ExampleCodecClass {&lt;br /&gt;
&lt;br /&gt;
    private final int someInt;&lt;br /&gt;
    private final Item item;&lt;br /&gt;
    private final List&amp;lt;BlockPos&amp;gt; blockPositions;&lt;br /&gt;
&lt;br /&gt;
    public ExampleCodecClass(int someInt, Item item, List&amp;lt;BlockPos&amp;gt; blockPositions) {...}&lt;br /&gt;
&lt;br /&gt;
    public int getSomeInt() { return this.someInt; }&lt;br /&gt;
    public Item getItem() { return this.someItem; }&lt;br /&gt;
    public List&amp;lt;BlockPos&amp;gt; getBlockPositions() { return this.blockPositions; }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Where a json file for an instance of this class might look like:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;json&amp;quot;&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
	&amp;quot;some_int&amp;quot;: 42,&lt;br /&gt;
	&amp;quot;item&amp;quot;: &amp;quot;minecraft:gold_ingot&amp;quot;,&lt;br /&gt;
	&amp;quot;block_positions&amp;quot;:&lt;br /&gt;
	[&lt;br /&gt;
		[0,0,0],&lt;br /&gt;
		[10,20,-100]&lt;br /&gt;
	]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We can assemble a codec for this class by building a new codec out of smaller codecs. We'll need a codec for each of these fields:&lt;br /&gt;
* a &amp;lt;code&amp;gt;Codec&amp;lt;Integer&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
* a &amp;lt;code&amp;gt;Codec&amp;lt;Item&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
* a &amp;lt;code&amp;gt;Codec&amp;lt;List&amp;lt;BlockPos&amp;gt;&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
And then we'll need to assemble these into a &amp;lt;code&amp;gt;Codec&amp;lt;ExampleCodecClass&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
As previously mentioned, we can use &amp;lt;code&amp;gt;Codec.INT&amp;lt;/code&amp;gt; for the integer codec, and &amp;lt;code&amp;gt;Registry.ITEM&amp;lt;/code&amp;gt; for the Item codec. We don't have a builtin codec for list-of-blockpos, but we can use BlockPos.CODEC to create one.&lt;br /&gt;
&lt;br /&gt;
== Lists ==&lt;br /&gt;
The &amp;lt;code&amp;gt;Codec#listOf&amp;lt;/code&amp;gt; instance method can be used to generate a codec for a List from an existing codec:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
// BlockPos.CODEC is a Codec&amp;lt;BlockPos&amp;gt;&lt;br /&gt;
Codec&amp;lt;List&amp;lt;BlockPos&amp;gt;&amp;gt; = BlockPos.CODEC.listOf();&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Codecs created via listOf() serialize things to listlike objects, such as [] json arrays or ListNBTs.&lt;br /&gt;
&lt;br /&gt;
== Records ==&lt;br /&gt;
RecordCodecBuilder is used to generate codecs that serialize instances of classes with explicitly named fields, like our example above. Codecs created via RecordCodecBuilder serialize things to maplike objects, such as {} json objects or CompoundNBTs.&lt;br /&gt;
&lt;br /&gt;
RecordCodecBuilder can be used in several ways, but the simplest form is as follows:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
public static final Codec&amp;lt;SomeJavaClass&amp;gt; = RecordCodecBuilder.create(instance -&amp;gt; instance.group(&lt;br /&gt;
		someFieldCodecA.fieldOf(&amp;quot;field_name_a&amp;quot;).forGetter(SomeJavaClass::getFieldA),&lt;br /&gt;
		someFieldCodecB.fieldOf(&amp;quot;field_name_b&amp;quot;).forGetter(SomeJavaClass::getFieldB),&lt;br /&gt;
		someFieldCodecC.fieldOf(&amp;quot;field_name_c&amp;quot;).forGetter(SomeJavaClass::getFieldC),&lt;br /&gt;
		// up to 16 fields can be declared here&lt;br /&gt;
	).apply(instance, SomeJavaClass::new));&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Where each line in the group specifies a codec instance for the type of that field, the field name in the serialized object, and the corresponding getter function in the java class. The builder is concluded by specifying a constructor or factory for the java class whose arguments are the previously defined fields in the same order.&lt;br /&gt;
&lt;br /&gt;
For example, using RecordCodecBuilder to create a codec for our example class above:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
public static final Codec&amp;lt;ExampleCodecClass&amp;gt; = RecordCodecBuilder.create(instance -&amp;gt; instance.group(&lt;br /&gt;
		Codec.INT.fieldOf(&amp;quot;some_int&amp;quot;).forGetter(ExampleCodecClass::getSomeInt),&lt;br /&gt;
		Registry.ITEM.fieldOf(&amp;quot;item&amp;quot;).forGetter(ExampleCodecClass::getItem),&lt;br /&gt;
		BlockPos.CODEC.listOf().fieldOf(&amp;quot;block_positions&amp;quot;).forGetter(ExampleCodecClass::getBlockPositions)&lt;br /&gt;
	).apply(instance, ExampleCodecClass::new));&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Optional and Default Values in Record Fields===&lt;br /&gt;
When RecordCodecBuilder is used as shown above, all of the fields are *required* to be in the serialized object (the JsonObject/CompoundNBT/etc), or the entire thing will fail to parse when the codec tries to deserialize it. If we wish to have optional or default values, we have several alternatives of fieldOf() we can use.&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;someCodec.optionalFieldOf(&amp;quot;field_name&amp;quot;)&amp;lt;/code&amp;gt; creates a field for an Optional. If the field in the json/nbt is not present or invalid, it will deserialize as an empty optional. Empty optionals will not be serialized; the field will be omitted from the json or nbt.&lt;br /&gt;
* &amp;lt;code&amp;gt;someCodec.optionalFieldOf(&amp;quot;field_name&amp;quot;, someDefaultValue)&amp;lt;/code&amp;gt; creates an optional field that deserializes as the given default value if the field is not present in the json/nbt. When serializing, if the field in the java object equals the default value, the value will not be serialized and the field will be omitted from the json or nbt.&lt;br /&gt;
&lt;br /&gt;
When using optional fields, be wary that if the field contains bad data or otherwise fails to serialize, the error will be silently caught, and the field will serialize as the default value instead!&lt;br /&gt;
&lt;br /&gt;
==Unit==&lt;br /&gt;
The &amp;lt;code&amp;gt;Codec.unit(defaultValue)&amp;lt;/code&amp;gt; codec creates a Codec that always deserializes a specified default value, regardless of input. When serializing, it serializes nothing.&lt;br /&gt;
&lt;br /&gt;
==Pair==&lt;br /&gt;
The &amp;lt;code&amp;gt;Codec.pair(codecA, codecB)&amp;lt;/code&amp;gt; static method takes two codecs and generates a Codec&amp;lt;Pair&amp;lt;A,B&amp;gt;&amp;gt; from them.&lt;br /&gt;
&lt;br /&gt;
Using this function requires that codecA be a codec that serializes to a string.&lt;br /&gt;
&lt;br /&gt;
==Either==&lt;br /&gt;
The &amp;lt;code&amp;gt;Codec.either(codecA, codecB)&amp;lt;/code&amp;gt; static method takes two codecs and generates a Codec&amp;lt;Either&amp;lt;A,B&amp;gt;&amp;gt; from them.&lt;br /&gt;
&lt;br /&gt;
When this codec is used to de/serialize an object, it first attempts to use the first codec; if and only if that conversion fails, it then attempts to use the second codec. If that conversion also fails, then the returned DataResult will contain the error data from the *second* codec's conversion attempt.&lt;br /&gt;
&lt;br /&gt;
==Numeric Ranges==&lt;br /&gt;
The &amp;lt;code&amp;gt;Codec.intRange(min,max)&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;Codec.floatRange(min,max)&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;Codec.doubleRange(min,max)&amp;lt;/code&amp;gt; static methods generate Codecs for Integers, Floats, or Doubles, respectively, for which only a specified inclusive range is valid, and values outside that range will fail to de/serialize.&lt;br /&gt;
&lt;br /&gt;
==Maps==&lt;br /&gt;
Suppose we want to serialize a HashMap or other Map type, where we could have indefinitely many key-value pairs and we don't know what the keys are ahead of time.&lt;br /&gt;
&lt;br /&gt;
We can create a &amp;lt;code&amp;gt;Codec&amp;lt;Map&amp;lt;KEY,VALUE&amp;gt;&amp;gt;&amp;lt;/code&amp;gt; using the &amp;lt;code&amp;gt;Codec.unboundedMap&amp;lt;/code&amp;gt; static method, which takes a key codec and a value codec and creates a codec for a map type:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
public static final Codec&amp;lt;Map&amp;lt;String, BlockPos&amp;gt;&amp;gt; = Codec.unboundedMap(Codec.STRING, BlockPos.CODEC);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The serialized form of maps serialized by this codec will be a JsonObject or CompoundNBT, whose fields are the key-value pairs in the map.&lt;br /&gt;
&lt;br /&gt;
A limitation of using unboundedMap is that it only supports key codecs that serialize to Strings (including codecs for things like ResourceLocation that aren't Strings themselves but still serialize to strings). To create a codec for a Map whose keys are not fundamentally strings, the Map must be serialized as a list of key-value entries instead of using unboundedMap. As Codec.pair() also requires that the first codec serialize to a string, the pair function cannot be used for this purpose either.&lt;br /&gt;
&lt;br /&gt;
==Equivalent Types and xmap==&lt;br /&gt;
Suppose we have two java classes, Amalgam and Box; any Amalgam instance can be converted to a Box, and vice-versa. Now suppose we have a Codec&amp;lt;Amalgam&amp;gt;, but we'd also like to have a Codec&amp;lt;Box&amp;gt;. Rather than creating an entirely new codec for Box from scratch, we can simply xmap our Amalgam codec instead.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;Codec#xmap&amp;lt;/code&amp;gt; instance method is used to generate a second codec for a fundamentally equivalent type to the first codec's type. The method takes two function objects as arguments, which are used to convert the first type to the second when deserializing, and converting the second type to the first when serializing:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
public static final Codec&amp;lt;Box&amp;gt; = Amalgam.CODEC.xmap(Amalgam::toBox, Box::toAmalgam);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Codecs created in this manner will serialize objects in the same format as the starting codec.&lt;br /&gt;
&lt;br /&gt;
==Partially Equivalent Types, flatComapMap, comapFlatMap, and flatXMap==&lt;br /&gt;
Consider the ResourceLocation: Any ResourceLocation can be converted to a String, but not all Strings can be converted to a ResourceLocation; ResourceLocations have strict limits on their format and allowed characters.&lt;br /&gt;
&lt;br /&gt;
While we *could* use xmap to convert the Codec.STRING to a codec for ResourceLocations, this would cause attempts to parse an invalid string like &amp;lt;code&amp;gt;SHOUTY:MOD:Invalid$Characters&amp;lt;/code&amp;gt; to throw a runtime exception, when we really should be returning a failed DataResult to the parser instead -- which indeed is what the vanilla ResourceLocation codec does.&lt;br /&gt;
&lt;br /&gt;
Codecs have three additional instance methods for creating equivalent codecs for when we can *potentially* convert one type to another, but are not guaranteed to be able to do so. These take conversion function arguments that return DataResults, allowing validation to be performed during serialization and deserialization.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ Codec Conversion Methods&lt;br /&gt;
|-&lt;br /&gt;
! Can A always be converted to B? !! Can B always be converted to A? !! Which method of codecA should be used to create codecB?&lt;br /&gt;
|-&lt;br /&gt;
| yes || yes || codecA.xmap&lt;br /&gt;
|-&lt;br /&gt;
| yes || no || codecA.flatComapMap&lt;br /&gt;
|-&lt;br /&gt;
| no || yes || codecA.comapFlatMap&lt;br /&gt;
|-&lt;br /&gt;
| no || no || codecA.flatXmap&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Registry Dispatch ==&lt;br /&gt;
Registry Dispatch Codecs allow us to define a registry of codecs and delegate to a specific codec to deserialize a particular json based on a type field in that json. Dispatch codecs are used extensively when deserializing worldgen data.&lt;br /&gt;
&lt;br /&gt;
To create a dispatch codec for a Thing class, the following steps can be performed:&lt;br /&gt;
# Create a Thing abstract class class and ThingType interface. The ThingType interface should have a method that supplies a Codec&amp;lt;Thing&amp;gt;, while Thing subclasses must define a method that supplies a ThingType.&lt;br /&gt;
# Create a map or registry of ThingTypes, and register a ThingType for each sub-codec we want to have.&lt;br /&gt;
# Create a Codec&amp;lt;ThingType&amp;gt;, or have the ThingType registry implement Codec.&lt;br /&gt;
# Create our Codec&amp;lt;Thing&amp;gt; master codec by invoking &amp;lt;code&amp;gt;Codec#dispatch&amp;lt;/code&amp;gt; on our ThingType codec. This method's arguments are:&lt;br /&gt;
## A field name for the ID of the sub-codec (the example json below is using &amp;quot;type&amp;quot;)&lt;br /&gt;
## A function to retrieve a ThingType from a Thing&lt;br /&gt;
## A function to retrieve a Codec&amp;lt;Thing&amp;gt; from a ThingType&lt;br /&gt;
&lt;br /&gt;
We can then use our Codec&amp;lt;Thing&amp;gt; to create Thing fields in other codecs whose serialized format depends on the specific sub-codec used by a Thing instance.&lt;br /&gt;
&lt;br /&gt;
As an example of this, consider the ExampleCodecClass earlier. Suppose we make this class extend Thing and register our codec for it to a codec dispatch registry with the id &amp;quot;ourmod:exampleclass&amp;quot;. If we were to define an instance of this class in a Thing field in some json, it would look like&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;json&amp;quot;&amp;gt;&lt;br /&gt;
&amp;quot;some_thing&amp;quot;:&lt;br /&gt;
{&lt;br /&gt;
	&amp;quot;type&amp;quot;: &amp;quot;ourmod:exampleclass&amp;quot;,&lt;br /&gt;
	&amp;quot;some_int&amp;quot;: 42,&lt;br /&gt;
	&amp;quot;item&amp;quot;: &amp;quot;minecraft:gold_ingot&amp;quot;,&lt;br /&gt;
	&amp;quot;block_positions&amp;quot;:&lt;br /&gt;
	[&lt;br /&gt;
		[0,0,0],&lt;br /&gt;
		[10,20,-100]&lt;br /&gt;
	]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Other ThingTypes we register would have different fields in this json object, but would still be valid for the &amp;quot;some_thing&amp;quot; field.&lt;br /&gt;
&lt;br /&gt;
Several examples of vanilla classes that use dispatch codecs:&lt;br /&gt;
* RuleTest and IRuleTestType&lt;br /&gt;
* IParticleData and ParticleType&lt;br /&gt;
* ConfiguredPlacement and Placement&lt;br /&gt;
&lt;br /&gt;
=External Links=&lt;br /&gt;
* [https://github.com/Mojang/DataFixerUpper/blob/master/src/main/java/com/mojang/serialization/Codec.java Codecs in Mojang's official public DataFixerUpper repository]&lt;br /&gt;
* [https://kvverti.github.io/Documented-DataFixerUpper/snapshot/com/mojang/serialization/Codec.html#flatXmap-java.util.function.Function-java.util.function.Function- Unofficial Codec Javadocs]&lt;/div&gt;</summary>
		<author><name>Commoble</name></author>
	</entry>
	<entry>
		<id>https://forge.gemwire.uk/index.php?title=Codecs&amp;diff=2323</id>
		<title>Codecs</title>
		<link rel="alternate" type="text/html" href="https://forge.gemwire.uk/index.php?title=Codecs&amp;diff=2323"/>
		<updated>2021-01-04T23:06:39Z</updated>

		<summary type="html">&lt;p&gt;Commoble: Expand and rewrite, describe codec utilities in greater detail&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Codecs are a serialization tool from mojang's DataFixerUpper library. Codecs are used alongside [[DynamicOps|DynamicOps]] to allow objects to be serialized to different formats and back, such as JSON or NBT. While the DynamicOps describes the format the object is to be serialized to, the Codec describes the manner in which the object is to be serialized; a single Codec can be used to serialize an object to any format for which a DynamicOps exists. Codecs and DynamicOps jointly form an abstraction layer over data serialization, simplifying the effort needed to serialize or deserialize data.&lt;br /&gt;
&lt;br /&gt;
= Using Codecs =&lt;br /&gt;
&lt;br /&gt;
== Serialization and Deserialization ==&lt;br /&gt;
&lt;br /&gt;
The primary use for Codecs is to serialize java objects to some serialized type, such as a JsonElement or an INBT, and to deserialize an serialized object back to its proper java type. This is accomplished with &amp;lt;code&amp;gt;Codec#encodeStart&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;Codec#parse&amp;lt;/code&amp;gt;, respectively. Given a Codec&amp;lt;SomeJavaType&amp;gt; and a DynamicOps&amp;lt;SomeSerializedType&amp;gt;, we can convert instances of SomeJavaType to instances of SomeSerializedType and back.&lt;br /&gt;
&lt;br /&gt;
Each of these methods take a [[DynamicOps]] instance and an instance of the object we are serializing or deserializing, and returns a DataResult:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
// let someCodec be a Codec&amp;lt;SomeJavaType&amp;gt;&lt;br /&gt;
// let someJavaObject be an instance of SomeJavaType&lt;br /&gt;
// let someNBT and someJsonElement be instances of INBT and JsonElement, respectively&lt;br /&gt;
&lt;br /&gt;
// serialize some java object to INBT&lt;br /&gt;
DataResult&amp;lt;INBT&amp;gt; result = someCodec.encodeStart(NBTDynamicOps.INSTANCE, someJavaObject);&lt;br /&gt;
&lt;br /&gt;
// deserialize some INBT instance back to a proper java object&lt;br /&gt;
DataResult&amp;lt;SomeJavaType&amp;gt; result = someCodec.parse(NBTDynamicOps.INSTANCE, someNBT);&lt;br /&gt;
&lt;br /&gt;
// serialize some java object to a JsonElement&lt;br /&gt;
DataResult&amp;lt;JsonElement&amp;gt; result = someCodec.encodeStart(JsonOps.INSTANCE, someJavaObject);&lt;br /&gt;
&lt;br /&gt;
// deserialize a JsonElement back to a proper java object&lt;br /&gt;
DataResult&amp;lt;SomeJavaType&amp;gt; result = someCodec.parse(JsonOps.INSTANCE, someJsonElement);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A DataResult either holds the converted instance, or it holds some error data, depending on whether the conversion was successful or not, respectively. There are several things we can do with this DataResult; &amp;lt;code&amp;gt;DataResult#result&amp;lt;/code&amp;gt; simply returns an Optional containing the converted object if the conversion was successful, while &amp;lt;code&amp;gt;DataResult#resultOrPartial&amp;lt;/code&amp;gt; also runs a given function if the conversion was unsuccessful (in addition to returning the Optional). #resultOrPartial is particularly useful for logging errors during datapack deserialization:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
// deserialize something from json&lt;br /&gt;
someCodec.parse(JsonOps.INSTANCE, someJsonElement)&lt;br /&gt;
	.resultOrPartial(errorMessage -&amp;gt; doSomethingIfBadData(errorMessage))&lt;br /&gt;
	.ifPresent(someJavaObject -&amp;gt; doSomethingIfGoodData(someJavaObject))&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Builtin Codecs ==&lt;br /&gt;
=== Primitive Codecs ===&lt;br /&gt;
The Codec class itself contains static instances of codecs for all supported primitive types, e.g. &amp;lt;code&amp;gt;Codec.STRING&amp;lt;/code&amp;gt; is the canonical &amp;lt;code&amp;gt;Codec&amp;lt;String&amp;gt;&amp;lt;/code&amp;gt; implementation. Primitive codecs include:&lt;br /&gt;
* BOOL, which serializes to a boolean value&lt;br /&gt;
* BYTE, SHORT, INT, LONG, FLOAT, and DOUBLE, which serialize to numeric values&lt;br /&gt;
* STRING, which serializes to a string&lt;br /&gt;
* BYTE_BUFFER, INT_STREAM, and LONG_STREAM, which serialize to lists of numbers&lt;br /&gt;
* EMPTY, which represents null objects&lt;br /&gt;
&lt;br /&gt;
=== Other Builtin Codecs ===&lt;br /&gt;
Vanilla minecraft has many builtin codecs for objects that it frequently serializes. These codecs are typically static instances in the class the codec is serializing; e.g. &amp;lt;code&amp;gt;ResourceLocation.CODEC&amp;lt;/code&amp;gt; is the canonical &amp;lt;code&amp;gt;Codec&amp;lt;ResourceLocation&amp;gt;&amp;lt;/code&amp;gt;, while &amp;lt;code&amp;gt;BlockPos.CODEC&amp;lt;/code&amp;gt; is the codec used for serializing a BlockPos.&lt;br /&gt;
&lt;br /&gt;
Each vanilla &amp;lt;code&amp;gt;Registry&amp;lt;/code&amp;gt; acts as the Codec for the type of object the registry contains; e.g. &amp;lt;code&amp;gt;Registry.BLOCK&amp;lt;/code&amp;gt; is itself a &amp;lt;code&amp;gt;Codec&amp;lt;Block&amp;gt;&amp;lt;/code&amp;gt;. Forge Registries, however, do not currently implement Codec and cannot yet be used in this way; custom codecs must be created for forge-specific registries that are not tied to specific vanilla registries.&lt;br /&gt;
&lt;br /&gt;
Of particular note here is the CompoundNBT.CODEC, which can be used to e.g. serialize a CompoundNBT into a json file. This has a notable limitation in that CompoundNBT.CODEC *cannot* safely deserialize lists of numbers from json, due to the strong typing of ListNBT and the way that the NBTDynamicOps deserializer reads numeric values.&lt;br /&gt;
&lt;br /&gt;
= Creating Codecs =&lt;br /&gt;
&lt;br /&gt;
Suppose we have the following class, and we want to deserialize json files to instances of this class:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
public class ExampleCodecClass {&lt;br /&gt;
&lt;br /&gt;
    private final int someInt;&lt;br /&gt;
    private final Item item;&lt;br /&gt;
    private final List&amp;lt;BlockPos&amp;gt; blockPositions;&lt;br /&gt;
&lt;br /&gt;
    public ExampleCodecClass(int someInt, Item item, List&amp;lt;BlockPos&amp;gt; blockPositions) {...}&lt;br /&gt;
&lt;br /&gt;
    public int getSomeInt() { return this.someInt; }&lt;br /&gt;
    public Item getItem() { return this.someItem; }&lt;br /&gt;
    public List&amp;lt;BlockPos&amp;gt; getBlockPositions() { return this.blockPositions; }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Where a json file for an instance of this class might look like:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;json&amp;quot;&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
	&amp;quot;some_int&amp;quot;: 42,&lt;br /&gt;
	&amp;quot;item&amp;quot;: &amp;quot;minecraft:gold_ingot&amp;quot;,&lt;br /&gt;
	&amp;quot;block_positions&amp;quot;:&lt;br /&gt;
	[&lt;br /&gt;
		[0,0,0],&lt;br /&gt;
		[10,20,-100]&lt;br /&gt;
	]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We can assemble a codec for this class by building a new codec out of smaller codecs. We'll need a codec for each of these fields:&lt;br /&gt;
* a &amp;lt;code&amp;gt;Codec&amp;lt;Integer&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
* a &amp;lt;code&amp;gt;Codec&amp;lt;Item&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
* a &amp;lt;code&amp;gt;Codec&amp;lt;List&amp;lt;BlockPos&amp;gt;&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
And then we'll need to assemble these into a &amp;lt;code&amp;gt;Codec&amp;lt;ExampleCodecClass&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
As previously mentioned, we can use &amp;lt;code&amp;gt;Codec.INT&amp;lt;/code&amp;gt; for the integer codec, and &amp;lt;code&amp;gt;Registry.ITEM&amp;lt;/code&amp;gt; for the Item codec. We don't have a builtin codec for list-of-blockpos, but we can use BlockPos.CODEC to create one.&lt;br /&gt;
&lt;br /&gt;
== Lists ==&lt;br /&gt;
The &amp;lt;code&amp;gt;Codec#listOf&amp;lt;/code&amp;gt; instance method can be used to generate a codec for a List from an existing codec:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
// BlockPos.CODEC is a Codec&amp;lt;BlockPos&amp;gt;&lt;br /&gt;
Codec&amp;lt;List&amp;lt;BlockPos&amp;gt;&amp;gt; = BlockPos.CODEC.listOf();&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Codecs created via listOf() serialize things to listlike objects, such as [] json arrays or ListNBTs.&lt;br /&gt;
&lt;br /&gt;
== Records ==&lt;br /&gt;
RecordCodecBuilder is used to generate codecs that serialize instances of classes with explicitly named fields, like our example above. Codecs created via RecordCodecBuilder serialize things to maplike objects, such as {} json objects or CompoundNBTs.&lt;br /&gt;
&lt;br /&gt;
RecordCodecBuilder can be used in several ways, but the simplest form is as follows:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
public static final Codec&amp;lt;SomeJavaClass&amp;gt; = RecordCodecBuilder.create(instance -&amp;gt; instance.group(&lt;br /&gt;
		someFieldCodecA.fieldOf(&amp;quot;field_name_a&amp;quot;).forGetter(SomeJavaClass::getFieldA),&lt;br /&gt;
		someFieldCodecB.fieldOf(&amp;quot;field_name_b&amp;quot;).forGetter(SomeJavaClass::getFieldB),&lt;br /&gt;
		someFieldCodecC.fieldOf(&amp;quot;field_name_c&amp;quot;).forGetter(SomeJavaClass::getFieldC),&lt;br /&gt;
		// up to 16 fields can be declared here&lt;br /&gt;
	).apply(instance, SomeJavaClass::new));&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Where each line in the group specifies a codec instance for the type of that field, the field name in the serialized object, and the corresponding getter function in the java class. The builder is concluded by specifying a constructor or factory for the java class whose arguments are the previously defined fields in the same order.&lt;br /&gt;
&lt;br /&gt;
For example, using RecordCodecBuilder to create a codec for our example class above:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
public static final Codec&amp;lt;ExampleCodecClass&amp;gt; = RecordCodecBuilder.create(instance -&amp;gt; instance.group(&lt;br /&gt;
		Codec.INT.fieldOf(&amp;quot;some_int&amp;quot;).forGetter(ExampleCodecClass::getSomeInt),&lt;br /&gt;
		Registry.ITEM.fieldOf(&amp;quot;item&amp;quot;).forGetter(ExampleCodecClass::getItem),&lt;br /&gt;
		BlockPos.CODEC.listOf().fieldOf(&amp;quot;block_positions&amp;quot;).forGetter(ExampleCodecClass::getBlockPositions)&lt;br /&gt;
	).apply(instance, ExampleCodecClass::new));&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Optional and Default Values in Record Fields===&lt;br /&gt;
When RecordCodecBuilder is used as shown above, all of the fields are *required* to be in the serialized object (the JsonObject/CompoundNBT/etc), or the entire thing will fail to parse when the codec tries to deserialize it. If we wish to have optional or default values, we have several alternatives of fieldOf() we can use.&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;someCodec.optionalFieldOf(&amp;quot;field_name&amp;quot;)&amp;lt;/code&amp;gt; creates a field for an Optional. If the field in the json/nbt is not present or invalid, it will deserialize as an empty optional. Empty optionals will not be serialized; the field will be omitted from the json or nbt.&lt;br /&gt;
* &amp;lt;code&amp;gt;someCodec.optionalFieldOf(&amp;quot;field_name&amp;quot;, someDefaultValue)&amp;lt;/code&amp;gt; creates an optional field that deserializes as the given default value if the field is not present in the json/nbt. When serializing, if the field in the java object equals the default value, the value will not be serialized and the field will be omitted from the json or nbt.&lt;br /&gt;
&lt;br /&gt;
When using optional fields, be wary that if the field contains bad data or otherwise fails to serialize, the error will be silently caught, and the field will serialize as the default value instead!&lt;br /&gt;
&lt;br /&gt;
==Unit==&lt;br /&gt;
The &amp;lt;code&amp;gt;Codec.unit(defaultValue)&amp;lt;/code&amp;gt; codec creates a Codec that always deserializes a specified default value, regardless of input. When serializing, it serializes nothing.&lt;br /&gt;
&lt;br /&gt;
==Pair==&lt;br /&gt;
The &amp;lt;code&amp;gt;Codec.pair(codecA, codecB)&amp;lt;/code&amp;gt; static method takes two codecs and generates a Codec&amp;lt;Pair&amp;lt;A,B&amp;gt;&amp;gt; from them.&lt;br /&gt;
&lt;br /&gt;
Using this function requires that codecA be a codec that serializes to a string.&lt;br /&gt;
&lt;br /&gt;
==Either==&lt;br /&gt;
The &amp;lt;code&amp;gt;Codec.either(codecA, codecB)&amp;lt;/code&amp;gt; static method takes two codecs and generates a Codec&amp;lt;Either&amp;lt;A,B&amp;gt;&amp;gt; from them.&lt;br /&gt;
&lt;br /&gt;
When this codec is used to de/serialize an object, it first attempts to use the first codec; if and only if that conversion fails, it then attempts to use the second codec. If that conversion also fails, then the returned DataResult will contain the error data from the *second* codec's conversion attempt.&lt;br /&gt;
&lt;br /&gt;
==Numeric Ranges==&lt;br /&gt;
The &amp;lt;code&amp;gt;intRange(min,max)&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;floatRange(min,max)&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;doubleRange(min,max)&amp;lt;/code&amp;gt; static methods in Codec generate Codecs for Integers, Floats, or Doubles, respectively, for which only a specified inclusive range is valid, and values outside that range will fail to de/serialize.&lt;br /&gt;
&lt;br /&gt;
==Maps==&lt;br /&gt;
Suppose we want to serialize a HashMap or other Map type, where we could have indefinitely many key-value pairs and we don't know what the keys are ahead of time.&lt;br /&gt;
&lt;br /&gt;
We can create a &amp;lt;code&amp;gt;Codec&amp;lt;Map&amp;lt;KEY,VALUE&amp;gt;&amp;gt;&amp;lt;/code&amp;gt; using the &amp;lt;code&amp;gt;Codec.unboundedMap&amp;lt;/code&amp;gt; static method, which takes a key codec and a value codec and creates a codec for a map type:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
public static final Codec&amp;lt;Map&amp;lt;String, BlockPos&amp;gt;&amp;gt; = Codec.unboundedMap(Codec.STRING, BlockPos.CODEC);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The serialized form of maps serialized by this codec will be a JsonObject or CompoundNBT, whose fields are the key-value pairs in the map.&lt;br /&gt;
&lt;br /&gt;
A limitation of using unboundedMap is that it only supports key codecs that serialize to Strings (including codecs for things like ResourceLocation that aren't Strings themselves but still serialize to strings). To create a codec for a Map whose keys are not fundamentally strings, the Map must be serialized as a list of key-value entries instead of using unboundedMap. As Codec.pair() also requires that the first codec serialize to a string, the pair function cannot be used for this purpose either.&lt;br /&gt;
&lt;br /&gt;
==Equivalent Types and xmap==&lt;br /&gt;
Suppose we have two java classes, Amalgam and Box; any Amalgam instance can be converted to a Box, and vice-versa. Now suppose we have a Codec&amp;lt;Amalgam&amp;gt;, but we'd also like to have a Codec&amp;lt;Box&amp;gt;. Rather than creating an entirely new codec for Box from scratch, we can simply xmap our Amalgam codec instead.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;Codec#xmap&amp;lt;/code&amp;gt; instance method is used to generate a second codec for a fundamentally equivalent type to the first codec's type. The method takes two function objects as arguments, which are used to convert the first type to the second when deserializing, and converting the second type to the first when serializing:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
public static final Codec&amp;lt;Box&amp;gt; = Amalgam.CODEC.xmap(Amalgam::toBox, Box::toAmalgam);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Codecs created in this manner will serialize objects in the same format as the starting codec.&lt;br /&gt;
&lt;br /&gt;
==Partially Equivalent Types, flatComapMap, comapFlatMap, and flatXMap==&lt;br /&gt;
Consider the ResourceLocation: Any ResourceLocation can be converted to a String, but not all Strings can be converted to a ResourceLocation; ResourceLocations have strict limits on their format and allowed characters.&lt;br /&gt;
&lt;br /&gt;
While we *could* use xmap to convert the Codec.STRING to a codec for ResourceLocations, this would cause attempts to parse an invalid string like &amp;lt;code&amp;gt;SHOUTY:MOD:Invalid$Characters&amp;lt;/code&amp;gt; to throw a runtime exception, when we really should be returning a failed DataResult to the parser instead -- which indeed is what the vanilla ResourceLocation codec does.&lt;br /&gt;
&lt;br /&gt;
Codecs have three additional instance methods for creating equivalent codecs for when we can *potentially* convert one type to another, but are not guaranteed to be able to do so. These take conversion function arguments that return DataResults, allowing validation to be performed during serialization and deserialization.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ Codec Conversion Methods&lt;br /&gt;
|-&lt;br /&gt;
! Can A always be converted to B? !! Can B always be converted to A? !! Which method of codecA should be used to create codecB?&lt;br /&gt;
|-&lt;br /&gt;
| yes || yes || codecA.xmap&lt;br /&gt;
|-&lt;br /&gt;
| yes || no || codecA.flatComapMap&lt;br /&gt;
|-&lt;br /&gt;
| no || yes || codecA.comapFlatMap&lt;br /&gt;
|-&lt;br /&gt;
| no || no || codecA.flatXmap&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Registry Dispatch ==&lt;br /&gt;
Registry Dispatch Codecs allow us to define a registry of codecs and delegate to a specific codec to deserialize a particular json based on a type field in that json. Dispatch codecs are used extensively when deserializing worldgen data.&lt;br /&gt;
&lt;br /&gt;
To create a dispatch codec for a Thing class, the following steps can be performed:&lt;br /&gt;
# Create a Thing abstract class class and ThingType interface. The ThingType interface should have a method that supplies a Codec&amp;lt;Thing&amp;gt;, while Thing subclasses must define a method that supplies a ThingType.&lt;br /&gt;
# Create a map or registry of ThingTypes, and register a ThingType for each sub-codec we want to have.&lt;br /&gt;
# Create a Codec&amp;lt;ThingType&amp;gt;, or have the ThingType registry implement Codec.&lt;br /&gt;
# Create our Codec&amp;lt;Thing&amp;gt; master codec by invoking &amp;lt;code&amp;gt;Codec#dispatch&amp;lt;/code&amp;gt; on our ThingType codec. This method's arguments are:&lt;br /&gt;
## A field name for the ID of the sub-codec (the example json below is using &amp;quot;type&amp;quot;)&lt;br /&gt;
## A function to retrieve a ThingType from a Thing&lt;br /&gt;
## A function to retrieve a Codec&amp;lt;Thing&amp;gt; from a ThingType&lt;br /&gt;
&lt;br /&gt;
We can then use our Codec&amp;lt;Thing&amp;gt; to create Thing fields in other codecs whose serialized format depends on the specific sub-codec used by a Thing instance.&lt;br /&gt;
&lt;br /&gt;
As an example of this, consider the ExampleCodecClass earlier. Suppose we make this class extend Thing and register our codec for it to a codec dispatch registry with the id &amp;quot;ourmod:exampleclass&amp;quot;. If we were to define an instance of this class in a Thing field in some json, it would look like&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;json&amp;quot;&amp;gt;&lt;br /&gt;
&amp;quot;some_thing&amp;quot;:&lt;br /&gt;
{&lt;br /&gt;
	&amp;quot;type&amp;quot;: &amp;quot;ourmod:exampleclass&amp;quot;,&lt;br /&gt;
	&amp;quot;some_int&amp;quot;: 42,&lt;br /&gt;
	&amp;quot;item&amp;quot;: &amp;quot;minecraft:gold_ingot&amp;quot;,&lt;br /&gt;
	&amp;quot;block_positions&amp;quot;:&lt;br /&gt;
	[&lt;br /&gt;
		[0,0,0],&lt;br /&gt;
		[10,20,-100]&lt;br /&gt;
	]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Other ThingTypes we register would have different fields in this json object, but would still be valid for the &amp;quot;some_thing&amp;quot; field.&lt;br /&gt;
&lt;br /&gt;
Several examples of vanilla classes that use dispatch codecs:&lt;br /&gt;
* RuleTest and IRuleTestType&lt;br /&gt;
* IParticleData and ParticleType&lt;br /&gt;
* ConfiguredPlacement and Placement&lt;br /&gt;
&lt;br /&gt;
=External Links=&lt;br /&gt;
* [https://github.com/Mojang/DataFixerUpper/blob/master/src/main/java/com/mojang/serialization/Codec.java Codecs in Mojang's official public DataFixerUpper repository]&lt;br /&gt;
* [https://kvverti.github.io/Documented-DataFixerUpper/snapshot/com/mojang/serialization/Codec.html#flatXmap-java.util.function.Function-java.util.function.Function- Unofficial Codec Javadocs]&lt;/div&gt;</summary>
		<author><name>Commoble</name></author>
	</entry>
	<entry>
		<id>https://forge.gemwire.uk/index.php?title=DynamicOps&amp;diff=2321</id>
		<title>DynamicOps</title>
		<link rel="alternate" type="text/html" href="https://forge.gemwire.uk/index.php?title=DynamicOps&amp;diff=2321"/>
		<updated>2021-01-04T17:56:04Z</updated>

		<summary type="html">&lt;p&gt;Commoble: Expand and rewrite; emphasize relationship between dynamicops and codecs&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;The &amp;lt;code&amp;gt;DynamicOps&amp;lt;/code&amp;gt; class is part of mojang's DataFixerUpper serialization library; DynamicOps are used alongside [[codecs]] to convert java objects to a serialized format and back. While Codecs describe how a java object is to be serialized, DynamicOps describe the format the object is to be serialized to.&lt;br /&gt;
&lt;br /&gt;
The DataFixerUpper library includes several DynamicOps for serializing to json; vanilla minecraft also includes a DynamicOps for serializing to minecraft's [[Using_NBT|NBT]] format.&lt;br /&gt;
&lt;br /&gt;
= Builtin DynamicOps =&lt;br /&gt;
&lt;br /&gt;
== JsonOps ==&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;JsonOps&amp;lt;/code&amp;gt; DynamicOps are used to serialize and deserialize json data. These are instances of &amp;lt;code&amp;gt;DynamicOps&amp;lt;JsonElement&amp;gt;&amp;lt;/code&amp;gt;, meaning that they are used to convert java objects to and from &amp;lt;code&amp;gt;JsonElement&amp;lt;/code&amp;gt; instances. These can used in conjunction with codecs to serialize/deserialize objects from assets and datapacks.&lt;br /&gt;
&lt;br /&gt;
There are two public instances of JsonOps: &amp;lt;code&amp;gt;JsonOps.INSTANCE&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;JsonOps.COMPRESSED&amp;lt;/code&amp;gt;. Compressed data is represented as a single string to read/write. However, this is never used within vanilla itself.&lt;br /&gt;
&lt;br /&gt;
== NBTDynamicOps ==&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;NBTDynamicOps.INSTANCE&amp;lt;/code&amp;gt; is an instance of &amp;lt;code&amp;gt;DynamicOps&amp;lt;INBT&amp;gt;&amp;lt;/code&amp;gt;, meaning it is used to convert java objects to and from &amp;lt;code&amp;gt;INBT&amp;lt;/code&amp;gt; instances. This can be used for serializing data into packets to send across networks, as well as serializing persistant data for entities and similar objects.&lt;br /&gt;
&lt;br /&gt;
There is only one public instance of NBTDynamicOps: &amp;lt;code&amp;gt;NBTDynamicOps.INSTANCE&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
= Using DynamicOps =&lt;br /&gt;
&lt;br /&gt;
== Serializing and Deserializing ==&lt;br /&gt;
&lt;br /&gt;
By combining a &amp;lt;code&amp;gt;Codec&amp;lt;SomeJavaType&amp;gt;&amp;lt;/code&amp;gt; with a &amp;lt;code&amp;gt;DynamicOps&amp;lt;SomeSerializedFormat&amp;gt;&amp;lt;/code&amp;gt;, the proper java object can be converted to the serialized form and back. See [[codecs]] for details on this subject.&lt;br /&gt;
&lt;br /&gt;
== Format Conversion ==&lt;br /&gt;
&lt;br /&gt;
By using the &amp;lt;code&amp;gt;DynamicOps#convertTo&amp;lt;/code&amp;gt; instance method with a second DynamicOps instance, data can be converted between two different serialized formats, such as JsonElement to INBT and back.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=java&amp;gt;&lt;br /&gt;
// converting INBT to JsonElement&lt;br /&gt;
JsonElement someJsonElement = NBTDynamicOps.INSTANCE.convertTo(JsonOps.INSTANCE, someNBT);&lt;br /&gt;
&lt;br /&gt;
// converting JsonElement to INBT&lt;br /&gt;
INBT someNBT = JsonOps.INSTANCE.convertTo(NBTDynamicOps.INSTANCE, someJsonElement);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Depending on the implementation of the DynamicOps used, this may throw an exception or return an empty object if the two formats are incompatible.&lt;br /&gt;
&lt;br /&gt;
In particular, it is *not* safe to convert lists of numbers to NBT in this manner, due to the NBT format's strong typing and the way the NBTDynamicOps attempts to create lists of numbers.&lt;br /&gt;
&lt;br /&gt;
= External Links =&lt;br /&gt;
* [https://kvverti.github.io/Documented-DataFixerUpper/snapshot/com/mojang/serialization/DynamicOps.html DynamicOps unofficial javadocs]&lt;/div&gt;</summary>
		<author><name>Commoble</name></author>
	</entry>
</feed>