<?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=SizableShrimp</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=SizableShrimp"/>
	<link rel="alternate" type="text/html" href="https://forge.gemwire.uk/wiki/Special:Contributions/SizableShrimp"/>
	<updated>2026-06-02T03:35:13Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.35.0</generator>
	<entry>
		<id>https://forge.gemwire.uk/index.php?title=Capabilities&amp;diff=3407</id>
		<title>Capabilities</title>
		<link rel="alternate" type="text/html" href="https://forge.gemwire.uk/index.php?title=Capabilities&amp;diff=3407"/>
		<updated>2023-07-02T16:08:25Z</updated>

		<summary type="html">&lt;p&gt;SizableShrimp: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Capabilities''' are a Forge system that allows cross-mod interactions by allowing capability ''providers'' to&lt;br /&gt;
dynamically respect contracts and provide specialized behavior without requiring the implementation of many interfaces&lt;br /&gt;
or hard dependencies on mods.&lt;br /&gt;
&lt;br /&gt;
== History ==&lt;br /&gt;
In an ideal world, all that would be needed for a mod to provide the equivalent of a capability would be implementing an&lt;br /&gt;
interface. This is in fact how cross-mod interaction used to work prior to the introduction of capabilities.&lt;br /&gt;
&lt;br /&gt;
The real world, though, is often much more complicated: users wanted to be free to combine mods the way they wanted and&lt;br /&gt;
saw fit, and developers wanted to be able to declare ''soft'' dependencies on other mods, thus reducing the need of&lt;br /&gt;
having a huge mod pack just for testing.&lt;br /&gt;
&lt;br /&gt;
The first approach used by Forge was conditional stripping of interfaces and methods, but this proved to be problematic.&lt;br /&gt;
While the idea works well in theory, in practice the ASM editing of classes relied on complex mechanics and could lead&lt;br /&gt;
to hard to spot bugs.&lt;br /&gt;
&lt;br /&gt;
For this reason, the entire system was redesigned and the concept of '''capabilities''' was born.&lt;br /&gt;
&lt;br /&gt;
== The Concept ==&lt;br /&gt;
A capability allows any capability provider to conditionally expose a certain ability to do something, e.g. accepting&lt;br /&gt;
power or handling items. A capability provider, moreover, can decide to expose a capability only on certain sides,&lt;br /&gt;
allowing for easy interactions with hoppers, cables, etc.&lt;br /&gt;
&lt;br /&gt;
Capabilities may also be added and removed dynamically both from the &amp;quot;owner&amp;quot; of the capability provider and other mods,&lt;br /&gt;
allowing even easier cross-mod interaction. For example, a mod that isn't compatible with Forge Energy could be&lt;br /&gt;
converted into one by dynamically attaching the Forge Energy capability and handling the conversion to a third-party&lt;br /&gt;
energy system without having to alter the original mod.&lt;br /&gt;
&lt;br /&gt;
== Terminology ==&lt;br /&gt;
The high flexibility of the system comes with a cost, though, which is terminology. The following section wants to be a&lt;br /&gt;
dictionary of sorts, defining all the terms that you may come across when dealing with capabilities.&lt;br /&gt;
&lt;br /&gt;
In the rest of this article, we will refer to these terms frequently, so make sure you are familiar with them.&lt;br /&gt;
&lt;br /&gt;
; Capability&lt;br /&gt;
: the ability to perform something. In-code this is represented by the &amp;lt;code&amp;gt;Capability&amp;lt;/code&amp;gt; class.&lt;br /&gt;
; Capability Provider&lt;br /&gt;
: something that is able to support capabilities and provides a mean of accessing them. In-code they are represented by implementations of &amp;lt;code&amp;gt;ICapabilityProvider&amp;lt;/code&amp;gt;. There are multiple kinds of capability providers:&lt;br /&gt;
:; Volatile Provider&lt;br /&gt;
:: a provider that doesn't persist data to disk; once the provider ceases to exist for any number of reasons, all capability data gets deleted.&lt;br /&gt;
:; Persistent Provider&lt;br /&gt;
:: a provider that requires all capabilities to serialize data to disk, in order to persist data even across game restarts. They implement the &amp;lt;code&amp;gt;INBTSerializable&amp;lt;/code&amp;gt; interface.&lt;br /&gt;
:; Agnostic Provider&lt;br /&gt;
:: a provider that isn't neither volatile nor persistent, rather delegates the decision either to the capability directly or to sub-implementations. They also implement the &amp;lt;code&amp;gt;INBTSerializable&amp;lt;/code&amp;gt; interface.&lt;br /&gt;
; Capability Interface&lt;br /&gt;
: the interface that defines the contract of the capability, so what operations the capability exposes.&lt;br /&gt;
; Capability Implementation&lt;br /&gt;
: one of the possibly many implementations of the capability interface, that actually carries out the work.&lt;br /&gt;
&lt;br /&gt;
The wary reader may note that both ''persistent'' and ''agnostic'' providers are represented the same way in code. In&lt;br /&gt;
fact, the only difference between them comes from pure semantics in how their serialization methods are designed. This&lt;br /&gt;
will be further discussed in their respective sections.&lt;br /&gt;
&lt;br /&gt;
Moreover, it is also common to refer to the capability interface as simply the ''capability''. While not strictly&lt;br /&gt;
correct, due to common usage we will also use this convention. So, to refer to the capability interface&lt;br /&gt;
&amp;lt;code&amp;gt;MyCapability&amp;lt;/code&amp;gt;, we will usually talk about the &amp;quot;&amp;lt;code&amp;gt;MyCapability&amp;lt;/code&amp;gt; capability&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
== Forge-provided Capabilities and Providers ==&lt;br /&gt;
In order to ensure mods can work together seamlessly, Forge provides a set of default capabilities and capability&lt;br /&gt;
providers.&lt;br /&gt;
&lt;br /&gt;
The default capability providers in a Forge environment are: &amp;lt;code&amp;gt;BlockEntity&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;Entity&amp;lt;/code&amp;gt;,&lt;br /&gt;
&amp;lt;code&amp;gt;ItemStack&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;Level&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;LevelChunk&amp;lt;/code&amp;gt;. These are all agnostic providers, since they don't&lt;br /&gt;
mandate any sort of capability persistency requirements. Rather, it is the job of whoever subclasses these providers to&lt;br /&gt;
deal with either volatile or non-volatile capabilities.&lt;br /&gt;
&lt;br /&gt;
The default capabilities that forge provides are represented by the interfaces &amp;lt;code&amp;gt;IItemHandler&amp;lt;/code&amp;gt;,&lt;br /&gt;
&amp;lt;code&amp;gt;IFluidHandler&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;IFluidHandlerItem&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;IEnergyStorage&amp;lt;/code&amp;gt;. Each one of these capabilities will be discussed in the corresponding section.&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;IItemHandler&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;IItemHandler&amp;lt;/code&amp;gt; capability refers to the ability for any capability provider to have some sort of internal&lt;br /&gt;
'''inventory''' with a certain number of slots, from which items can be inserted and extracted. It is also possible,&lt;br /&gt;
though, to expose this capability even if no such inventory is present as long as the capability provider can emulate&lt;br /&gt;
its presence (e.g. tools that allow accessing remote inventories).&lt;br /&gt;
&lt;br /&gt;
This effectively '''replaces''' the vanilla interfaces &amp;lt;code&amp;gt;Container&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;WorldlyContainer&amp;lt;/code&amp;gt;. These&lt;br /&gt;
interfaces are in fact retained only to allow vanilla code to compile and should not be used in mod code. This extends&lt;br /&gt;
to anything that implements those vanilla interfaces, such as &amp;lt;code&amp;gt;RandomizableContainerBlockEntity&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
A default reference implementation for this capability interface is provided in &amp;lt;code&amp;gt;ItemStackHandler&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;IFluidHandler&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;IFluidHandler&amp;lt;/code&amp;gt; capability refers to the ability for any capability provider to handle and store fluids&lt;br /&gt;
in one or multiple fluid tanks. It is effectively the equivalent in terms of fluids of the &amp;lt;code&amp;gt;IItemHandler&amp;lt;/code&amp;gt;&lt;br /&gt;
capability.&lt;br /&gt;
&lt;br /&gt;
A default reference implementation for this capability interface is provided in &amp;lt;code&amp;gt;TileFluidHandler&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;IFluidHandlerItem&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;IFluidHandlerItem&amp;lt;/code&amp;gt; capability refers to the ability for an &amp;lt;code&amp;gt;ItemStack&amp;lt;/code&amp;gt; capability provider&lt;br /&gt;
to handle and store fluids in one or multiple fluid tanks. It is basically a specialized version of the&lt;br /&gt;
&amp;lt;code&amp;gt;IFluidHandler&amp;lt;/code&amp;gt; capability that allows &amp;lt;code&amp;gt;ItemStack&amp;lt;/code&amp;gt;s to define a custom container.&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;IEnergyStorage&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;IEnergyStorage&amp;lt;/code&amp;gt; capability refers to the ability for any capability provider to store, consume, and&lt;br /&gt;
produce energy. This capability is the base capability for what's commonly known in the modded world as Forge Energy (or&lt;br /&gt;
FE), i.e. the energy system most mods use. Its internal design is heavily based on the (now defunct) Redstone Flux&lt;br /&gt;
Energy API, supporting both a push and pull system.&lt;br /&gt;
&lt;br /&gt;
A default reference implementation for this capability interface is provided in &amp;lt;code&amp;gt;EnergyStorage&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Working with Capabilities ==&lt;br /&gt;
&lt;br /&gt;
Both capability providers and users need to be able to provide and access capabilities through a common framework,&lt;br /&gt;
otherwise the idea of a dynamic and mod-agnostic system would not really exist. For this reason, both capability providers and&lt;br /&gt;
capability ''accessors'' (which we define as everything that wants to access a capability), also known as '''clients''' or '''users''',&lt;br /&gt;
need to work together and with Forge to ensure that the common interface is used sensibly and correctly by all parties.&lt;br /&gt;
&lt;br /&gt;
=== Obtaining a Capability ===&lt;br /&gt;
&lt;br /&gt;
Before being able to work with a capability, it is necessary to obtain an instance of the &amp;lt;code&amp;gt;Capability&amp;lt;/code&amp;gt; object itself.&lt;br /&gt;
&lt;br /&gt;
A &amp;lt;code&amp;gt;Capability&amp;lt;/code&amp;gt; can be obtained at any time using &amp;lt;code&amp;gt;CapabilityManager#get&amp;lt;/code&amp;gt;. This takes in an anonymous &amp;lt;code&amp;gt;CapabilityToken&amp;lt;/code&amp;gt; to still allow for a soft dependency system while also keeping hold of any generic information needed. As such, you can always obtain a non-null capability.&lt;br /&gt;
&lt;br /&gt;
{{Tabs/Code Snippets&lt;br /&gt;
|java=&lt;br /&gt;
public static Capability&amp;lt;IItemHandler&amp;gt; ITEM_HANDLER = CapabilityManager.get(new CapabilityToken&amp;lt;&amp;gt;(){});&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
The above code will let Forge know that the field &amp;lt;code&amp;gt;ITEM_HANDLER&amp;lt;/code&amp;gt; should be analogous with the &amp;lt;code&amp;gt;IItemHandler&amp;lt;/code&amp;gt; capability. Note that this does not mean the capability is accessible or registered. To check if it is, call &amp;lt;code&amp;gt;Capability#isRegistered&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
This is, for obvious reasons, redundant, since that capability is also available through&lt;br /&gt;
&amp;lt;code&amp;gt;ForgeCapabilities&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Exposing a Capability ===&lt;br /&gt;
&lt;br /&gt;
Exposing a capability is a voluntary act by a capability provider that allows the capability to be discovered and&lt;br /&gt;
accessed by users.&lt;br /&gt;
&lt;br /&gt;
To do so, a capability provider needs to juggle a couple more moving pieces to ensure that the capability state remains&lt;br /&gt;
consistent and that the lookup remains fast. It is in fact possible for a capability provider to be asked to provide&lt;br /&gt;
many capabilities many times in the same tick. For this reason, a provider is asked to do the following:&lt;br /&gt;
&lt;br /&gt;
* the &amp;lt;code&amp;gt;LazyOptional&amp;lt;/code&amp;gt;s that get returned '''must be cached''';&lt;br /&gt;
* if a capability changes exposure state (more on this later), all listeners '''must be notified''';&lt;br /&gt;
* if a capability gets invalidated (more on this later), all listeners '''must be notified'''&lt;br /&gt;
* the lookup inside &amp;lt;code&amp;gt;getCapability&amp;lt;/code&amp;gt; must be performed with '''an &amp;lt;code&amp;gt;if&amp;lt;/code&amp;gt;-&amp;lt;code&amp;gt;else&amp;lt;/code&amp;gt; chain''';&lt;br /&gt;
* all unexposed but still present capabilities '''should be available''' if the provider is queried with a &amp;lt;code&amp;gt;null&amp;lt;/code&amp;gt; direction (see ''Accessing a Capability'' for more information);&lt;br /&gt;
* if no capability of a given type is available or accessible, the provider '''must call &amp;lt;code&amp;gt;super&amp;lt;/code&amp;gt; as long as it is possible to do so'''.&lt;br /&gt;
&lt;br /&gt;
Capability providers must also reflect changes in the ''exposure state'' of a capability, meaning that if the&lt;br /&gt;
accessibility of a capability from a certain &amp;lt;code&amp;gt;Direction&amp;lt;/code&amp;gt; changes (refer to&lt;br /&gt;
[[#Accessing a Capability|Accessing a Capability]] for more information), it is the provider's responsibility to trigger&lt;br /&gt;
a state response by invalidating the returned &amp;lt;code&amp;gt;LazyOptional&amp;lt;/code&amp;gt; and caching a new one. This should also be&lt;br /&gt;
performed when a capability gets ''invalidated'', such as when a capability provider gets removed.&lt;br /&gt;
&lt;br /&gt;
With all of the above in mind, part of a capability provider implementation may be similar to the following snippet:&lt;br /&gt;
&lt;br /&gt;
{{Tabs/Code Snippets&lt;br /&gt;
|java=&lt;br /&gt;
// suppose the presence of a field 'inventory' of type 'IItemHandler'&lt;br /&gt;
&lt;br /&gt;
private final LazyOptional&amp;lt;IItemhandler&amp;gt; inventoryOptional = LazyOptional.of(() -&amp;gt; this.inventory);&lt;br /&gt;
&lt;br /&gt;
@Override&lt;br /&gt;
public &amp;lt;T&amp;gt; LazyOptional&amp;lt;T&amp;gt; getCapability(Capability&amp;lt;T&amp;gt; capability, @Nullable Direction direction) {&lt;br /&gt;
    if (capability == ForgeCapabilities.ITEM_HANDLER&lt;br /&gt;
            &amp;amp;&amp;amp; (direction == null {{!}}{{!}} direction == Direction.UP {{!}}{{!}} direction == Direction.DOWN)) {&lt;br /&gt;
        return this.inventoryOptional.cast();&lt;br /&gt;
    }&lt;br /&gt;
    return super.getCapability(capability, direction); // See note after snippet&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
@Override&lt;br /&gt;
protected void invalidateCaps() {&lt;br /&gt;
    super.invalidateCaps();&lt;br /&gt;
    this.inventoryOptional.invalidate();&lt;br /&gt;
}&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
This possible implementation of a capability provider exposes an &amp;lt;code&amp;gt;IItemHandler&amp;lt;/code&amp;gt; capability and restricts&lt;br /&gt;
access only to the &amp;lt;code&amp;gt;UP&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;DOWN&amp;lt;/code&amp;gt; directions. If we assume this capability provider is a&lt;br /&gt;
&amp;lt;code&amp;gt;BlockEntity&amp;lt;/code&amp;gt;, then we may also say that the inventory is only accessible from the top and the bottom of the&lt;br /&gt;
block.&lt;br /&gt;
&lt;br /&gt;
Moreover, the capability gets automatically invalidated when the provider gets invalidated. Assuming this is a&lt;br /&gt;
&amp;lt;code&amp;gt;BlockEntity&amp;lt;/code&amp;gt;, this usually happens when the block gets removed from the level or unloaded due to distance.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;super&amp;lt;/code&amp;gt; call at the end of the &amp;lt;code&amp;gt;getCapability&amp;lt;/code&amp;gt; method is extremely important, since it's what&lt;br /&gt;
allows Attaching external Capabilities to capability providers. Nevertheless, it is not always possible to invoke&lt;br /&gt;
&amp;lt;code&amp;gt;super&amp;lt;/code&amp;gt;: in those cases, an empty &amp;lt;code&amp;gt;LazyOptional&amp;lt;/code&amp;gt; should be returned.&lt;br /&gt;
&lt;br /&gt;
=== Attaching a Capability ===&lt;br /&gt;
&lt;br /&gt;
Attaching a Capability is a process by which external agents &amp;quot;modify&amp;quot; a Capability Provider, making it expose additional&lt;br /&gt;
capabilities other than the already available ones.&lt;br /&gt;
&lt;br /&gt;
To do so, the '''attaching agent''' (which means the thing that wants to attach a capability to another provider) must&lt;br /&gt;
listen to the &amp;lt;code&amp;gt;AttachCapabilitiesEvent&amp;amp;lt;T&amp;amp;gt;&amp;lt;/code&amp;gt;. The &amp;lt;code&amp;gt;T&amp;lt;/code&amp;gt; in this case represents the capability&lt;br /&gt;
provider you want to attach the capability to. Note that the type of &amp;lt;code&amp;gt;T&amp;lt;/code&amp;gt; '''must''' be the base type of the&lt;br /&gt;
capability provider, not a subclass. As an example, if you want to attach a capability to a &amp;lt;code&amp;gt;MyBlockEntity&amp;lt;/code&amp;gt;,&lt;br /&gt;
which extends &amp;lt;code&amp;gt;BlockEntity&amp;lt;/code&amp;gt;, you'll have to listen to &amp;lt;code&amp;gt;AttachCapabilitiesEvent&amp;amp;lt;BlockEntity&amp;amp;gt;&amp;lt;/code&amp;gt;,&lt;br /&gt;
'''NOT''' to &amp;lt;code&amp;gt;AttachCapabilitiesEvent&amp;amp;lt;MyBlockEntity&amp;amp;gt;&amp;lt;/code&amp;gt;, since the latter will never fire.&lt;br /&gt;
&lt;br /&gt;
The attaching agent can use the provided methods &amp;lt;code&amp;gt;getObject&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;addCapability&amp;lt;/code&amp;gt;, and &lt;br /&gt;
&amp;lt;code&amp;gt;addListener&amp;lt;/code&amp;gt; to check whether the capability should be attached to the current object and perform the&lt;br /&gt;
desired action.&lt;br /&gt;
&lt;br /&gt;
When attaching a capability, the attaching agent should also provide a name in the form of a&lt;br /&gt;
&amp;lt;code&amp;gt;ResourceLocation&amp;lt;/code&amp;gt;. The name '''must''' be under the attaching agent's namespace, but no restrictions are&lt;br /&gt;
placed on the actual name, as long as it is unique inside the given namespace.&lt;br /&gt;
&lt;br /&gt;
Maybe a little counter-intuitively, the process of attaching does not attach a capability nor a capability interface&lt;br /&gt;
directly. Rather, the attaching agent should create its own implementation of a '''Capability Provider''' and attach it&lt;br /&gt;
via the event. This is done so that the attaching agent can have control over when, how, and where its capabilities are&lt;br /&gt;
exposed, instead of relying on the game itself deciding these parameters. For this reason, all considerations given in&lt;br /&gt;
the [[#Exposing a Capability|Exposing a Capability]] section on how to correctly create a Capability Provider.&lt;br /&gt;
&lt;br /&gt;
With the above in mind, part of an attaching agent may be similar to the following snippet of code:&lt;br /&gt;
&lt;br /&gt;
{{Tabs/Code Snippets&lt;br /&gt;
|java=&lt;br /&gt;
@SubscribeEvent&lt;br /&gt;
public void onAttachingCapabilities(final AttachCapabilitiesEvent&amp;lt;BlockEntity&amp;gt; event) {&lt;br /&gt;
    if (!(event.getObject() instanceof EnergyBasedBlockEntity)) return;&lt;br /&gt;
&lt;br /&gt;
    EnergyStorage backend = new EnergyStorage(((EnergyBasedBlockEntity) event.getObject()).capacity);&lt;br /&gt;
    LazyOptional&amp;lt;IEnergyStorage&amp;gt; optionalStorage = LazyOptional.of(() -&amp;gt; backend);&lt;br /&gt;
&lt;br /&gt;
    ICapabilityProvider provider = new ICapabilityProvider() {&lt;br /&gt;
        @Override&lt;br /&gt;
        public &amp;lt;T&amp;gt; LazyOptional&amp;lt;T&amp;gt; getCapability(Capability&amp;lt;T&amp;gt; cap, @Nullable Direction direction) {&lt;br /&gt;
            if (cap == ForgeCapabilities.ENERGY) {&lt;br /&gt;
                return optionalStorage.cast();&lt;br /&gt;
            }&lt;br /&gt;
            return LazyOptional.empty();&lt;br /&gt;
        }&lt;br /&gt;
    };&lt;br /&gt;
&lt;br /&gt;
    event.addCapability(new ResourceLocation(&amp;quot;examplemod&amp;quot;, &amp;quot;fe_compatibility&amp;quot;), provider);&lt;br /&gt;
}&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
This example implementation of an attaching agent attaches a &amp;lt;code&amp;gt;IEnergyStorage&amp;lt;/code&amp;gt; capability to all&lt;br /&gt;
&amp;lt;code&amp;gt;BlockEntity&amp;lt;/code&amp;gt; instance that are a subclass of &amp;lt;code&amp;gt;EnergyBasedBlockEntity&amp;lt;/code&amp;gt;. It also sets up the&lt;br /&gt;
&amp;lt;code&amp;gt;LazyOptional&amp;lt;/code&amp;gt; for invalidation if the parent capability provider gets invalidated.&lt;br /&gt;
&lt;br /&gt;
Note also the call of &amp;lt;code&amp;gt;LazyOptional.empty()&amp;lt;/code&amp;gt; rather than a &amp;lt;code&amp;gt;super&amp;lt;/code&amp;gt;. This is needed because when&lt;br /&gt;
attaching a capability, the parent capability provider isn't known. For this reason, it is necessary to return an empty&lt;br /&gt;
&amp;lt;code&amp;gt;LazyOptional&amp;lt;/code&amp;gt;. The game will then handle automatic merging of the various different providers into a single&lt;br /&gt;
one.&lt;br /&gt;
&lt;br /&gt;
The above example is one of a '''Volatile''' Capability Provider. On the other hand, mods may want to persist their&lt;br /&gt;
data across sessions. In this case, they should attach a '''Persistent''' Capability Provider: this can be done either&lt;br /&gt;
by implementing the &amp;lt;code&amp;gt;INBTSerializable&amp;lt;/code&amp;gt; interface along with &amp;lt;code&amp;gt;ICapabilityProvider&amp;lt;/code&amp;gt; or by&lt;br /&gt;
implementing the &amp;lt;code&amp;gt;ICapabilitySerializable&amp;lt;/code&amp;gt; interface.&lt;br /&gt;
&lt;br /&gt;
The previous example reworked to use a Persistent Capability Provider may be similar to the following snippet:&lt;br /&gt;
&lt;br /&gt;
{{Tabs/Code Snippets&lt;br /&gt;
|java=&lt;br /&gt;
@SubscribeEvent&lt;br /&gt;
public void onAttachingCapabilities(final AttachCapabilitiesEvent&amp;lt;BlockEntity&amp;gt; event) {&lt;br /&gt;
    if (!(event.getObject() instanceof EnergyBasedBlockEntity)) return;&lt;br /&gt;
&lt;br /&gt;
    EnergyStorage backend = new EnergyStorage(((EnergyBasedBlockEntity) event.getObject()).capacity);&lt;br /&gt;
    LazyOptional&amp;lt;IEnergyStorage&amp;gt; optionalStorage = LazyOptional.of(() -&amp;gt; backend);&lt;br /&gt;
    Capability&amp;lt;IEnergyStorage&amp;gt; capability = ForgeCapabilities.ENERGY;&lt;br /&gt;
&lt;br /&gt;
    ICapabilityProvider provider = new ICapabilitySerializable&amp;lt;IntTag&amp;gt;() {&lt;br /&gt;
        @Override&lt;br /&gt;
        public &amp;lt;T&amp;gt; LazyOptional&amp;lt;T&amp;gt; getCapability(Capability&amp;lt;T&amp;gt; cap, @Nullable Direction direction) {&lt;br /&gt;
            if (cap == capability) {&lt;br /&gt;
                return optionalStorage.cast();&lt;br /&gt;
            }&lt;br /&gt;
            return LazyOptional.empty();&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        @Override&lt;br /&gt;
        public IntTag serializeNBT() {&lt;br /&gt;
            return backend.serializeNBT();&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        @Override&lt;br /&gt;
        public void deserializeNBT(IntTag tag) {&lt;br /&gt;
            backend.deserializeNBT(tag);&lt;br /&gt;
        }&lt;br /&gt;
    };&lt;br /&gt;
&lt;br /&gt;
    event.addCapabilities(new ResourceLocation(&amp;quot;examplemod&amp;quot;, &amp;quot;fe_compatibility&amp;quot;), provider);&lt;br /&gt;
}&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Note that when using capabilities on entities, you should manually invalidate the capability via &amp;lt;code&amp;gt;invalidateCaps()&amp;lt;/code&amp;gt;, using e.g. &amp;lt;code&amp;gt;PlayerEvent.Clone&amp;lt;/code&amp;gt;. This is due to the fact that players are recreated &amp;amp; copied when moving across dimensions, not simply moved.&lt;br /&gt;
&lt;br /&gt;
=== Accessing a Capability ===&lt;br /&gt;
&lt;br /&gt;
Accessing a Capability is the process by which a user is able to '''query''' a Capability Provider for a specific&lt;br /&gt;
instance of a capability.&lt;br /&gt;
&lt;br /&gt;
This is perhaps the second most important part of the entire capability system, since it is what allows cross-mod&lt;br /&gt;
interaction. To obtain an instance of a Capability, the user must first get a hold of the Capability Provider that&lt;br /&gt;
should be queried. This can be done in a variety of ways and is outside the scope of this article. The user should&lt;br /&gt;
then invoke the &amp;lt;code&amp;gt;getCapability&amp;lt;/code&amp;gt; method passing the unique instance of the capability that should be queried&lt;br /&gt;
(see [[#Obtaining a Capability|Obtaining a Capability]] for more information) and the querying &amp;lt;code&amp;gt;Direction&amp;lt;/code&amp;gt;,&lt;br /&gt;
if applicable.&lt;br /&gt;
&lt;br /&gt;
The returned object is a &amp;lt;code&amp;gt;LazyOptional&amp;lt;/code&amp;gt; wrapping the queried Capability, if the capability provider exposes&lt;br /&gt;
it, otherwise it will be empty. The &amp;lt;code&amp;gt;LazyOptional&amp;lt;/code&amp;gt; can be either unwrapped via an &amp;lt;code&amp;gt;orElse&amp;lt;/code&amp;gt; or&lt;br /&gt;
used directly via &amp;lt;code&amp;gt;ifPresent&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
It is '''highly suggested''' to cache the returned &amp;lt;code&amp;gt;LazyOptional&amp;lt;/code&amp;gt; to avoid querying the same provider every&lt;br /&gt;
time, in order to improve performance. The user should thus register itself to the invalidation listener via the&lt;br /&gt;
&amp;lt;code&amp;gt;addListener&amp;lt;/code&amp;gt; method. This ensures that the user will be able to react to the invalidation of the&lt;br /&gt;
&amp;lt;code&amp;gt;LazyOptional&amp;lt;/code&amp;gt; and remove it from the cache.&lt;br /&gt;
&lt;br /&gt;
With the above in mind, part of an user may be similar to the following snippet of code:&lt;br /&gt;
&lt;br /&gt;
{{Tabs/Code Snippets&lt;br /&gt;
|java=&lt;br /&gt;
// note the use of EnumMap, which is much more performant than HashMap for enum keys&lt;br /&gt;
private final Map&amp;lt;Direction, LazyOptional&amp;lt;IEnergyStorage&amp;gt;&amp;gt; cache = new EnumMap&amp;lt;&amp;gt;(Direction.class);&lt;br /&gt;
&lt;br /&gt;
private void sendPowerTo(int power, Direction direction) {&lt;br /&gt;
    LazyOptional&amp;lt;IEnergyStorage&amp;gt; targetCapability = cache.get(direction);&lt;br /&gt;
&lt;br /&gt;
    if (targetCapability == null) {&lt;br /&gt;
        ICapabilityProvider provider = level.getBlockEntity(pos.relative(direction));&lt;br /&gt;
        targetCapability = provider.getCapability(ForgeCapabilities.ENERGY, direction.getOpposite());&lt;br /&gt;
        cache.put(direction, targetCapability);&lt;br /&gt;
        targetCapability.addListener(self -&amp;gt; cache.put(direction, null));&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    targetCapability.ifPresent(storage -&amp;gt; storage.receiveEnergy(power, false));&lt;br /&gt;
}&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
This example implementation of an user is querying via a &amp;lt;code&amp;gt;BlockEntity&amp;lt;/code&amp;gt; the neighboring capability provider&lt;br /&gt;
for an &amp;lt;code&amp;gt;IEnergyStorage&amp;lt;/code&amp;gt; capability. Before obtaining the provider, the code performs a cache lookup for the&lt;br /&gt;
targeted capability. If the check succeeds, then no lookup is performed; if the check fails, the targeted Capability&lt;br /&gt;
Provider is obtained and queried for the Capability. The obtained &amp;lt;code&amp;gt;LazyOptional&amp;lt;/code&amp;gt; is then cached and a&lt;br /&gt;
listener is attached to it so that the cache would be emptied on invalidation. The code then continues with the&lt;br /&gt;
interaction with the capability, which is outside the scope of this article.&lt;br /&gt;
&lt;br /&gt;
== Creating Custom Capabilities ==&lt;br /&gt;
&lt;br /&gt;
While the various capabilities provided by Forge may satisfy the most common use cases, there is always the chance that&lt;br /&gt;
a mod may require a custom solution. For this reason, Forge provides a way to define a custom Capability.&lt;br /&gt;
&lt;br /&gt;
Defining a custom Capability requires the user to provide one main component: the Capability Interface. Optionally, a &lt;br /&gt;
Capability Implementation and Capability Provider can also be created. In this&lt;br /&gt;
case, the provider will be used as described in [[#Attaching a Capability|Attaching a Capability]]. The various details &lt;br /&gt;
for all these components are described in the respective sections of this article.&lt;br /&gt;
&lt;br /&gt;
In this section, we will refer to the implementation of a &amp;lt;code&amp;gt;MyCapability&amp;lt;/code&amp;gt; capability, that can be used to&lt;br /&gt;
store a single mutable &amp;lt;code&amp;gt;String&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Refer also to [[#Code Examples|Code Examples]] for an example on how the various components may be implemented in a&lt;br /&gt;
real-world scenario.&lt;br /&gt;
&lt;br /&gt;
=== The Capability Interface and the Capability Implementation ===&lt;br /&gt;
&lt;br /&gt;
The Capability Interface is one of the most important parts of a Capability: without it, the Capability effectively does&lt;br /&gt;
not exist. Designing a Capability Interface is exactly like designing any Java interface, so the particular details will&lt;br /&gt;
be glossed over in this section.&lt;br /&gt;
&lt;br /&gt;
The Capability Implementation, on the other hand, is the implementation of the previously defined Capability Interface.&lt;br /&gt;
Usual rules for interface implementations follow. There can be more than one Capability Implementation for each&lt;br /&gt;
capability. &lt;br /&gt;
&lt;br /&gt;
Note that a '''well-formed''' capability implementation should '''not store''' the Capability Provider inside of it: we&lt;br /&gt;
call the capability implementation ''provider-agnostic''. This is not a hard-requirement, though, rather it should act&lt;br /&gt;
more as a guideline. There are in fact certain situations where this cannot be avoided (e.g. attaching a client-synced&lt;br /&gt;
capability to an &amp;lt;code&amp;gt;ItemStack&amp;lt;/code&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
Given all of the above information, this may be an example implementation of both a Capability Interface and a&lt;br /&gt;
Capability Implementation:&lt;br /&gt;
&lt;br /&gt;
{{Tabs/Code Snippets&lt;br /&gt;
|java=&lt;br /&gt;
public interface MyCapability {&lt;br /&gt;
    String getValue();&lt;br /&gt;
    void setValue(String value);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
public class MyCapabilityImplementation implements MyCapability {&lt;br /&gt;
    private String value;&lt;br /&gt;
&lt;br /&gt;
    @Override&lt;br /&gt;
    public String getValue() {&lt;br /&gt;
        return this.value;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    @Override&lt;br /&gt;
    public void setValue(String value) {&lt;br /&gt;
        this.value = value;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Note that in this case, only a single implementation is provided.&lt;br /&gt;
&lt;br /&gt;
=== The Capability Provider ===&lt;br /&gt;
&lt;br /&gt;
The Capability Provider is an optional component of the capability that allows the Capability to be attached to a&lt;br /&gt;
component. The details on how a Capability Provider should behave have already been discussed in the two previous&lt;br /&gt;
sections [[#Exposing a Capability|Exposing a Capability]] and [[#Attaching a Capability|Attaching a Capability]]: refer&lt;br /&gt;
to those for more information.&lt;br /&gt;
&lt;br /&gt;
=== Registering Capabilities ===&lt;br /&gt;
&lt;br /&gt;
Once all components of a Capability have been created, they must be registered so that the game is aware of the&lt;br /&gt;
capability's presence. The registration only requires the Capability Interface.&lt;br /&gt;
After registering, the created Capability will be automatically injected into all relevant fields and methods, see [[#Obtaining a Capability|Obtaining a Capability]] for more information.&lt;br /&gt;
As of Forge 1.19.2-43.1.1, there are two ways to register capabilities.&lt;br /&gt;
&lt;br /&gt;
==== AutoRegisterCapability annotation ====&lt;br /&gt;
On Forge 1.19.2-43.1.1 or higher, a quick and easy way to register a capability is by annotating the Capability Interface with &amp;lt;code&amp;gt;@AutoRegisterCapability&amp;lt;/code&amp;gt;. This would look like so:&lt;br /&gt;
&lt;br /&gt;
{{Tabs/Code Snippets&lt;br /&gt;
|java=&lt;br /&gt;
@AutoRegisterCapability&lt;br /&gt;
public interface MyCapability {&lt;br /&gt;
    ...&lt;br /&gt;
}&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
==== RegisterCapabilitiesEvent ====&lt;br /&gt;
An alternative way to register capabilities is by calling the &amp;lt;code&amp;gt;register&amp;lt;/code&amp;gt; method within the &amp;lt;code&amp;gt;RegisterCapabilitiesEvent&amp;lt;/code&amp;gt;. This event is fired on the &amp;lt;code&amp;gt;MOD&amp;lt;/code&amp;gt; event bus. For example:&lt;br /&gt;
&lt;br /&gt;
{{Tabs/Code Snippets&lt;br /&gt;
|java=&lt;br /&gt;
@SubscribeEvent&lt;br /&gt;
public void registerCaps(RegisterCapabilitiesEvent event) {&lt;br /&gt;
    event.register(MyCapability.class);&lt;br /&gt;
}&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
=== Class Diagram ===&lt;br /&gt;
&lt;br /&gt;
[[File:Custom Capability Class Diagram.svg|800px|thumb|center|Custom Capability Class Diagram]]&lt;br /&gt;
&lt;br /&gt;
In the above diagram the green and red marked areas are classes from Minecraft and Forge respectively. The classes inside the purple area are only needed if you want to [[#Attaching a Capability|Attach a Capability]]. Furthermore this diagram models a persistent provider and its most basic form, for more information on how to create a more complex provider see [[#Custom Capability Providers|Custom Capability Providers]]. To create a volatile provider instead just do not implement &amp;lt;code&amp;gt;INBTSerializable&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Custom Capability Providers ==&lt;br /&gt;
&lt;br /&gt;
Much like custom Capabilities, Forge also allows the creation of custom Capability Providers. The main advantage of this&lt;br /&gt;
is allowing mods to create custom providers for their custom objects, in order to promote not only cross-mod&lt;br /&gt;
compatibility, but also uniformity in the way users may interact with different mod APIs.&lt;br /&gt;
&lt;br /&gt;
This section will only give the basic outline of what is necessary to implement a custom Capability Provider: for more&lt;br /&gt;
in-depth explanation, people are referred to the game code.&lt;br /&gt;
&lt;br /&gt;
By definition, a custom Capability Provider is everything that implements the &amp;lt;code&amp;gt;ICapabilityProvider&amp;lt;/code&amp;gt;&lt;br /&gt;
interface. In this section, though, we will only cover people that may want to replicate the functionality of one of&lt;br /&gt;
the default providers, such as &amp;lt;code&amp;gt;BlockEntity&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;LevelChunk&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
The easiest way of doing this is extending the &amp;lt;code&amp;gt;CapabilityProvider&amp;lt;/code&amp;gt; class provided by Forge. This will&lt;br /&gt;
automatically set up an ''agnostic'' Capability Provider. To fully initialize the capability provider, the subclass&lt;br /&gt;
should then invoke the &amp;lt;code&amp;gt;gatherCapabilities&amp;lt;/code&amp;gt; method as the last instruction in its constructor, to ensure that&lt;br /&gt;
the game is able to recollect and attach all capabilities that other mods may want to attach to the capability provider.&lt;br /&gt;
&lt;br /&gt;
== Code Examples ==&lt;br /&gt;
&lt;br /&gt;
* [https://gist.github.com/TheCurle/6db954d680f6f067dcdc791355c32c89 A Gist showing a quick and dirty example on how to implement a Capability effectively]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Data Storage]]&lt;/div&gt;</summary>
		<author><name>SizableShrimp</name></author>
	</entry>
	<entry>
		<id>https://forge.gemwire.uk/index.php?title=Block_Entity_Renderer&amp;diff=3355</id>
		<title>Block Entity Renderer</title>
		<link rel="alternate" type="text/html" href="https://forge.gemwire.uk/index.php?title=Block_Entity_Renderer&amp;diff=3355"/>
		<updated>2022-10-08T14:01:35Z</updated>

		<summary type="html">&lt;p&gt;SizableShrimp: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;A &amp;lt;code&amp;gt;BlockEntityRenderer&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;BER&amp;lt;/code&amp;gt; is used to render blocks in a way that cannot be represented with a static baked model (JSON, OBJ, B3D, etc.). A block entity renderer requires the block to have a &amp;lt;code&amp;gt;BlockEntity&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Creating a BER ==&lt;br /&gt;
To create a BER, create a class that inherits from &amp;lt;code&amp;gt;BlockEntityRenderer&amp;lt;/code&amp;gt;. It takes a generic argument specifying the block's &amp;lt;code&amp;gt;BlockEntity&amp;lt;/code&amp;gt; class. The generic argument is used in the BER's &amp;lt;code&amp;gt;render&amp;lt;/code&amp;gt; method.&lt;br /&gt;
&lt;br /&gt;
Only one BER exists for a given &amp;lt;code&amp;gt;BlockEntityType&amp;lt;/code&amp;gt;. Therefore, values that are specific to a single instance in the world should be stored in the block entity being passed to the renderer rather than in the BER itself. For example, an integer that increments every frame, if stored in the BER, will increment every frame for every block entity of this type in the world.&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;code&amp;gt; render &amp;lt;/code&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
This method is called every frame in order to render the block entity.&lt;br /&gt;
&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
* &amp;lt;code&amp;gt;blockEntity&amp;lt;/code&amp;gt;: This is the instance of the block entity being rendered.&lt;br /&gt;
* &amp;lt;code&amp;gt;partialTick&amp;lt;/code&amp;gt;: The amount of time, in fraction of a tick, that has passed since the last full tick.&lt;br /&gt;
* &amp;lt;code&amp;gt;poseStack&amp;lt;/code&amp;gt;: A stack holding four-dimensional matrix entries offset to the current position of the block entity.&lt;br /&gt;
* &amp;lt;code&amp;gt;bufferSource&amp;lt;/code&amp;gt;: A rendering buffer able to access a vertex consumer.&lt;br /&gt;
* &amp;lt;code&amp;gt;combinedLight&amp;lt;/code&amp;gt;: An integer of the current light value on the block entity.&lt;br /&gt;
* &amp;lt;code&amp;gt;combinedOverlay&amp;lt;/code&amp;gt;: An integer set to the current overlay of the block entity, usually &amp;lt;code&amp;gt;OverlayTexture#NO_OVERLAY&amp;lt;/code&amp;gt; or 655,360.&lt;br /&gt;
&lt;br /&gt;
==Registering a BER==&lt;br /&gt;
In order to register a BER, you must subscribe to the &amp;lt;code&amp;gt;EntityRenderersEvent$RegisterRenderers&amp;lt;/code&amp;gt; event on the mod event bus and call &amp;lt;code&amp;gt;#registerBlockEntityRenderer&amp;lt;/code&amp;gt;.&lt;/div&gt;</summary>
		<author><name>SizableShrimp</name></author>
	</entry>
	<entry>
		<id>https://forge.gemwire.uk/index.php?title=Capabilities&amp;diff=3337</id>
		<title>Capabilities</title>
		<link rel="alternate" type="text/html" href="https://forge.gemwire.uk/index.php?title=Capabilities&amp;diff=3337"/>
		<updated>2022-09-25T02:31:43Z</updated>

		<summary type="html">&lt;p&gt;SizableShrimp: Change back to ForgeCapabilities for cap references since the others are deprecated&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Capabilities''' are a Forge system that allows cross-mod interactions by allowing capability ''providers'' to&lt;br /&gt;
dynamically respect contracts and provide specialized behavior without requiring the implementation of many interfaces&lt;br /&gt;
or hard dependencies on mods.&lt;br /&gt;
&lt;br /&gt;
== History ==&lt;br /&gt;
In an ideal world, all that would be needed for a mod to provide the equivalent of a capability would be implementing an&lt;br /&gt;
interface. This is in fact how cross-mod interaction used to work prior to the introduction of capabilities.&lt;br /&gt;
&lt;br /&gt;
The real world, though, is often much more complicated: users wanted to be free to combine mods the way they wanted and&lt;br /&gt;
saw fit, and developers wanted to be able to declare ''soft'' dependencies on other mods, thus reducing the need of&lt;br /&gt;
having a huge mod pack just for testing.&lt;br /&gt;
&lt;br /&gt;
The first approach used by Forge was conditional stripping of interfaces and methods, but this proved to be problematic.&lt;br /&gt;
While the idea works well in theory, in practice the ASM editing of classes relied on complex mechanics and could lead&lt;br /&gt;
to hard to spot bugs.&lt;br /&gt;
&lt;br /&gt;
For this reason, the entire system was redesigned and the concept of '''capabilities''' was born.&lt;br /&gt;
&lt;br /&gt;
== The Concept ==&lt;br /&gt;
A capability allows any capability provider to conditionally expose a certain ability to do something, e.g. accepting&lt;br /&gt;
power or handling items. A capability provider, moreover, can decide to expose a capability only on certain sides,&lt;br /&gt;
allowing for easy interactions with hoppers, cables, etc.&lt;br /&gt;
&lt;br /&gt;
Capabilities may also be added and removed dynamically both from the &amp;quot;owner&amp;quot; of the capability provider and other mods,&lt;br /&gt;
allowing even easier cross-mod interaction. For example, a mod that isn't compatible with Forge Energy could be&lt;br /&gt;
converted into one by dynamically attaching the Forge Energy capability and handling the conversion to a third-party&lt;br /&gt;
energy system without having to alter the original mod.&lt;br /&gt;
&lt;br /&gt;
== Terminology ==&lt;br /&gt;
The high flexibility of the system comes with a cost, though, which is terminology. The following section wants to be a&lt;br /&gt;
dictionary of sorts, defining all the terms that you may come across when dealing with capabilities.&lt;br /&gt;
&lt;br /&gt;
In the rest of this article, we will refer to these terms frequently, so make sure you are familiar with them.&lt;br /&gt;
&lt;br /&gt;
; Capability&lt;br /&gt;
: the ability to perform something. In-code this is represented by the &amp;lt;code&amp;gt;Capability&amp;lt;/code&amp;gt; class.&lt;br /&gt;
; Capability Provider&lt;br /&gt;
: something that is able to support capabilities and provides a mean of accessing them. In-code they are represented by implementations of &amp;lt;code&amp;gt;ICapabilityProvider&amp;lt;/code&amp;gt;. There are multiple kinds of capability providers:&lt;br /&gt;
:; Volatile Provider&lt;br /&gt;
:: a provider that doesn't persist data to disk; once the provider ceases to exist for any number of reasons, all capability data gets deleted.&lt;br /&gt;
:; Persistent Provider&lt;br /&gt;
:: a provider that requires all capabilities to serialize data to disk, in order to persist data even across game restarts. They implement the &amp;lt;code&amp;gt;INBTSerializable&amp;lt;/code&amp;gt; interface.&lt;br /&gt;
:; Agnostic Provider&lt;br /&gt;
:: a provider that isn't neither volatile nor persistent, rather delegates the decision either to the capability directly or to sub-implementations. They also implement the &amp;lt;code&amp;gt;INBTSerializable&amp;lt;/code&amp;gt; interface.&lt;br /&gt;
; Capability Interface&lt;br /&gt;
: the interface that defines the contract of the capability, so what operations the capability exposes.&lt;br /&gt;
; Capability Implementation&lt;br /&gt;
: one of the possibly many implementations of the capability interface, that actually carries out the work.&lt;br /&gt;
&lt;br /&gt;
The wary reader may note that both ''persistent'' and ''agnostic'' providers are represented the same way in code. In&lt;br /&gt;
fact, the only difference between them comes from pure semantics in how their serialization methods are designed. This&lt;br /&gt;
will be further discussed in their respective sections.&lt;br /&gt;
&lt;br /&gt;
Moreover, it is also common to refer to the capability interface as simply the ''capability''. While not strictly&lt;br /&gt;
correct, due to common usage we will also use this convention. So, to refer to the capability interface&lt;br /&gt;
&amp;lt;code&amp;gt;MyCapability&amp;lt;/code&amp;gt;, we will usually talk about the &amp;quot;&amp;lt;code&amp;gt;MyCapability&amp;lt;/code&amp;gt; capability&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
== Forge-provided Capabilities and Providers ==&lt;br /&gt;
In order to ensure mods can work together seamlessly, Forge provides a set of default capabilities and capability&lt;br /&gt;
providers.&lt;br /&gt;
&lt;br /&gt;
The default capability providers in a Forge environment are: &amp;lt;code&amp;gt;BlockEntity&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;Entity&amp;lt;/code&amp;gt;,&lt;br /&gt;
&amp;lt;code&amp;gt;ItemStack&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;Level&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;LevelChunk&amp;lt;/code&amp;gt;. These are all agnostic providers, since they don't&lt;br /&gt;
mandate any sort of capability persistency requirements. Rather, it is the job of whoever subclasses these providers to&lt;br /&gt;
deal with either volatile or non-volatile capabilities.&lt;br /&gt;
&lt;br /&gt;
The default capabilities that forge provides are represented by the interfaces &amp;lt;code&amp;gt;IItemHandler&amp;lt;/code&amp;gt;,&lt;br /&gt;
&amp;lt;code&amp;gt;IFluidHandler&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;IFluidHandlerItem&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;IEnergyStorage&amp;lt;/code&amp;gt;. Each one of these capabilities will be discussed in the corresponding section.&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;IItemHandler&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;IItemHandler&amp;lt;/code&amp;gt; capability refers to the ability for any capability provider to have some sort of internal&lt;br /&gt;
'''inventory''' with a certain number of slots, from which items can be inserted and extracted. It is also possible,&lt;br /&gt;
though, to expose this capability even if no such inventory is present as long as the capability provider can emulate&lt;br /&gt;
its presence (e.g. tools that allow accessing remote inventories).&lt;br /&gt;
&lt;br /&gt;
This effectively '''replaces''' the vanilla interfaces &amp;lt;code&amp;gt;Container&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;WorldlyContainer&amp;lt;/code&amp;gt;. These&lt;br /&gt;
interfaces are in fact retained only to allow vanilla code to compile and should not be used in mod code. This extends&lt;br /&gt;
to anything that implements those vanilla interfaces, such as &amp;lt;code&amp;gt;RandomizableContainerBlockEntity&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
A default reference implementation for this capability interface is provided in &amp;lt;code&amp;gt;ItemStackHandler&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;IFluidHandler&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;IFluidHandler&amp;lt;/code&amp;gt; capability refers to the ability for any capability provider to handle and store fluids&lt;br /&gt;
in one or multiple fluid tanks. It is effectively the equivalent in terms of fluids of the &amp;lt;code&amp;gt;IItemHandler&amp;lt;/code&amp;gt;&lt;br /&gt;
capability.&lt;br /&gt;
&lt;br /&gt;
A default reference implementation for this capability interface is provided in &amp;lt;code&amp;gt;TileFluidHandler&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;IFluidHandlerItem&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;IFluidHandlerItem&amp;lt;/code&amp;gt; capability refers to the ability for an &amp;lt;code&amp;gt;ItemStack&amp;lt;/code&amp;gt; capability provider&lt;br /&gt;
to handle and store fluids in one or multiple fluid tanks. It is basically a specialized version of the&lt;br /&gt;
&amp;lt;code&amp;gt;IFluidHandler&amp;lt;/code&amp;gt; capability that allows &amp;lt;code&amp;gt;ItemStack&amp;lt;/code&amp;gt;s to define a custom container.&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;IEnergyStorage&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;IEnergyStorage&amp;lt;/code&amp;gt; capability refers to the ability for any capability provider to store, consume, and&lt;br /&gt;
produce energy. This capability is the base capability for what's commonly known in the modded world as Forge Energy (or&lt;br /&gt;
FE), i.e. the energy system most mods use. Its internal design is heavily based on the (now defunct) Redstone Flux&lt;br /&gt;
Energy API, supporting both a push and pull system.&lt;br /&gt;
&lt;br /&gt;
A default reference implementation for this capability interface is provided in &amp;lt;code&amp;gt;EnergyStorage&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Working with Capabilities ==&lt;br /&gt;
&lt;br /&gt;
Both capability providers and users need to be able to provide and access capabilities through a common framework,&lt;br /&gt;
otherwise the ideal of dynamic and mod-agnostic would not really exist. For this reason, both capability providers and&lt;br /&gt;
capability ''accessors'' (which we define as everything that wants to access a capability), also known as '''clients''' or '''users''',&lt;br /&gt;
need to work together and with Forge to ensure that the common interface is used sensibly and correctly by all parties.&lt;br /&gt;
&lt;br /&gt;
=== Obtaining a Capability ===&lt;br /&gt;
&lt;br /&gt;
Before being able to work with a capability, it is necessary to obtain an instance of the &amp;lt;code&amp;gt;Capability&amp;lt;/code&amp;gt; object itself.&lt;br /&gt;
&lt;br /&gt;
A &amp;lt;code&amp;gt;Capability&amp;lt;/code&amp;gt; can obtained at any time using &amp;lt;code&amp;gt;CapabilityManager#get&amp;lt;/code&amp;gt;. This takes in an anonymous &amp;lt;code&amp;gt;CapabilityToken&amp;lt;/code&amp;gt; to still allow for a soft dependency system while also keeping hold of any generic information needed. As such, you can always obtain a non-null capability.&lt;br /&gt;
&lt;br /&gt;
{{Tabs/Code Snippets&lt;br /&gt;
|java=&lt;br /&gt;
public static Capability&amp;lt;IItemHandler&amp;gt; ITEM_HANDLER = CapabilityManager.get(new CapabilityToken&amp;lt;&amp;gt;(){});&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
The above code will let Forge know that the field &amp;lt;code&amp;gt;ITEM_HANDLER&amp;lt;/code&amp;gt; should be analogous with the &amp;lt;code&amp;gt;IItemHandler&amp;lt;/code&amp;gt; capability. Note that this does not mean the capability is accessible or registered. To check if it is, call &amp;lt;code&amp;gt;Capability#isRegistered&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
This is, for obvious reasons, redundant, since that capability is also available through&lt;br /&gt;
&amp;lt;code&amp;gt;ForgeCapabilities&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Exposing a Capability ===&lt;br /&gt;
&lt;br /&gt;
Exposing a capability is a voluntary act by a capability provider that allows the capability to be discovered and&lt;br /&gt;
accessed by users.&lt;br /&gt;
&lt;br /&gt;
To do so, a capability provider needs to juggle a couple more moving pieces to ensure that the capability state remains&lt;br /&gt;
consistent and that the lookup remains fast. It is in fact possible for a capability provider to be asked to provide&lt;br /&gt;
many capabilities many times in the same tick. For this reason, a provider is asked to do the following:&lt;br /&gt;
&lt;br /&gt;
* the &amp;lt;code&amp;gt;LazyOptional&amp;lt;/code&amp;gt;s that get returned '''must be cached''';&lt;br /&gt;
* if a capability changes exposure state (more on this later), all listeners '''must be notified''';&lt;br /&gt;
* if a capability gets invalidated (more on this later), all listeners '''must be notified'''&lt;br /&gt;
* the lookup inside &amp;lt;code&amp;gt;getCapability&amp;lt;/code&amp;gt; must be performed with '''an &amp;lt;code&amp;gt;if&amp;lt;/code&amp;gt;-&amp;lt;code&amp;gt;else&amp;lt;/code&amp;gt; chain''';&lt;br /&gt;
* all unexposed but still present capabilities '''should be available''' if the provider is queried with a &amp;lt;code&amp;gt;null&amp;lt;/code&amp;gt; direction (see ''Accessing a Capability'' for more information);&lt;br /&gt;
* if no capability of a given type is available or accessible, the provider '''must call &amp;lt;code&amp;gt;super&amp;lt;/code&amp;gt; as long as it is possible to do so'''.&lt;br /&gt;
&lt;br /&gt;
Capability providers must also reflect changes in the ''exposure state'' of a capability, meaning that if the&lt;br /&gt;
accessibility of a capability from a certain &amp;lt;code&amp;gt;Direction&amp;lt;/code&amp;gt; changes (refer to&lt;br /&gt;
[[#Accessing a Capability|Accessing a Capability]] for more information), it is the provider's responsibility to trigger&lt;br /&gt;
a state response by invalidating the returned &amp;lt;code&amp;gt;LazyOptional&amp;lt;/code&amp;gt; and caching a new one. This should also be&lt;br /&gt;
performed when a capability gets ''invalidated'', such as when a capability provider gets removed.&lt;br /&gt;
&lt;br /&gt;
With all of the above in mind, part of a capability provider implementation may be similar to the following snippet:&lt;br /&gt;
&lt;br /&gt;
{{Tabs/Code Snippets&lt;br /&gt;
|java=&lt;br /&gt;
// suppose the presence of a field 'inventory' of type 'IItemHandler'&lt;br /&gt;
&lt;br /&gt;
private final LazyOptional&amp;lt;IItemhandler&amp;gt; inventoryOptional = LazyOptional.of(() -&amp;gt; this.inventory);&lt;br /&gt;
&lt;br /&gt;
@Override&lt;br /&gt;
public &amp;lt;T&amp;gt; LazyOptional&amp;lt;T&amp;gt; getCapability(Capability&amp;lt;T&amp;gt; capability, @Nullable Direction direction) {&lt;br /&gt;
    if (capability == ForgeCapabilities.ITEM_HANDLER&lt;br /&gt;
            &amp;amp;&amp;amp; (direction == null || direction == Direction.UP || direction == Direction.DOWN)) {&lt;br /&gt;
        return this.inventoryOptional.cast();&lt;br /&gt;
    }&lt;br /&gt;
    return super.getCapability(capability, direction); // See note after snippet&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
@Override&lt;br /&gt;
protected void invalidateCaps() {&lt;br /&gt;
    super.invalidateCaps();&lt;br /&gt;
    this.inventoryOptional.invalidate();&lt;br /&gt;
}&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
This possible implementation of a capability provider exposes an &amp;lt;code&amp;gt;IItemHandler&amp;lt;/code&amp;gt; capability and restricts&lt;br /&gt;
access only to the &amp;lt;code&amp;gt;UP&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;DOWN&amp;lt;/code&amp;gt; directions. If we assume this capability provider is a&lt;br /&gt;
&amp;lt;code&amp;gt;BlockEntity&amp;lt;/code&amp;gt;, then we may also say that the inventory is only accessible from the top and the bottom of the&lt;br /&gt;
block.&lt;br /&gt;
&lt;br /&gt;
Moreover, the capability gets automatically invalidated when the provider gets invalidated. Assuming this is a&lt;br /&gt;
&amp;lt;code&amp;gt;BlockEntity&amp;lt;/code&amp;gt;, this usually happens when the block gets removed from the level or unloaded due to distance.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;super&amp;lt;/code&amp;gt; call at the end of the &amp;lt;code&amp;gt;getCapability&amp;lt;/code&amp;gt; method is extremely important, since it's what&lt;br /&gt;
allows Attaching external Capabilities to capability providers. Nevertheless, it is not always possible to invoke&lt;br /&gt;
&amp;lt;code&amp;gt;super&amp;lt;/code&amp;gt;: in those cases, an empty &amp;lt;code&amp;gt;LazyOptional&amp;lt;/code&amp;gt; should be returned.&lt;br /&gt;
&lt;br /&gt;
=== Attaching a Capability ===&lt;br /&gt;
&lt;br /&gt;
Attaching a Capability is a process by which external agents &amp;quot;modify&amp;quot; a Capability Provider, making it expose additional&lt;br /&gt;
capabilities other than the already available ones.&lt;br /&gt;
&lt;br /&gt;
To do so, the '''attaching agent''' (which means the thing that wants to attach a capability to another provider) must&lt;br /&gt;
listen to the &amp;lt;code&amp;gt;AttachCapabilitiesEvent&amp;amp;lt;T&amp;amp;gt;&amp;lt;/code&amp;gt;. The &amp;lt;code&amp;gt;T&amp;lt;/code&amp;gt; in this case represents the capability&lt;br /&gt;
provider you want to attach the capability to. Note that the type of &amp;lt;code&amp;gt;T&amp;lt;/code&amp;gt; '''must''' be the base type of the&lt;br /&gt;
capability provider, not a subclass. As an example, if you want to attach a capability to a &amp;lt;code&amp;gt;MyBlockEntity&amp;lt;/code&amp;gt;,&lt;br /&gt;
which extends &amp;lt;code&amp;gt;BlockEntity&amp;lt;/code&amp;gt;, you'll have to listen to &amp;lt;code&amp;gt;AttachCapabilitiesEvent&amp;amp;lt;BlockEntity&amp;amp;gt;&amp;lt;/code&amp;gt;,&lt;br /&gt;
'''NOT''' to &amp;lt;code&amp;gt;AttachCapabilitiesEvent&amp;amp;lt;MyBlockEntity&amp;amp;gt;&amp;lt;/code&amp;gt;, since the latter will never fire.&lt;br /&gt;
&lt;br /&gt;
The attaching agent can use the provided methods &amp;lt;code&amp;gt;getObject&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;addCapability&amp;lt;/code&amp;gt;, and &lt;br /&gt;
&amp;lt;code&amp;gt;addListener&amp;lt;/code&amp;gt; to check whether the capability should be attached to the current object and perform the&lt;br /&gt;
desired action.&lt;br /&gt;
&lt;br /&gt;
When attaching a capability, the attaching agent should also provide a name in the form of a&lt;br /&gt;
&amp;lt;code&amp;gt;ResourceLocation&amp;lt;/code&amp;gt;. The name '''must''' be under the attaching agent's namespace, but no restrictions are&lt;br /&gt;
placed on the actual name, as long as it is unique inside the given namespace.&lt;br /&gt;
&lt;br /&gt;
Maybe a little counter-intuitively, the process of attaching does not attach a capability nor a capability interface&lt;br /&gt;
directly. Rather, the attaching agent should create its own implementation of a '''Capability Provider''' and attach it&lt;br /&gt;
via the event. This is done so that the attaching agent can have control over when, how, and where its capabilities are&lt;br /&gt;
exposed, instead of relying on the game itself deciding these parameters. For this reason, all considerations given in&lt;br /&gt;
the [[#Exposing a Capability|Exposing a Capability]] section on how to correctly create a Capability Provider.&lt;br /&gt;
&lt;br /&gt;
With the above in mind, part of an attaching agent may be similar to the following snippet of code:&lt;br /&gt;
&lt;br /&gt;
{{Tabs/Code Snippets&lt;br /&gt;
|java=&lt;br /&gt;
@SubscribeEvent&lt;br /&gt;
public void onAttachingCapabilities(final AttachCapabilitiesEvent&amp;lt;BlockEntity&amp;gt; event) {&lt;br /&gt;
    if (!(event.getObject() instanceof EnergyBasedBlockEntity)) return;&lt;br /&gt;
&lt;br /&gt;
    EnergyStorage backend = new EnergyStorage(((EnergyBasedBlockEntity) event.getObject()).capacity);&lt;br /&gt;
    LazyOptional&amp;lt;IEnergyStorage&amp;gt; optionalStorage = LazyOptional.of(() -&amp;gt; backend);&lt;br /&gt;
&lt;br /&gt;
    ICapabilityProvider provider = new ICapabilityProvider() {&lt;br /&gt;
        @Override&lt;br /&gt;
        public &amp;lt;T&amp;gt; LazyOptional&amp;lt;T&amp;gt; getCapability(Capability&amp;lt;T&amp;gt; cap, @Nullable Direction direction) {&lt;br /&gt;
            if (cap == ForgeCapabilities.ENERGY) {&lt;br /&gt;
                return optionalStorage.cast();&lt;br /&gt;
            }&lt;br /&gt;
            return LazyOptional.empty();&lt;br /&gt;
        }&lt;br /&gt;
    };&lt;br /&gt;
&lt;br /&gt;
    event.addCapability(new ResourceLocation(&amp;quot;examplemod&amp;quot;, &amp;quot;fe_compatibility&amp;quot;), provider);&lt;br /&gt;
}&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
This example implementation of an attaching agent attaches a &amp;lt;code&amp;gt;IEnergyStorage&amp;lt;/code&amp;gt; capability to all&lt;br /&gt;
&amp;lt;code&amp;gt;BlockEntity&amp;lt;/code&amp;gt; instance that are a subclass of &amp;lt;code&amp;gt;EnergyBasedBlockEntity&amp;lt;/code&amp;gt;. It also sets up the&lt;br /&gt;
&amp;lt;code&amp;gt;LazyOptional&amp;lt;/code&amp;gt; for invalidation if the parent capability provider gets invalidated.&lt;br /&gt;
&lt;br /&gt;
Note also the call of &amp;lt;code&amp;gt;LazyOptional.empty()&amp;lt;/code&amp;gt; rather than a &amp;lt;code&amp;gt;super&amp;lt;/code&amp;gt;. This is needed because when&lt;br /&gt;
attaching a capability, the parent capability provider isn't known. For this reason, it is necessary to return an empty&lt;br /&gt;
&amp;lt;code&amp;gt;LazyOptional&amp;lt;/code&amp;gt;. The game will then handle automatic merging of the various different providers into a single&lt;br /&gt;
one.&lt;br /&gt;
&lt;br /&gt;
The above example is one of a '''Volatile''' Capability Provider. On the other hand, mods may want to persist their&lt;br /&gt;
data across sessions. In this case, they should attach a '''Persistent''' Capability Provider: this can be done either&lt;br /&gt;
by implementing the &amp;lt;code&amp;gt;INBTSerializable&amp;lt;/code&amp;gt; interface along with &amp;lt;code&amp;gt;ICapabilityProvider&amp;lt;/code&amp;gt; or by&lt;br /&gt;
implementing the &amp;lt;code&amp;gt;ICapabilitySerializable&amp;lt;/code&amp;gt; interface.&lt;br /&gt;
&lt;br /&gt;
The previous example reworked to use a Persistent Capability Provider may be similar to the following snippet:&lt;br /&gt;
&lt;br /&gt;
{{Tabs/Code Snippets&lt;br /&gt;
|java=&lt;br /&gt;
@SubscribeEvent&lt;br /&gt;
public void onAttachingCapabilities(final AttachCapabilitiesEvent&amp;lt;BlockEntity&amp;gt; event) {&lt;br /&gt;
    if (!(event.getObject() instanceof EnergyBasedBlockEntity)) return;&lt;br /&gt;
&lt;br /&gt;
    EnergyStorage backend = new EnergyStorage(((EnergyBasedBlockEntity) event.getObject()).capacity);&lt;br /&gt;
    LazyOptional&amp;lt;IEnergyStorage&amp;gt; optionalStorage = LazyOptional.of(() -&amp;gt; backend);&lt;br /&gt;
    Capability&amp;lt;IEnergyStorage&amp;gt; capability = ForgeCapabilities.ENERGY;&lt;br /&gt;
&lt;br /&gt;
    ICapabilityProvider provider = new ICapabilitySerializable&amp;lt;IntTag&amp;gt;() {&lt;br /&gt;
        @Override&lt;br /&gt;
        public &amp;lt;T&amp;gt; LazyOptional&amp;lt;T&amp;gt; getCapability(Capability&amp;lt;T&amp;gt; cap, @Nullable Direction direction) {&lt;br /&gt;
            if (cap == capability) {&lt;br /&gt;
                return optionalStorage.cast();&lt;br /&gt;
            }&lt;br /&gt;
            return LazyOptional.empty();&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        @Override&lt;br /&gt;
        public IntTag serializeNBT() {&lt;br /&gt;
            return backend.serializeNBT();&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        @Override&lt;br /&gt;
        public void deserializeNBT(IntTag tag) {&lt;br /&gt;
            backend.deserializeNBT(tag);&lt;br /&gt;
        }&lt;br /&gt;
    };&lt;br /&gt;
&lt;br /&gt;
    event.addCapabilities(new ResourceLocation(&amp;quot;examplemod&amp;quot;, &amp;quot;fe_compatibility&amp;quot;), provider);&lt;br /&gt;
}&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Note that when using capabilities on entities, you should manually invalidate the capability via &amp;lt;code&amp;gt;invalidateCaps()&amp;lt;/code&amp;gt;, via etc. &amp;lt;code&amp;gt;PlayerEvent.Clone&amp;lt;/code&amp;gt;. This is due to the fact that players are recreated &amp;amp; copied when moving across dimensions, not simply moved.&lt;br /&gt;
&lt;br /&gt;
=== Accessing a Capability ===&lt;br /&gt;
&lt;br /&gt;
Accessing a Capability is the process by which a user is able to '''query''' a Capability Provider for a specific&lt;br /&gt;
instance of a capability.&lt;br /&gt;
&lt;br /&gt;
This is perhaps the second most important part of the entire capability system, since it is what allows cross-mod&lt;br /&gt;
interaction. To obtain an instance of a Capability, the user must first get a hold of the Capability Provider that&lt;br /&gt;
should be queried. This can be done in a variety of ways and is outside the scope of this article. The user should&lt;br /&gt;
then invoke the &amp;lt;code&amp;gt;getCapability&amp;lt;/code&amp;gt; method passing the unique instance of the capability that should be queried&lt;br /&gt;
(see [[#Obtaining a Capability|Obtaining a Capability]] for more information) and the querying &amp;lt;code&amp;gt;Direction&amp;lt;/code&amp;gt;,&lt;br /&gt;
if applicable.&lt;br /&gt;
&lt;br /&gt;
The returned object is a &amp;lt;code&amp;gt;LazyOptional&amp;lt;/code&amp;gt; wrapping the queried Capability, if the capability provider exposes&lt;br /&gt;
it, otherwise it will be empty. The &amp;lt;code&amp;gt;LazyOptional&amp;lt;/code&amp;gt; can be either unwrapped via an &amp;lt;code&amp;gt;orElse&amp;lt;/code&amp;gt; or&lt;br /&gt;
used directly via &amp;lt;code&amp;gt;ifPresent&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
It is '''highly suggested''' to cache the returned &amp;lt;code&amp;gt;LazyOptional&amp;lt;/code&amp;gt; to avoid querying the same provider every&lt;br /&gt;
time, in order to improve performance. The user should thus register itself to the invalidation listener via the&lt;br /&gt;
&amp;lt;code&amp;gt;addListener&amp;lt;/code&amp;gt; method. This ensures that the user will be able to react to the invalidation of the&lt;br /&gt;
&amp;lt;code&amp;gt;LazyOptional&amp;lt;/code&amp;gt; and remove it from the cache.&lt;br /&gt;
&lt;br /&gt;
With the above in mind, part of an user may be similar to the following snippet of code:&lt;br /&gt;
&lt;br /&gt;
{{Tabs/Code Snippets&lt;br /&gt;
|java=&lt;br /&gt;
// note the use of EnumMap, which is much more performant than HashMap for enum keys&lt;br /&gt;
private final Map&amp;lt;Direction, LazyOptional&amp;lt;IEnergyStorage&amp;gt;&amp;gt; cache = new EnumMap&amp;lt;&amp;gt;(Direction.class);&lt;br /&gt;
&lt;br /&gt;
private void sendPowerTo(int power, Direction direction) {&lt;br /&gt;
    LazyOptional&amp;lt;IEnergyStorage&amp;gt; targetCapability = cache.get(direction);&lt;br /&gt;
&lt;br /&gt;
    if (targetCapability == null) {&lt;br /&gt;
        ICapabilityProvider provider = level.getBlockEntity(pos.relative(direction));&lt;br /&gt;
        targetCapability = provider.getCapability(ForgeCapabilities.ENERGY, direction.getOpposite());&lt;br /&gt;
        cache.put(direction, targetCapability);&lt;br /&gt;
        targetCapability.addListener(self -&amp;gt; cache.put(direction, null));&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    targetCapability.ifPresent(storage -&amp;gt; storage.receiveEnergy(power, false));&lt;br /&gt;
}&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
This example implementation of an user is querying via a &amp;lt;code&amp;gt;BlockEntity&amp;lt;/code&amp;gt; the neighboring capability provider&lt;br /&gt;
for an &amp;lt;code&amp;gt;IEnergyStorage&amp;lt;/code&amp;gt; capability. Before obtaining the provider, the code performs a cache lookup for the&lt;br /&gt;
targeted capability. If the check succeeds, then no lookup is performed; if the check fails, the targeted Capability&lt;br /&gt;
Provider is obtained and queried for the Capability. The obtained &amp;lt;code&amp;gt;LazyOptional&amp;lt;/code&amp;gt; is then cached and a&lt;br /&gt;
listener is attached to it so that the cache would be emptied on invalidation. The code then continues with the&lt;br /&gt;
interaction with the capability, which is outside the scope of this article.&lt;br /&gt;
&lt;br /&gt;
== Creating Custom Capabilities ==&lt;br /&gt;
&lt;br /&gt;
While the various capabilities provided by Forge may satisfy the most common use cases, there is always the chance that&lt;br /&gt;
a mod may require a custom solution. For this reason, Forge provides a way to define a custom Capability.&lt;br /&gt;
&lt;br /&gt;
Defining a custom Capability requires the user to provide one main component: the Capability Interface. Optionally, a &lt;br /&gt;
Capability Implementation and Capability Provider can also be created. In this&lt;br /&gt;
case, the provider will be used as described in [[#Attaching a Capability|Attaching a Capability]]. The various details &lt;br /&gt;
for all these components are described in the respective sections of this article.&lt;br /&gt;
&lt;br /&gt;
In this section, we will refer to the implementation of a &amp;lt;code&amp;gt;MyCapability&amp;lt;/code&amp;gt; capability, that can be used to&lt;br /&gt;
store a single mutable &amp;lt;code&amp;gt;String&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Refer also to [[#Code Examples|Code Examples]] for an example on how the various components may be implemented in a&lt;br /&gt;
real-world scenario.&lt;br /&gt;
&lt;br /&gt;
=== The Capability Interface and the Capability Implementation ===&lt;br /&gt;
&lt;br /&gt;
The Capability Interface is one of the most important parts of a Capability: without it, the Capability effectively does&lt;br /&gt;
not exist. Designing a Capability Interface is exactly like designing any Java interface, so the particular details will&lt;br /&gt;
be glossed over in this section.&lt;br /&gt;
&lt;br /&gt;
The Capability Implementation, on the other hand, is the implementation of the previously defined Capability Interface.&lt;br /&gt;
Usual rules for interface implementations follow. There can be more than one Capability Implementation for each&lt;br /&gt;
capability. &lt;br /&gt;
&lt;br /&gt;
Note that a '''well-formed''' capability implementation should '''not store''' the Capability Provider inside of it: we&lt;br /&gt;
call the capability implementation ''provider-agnostic''. This is not a hard-requirement, though, rather it should act&lt;br /&gt;
more as a guideline. There are in fact certain situations where this cannot be avoided (e.g. attaching a client-synced&lt;br /&gt;
capability to an &amp;lt;code&amp;gt;ItemStack&amp;lt;/code&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
Given all of the above information, this may be an example implementation of both a Capability Interface and a&lt;br /&gt;
Capability Implementation:&lt;br /&gt;
&lt;br /&gt;
{{Tabs/Code Snippets&lt;br /&gt;
|java=&lt;br /&gt;
public interface MyCapability {&lt;br /&gt;
    String getValue();&lt;br /&gt;
    void setValue(String value);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
public class MyCapabilityImplementation implements MyCapability {&lt;br /&gt;
    private String value;&lt;br /&gt;
&lt;br /&gt;
    @Override&lt;br /&gt;
    public String getValue() {&lt;br /&gt;
        return this.value;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    @Override&lt;br /&gt;
    public void setValue(String value) {&lt;br /&gt;
        this.value = value;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Note that in this case, only a single implementation is provided.&lt;br /&gt;
&lt;br /&gt;
=== The Capability Provider ===&lt;br /&gt;
&lt;br /&gt;
The Capability Provider is an optional component of the capability that allows the Capability to be attached to a&lt;br /&gt;
component. The details on how a Capability Provider should behave have already been discussed in the two previous&lt;br /&gt;
sections [[#Exposing a Capability|Exposing a Capability]] and [[#Attaching a Capability|Attaching a Capability]]: refer&lt;br /&gt;
to those for more information.&lt;br /&gt;
&lt;br /&gt;
=== Registering Capabilities ===&lt;br /&gt;
&lt;br /&gt;
Once all components of a Capability have been created, they must be registered so that the game is aware of the&lt;br /&gt;
capability's presence. The registration only requires the Capability Interface.&lt;br /&gt;
After registering, the created Capability will be automatically injected into all relevant fields and methods, see [[#Obtaining a Capability|Obtaining a Capability]] for more information.&lt;br /&gt;
As of Forge 1.19.2-43.1.1, there are two ways to register capabilities.&lt;br /&gt;
&lt;br /&gt;
==== AutoRegisterCapability annotation ====&lt;br /&gt;
On Forge 1.19.2-43.1.1 or higher, a quick and easy way to register a capability is by annotating the Capability Interface with &amp;lt;code&amp;gt;@AutoRegisterCapability&amp;lt;/code&amp;gt;. This would look like so:&lt;br /&gt;
&lt;br /&gt;
{{Tabs/Code Snippets&lt;br /&gt;
|java=&lt;br /&gt;
@AutoRegisterCapability&lt;br /&gt;
public interface MyCapability {&lt;br /&gt;
    ...&lt;br /&gt;
}&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
==== RegisterCapabilitiesEvent ====&lt;br /&gt;
An alternative way to register capabilities is by calling the &amp;lt;code&amp;gt;register&amp;lt;/code&amp;gt; method within the &amp;lt;code&amp;gt;RegisterCapabilitiesEvent&amp;lt;/code&amp;gt;. This event is fired on the &amp;lt;code&amp;gt;MOD&amp;lt;/code&amp;gt; event bus. For example:&lt;br /&gt;
&lt;br /&gt;
{{Tabs/Code Snippets&lt;br /&gt;
|java=&lt;br /&gt;
@SubscribeEvent&lt;br /&gt;
public void registerCaps(RegisterCapabilitiesEvent event) {&lt;br /&gt;
    event.register(MyCapability.class);&lt;br /&gt;
}&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
=== Class Diagram ===&lt;br /&gt;
&lt;br /&gt;
[[File:Custom Capability Class Diagram.svg|800px|thumb|center|Custom Capability Class Diagram]]&lt;br /&gt;
&lt;br /&gt;
In the above diagram the green and red marked areas are classes from Minecraft and Forge respectively. The classes inside the purple area are only needed if you want to [[#Attaching a Capability|Attach a Capability]]. Furthermore this diagram models a persistent provider and its most basic form, for more information on how to create a more complex provider see [[#Custom Capability Providers|Custom Capability Providers]]. To create a volatile provider instead just do not implement &amp;lt;code&amp;gt;INBTSerializable&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Custom Capability Providers ==&lt;br /&gt;
&lt;br /&gt;
Much like custom Capabilities, Forge also allows the creation of custom Capability Providers. The main advantage of this&lt;br /&gt;
is allowing mods to create custom providers for their custom objects, in order to promote not only cross-mod&lt;br /&gt;
compatibility, but also uniformity in the way users may interact with different mod APIs.&lt;br /&gt;
&lt;br /&gt;
This section will only give the basic outline of what is necessary to implement a custom Capability Provider: for more&lt;br /&gt;
in-depth explanation, people are referred to the game code.&lt;br /&gt;
&lt;br /&gt;
By definition, a custom Capability Provider is everything that implements the &amp;lt;code&amp;gt;ICapabilityProvider&amp;lt;/code&amp;gt;&lt;br /&gt;
interface. In this section, though, we will only cover people that may want to replicate the functionality of one of&lt;br /&gt;
the default providers, such as &amp;lt;code&amp;gt;BlockEntity&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;LevelChunk&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
The easiest way of doing this is extending the &amp;lt;code&amp;gt;CapabilityProvider&amp;lt;/code&amp;gt; class provided by Forge. This will&lt;br /&gt;
automatically set up an ''agnostic'' Capability Provider. To fully initialize the capability provider, the subclass&lt;br /&gt;
should then invoke the &amp;lt;code&amp;gt;gatherCapabilities&amp;lt;/code&amp;gt; method as the last instruction in its constructor, to ensure that&lt;br /&gt;
the game is able to recollect and attach all capabilities that other mods may want to attach to the capability provider.&lt;br /&gt;
&lt;br /&gt;
== Code Examples ==&lt;br /&gt;
&lt;br /&gt;
* [https://gist.github.com/TheCurle/6db954d680f6f067dcdc791355c32c89 A Gist showing a quick and dirty example on how to implement a Capability effectively]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Data Storage]]&lt;/div&gt;</summary>
		<author><name>SizableShrimp</name></author>
	</entry>
	<entry>
		<id>https://forge.gemwire.uk/index.php?title=Capabilities&amp;diff=3336</id>
		<title>Capabilities</title>
		<link rel="alternate" type="text/html" href="https://forge.gemwire.uk/index.php?title=Capabilities&amp;diff=3336"/>
		<updated>2022-09-25T02:24:52Z</updated>

		<summary type="html">&lt;p&gt;SizableShrimp: Clean up information about registering cap classes&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Capabilities''' are a Forge system that allows cross-mod interactions by allowing capability ''providers'' to&lt;br /&gt;
dynamically respect contracts and provide specialized behavior without requiring the implementation of many interfaces&lt;br /&gt;
or hard dependencies on mods.&lt;br /&gt;
&lt;br /&gt;
== History ==&lt;br /&gt;
In an ideal world, all that would be needed for a mod to provide the equivalent of a capability would be implementing an&lt;br /&gt;
interface. This is in fact how cross-mod interaction used to work prior to the introduction of capabilities.&lt;br /&gt;
&lt;br /&gt;
The real world, though, is often much more complicated: users wanted to be free to combine mods the way they wanted and&lt;br /&gt;
saw fit, and developers wanted to be able to declare ''soft'' dependencies on other mods, thus reducing the need of&lt;br /&gt;
having a huge mod pack just for testing.&lt;br /&gt;
&lt;br /&gt;
The first approach used by Forge was conditional stripping of interfaces and methods, but this proved to be problematic.&lt;br /&gt;
While the idea works well in theory, in practice the ASM editing of classes relied on complex mechanics and could lead&lt;br /&gt;
to hard to spot bugs.&lt;br /&gt;
&lt;br /&gt;
For this reason, the entire system was redesigned and the concept of '''capabilities''' was born.&lt;br /&gt;
&lt;br /&gt;
== The Concept ==&lt;br /&gt;
A capability allows any capability provider to conditionally expose a certain ability to do something, e.g. accepting&lt;br /&gt;
power or handling items. A capability provider, moreover, can decide to expose a capability only on certain sides,&lt;br /&gt;
allowing for easy interactions with hoppers, cables, etc.&lt;br /&gt;
&lt;br /&gt;
Capabilities may also be added and removed dynamically both from the &amp;quot;owner&amp;quot; of the capability provider and other mods,&lt;br /&gt;
allowing even easier cross-mod interaction. For example, a mod that isn't compatible with Forge Energy could be&lt;br /&gt;
converted into one by dynamically attaching the Forge Energy capability and handling the conversion to a third-party&lt;br /&gt;
energy system without having to alter the original mod.&lt;br /&gt;
&lt;br /&gt;
== Terminology ==&lt;br /&gt;
The high flexibility of the system comes with a cost, though, which is terminology. The following section wants to be a&lt;br /&gt;
dictionary of sorts, defining all the terms that you may come across when dealing with capabilities.&lt;br /&gt;
&lt;br /&gt;
In the rest of this article, we will refer to these terms frequently, so make sure you are familiar with them.&lt;br /&gt;
&lt;br /&gt;
; Capability&lt;br /&gt;
: the ability to perform something. In-code this is represented by the &amp;lt;code&amp;gt;Capability&amp;lt;/code&amp;gt; class.&lt;br /&gt;
; Capability Provider&lt;br /&gt;
: something that is able to support capabilities and provides a mean of accessing them. In-code they are represented by implementations of &amp;lt;code&amp;gt;ICapabilityProvider&amp;lt;/code&amp;gt;. There are multiple kinds of capability providers:&lt;br /&gt;
:; Volatile Provider&lt;br /&gt;
:: a provider that doesn't persist data to disk; once the provider ceases to exist for any number of reasons, all capability data gets deleted.&lt;br /&gt;
:; Persistent Provider&lt;br /&gt;
:: a provider that requires all capabilities to serialize data to disk, in order to persist data even across game restarts. They implement the &amp;lt;code&amp;gt;INBTSerializable&amp;lt;/code&amp;gt; interface.&lt;br /&gt;
:; Agnostic Provider&lt;br /&gt;
:: a provider that isn't neither volatile nor persistent, rather delegates the decision either to the capability directly or to sub-implementations. They also implement the &amp;lt;code&amp;gt;INBTSerializable&amp;lt;/code&amp;gt; interface.&lt;br /&gt;
; Capability Interface&lt;br /&gt;
: the interface that defines the contract of the capability, so what operations the capability exposes.&lt;br /&gt;
; Capability Implementation&lt;br /&gt;
: one of the possibly many implementations of the capability interface, that actually carries out the work.&lt;br /&gt;
&lt;br /&gt;
The wary reader may note that both ''persistent'' and ''agnostic'' providers are represented the same way in code. In&lt;br /&gt;
fact, the only difference between them comes from pure semantics in how their serialization methods are designed. This&lt;br /&gt;
will be further discussed in their respective sections.&lt;br /&gt;
&lt;br /&gt;
Moreover, it is also common to refer to the capability interface as simply the ''capability''. While not strictly&lt;br /&gt;
correct, due to common usage we will also use this convention. So, to refer to the capability interface&lt;br /&gt;
&amp;lt;code&amp;gt;MyCapability&amp;lt;/code&amp;gt;, we will usually talk about the &amp;quot;&amp;lt;code&amp;gt;MyCapability&amp;lt;/code&amp;gt; capability&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
== Forge-provided Capabilities and Providers ==&lt;br /&gt;
In order to ensure mods can work together seamlessly, Forge provides a set of default capabilities and capability&lt;br /&gt;
providers.&lt;br /&gt;
&lt;br /&gt;
The default capability providers in a Forge environment are: &amp;lt;code&amp;gt;BlockEntity&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;Entity&amp;lt;/code&amp;gt;,&lt;br /&gt;
&amp;lt;code&amp;gt;ItemStack&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;Level&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;LevelChunk&amp;lt;/code&amp;gt;. These are all agnostic providers, since they don't&lt;br /&gt;
mandate any sort of capability persistency requirements. Rather, it is the job of whoever subclasses these providers to&lt;br /&gt;
deal with either volatile or non-volatile capabilities.&lt;br /&gt;
&lt;br /&gt;
The default capabilities that forge provides are represented by the interfaces &amp;lt;code&amp;gt;IItemHandler&amp;lt;/code&amp;gt;,&lt;br /&gt;
&amp;lt;code&amp;gt;IFluidHandler&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;IFluidHandlerItem&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;IEnergyStorage&amp;lt;/code&amp;gt;. Each one of these capabilities will be discussed in the corresponding section.&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;IItemHandler&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;IItemHandler&amp;lt;/code&amp;gt; capability refers to the ability for any capability provider to have some sort of internal&lt;br /&gt;
'''inventory''' with a certain number of slots, from which items can be inserted and extracted. It is also possible,&lt;br /&gt;
though, to expose this capability even if no such inventory is present as long as the capability provider can emulate&lt;br /&gt;
its presence (e.g. tools that allow accessing remote inventories).&lt;br /&gt;
&lt;br /&gt;
This effectively '''replaces''' the vanilla interfaces &amp;lt;code&amp;gt;Container&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;WorldlyContainer&amp;lt;/code&amp;gt;. These&lt;br /&gt;
interfaces are in fact retained only to allow vanilla code to compile and should not be used in mod code. This extends&lt;br /&gt;
to anything that implements those vanilla interfaces, such as &amp;lt;code&amp;gt;RandomizableContainerBlockEntity&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
A default reference implementation for this capability interface is provided in &amp;lt;code&amp;gt;ItemStackHandler&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;IFluidHandler&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;IFluidHandler&amp;lt;/code&amp;gt; capability refers to the ability for any capability provider to handle and store fluids&lt;br /&gt;
in one or multiple fluid tanks. It is effectively the equivalent in terms of fluids of the &amp;lt;code&amp;gt;IItemHandler&amp;lt;/code&amp;gt;&lt;br /&gt;
capability.&lt;br /&gt;
&lt;br /&gt;
A default reference implementation for this capability interface is provided in &amp;lt;code&amp;gt;TileFluidHandler&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;IFluidHandlerItem&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;IFluidHandlerItem&amp;lt;/code&amp;gt; capability refers to the ability for an &amp;lt;code&amp;gt;ItemStack&amp;lt;/code&amp;gt; capability provider&lt;br /&gt;
to handle and store fluids in one or multiple fluid tanks. It is basically a specialized version of the&lt;br /&gt;
&amp;lt;code&amp;gt;IFluidHandler&amp;lt;/code&amp;gt; capability that allows &amp;lt;code&amp;gt;ItemStack&amp;lt;/code&amp;gt;s to define a custom container.&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;IEnergyStorage&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;IEnergyStorage&amp;lt;/code&amp;gt; capability refers to the ability for any capability provider to store, consume, and&lt;br /&gt;
produce energy. This capability is the base capability for what's commonly known in the modded world as Forge Energy (or&lt;br /&gt;
FE), i.e. the energy system most mods use. Its internal design is heavily based on the (now defunct) Redstone Flux&lt;br /&gt;
Energy API, supporting both a push and pull system.&lt;br /&gt;
&lt;br /&gt;
A default reference implementation for this capability interface is provided in &amp;lt;code&amp;gt;EnergyStorage&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Working with Capabilities ==&lt;br /&gt;
&lt;br /&gt;
Both capability providers and users need to be able to provide and access capabilities through a common framework,&lt;br /&gt;
otherwise the ideal of dynamic and mod-agnostic would not really exist. For this reason, both capability providers and&lt;br /&gt;
capability ''accessors'' (which we define as everything that wants to access a capability), also known as '''clients''' or '''users''',&lt;br /&gt;
need to work together and with Forge to ensure that the common interface is used sensibly and correctly by all parties.&lt;br /&gt;
&lt;br /&gt;
=== Obtaining a Capability ===&lt;br /&gt;
&lt;br /&gt;
Before being able to work with a capability, it is necessary to obtain an instance of the &amp;lt;code&amp;gt;Capability&amp;lt;/code&amp;gt; object itself.&lt;br /&gt;
&lt;br /&gt;
A &amp;lt;code&amp;gt;Capability&amp;lt;/code&amp;gt; can obtained at any time using &amp;lt;code&amp;gt;CapabilityManager#get&amp;lt;/code&amp;gt;. This takes in an anonymous &amp;lt;code&amp;gt;CapabilityToken&amp;lt;/code&amp;gt; to still allow for a soft dependency system while also keeping hold of any generic information needed. As such, you can always obtain a non-null capability.&lt;br /&gt;
&lt;br /&gt;
{{Tabs/Code Snippets&lt;br /&gt;
|java=&lt;br /&gt;
public static Capability&amp;lt;IItemHandler&amp;gt; ITEM_HANDLER_CAPABILITY = CapabilityManager.get(new CapabilityToken&amp;lt;&amp;gt;(){});&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
The above code will let Forge know that the field &amp;lt;code&amp;gt;ITEM_HANDLER_CAPABILITY&amp;lt;/code&amp;gt; should be analogous with the &amp;lt;code&amp;gt;IItemHandler&amp;lt;/code&amp;gt; capability. Note that this does not mean the capability is accessible or registered. To check if it is, call &amp;lt;code&amp;gt;Capability#isRegistered&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
This is, for obvious reasons, redundant, since that capability is also available through&lt;br /&gt;
&amp;lt;code&amp;gt;CapabilityItemHandler&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Exposing a Capability ===&lt;br /&gt;
&lt;br /&gt;
Exposing a capability is a voluntary act by a capability provider that allows the capability to be discovered and&lt;br /&gt;
accessed by users.&lt;br /&gt;
&lt;br /&gt;
To do so, a capability provider needs to juggle a couple more moving pieces to ensure that the capability state remains&lt;br /&gt;
consistent and that the lookup remains fast. It is in fact possible for a capability provider to be asked to provide&lt;br /&gt;
many capabilities many times in the same tick. For this reason, a provider is asked to do the following:&lt;br /&gt;
&lt;br /&gt;
* the &amp;lt;code&amp;gt;LazyOptional&amp;lt;/code&amp;gt;s that get returned '''must be cached''';&lt;br /&gt;
* if a capability changes exposure state (more on this later), all listeners '''must be notified''';&lt;br /&gt;
* if a capability gets invalidated (more on this later), all listeners '''must be notified'''&lt;br /&gt;
* the lookup inside &amp;lt;code&amp;gt;getCapability&amp;lt;/code&amp;gt; must be performed with '''an &amp;lt;code&amp;gt;if&amp;lt;/code&amp;gt;-&amp;lt;code&amp;gt;else&amp;lt;/code&amp;gt; chain''';&lt;br /&gt;
* all unexposed but still present capabilities '''should be available''' if the provider is queried with a &amp;lt;code&amp;gt;null&amp;lt;/code&amp;gt; direction (see ''Accessing a Capability'' for more information);&lt;br /&gt;
* if no capability of a given type is available or accessible, the provider '''must call &amp;lt;code&amp;gt;super&amp;lt;/code&amp;gt; as long as it is possible to do so'''.&lt;br /&gt;
&lt;br /&gt;
Capability providers must also reflect changes in the ''exposure state'' of a capability, meaning that if the&lt;br /&gt;
accessibility of a capability from a certain &amp;lt;code&amp;gt;Direction&amp;lt;/code&amp;gt; changes (refer to&lt;br /&gt;
[[#Accessing a Capability|Accessing a Capability]] for more information), it is the provider's responsibility to trigger&lt;br /&gt;
a state response by invalidating the returned &amp;lt;code&amp;gt;LazyOptional&amp;lt;/code&amp;gt; and caching a new one. This should also be&lt;br /&gt;
performed when a capability gets ''invalidated'', such as when a capability provider gets removed.&lt;br /&gt;
&lt;br /&gt;
With all of the above in mind, part of a capability provider implementation may be similar to the following snippet:&lt;br /&gt;
&lt;br /&gt;
{{Tabs/Code Snippets&lt;br /&gt;
|java=&lt;br /&gt;
// suppose the presence of a field 'inventory' of type 'IItemHandler'&lt;br /&gt;
&lt;br /&gt;
private final LazyOptional&amp;lt;IItemhandler&amp;gt; inventoryOptional = LazyOptional.of(() -&amp;gt; this.inventory);&lt;br /&gt;
&lt;br /&gt;
@Override&lt;br /&gt;
public &amp;lt;T&amp;gt; LazyOptional&amp;lt;T&amp;gt; getCapability(Capability&amp;lt;T&amp;gt; capability, @Nullable Direction direction) {&lt;br /&gt;
    if (capability == CapabilityItemHandler.ITEM_HANDLER_CAPABILITY&lt;br /&gt;
            &amp;amp;&amp;amp; (direction == null || direction == Direction.UP || direction == Direction.DOWN)) {&lt;br /&gt;
        return this.inventoryOptional.cast();&lt;br /&gt;
    }&lt;br /&gt;
    return super.getCapability(capability, direction); // See note after snippet&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
@Override&lt;br /&gt;
protected void invalidateCaps() {&lt;br /&gt;
    super.invalidateCaps();&lt;br /&gt;
    this.inventoryOptional.invalidate();&lt;br /&gt;
}&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
This possible implementation of a capability provider exposes an &amp;lt;code&amp;gt;IItemHandler&amp;lt;/code&amp;gt; capability and restricts&lt;br /&gt;
access only to the &amp;lt;code&amp;gt;UP&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;DOWN&amp;lt;/code&amp;gt; directions. If we assume this capability provider is a&lt;br /&gt;
&amp;lt;code&amp;gt;BlockEntity&amp;lt;/code&amp;gt;, then we may also say that the inventory is only accessible from the top and the bottom of the&lt;br /&gt;
block.&lt;br /&gt;
&lt;br /&gt;
Moreover, the capability gets automatically invalidated when the provider gets invalidated. Assuming this is a&lt;br /&gt;
&amp;lt;code&amp;gt;BlockEntity&amp;lt;/code&amp;gt;, this usually happens when the block gets removed from the level or unloaded due to distance.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;super&amp;lt;/code&amp;gt; call at the end of the &amp;lt;code&amp;gt;getCapability&amp;lt;/code&amp;gt; method is extremely important, since it's what&lt;br /&gt;
allows Attaching external Capabilities to capability providers. Nevertheless, it is not always possible to invoke&lt;br /&gt;
&amp;lt;code&amp;gt;super&amp;lt;/code&amp;gt;: in those cases, an empty &amp;lt;code&amp;gt;LazyOptional&amp;lt;/code&amp;gt; should be returned.&lt;br /&gt;
&lt;br /&gt;
=== Attaching a Capability ===&lt;br /&gt;
&lt;br /&gt;
Attaching a Capability is a process by which external agents &amp;quot;modify&amp;quot; a Capability Provider, making it expose additional&lt;br /&gt;
capabilities other than the already available ones.&lt;br /&gt;
&lt;br /&gt;
To do so, the '''attaching agent''' (which means the thing that wants to attach a capability to another provider) must&lt;br /&gt;
listen to the &amp;lt;code&amp;gt;AttachCapabilitiesEvent&amp;amp;lt;T&amp;amp;gt;&amp;lt;/code&amp;gt;. The &amp;lt;code&amp;gt;T&amp;lt;/code&amp;gt; in this case represents the capability&lt;br /&gt;
provider you want to attach the capability to. Note that the type of &amp;lt;code&amp;gt;T&amp;lt;/code&amp;gt; '''must''' be the base type of the&lt;br /&gt;
capability provider, not a subclass. As an example, if you want to attach a capability to a &amp;lt;code&amp;gt;MyBlockEntity&amp;lt;/code&amp;gt;,&lt;br /&gt;
which extends &amp;lt;code&amp;gt;BlockEntity&amp;lt;/code&amp;gt;, you'll have to listen to &amp;lt;code&amp;gt;AttachCapabilitiesEvent&amp;amp;lt;BlockEntity&amp;amp;gt;&amp;lt;/code&amp;gt;,&lt;br /&gt;
'''NOT''' to &amp;lt;code&amp;gt;AttachCapabilitiesEvent&amp;amp;lt;MyBlockEntity&amp;amp;gt;&amp;lt;/code&amp;gt;, since the latter will never fire.&lt;br /&gt;
&lt;br /&gt;
The attaching agent can use the provided methods &amp;lt;code&amp;gt;getObject&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;addCapability&amp;lt;/code&amp;gt;, and &lt;br /&gt;
&amp;lt;code&amp;gt;addListener&amp;lt;/code&amp;gt; to check whether the capability should be attached to the current object and perform the&lt;br /&gt;
desired action.&lt;br /&gt;
&lt;br /&gt;
When attaching a capability, the attaching agent should also provide a name in the form of a&lt;br /&gt;
&amp;lt;code&amp;gt;ResourceLocation&amp;lt;/code&amp;gt;. The name '''must''' be under the attaching agent's namespace, but no restrictions are&lt;br /&gt;
placed on the actual name, as long as it is unique inside the given namespace.&lt;br /&gt;
&lt;br /&gt;
Maybe a little counter-intuitively, the process of attaching does not attach a capability nor a capability interface&lt;br /&gt;
directly. Rather, the attaching agent should create its own implementation of a '''Capability Provider''' and attach it&lt;br /&gt;
via the event. This is done so that the attaching agent can have control over when, how, and where its capabilities are&lt;br /&gt;
exposed, instead of relying on the game itself deciding these parameters. For this reason, all considerations given in&lt;br /&gt;
the [[#Exposing a Capability|Exposing a Capability]] section on how to correctly create a Capability Provider.&lt;br /&gt;
&lt;br /&gt;
With the above in mind, part of an attaching agent may be similar to the following snippet of code:&lt;br /&gt;
&lt;br /&gt;
{{Tabs/Code Snippets&lt;br /&gt;
|java=&lt;br /&gt;
@SubscribeEvent&lt;br /&gt;
public void onAttachingCapabilities(final AttachCapabilitiesEvent&amp;lt;BlockEntity&amp;gt; event) {&lt;br /&gt;
    if (!(event.getObject() instanceof EnergyBasedBlockEntity)) return;&lt;br /&gt;
&lt;br /&gt;
    EnergyStorage backend = new EnergyStorage(((EnergyBasedBlockEntity) event.getObject()).capacity);&lt;br /&gt;
    LazyOptional&amp;lt;IEnergyStorage&amp;gt; optionalStorage = LazyOptional.of(() -&amp;gt; backend);&lt;br /&gt;
&lt;br /&gt;
    ICapabilityProvider provider = new ICapabilityProvider() {&lt;br /&gt;
        @Override&lt;br /&gt;
        public &amp;lt;T&amp;gt; LazyOptional&amp;lt;T&amp;gt; getCapability(Capability&amp;lt;T&amp;gt; cap, @Nullable Direction direction) {&lt;br /&gt;
            if (cap == CapabilityEnergy.ENERGY) {&lt;br /&gt;
                return optionalStorage.cast();&lt;br /&gt;
            }&lt;br /&gt;
            return LazyOptional.empty();&lt;br /&gt;
        }&lt;br /&gt;
    };&lt;br /&gt;
&lt;br /&gt;
    event.addCapability(new ResourceLocation(&amp;quot;examplemod&amp;quot;, &amp;quot;fe_compatibility&amp;quot;), provider);&lt;br /&gt;
}&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
This example implementation of an attaching agent attaches a &amp;lt;code&amp;gt;IEnergyStorage&amp;lt;/code&amp;gt; capability to all&lt;br /&gt;
&amp;lt;code&amp;gt;BlockEntity&amp;lt;/code&amp;gt; instance that are a subclass of &amp;lt;code&amp;gt;EnergyBasedBlockEntity&amp;lt;/code&amp;gt;. It also sets up the&lt;br /&gt;
&amp;lt;code&amp;gt;LazyOptional&amp;lt;/code&amp;gt; for invalidation if the parent capability provider gets invalidated.&lt;br /&gt;
&lt;br /&gt;
Note also the call of &amp;lt;code&amp;gt;LazyOptional.empty()&amp;lt;/code&amp;gt; rather than a &amp;lt;code&amp;gt;super&amp;lt;/code&amp;gt;. This is needed because when&lt;br /&gt;
attaching a capability, the parent capability provider isn't known. For this reason, it is necessary to return an empty&lt;br /&gt;
&amp;lt;code&amp;gt;LazyOptional&amp;lt;/code&amp;gt;. The game will then handle automatic merging of the various different providers into a single&lt;br /&gt;
one.&lt;br /&gt;
&lt;br /&gt;
The above example is one of a '''Volatile''' Capability Provider. On the other hand, mods may want to persist their&lt;br /&gt;
data across sessions. In this case, they should attach a '''Persistent''' Capability Provider: this can be done either&lt;br /&gt;
by implementing the &amp;lt;code&amp;gt;INBTSerializable&amp;lt;/code&amp;gt; interface along with &amp;lt;code&amp;gt;ICapabilityProvider&amp;lt;/code&amp;gt; or by&lt;br /&gt;
implementing the &amp;lt;code&amp;gt;ICapabilitySerializable&amp;lt;/code&amp;gt; interface.&lt;br /&gt;
&lt;br /&gt;
The previous example reworked to use a Persistent Capability Provider may be similar to the following snippet:&lt;br /&gt;
&lt;br /&gt;
{{Tabs/Code Snippets&lt;br /&gt;
|java=&lt;br /&gt;
@SubscribeEvent&lt;br /&gt;
public void onAttachingCapabilities(final AttachCapabilitiesEvent&amp;lt;BlockEntity&amp;gt; event) {&lt;br /&gt;
    if (!(event.getObject() instanceof EnergyBasedBlockEntity)) return;&lt;br /&gt;
&lt;br /&gt;
    EnergyStorage backend = new EnergyStorage(((EnergyBasedBlockEntity) event.getObject()).capacity);&lt;br /&gt;
    LazyOptional&amp;lt;IEnergyStorage&amp;gt; optionalStorage = LazyOptional.of(() -&amp;gt; backend);&lt;br /&gt;
    Capability&amp;lt;IEnergyStorage&amp;gt; capability = CapabilityEnergy.ENERGY;&lt;br /&gt;
&lt;br /&gt;
    ICapabilityProvider provider = new ICapabilitySerializable&amp;lt;IntTag&amp;gt;() {&lt;br /&gt;
        @Override&lt;br /&gt;
        public &amp;lt;T&amp;gt; LazyOptional&amp;lt;T&amp;gt; getCapability(Capability&amp;lt;T&amp;gt; cap, @Nullable Direction direction) {&lt;br /&gt;
            if (cap == capability) {&lt;br /&gt;
                return optionalStorage.cast();&lt;br /&gt;
            }&lt;br /&gt;
            return LazyOptional.empty();&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        @Override&lt;br /&gt;
        public IntTag serializeNBT() {&lt;br /&gt;
            return backend.serializeNBT();&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        @Override&lt;br /&gt;
        public void deserializeNBT(IntTag tag) {&lt;br /&gt;
            backend.deserializeNBT(tag);&lt;br /&gt;
        }&lt;br /&gt;
    };&lt;br /&gt;
&lt;br /&gt;
    event.addCapabilities(new ResourceLocation(&amp;quot;examplemod&amp;quot;, &amp;quot;fe_compatibility&amp;quot;), provider);&lt;br /&gt;
}&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Note that when using capabilities on entities, you should manually invalidate the capability via &amp;lt;code&amp;gt;invalidateCaps()&amp;lt;/code&amp;gt;, via etc. &amp;lt;code&amp;gt;PlayerEvent.Clone&amp;lt;/code&amp;gt;. This is due to the fact that players are recreated &amp;amp; copied when moving across dimensions, not simply moved.&lt;br /&gt;
&lt;br /&gt;
=== Accessing a Capability ===&lt;br /&gt;
&lt;br /&gt;
Accessing a Capability is the process by which a user is able to '''query''' a Capability Provider for a specific&lt;br /&gt;
instance of a capability.&lt;br /&gt;
&lt;br /&gt;
This is perhaps the second most important part of the entire capability system, since it is what allows cross-mod&lt;br /&gt;
interaction. To obtain an instance of a Capability, the user must first get a hold of the Capability Provider that&lt;br /&gt;
should be queried. This can be done in a variety of ways and is outside the scope of this article. The user should&lt;br /&gt;
then invoke the &amp;lt;code&amp;gt;getCapability&amp;lt;/code&amp;gt; method passing the unique instance of the capability that should be queried&lt;br /&gt;
(see [[#Obtaining a Capability|Obtaining a Capability]] for more information) and the querying &amp;lt;code&amp;gt;Direction&amp;lt;/code&amp;gt;,&lt;br /&gt;
if applicable.&lt;br /&gt;
&lt;br /&gt;
The returned object is a &amp;lt;code&amp;gt;LazyOptional&amp;lt;/code&amp;gt; wrapping the queried Capability, if the capability provider exposes&lt;br /&gt;
it, otherwise it will be empty. The &amp;lt;code&amp;gt;LazyOptional&amp;lt;/code&amp;gt; can be either unwrapped via an &amp;lt;code&amp;gt;orElse&amp;lt;/code&amp;gt; or&lt;br /&gt;
used directly via &amp;lt;code&amp;gt;ifPresent&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
It is '''highly suggested''' to cache the returned &amp;lt;code&amp;gt;LazyOptional&amp;lt;/code&amp;gt; to avoid querying the same provider every&lt;br /&gt;
time, in order to improve performance. The user should thus register itself to the invalidation listener via the&lt;br /&gt;
&amp;lt;code&amp;gt;addListener&amp;lt;/code&amp;gt; method. This ensures that the user will be able to react to the invalidation of the&lt;br /&gt;
&amp;lt;code&amp;gt;LazyOptional&amp;lt;/code&amp;gt; and remove it from the cache.&lt;br /&gt;
&lt;br /&gt;
With the above in mind, part of an user may be similar to the following snippet of code:&lt;br /&gt;
&lt;br /&gt;
{{Tabs/Code Snippets&lt;br /&gt;
|java=&lt;br /&gt;
// note the use of EnumMap, which is much more performant than HashMap for enum keys&lt;br /&gt;
private final Map&amp;lt;Direction, LazyOptional&amp;lt;IEnergyStorage&amp;gt;&amp;gt; cache = new EnumMap&amp;lt;&amp;gt;(Direction.class);&lt;br /&gt;
&lt;br /&gt;
private void sendPowerTo(int power, Direction direction) {&lt;br /&gt;
    LazyOptional&amp;lt;IEnergyStorage&amp;gt; targetCapability = cache.get(direction);&lt;br /&gt;
&lt;br /&gt;
    if (targetCapability == null) {&lt;br /&gt;
        ICapabilityProvider provider = level.getBlockEntity(pos.relative(direction));&lt;br /&gt;
        targetCapability = provider.getCapability(CapabilityEnergy.ENERGY, direction.getOpposite());&lt;br /&gt;
        cache.put(direction, targetCapability);&lt;br /&gt;
        targetCapability.addListener(self -&amp;gt; cache.put(direction, null));&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    targetCapability.ifPresent(storage -&amp;gt; storage.receiveEnergy(power, false));&lt;br /&gt;
}&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
This example implementation of an user is querying via a &amp;lt;code&amp;gt;BlockEntity&amp;lt;/code&amp;gt; the neighboring capability provider&lt;br /&gt;
for an &amp;lt;code&amp;gt;IEnergyStorage&amp;lt;/code&amp;gt; capability. Before obtaining the provider, the code performs a cache lookup for the&lt;br /&gt;
targeted capability. If the check succeeds, then no lookup is performed; if the check fails, the targeted Capability&lt;br /&gt;
Provider is obtained and queried for the Capability. The obtained &amp;lt;code&amp;gt;LazyOptional&amp;lt;/code&amp;gt; is then cached and a&lt;br /&gt;
listener is attached to it so that the cache would be emptied on invalidation. The code then continues with the&lt;br /&gt;
interaction with the capability, which is outside the scope of this article.&lt;br /&gt;
&lt;br /&gt;
== Creating Custom Capabilities ==&lt;br /&gt;
&lt;br /&gt;
While the various capabilities provided by Forge may satisfy the most common use cases, there is always the chance that&lt;br /&gt;
a mod may require a custom solution. For this reason, Forge provides a way to define a custom Capability.&lt;br /&gt;
&lt;br /&gt;
Defining a custom Capability requires the user to provide one main component: the Capability Interface. Optionally, a &lt;br /&gt;
Capability Implementation and Capability Provider can also be created. In this&lt;br /&gt;
case, the provider will be used as described in [[#Attaching a Capability|Attaching a Capability]]. The various details &lt;br /&gt;
for all these components are described in the respective sections of this article.&lt;br /&gt;
&lt;br /&gt;
In this section, we will refer to the implementation of a &amp;lt;code&amp;gt;MyCapability&amp;lt;/code&amp;gt; capability, that can be used to&lt;br /&gt;
store a single mutable &amp;lt;code&amp;gt;String&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Refer also to [[#Code Examples|Code Examples]] for an example on how the various components may be implemented in a&lt;br /&gt;
real-world scenario.&lt;br /&gt;
&lt;br /&gt;
=== The Capability Interface and the Capability Implementation ===&lt;br /&gt;
&lt;br /&gt;
The Capability Interface is one of the most important parts of a Capability: without it, the Capability effectively does&lt;br /&gt;
not exist. Designing a Capability Interface is exactly like designing any Java interface, so the particular details will&lt;br /&gt;
be glossed over in this section.&lt;br /&gt;
&lt;br /&gt;
The Capability Implementation, on the other hand, is the implementation of the previously defined Capability Interface.&lt;br /&gt;
Usual rules for interface implementations follow. There can be more than one Capability Implementation for each&lt;br /&gt;
capability. &lt;br /&gt;
&lt;br /&gt;
Note that a '''well-formed''' capability implementation should '''not store''' the Capability Provider inside of it: we&lt;br /&gt;
call the capability implementation ''provider-agnostic''. This is not a hard-requirement, though, rather it should act&lt;br /&gt;
more as a guideline. There are in fact certain situations where this cannot be avoided (e.g. attaching a client-synced&lt;br /&gt;
capability to an &amp;lt;code&amp;gt;ItemStack&amp;lt;/code&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
Given all of the above information, this may be an example implementation of both a Capability Interface and a&lt;br /&gt;
Capability Implementation:&lt;br /&gt;
&lt;br /&gt;
{{Tabs/Code Snippets&lt;br /&gt;
|java=&lt;br /&gt;
public interface MyCapability {&lt;br /&gt;
    String getValue();&lt;br /&gt;
    void setValue(String value);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
public class MyCapabilityImplementation implements MyCapability {&lt;br /&gt;
    private String value;&lt;br /&gt;
&lt;br /&gt;
    @Override&lt;br /&gt;
    public String getValue() {&lt;br /&gt;
        return this.value;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    @Override&lt;br /&gt;
    public void setValue(String value) {&lt;br /&gt;
        this.value = value;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Note that in this case, only a single implementation is provided.&lt;br /&gt;
&lt;br /&gt;
=== The Capability Provider ===&lt;br /&gt;
&lt;br /&gt;
The Capability Provider is an optional component of the capability that allows the Capability to be attached to a&lt;br /&gt;
component. The details on how a Capability Provider should behave have already been discussed in the two previous&lt;br /&gt;
sections [[#Exposing a Capability|Exposing a Capability]] and [[#Attaching a Capability|Attaching a Capability]]: refer&lt;br /&gt;
to those for more information.&lt;br /&gt;
&lt;br /&gt;
=== Registering Capabilities ===&lt;br /&gt;
&lt;br /&gt;
Once all components of a Capability have been created, they must be registered so that the game is aware of the&lt;br /&gt;
capability's presence. The registration only requires the Capability Interface.&lt;br /&gt;
After registering, the created Capability will be automatically injected into all relevant fields and methods, see [[#Obtaining a Capability|Obtaining a Capability]] for more information.&lt;br /&gt;
As of Forge 1.19.2-43.1.1, there are two ways to register capabilities.&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;code&amp;gt;AutoRegisterCapability&amp;lt;/code&amp;gt; annotation ====&lt;br /&gt;
On Forge 1.19.2-43.1.1 or higher, a quick and easy way to register a capability is by annotating the Capability Interface with &amp;lt;code&amp;gt;@AutoRegisterCapability&amp;lt;/code&amp;gt;. This would look like so:&lt;br /&gt;
&lt;br /&gt;
{{Tabs/Code Snippets&lt;br /&gt;
|java=&lt;br /&gt;
@AutoRegisterCapability&lt;br /&gt;
public interface MyCapability {&lt;br /&gt;
    ...&lt;br /&gt;
}&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
==== RegisterCapabilitiesEvent ====&lt;br /&gt;
An alternative way to register capabilities is by calling the &amp;lt;code&amp;gt;register&amp;lt;/code&amp;gt; method within the &amp;lt;code&amp;gt;RegisterCapabilitiesEvent&amp;lt;/code&amp;gt;. This event is fired on the &amp;lt;code&amp;gt;MOD&amp;lt;/code&amp;gt; event bus. For example:&lt;br /&gt;
&lt;br /&gt;
{{Tabs/Code Snippets&lt;br /&gt;
|java=&lt;br /&gt;
@SubscribeEvent&lt;br /&gt;
public void registerCaps(RegisterCapabilitiesEvent event) {&lt;br /&gt;
    event.register(MyCapability.class);&lt;br /&gt;
}&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
=== Class Diagram ===&lt;br /&gt;
&lt;br /&gt;
[[File:Custom Capability Class Diagram.svg|800px|thumb|center|Custom Capability Class Diagram]]&lt;br /&gt;
&lt;br /&gt;
In the above diagram the green and red marked areas are classes from Minecraft and Forge respectively. The classes inside the purple area are only needed if you want to [[#Attaching a Capability|Attach a Capability]]. Furthermore this diagram models a persistent provider and its most basic form, for more information on how to create a more complex provider see [[#Custom Capability Providers|Custom Capability Providers]]. To create a volatile provider instead just do not implement &amp;lt;code&amp;gt;INBTSerializable&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Custom Capability Providers ==&lt;br /&gt;
&lt;br /&gt;
Much like custom Capabilities, Forge also allows the creation of custom Capability Providers. The main advantage of this&lt;br /&gt;
is allowing mods to create custom providers for their custom objects, in order to promote not only cross-mod&lt;br /&gt;
compatibility, but also uniformity in the way users may interact with different mod APIs.&lt;br /&gt;
&lt;br /&gt;
This section will only give the basic outline of what is necessary to implement a custom Capability Provider: for more&lt;br /&gt;
in-depth explanation, people are referred to the game code.&lt;br /&gt;
&lt;br /&gt;
By definition, a custom Capability Provider is everything that implements the &amp;lt;code&amp;gt;ICapabilityProvider&amp;lt;/code&amp;gt;&lt;br /&gt;
interface. In this section, though, we will only cover people that may want to replicate the functionality of one of&lt;br /&gt;
the default providers, such as &amp;lt;code&amp;gt;BlockEntity&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;LevelChunk&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
The easiest way of doing this is extending the &amp;lt;code&amp;gt;CapabilityProvider&amp;lt;/code&amp;gt; class provided by Forge. This will&lt;br /&gt;
automatically set up an ''agnostic'' Capability Provider. To fully initialize the capability provider, the subclass&lt;br /&gt;
should then invoke the &amp;lt;code&amp;gt;gatherCapabilities&amp;lt;/code&amp;gt; method as the last instruction in its constructor, to ensure that&lt;br /&gt;
the game is able to recollect and attach all capabilities that other mods may want to attach to the capability provider.&lt;br /&gt;
&lt;br /&gt;
== Code Examples ==&lt;br /&gt;
&lt;br /&gt;
* [https://gist.github.com/TheCurle/6db954d680f6f067dcdc791355c32c89 A Gist showing a quick and dirty example on how to implement a Capability effectively]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Data Storage]]&lt;/div&gt;</summary>
		<author><name>SizableShrimp</name></author>
	</entry>
	<entry>
		<id>https://forge.gemwire.uk/index.php?title=Main_Page&amp;diff=3325</id>
		<title>Main Page</title>
		<link rel="alternate" type="text/html" href="https://forge.gemwire.uk/index.php?title=Main_Page&amp;diff=3325"/>
		<updated>2022-09-12T04:56:32Z</updated>

		<summary type="html">&lt;p&gt;SizableShrimp: Add entities category&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;
* [[Custom Item Animations]]&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;Entities&amp;lt;/h3&amp;gt;&lt;br /&gt;
* [[Making Entities]]&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;
* [[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;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>SizableShrimp</name></author>
	</entry>
	<entry>
		<id>https://forge.gemwire.uk/index.php?title=Making_Entities&amp;diff=3324</id>
		<title>Making Entities</title>
		<link rel="alternate" type="text/html" href="https://forge.gemwire.uk/index.php?title=Making_Entities&amp;diff=3324"/>
		<updated>2022-09-12T04:53:49Z</updated>

		<summary type="html">&lt;p&gt;SizableShrimp: boop&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Under construction}}&lt;br /&gt;
&lt;br /&gt;
Entities are core to the Minecraft world and make up all movable objects that do not fall under [[Making Blocks|Blocks]] or [[Block Entities]]. Entities can tick and be controlled by AI or player input. This article serves as a guide for setting up a basic entity. It does not involve setting up the rendering for an entity, which is a required step to be able to see an entity in-game without crashing. See [[Entity Renderer]] for more information on entity rendering and setup.&lt;br /&gt;
&lt;br /&gt;
== Entity Type ==&lt;br /&gt;
Much of the identity of an entity is determined by its '''entity type'''. This contains information universal to an entity. An entity type must exist and be [[Registration|registered]] for the corresponding entity to be summonable. &lt;br /&gt;
&lt;br /&gt;
=== Creating the Builder ===&lt;br /&gt;
The primary way to make an &amp;lt;code&amp;gt;EntityType&amp;lt;/code&amp;gt; is to create and configure an &amp;lt;code&amp;gt;EntityType$Builder&amp;lt;/code&amp;gt;. Creating an entity type builder is done using the static factory &amp;lt;code&amp;gt;EntityType.Builder#of&amp;lt;/code&amp;gt;. It requires two parameters: an &amp;lt;code&amp;gt;EntityType.EntityFactory&amp;lt;/code&amp;gt; and a &amp;lt;code&amp;gt;MobCategory&amp;lt;/code&amp;gt;.&lt;br /&gt;
The entity factory is usually an entity class with a constructor taking its own &amp;lt;code&amp;gt;EntityType&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;Level&amp;lt;/code&amp;gt; of the form &amp;lt;code&amp;gt;MyEntity::new&amp;lt;/code&amp;gt;. This requires a class of the name &amp;lt;code&amp;gt;MyEntity&amp;lt;/code&amp;gt; to actually exist (see [[#Entity Class|the entity class section]] for more info).&lt;br /&gt;
The mob category is an enum describing mostly spawning properties about a category of mobs. This includes:&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;How many entities in a given mob category can spawn per chunk&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Whether the entity is friendly (and therefore will spawn in peaceful difficulty)&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Whether the entity is persistent (and therefore will save to disk and be reloaded)&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;How many blocks away a player must be for an entity in a given mob category to despawn&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Configuring the Builder ===&lt;br /&gt;
An entity type builder by itself is not very useful. It must be configured to match the desired properties of the entity.&lt;br /&gt;
The possible properties that can be configured are listed below:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=1&lt;br /&gt;
! Method !! Default Value !! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;sized&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt; || 0.6 meters wide by 1.8 meters tall (player dimensions) || Sets the default pose dimensions of the entity in order of square base width then height in meters/blocks. A value of 1.0 would be equivalent to the length of 1 full block. The base cannot be configured with a separate width and length.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;noSummon&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt; || Can summon || Calling this prevents spawning the entity through &amp;lt;code&amp;gt;/summon&amp;lt;/code&amp;gt;; intended for internal entities that a user should not be able to create. This also prevents summoning through natural spawning in biomes, if it is configured.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;noSave&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt; || Can save || Calling this prevents the entity from ever saving to disk. Unloading a chunk with a &amp;lt;code&amp;gt;noSave&amp;lt;/code&amp;gt; entity will effectively delete the entity.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;fireImmune&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt; || Vulnerable to fire || Calling this prevents the entity from taking any fire/lava damage.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;clientTrackingRange&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt; || 5 chunks || Sets the maximum range in chunks in which players should be sent update packet information about the entity. Sending update information about an entity to a player is known as the player ''tracking'' that entity. If the player is outside this chunk range, they will not know of the entity's existence.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;immuneTo&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt; || Empty set of blocks || Effectively useless for modding purposes.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;canSpawnFarFromPlayer&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt; || True for &amp;lt;code&amp;gt;MobCategory.CREATURE&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;MobCategory.MISC&amp;lt;/code&amp;gt;, false otherwise. || Calling this allows an entity to spawn outside of the despawn distance of its mob category.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;updateInterval&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt; || 3 ticks || How often, in ticks, update packets should be sent to all client players tracking this entity (see &amp;lt;code&amp;gt;clientTrackingRange&amp;lt;/code&amp;gt;). The update packets contain information like position, rotation, and velocity. They may be sent more quickly than this interval during specific actions.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;setShouldReceiveVelocityUpdates&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt; || true || Sets whether tracking client players should receive velocity information in update interval packets. If false, velocity information will not be sent to clients unless necessary.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Building the Builder ===&lt;br /&gt;
After creating and configuring the entity type builder, it must be built. This requires the modid and name of the entity type. For an entity type with the name &amp;quot;example_monster&amp;quot; in the mod &amp;quot;examplemod&amp;quot;, this would look like &amp;lt;code&amp;gt;builder.build(&amp;quot;examplemod:example_monster&amp;quot;)&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Tying It Together ===&lt;br /&gt;
Given the above information, a basic EntityType might look like the following:&lt;br /&gt;
{{Tabs/Code Snippets&lt;br /&gt;
|java=EntityType.Builder.of(ExampleMonsterEntity::new, MobCategory.MONSTER)&lt;br /&gt;
    .sized(1.0F, 2.0F)&lt;br /&gt;
    .fireImmune()&lt;br /&gt;
    .updateInterval(1)&lt;br /&gt;
    .build(&amp;quot;examplemod:example_monster&amp;quot;)&lt;br /&gt;
}}&lt;br /&gt;
To function, this example requires that an entity class of the name &amp;lt;code&amp;gt;ExampleMonsterEntity&amp;lt;/code&amp;gt; exist along with the entity type being [[Registration|registered]].&lt;br /&gt;
&lt;br /&gt;
== Entity Class ==&lt;br /&gt;
Alongside an entity type, an entity requires a class outlining its behavior and any information that may change from one instance to another. All entities must extend from the base class &amp;lt;code&amp;gt;Entity&amp;lt;/code&amp;gt;. However, some entities should extend from specific subclasses instead. For a completely generic entity, use &amp;lt;code&amp;gt;Entity&amp;lt;/code&amp;gt;. For a living entity with health, potion effects, and an inventory, use &amp;lt;code&amp;gt;LivingEntity&amp;lt;/code&amp;gt;. For a living entity with movement AI and AI goals, use &amp;lt;code&amp;gt;Mob&amp;lt;/code&amp;gt;. There are also many other entity subclasses which can be found through your IDE and picked depending on the scenario.&lt;br /&gt;
&lt;br /&gt;
Once picking a target superclass to extend, an entity class should be created and the constructor should be setup. It should look something like this:&lt;br /&gt;
{{Tabs/Code Snippets|&lt;br /&gt;
java=public class ExampleMonsterEntity extends Mob {&lt;br /&gt;
    public ExampleMonsterEntity(EntityType&amp;lt;? extends Mob&amp;gt; entityType, Level level) {&lt;br /&gt;
        super(entityType, level);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
To define custom behavior, methods must be overriden. Your IDE should have a feature to list all possible methods to override, although some common ones might be: &amp;lt;code&amp;gt;customServerAiStep&amp;lt;/code&amp;gt; for server AI, &amp;lt;code&amp;gt;tick&amp;lt;/code&amp;gt; for code to execute each tick on client/server, and &amp;lt;code&amp;gt;registerGoals&amp;lt;/code&amp;gt; to setup AI goals.&lt;br /&gt;
&lt;br /&gt;
== Natural Spawning ==&lt;br /&gt;
To make entities naturally spawn, they must be added to the spawn list for each biome that the entity should spawn in. This can be achieved with a [[Biome Modifiers#Add Spawns|&amp;lt;code&amp;gt;forge:add_spawns&amp;lt;/code&amp;gt; biome modifier]].&lt;/div&gt;</summary>
		<author><name>SizableShrimp</name></author>
	</entry>
	<entry>
		<id>https://forge.gemwire.uk/index.php?title=Making_Entities&amp;diff=3323</id>
		<title>Making Entities</title>
		<link rel="alternate" type="text/html" href="https://forge.gemwire.uk/index.php?title=Making_Entities&amp;diff=3323"/>
		<updated>2022-09-12T04:53:31Z</updated>

		<summary type="html">&lt;p&gt;SizableShrimp: Basic information about entities, entity types, and spawning&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Under construction}}&lt;br /&gt;
&lt;br /&gt;
Entities are core to the Minecraft world and make up all movable objects that do not fall under [[Making Blocks|Blocks]] or [[Block Entities]]. Entities can tick and be controlled by AI or player input. This article serves as a guide for setting up a basic entity. It does not involve setting up the rendering for an entity, which is a required step to be able to see an entity in-game without crashing. See [[Entity Renderer]] for more information on entity rendering and setup.&lt;br /&gt;
&lt;br /&gt;
== Entity Type ==&lt;br /&gt;
Much of the identity of an entity is determined by its '''entity type'''. This contains information universal to an entity. An entity type must exist and be [[Registration|registered]] for the corresponding entity to be summonable. &lt;br /&gt;
&lt;br /&gt;
=== Creating the Builder ===&lt;br /&gt;
The primary way to make an &amp;lt;code&amp;gt;EntityType&amp;lt;/code&amp;gt; is to create and configure an &amp;lt;code&amp;gt;EntityType$Builder&amp;lt;/code&amp;gt;. Creating an entity type builder is done using the static factory &amp;lt;code&amp;gt;EntityType.Builder#of&amp;lt;/code&amp;gt;. It requires two parameters: an &amp;lt;code&amp;gt;EntityType.EntityFactory&amp;lt;/code&amp;gt; and a &amp;lt;code&amp;gt;MobCategory&amp;lt;/code&amp;gt;.&lt;br /&gt;
The entity factory is usually an entity class with a constructor taking its own &amp;lt;code&amp;gt;EntityType&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;Level&amp;lt;/code&amp;gt; of the form &amp;lt;code&amp;gt;MyEntity::new&amp;lt;/code&amp;gt;. This requires a class of the name &amp;lt;code&amp;gt;MyEntity&amp;lt;/code&amp;gt; to actually exist (see [[#Entity Class|the entity class section]] for more info).&lt;br /&gt;
The mob category is an enum describing mostly spawning properties about a category of mobs. This includes:&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;How many entities in a given mob category can spawn per chunk&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Whether the entity is friendly (and therefore will spawn in peaceful difficulty)&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Whether the entity is persistent (and therefore will save to disk and be reloaded)&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;How many blocks away a player must be for an entity in a given mob category to despawn&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Configuring the Builder ===&lt;br /&gt;
An entity type builder by itself is not very useful. It must be configured to match the desired properties of the entity.&lt;br /&gt;
The possible properties that can be configured are listed below:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=1&lt;br /&gt;
! Method !! Default Value !! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;sized&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt; || 0.6 meters wide by 1.8 meters tall (player dimensions) || Sets the default pose dimensions of the entity in order of square base width then height in meters/blocks. A value of 1.0 would be equivalent to the length of 1 full block. The base cannot be configured with a separate width and length.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;noSummon&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt; || Can summon || Calling this prevents spawning the entity through &amp;lt;code&amp;gt;/summon&amp;lt;/code&amp;gt;; intended for internal entities that a user should not be able to create. This also prevents summoning through natural spawning in biomes, if it is configured.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;noSave&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt; || Can save || Calling this prevents the entity from ever saving to disk. Unloading a chunk with a &amp;lt;code&amp;gt;noSave&amp;lt;/code&amp;gt; entity will effectively delete the entity.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;fireImmune&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt; || Vulnerable to fire || Calling this prevents the entity from taking any fire/lava damage.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;clientTrackingRange&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt; || 5 chunks || Sets the maximum range in chunks in which players should be sent update packet information about the entity. Sending update information about an entity to a player is known as the player ''tracking'' that entity. If the player is outside this chunk range, they will not know of the entity's existence.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;immuneTo&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt; || Empty set of blocks || Effectively useless for modding purposes.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;canSpawnFarFromPlayer&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt; || True for &amp;lt;code&amp;gt;MobCategory.CREATURE&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;MobCategory.MISC&amp;lt;/code&amp;gt;, false otherwise. || Calling this allows an entity to spawn outside of the despawn distance of its mob category.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;updateInterval&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt; || 3 ticks || How often, in ticks, update packets should be sent to all client players tracking this entity (see &amp;lt;code&amp;gt;clientTrackingRange&amp;lt;/code&amp;gt;). The update packets contain information like position, rotation, and velocity. They may be sent more quickly than this interval during specific actions.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;setShouldReceiveVelocityUpdates&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt; || true || Sets whether tracking client players should receive velocity information in update interval packets. If false, velocity information will not be sent to clients unless necessary.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Building the Builder ===&lt;br /&gt;
After creating and configuring the entity type builder, it must be built. This requires the modid and name of the entity type. For an entity type with the name &amp;quot;example_monster&amp;quot; in the mod &amp;quot;examplemod&amp;quot;, this would look like &amp;lt;code&amp;gt;builder.build(&amp;quot;examplemod:example_monster&amp;quot;)&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Tying It Together ===&lt;br /&gt;
Given the above information, a basic EntityType might look like the following:&lt;br /&gt;
{{Tabs/Code Snippets&lt;br /&gt;
|java=EntityType.Builder.of(ExampleMonsterEntity::new, MobCategory.MONSTER)&lt;br /&gt;
    .sized(1.0F, 2.0F)&lt;br /&gt;
    .fireImmune()&lt;br /&gt;
    .updateInterval(1)&lt;br /&gt;
    .build(&amp;quot;examplemod:example_monster&amp;quot;)&lt;br /&gt;
}}&lt;br /&gt;
To function, this example requires that an entity class of the name &amp;lt;code&amp;gt;ExampleMonsterEntity&amp;lt;/code&amp;gt; exist along with the entity type being [[Registration|registered]].&lt;br /&gt;
&lt;br /&gt;
== Entity Class ==&lt;br /&gt;
Alongside an entity type, an entity requires a class outlining its behavior and any information that may change from one instance to another. All entities must extend from the base class &amp;lt;code&amp;gt;Entity&amp;lt;/code&amp;gt;. However, some entities should extend from specific subclasses instead. For a completely generic entity, use &amp;lt;code&amp;gt;Entity&amp;lt;/code&amp;gt;. For a living entity with health, potion effects, and an inventory, use &amp;lt;code&amp;gt;LivingEntity&amp;lt;/code&amp;gt;. For a living entity with movement AI and AI goals, use &amp;lt;code&amp;gt;Mob&amp;lt;/code&amp;gt;. There are also many other entity subclasses which can be found through your IDE and picked depending on the scenario.&lt;br /&gt;
&lt;br /&gt;
Once picking a target superclass to extend, an entity class should be created and the constructor should be setup. It should look something like this:&lt;br /&gt;
{{Tabs/Code Snippets|&lt;br /&gt;
java=public class ExampleMonsterEntity extends Mob {&lt;br /&gt;
    public ExampleMonsterEntity(EntityType&amp;lt;? extends Mob&amp;gt; entityType, Level level) {&lt;br /&gt;
        super(entityType, level);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
To define custom behavior, methods must be overriden. Your IDE should have a feature to list all possible methods to override, although some common ones might be: &amp;lt;code&amp;gt;customServerAiStep&amp;lt;/code&amp;gt; for server AI, &amp;lt;code&amp;gt;tick&amp;lt;/code&amp;gt; for code to execute each tick on client/server, and &amp;lt;code&amp;gt;registerGoals&amp;lt;/code&amp;gt; to setup AI goals.&lt;br /&gt;
&lt;br /&gt;
== Natural Spawning ==&lt;br /&gt;
To make entities naturally spawn, they must be added to the spawn list for each biome that the entity should spawn in. This can be achieved with a [[Biome_Modifiers#Add_Spawns|&amp;lt;code&amp;gt;forge:add_spawns&amp;lt;/code&amp;gt; biome modifier]].&lt;/div&gt;</summary>
		<author><name>SizableShrimp</name></author>
	</entry>
	<entry>
		<id>https://forge.gemwire.uk/index.php?title=Biome_Modifier&amp;diff=3322</id>
		<title>Biome Modifier</title>
		<link rel="alternate" type="text/html" href="https://forge.gemwire.uk/index.php?title=Biome_Modifier&amp;diff=3322"/>
		<updated>2022-09-12T04:45:35Z</updated>

		<summary type="html">&lt;p&gt;SizableShrimp: Redirected page to Biome Modifiers&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;#REDIRECT [[Biome Modifiers]]&lt;/div&gt;</summary>
		<author><name>SizableShrimp</name></author>
	</entry>
	<entry>
		<id>https://forge.gemwire.uk/index.php?title=Registration&amp;diff=3321</id>
		<title>Registration</title>
		<link rel="alternate" type="text/html" href="https://forge.gemwire.uk/index.php?title=Registration&amp;diff=3321"/>
		<updated>2022-09-08T17:06:38Z</updated>

		<summary type="html">&lt;p&gt;SizableShrimp: Some improvements of changes in 1.19; skimmed&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Registration is the process of making an object (such as an item or block) known to the game during runtime with an attached &amp;lt;code&amp;gt;ResourceLocation&amp;lt;/code&amp;gt; name. Unregistered objects are a likely cause of game loading crashes or bugs, so it is important to register objects correctly.&lt;br /&gt;
&lt;br /&gt;
Most objects that are known within the game are handled by a Vanilla &amp;lt;code&amp;gt;Registry&amp;lt;/code&amp;gt; or a Forge &amp;lt;code&amp;gt;IForgeRegistry&amp;lt;/code&amp;gt;. Each registry uniquely defines each of its own objects through a &amp;quot;registry name&amp;quot; via a [[Using Resources#ResourceLocation|ResourceLocation]].&lt;br /&gt;
Registries themselves have a name and are registered to the Vanilla root registry or &amp;lt;code&amp;gt;RegistryManager&amp;lt;/code&amp;gt;.&lt;br /&gt;
It is important to keep these distinct; although both are called registry names.&lt;br /&gt;
&lt;br /&gt;
{{Tip|In a global context, each object is universally unique through its &amp;lt;code&amp;gt;ResourceKey&amp;lt;/code&amp;gt;: a concatenation of its registry's id and the object's registry name.}}&lt;br /&gt;
&lt;br /&gt;
Forge expands Vanilla's registries to add important features for modded environments, such as world saving of integer ids and network syncing of integer ids, to ensure consistency when different mods and entries are present.&lt;br /&gt;
&lt;br /&gt;
Forge registries preserves the same loading order of Vanilla registries, with all modded registries fired after Vanilla in alphabetical order by string comparing namespace then path. This loading order determines what order registries have their entries registered. All registries wrapped by Forge can be found within the &amp;lt;code&amp;gt;ForgeRegistries&amp;lt;/code&amp;gt; class.&lt;br /&gt;
&lt;br /&gt;
{{Tip|All registries have their own set of names and objects, so the same name (e.g. &amp;lt;code&amp;gt;examplemod:object&amp;lt;/code&amp;gt;) can be reused in multiple registries, like blocks and items.}}&lt;br /&gt;
&lt;br /&gt;
{{Tip/Warning|If two registry objects within the '''same''' registry have the same name, the second object will override the first.}}&lt;br /&gt;
&lt;br /&gt;
== Methods for Registering ==&lt;br /&gt;
&lt;br /&gt;
There are two proper ways to register objects to a Forge registry or Vanilla registry: the &amp;lt;code&amp;gt;DeferredRegister&amp;lt;/code&amp;gt; class, and the &amp;lt;code&amp;gt;RegisterEvent&amp;lt;/code&amp;gt; lifecycle event.&lt;br /&gt;
&lt;br /&gt;
=== DeferredRegister ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;DeferredRegister&amp;lt;/code&amp;gt; is an abstraction layer over the registry event used to register objects. It maintains a map of &amp;quot;registry name&amp;quot; to their associated suppliers and resolves those suppliers during &amp;lt;code&amp;gt;RegisterEvent&amp;lt;/code&amp;gt; for the associated registry. This method is the currently recommended, and documented, way to handle these objects as it provides convenience and safety for those who want to statically initialize objects while avoiding some issues associated with it.&lt;br /&gt;
&lt;br /&gt;
{{Tip/Important|When using &amp;lt;code&amp;gt;DeferredRegister&amp;lt;/code&amp;gt;s with non-vanilla registries, the registry key or the registry name should be supplied to the &amp;lt;code&amp;gt;create&amp;lt;/code&amp;gt; method. These include the custom Forge registries for entity data serializers, global loot modifier serializers, world presets, and biome modifier serializers. Calling &amp;lt;code&amp;gt;Supplier#get&amp;lt;/code&amp;gt; on a &amp;lt;code&amp;gt;Supplier&amp;lt;IForgeRegistry&amp;lt;?&amp;gt;&amp;gt;&amp;lt;/code&amp;gt; when making a DeferredRegister will return null because the registry does not exist yet.}}&lt;br /&gt;
&lt;br /&gt;
An example of a mod registering a custom block:&lt;br /&gt;
&lt;br /&gt;
{{Template:Tabs/Code_Snippets&lt;br /&gt;
|java=private static final DeferredRegister&amp;lt;Block&amp;gt; BLOCKS = DeferredRegister.create(ForgeRegistries.BLOCKS, MODID);&lt;br /&gt;
&lt;br /&gt;
public static final RegistryObject&amp;lt;Block&amp;gt; EXAMPLE_BLOCK = BLOCKS.register(&amp;quot;example_block&amp;quot;, () -&amp;gt; new Block(BlockBehaviour.Properties.of(Material.STONE)));&lt;br /&gt;
&lt;br /&gt;
public ExampleMod() {&lt;br /&gt;
    BLOCKS.register(FMLJavaModLoadingContext.get().getModEventBus());&lt;br /&gt;
}&lt;br /&gt;
|kotlin=private val BLOCKS = DeferredRegister.create(ForgeRegistries.BLOCKS, MODID)&lt;br /&gt;
&lt;br /&gt;
val EXAMPLE_BLOCK: RegistryObject&amp;lt;Block&amp;gt; = BLOCKS.register(&amp;quot;example_block&amp;quot;) { Block(BlockBehaviour.Properties.of(Material.ROCK)) }&lt;br /&gt;
&lt;br /&gt;
internal class ExampleMod {&lt;br /&gt;
    init {&lt;br /&gt;
        BLOCKS.register(FMLJavaModLoadingContext.get().modEventBus)&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
|scala=object ExampleMod {&lt;br /&gt;
    private final val BLOCKS = DeferredRegister.create(ForgeRegistries.BLOCKS, MODID)&lt;br /&gt;
&lt;br /&gt;
    final val EXAMPLE_BLOCK = registerBlock(&amp;quot;example_block&amp;quot;, () =&amp;gt; new Block(BlockBehaviour.Properties.of(Material.ROCK)))&lt;br /&gt;
}&lt;br /&gt;
class ExampleMod {&lt;br /&gt;
    BLOCKS.register(FMLJavaModLoadingContext.get.getModEventBus)&lt;br /&gt;
}&lt;br /&gt;
|groovy=private static final DeferredRegister&amp;lt;Block&amp;gt; BLOCKS = DeferredRegister.create(ForgeRegistries.BLOCKS, MODID);&lt;br /&gt;
&lt;br /&gt;
public static final RegistryObject&amp;lt;Block&amp;gt; EXAMPLE_BLOCK = BLOCKS.register(&amp;quot;example_block&amp;quot;, () -&amp;gt; new Block(BlockBehaviour.Properties.of(Material.STONE)));&lt;br /&gt;
&lt;br /&gt;
ExampleMod() {&lt;br /&gt;
    BLOCKS.register(FMLJavaModLoadingContext.get().modEventBus);&lt;br /&gt;
}&lt;br /&gt;
|}}&lt;br /&gt;
&lt;br /&gt;
{{Tip|When using a &amp;lt;code&amp;gt;DeferredRegister&amp;lt;/code&amp;gt; to register any object, the name inputted will be automatically prefixed with the mod id passed in, giving the above object a &amp;quot;registry name&amp;quot; of &amp;lt;code&amp;gt;examplemod:example_block&amp;lt;/code&amp;gt;.}}&lt;br /&gt;
&lt;br /&gt;
=== RegisterEvent ===&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;RegisterEvent&amp;lt;/code&amp;gt; is the second way register objects. This [[Events|event]] is fired for each registry synchronously in vanilla registry order after &amp;lt;code&amp;gt;FMLConstructModEvent&amp;lt;/code&amp;gt; and before the configs are loaded. Objects are registered using &amp;lt;code&amp;gt;#register&amp;lt;/code&amp;gt; by passing in the registry key, the name of the registry object, and the object itself. There is an additional &amp;lt;code&amp;gt;#register&amp;lt;/code&amp;gt; overload which takes in a consumed helper to register an object with a given name. It is recommended to use this method to avoid unnecessary object creation.&lt;br /&gt;
&lt;br /&gt;
Here is an example: (the event handler is registered on the '''mod event bus''')&lt;br /&gt;
&lt;br /&gt;
{{Template:Tabs/Code_Snippets&lt;br /&gt;
|java=@SubscribeEvent&lt;br /&gt;
public void register(RegisterEvent event) {&lt;br /&gt;
    event.register(ForgeRegistries.Keys.BLOCKS,&lt;br /&gt;
        helper -&amp;gt; helper.register(new ResourceLocation(MODID, &amp;quot;example_block&amp;quot;), new Block(...))&lt;br /&gt;
    );&lt;br /&gt;
}&lt;br /&gt;
|kotlin=@JvmStatic&lt;br /&gt;
@SubscribeEvent&lt;br /&gt;
private fun register(event: RegisterEvent) =&lt;br /&gt;
    event.register(ForgeRegistries.Keys.BLOCKS) {&lt;br /&gt;
        helper -&amp;gt; helper.register(ResourceLocation(MODID, &amp;quot;example_block&amp;quot;), Block(...))&lt;br /&gt;
    }&lt;br /&gt;
|scala=@SubscribeEvent&lt;br /&gt;
def register(event: RegisterEvent): Unit =&lt;br /&gt;
    event.register(ForgeRegistries.Keys.BLOCKS,&lt;br /&gt;
        helper =&amp;gt; helper.register(new ResourceLocation(MODID, &amp;quot;example_block&amp;quot;), new Block(...))&lt;br /&gt;
    )&lt;br /&gt;
|}}&lt;br /&gt;
&lt;br /&gt;
{{Tip/Important|Since all objects registered must be singleton, some classes cannot by themselves be registered. Instead, &amp;lt;code&amp;gt;*Type&amp;lt;/code&amp;gt; classes are registered and used in the formers' constructors to wrap the flyweight objects. For example, a [[Basics_of_Block_Entities|&amp;lt;code&amp;gt;BlockEntity&amp;lt;/code&amp;gt;]] is wrapped via &amp;lt;code&amp;gt;BlockEntityType&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;Entity&amp;lt;/code&amp;gt; is wrapped via &amp;lt;code&amp;gt;EntityType&amp;lt;/code&amp;gt;. These &amp;lt;code&amp;gt;*Type&amp;lt;/code&amp;gt; classes hold factories that simply create the containing type on demand.&lt;br /&gt;
&lt;br /&gt;
These factory holders are created through the use of their &amp;lt;code&amp;gt;*Type$Builder&amp;lt;/code&amp;gt; classes. An example: (&amp;lt;code&amp;gt;REGISTER&amp;lt;/code&amp;gt; here refers to a &amp;lt;code&amp;gt;DeferredRegister&amp;lt;BlockEntityType&amp;lt;?&amp;gt;&amp;gt;&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
{{Template:Tabs/Code_Snippets&lt;br /&gt;
|java=public static final RegistryObject&amp;lt;BlockEntityType&amp;lt;ExampleBlockEntity&amp;gt;&amp;gt; EXAMPLE_BLOCK_ENTITY = REGISTER.register(&lt;br /&gt;
    &amp;quot;example_block_entity&amp;quot;, () -&amp;gt; BlockEntityType.Builder.of(ExampleBlockEntity::new, EXAMPLE_BLOCK.get()).build(null)&lt;br /&gt;
);&lt;br /&gt;
|kotlin=val EXAMPLE_BLOCK_ENTITY: RegistryObject&amp;lt;BlockEntityType&amp;lt;ExampleBlockEntity&amp;gt;&amp;gt; = REGISTER.register(&amp;quot;example_block_entity&amp;quot;) { BlockEntityType.Builder.of(::ExampleBlockEntity, EXAMPLE_BLOCK.get()).build(null)) }&lt;br /&gt;
|scala=final val EXAMPLE_BLOCK_ENTITY = REGISTER.register(&amp;quot;example_block_entity&amp;quot;, () =&amp;gt; BlockEntityType.Builder.of(() =&amp;gt; new ExampleBlockEntity(), GeneralRegistrar.EXAMPLE_BLOCK.get).build(null))&lt;br /&gt;
|}}&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
=== Non-Forge Registries ===&lt;br /&gt;
&lt;br /&gt;
Not all vanilla registries are wrapped as a Forge registry. To register objects to any one of these registries, create a &amp;lt;code&amp;gt;DeferredRegister&amp;lt;/code&amp;gt; via the &amp;lt;code&amp;gt;#create&amp;lt;/code&amp;gt; overload which takes in a resource key of the registry and the mod id to register the entries for. Then simply call &amp;lt;code&amp;gt;#register&amp;lt;/code&amp;gt; like any other &amp;lt;code&amp;gt;DeferredRegister&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
{{Template:Tabs/Code_Snippets&lt;br /&gt;
|java=private static final DeferredRegister&amp;lt;LootItemConditionType&amp;gt; REGISTER = DeferredRegister.create(Registry.LOOT_ITEM_REGISTRY, MODID);&lt;br /&gt;
&lt;br /&gt;
public static final RegistryObject&amp;lt;LootItemConditionType&amp;gt; EXAMPLE_LOOT_ITEM_CONDITION_TYPE = REGISTER.register(&amp;quot;example_loot_item_condition_type&amp;quot;, () -&amp;gt; new LootItemConditionType(...));&lt;br /&gt;
|kotlin=private val REGISTER = DeferredRegister.create(Registry.LOOT_ITEM_REGISTRY, MODID)&lt;br /&gt;
&lt;br /&gt;
val EXAMPLE_LOOT_ITEM_CONDITION_TYPE : RegistryObject&amp;lt;LootItemConditionType&amp;gt; = REGISTER.register(&amp;quot;example_loot_item_condition_type&amp;quot;) {&lt;br /&gt;
    LootItemConditionType(...)&lt;br /&gt;
}&lt;br /&gt;
|scala=private final val REGISTER = DeferredRegister.create(Registry.LOOT_ITEM_REGISTRY, MODID)&lt;br /&gt;
&lt;br /&gt;
final val EXAMPLE_LOOT_ITEM_CONDITION_TYPE = REGISTER.register(&amp;quot;example_loot_item_condition_type&amp;quot;, () =&amp;gt; new LootItemConditionType(...))&lt;br /&gt;
|groovy=private static final DeferredRegister&amp;lt;LootItemConditionType&amp;gt; REGISTER = DeferredRegister.create(Registry.LOOT_ITEM_REGISTRY, MODID);&lt;br /&gt;
&lt;br /&gt;
public static final RegistryObject&amp;lt;LootItemConditionType&amp;gt; EXAMPLE_LOOT_ITEM_CONDITION_TYPE = REGISTER.register(&amp;quot;example_loot_item_condition_type&amp;quot;, () -&amp;gt; new LootItemConditionType(...));&lt;br /&gt;
|}}&lt;br /&gt;
&lt;br /&gt;
If you attempt to make one of these instances require an instance of another registry object, you should use the lazy initialization method mentioned above to register the object in the correct order.&lt;br /&gt;
&lt;br /&gt;
=== Data Driven Entries ===&lt;br /&gt;
&lt;br /&gt;
Registries are considered to be data driven if they are located within &amp;lt;code&amp;gt;RegistryAccess&amp;lt;/code&amp;gt; with the exception of &amp;lt;code&amp;gt;LevelStem&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;Level&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
These registry objects only need to be registered within code if they are to be used within a pre-existing registry object (e.g. a &amp;lt;code&amp;gt;PlacedFeature&amp;lt;/code&amp;gt; for ore generation within an overworld &amp;lt;code&amp;gt;Biome&amp;lt;/code&amp;gt;). Otherwise, their instance can be purely registered using a JSON file.&lt;br /&gt;
&lt;br /&gt;
If a data driven registry object has to be registered within code, a dummy object should be supplied to hold a &amp;quot;registry name&amp;quot; and then constructed within a JSON file.&lt;br /&gt;
&lt;br /&gt;
== Referencing Registered Objects ==&lt;br /&gt;
&lt;br /&gt;
Each forge registered object should not be statically initialized nor reference another instance being registered. They must always be a new, singleton instance that is resolved during when &amp;lt;code&amp;gt;RegisterEvent&amp;lt;/code&amp;gt; is called for their registry. This is to maintain a sane loading order for registries and their objects along with dynamic loading/unloading of mods.&lt;br /&gt;
&lt;br /&gt;
Forge registered objects must always be referenced through a &amp;lt;code&amp;gt;RegistryObject&amp;lt;/code&amp;gt; or a field with &amp;lt;code&amp;gt;@ObjectHolder&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
===Using RegistryObjects===&lt;br /&gt;
&amp;lt;code&amp;gt;RegistryObject&amp;lt;/code&amp;gt;s can be used to retrieve references to registered objects once they become available. Their references are updated along with all &amp;lt;code&amp;gt;@ObjectHolder&amp;lt;/code&amp;gt; annotations after the registry that &amp;lt;code&amp;gt;RegisterEvent&amp;lt;/code&amp;gt; is called for is dispatched and frozen.&lt;br /&gt;
&lt;br /&gt;
A &amp;lt;code&amp;gt;RegistryObject&amp;lt;/code&amp;gt; can be retrieved as a result of using &amp;lt;code&amp;gt;DeferredRegister&amp;lt;/code&amp;gt; or calling the static factory &amp;lt;code&amp;gt;RegistryObject#create&amp;lt;/code&amp;gt;. Each static factory takes in the &amp;quot;registry name&amp;quot; of the object being referenced and one of the following: a &amp;lt;code&amp;gt;IForgeRegistry&amp;lt;/code&amp;gt;, a registry name of the type &amp;lt;code&amp;gt;ResourceLocation&amp;lt;/code&amp;gt;, or a registry key of the type &amp;lt;code&amp;gt;ResourceKey&amp;lt;? extends Registry&amp;lt;?&amp;gt;&amp;gt;&amp;lt;/code&amp;gt;. The &amp;lt;code&amp;gt;RegistryObject&amp;lt;/code&amp;gt; can be stored within some field and retrieve the registered object using &amp;lt;code&amp;gt;#get&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
An example using &amp;lt;code&amp;gt;RegistryObject&amp;lt;/code&amp;gt;:&lt;br /&gt;
{{Template:Tabs/Code_Snippets&lt;br /&gt;
|java=public static final RegistryObject&amp;lt;Item&amp;gt; EXAMPLE_ITEM = RegistryObject.create(new ResourceLocation(&amp;quot;examplemod&amp;quot;, &amp;quot;example_item&amp;quot;), ForgeRegistries.ITEMS);&lt;br /&gt;
&lt;br /&gt;
// Assume that 'examplemod:example_registry' is a valid registry, and 'examplemod:example_object' is a valid object within that registry&lt;br /&gt;
public static final RegistryObject&amp;lt;ExampleRegistry&amp;gt; EXAMPLE_OBJECT = RegistryObject.create(new ResourceLocation(&amp;quot;examplemod&amp;quot;, &amp;quot;example_object&amp;quot;), new ResourceLocation(&amp;quot;examplemod&amp;quot;, &amp;quot;example_registry&amp;quot;), &amp;quot;examplemod&amp;quot;); &lt;br /&gt;
|kotlin=val EXAMPLE_ITEM: RegistryObject&amp;lt;Item&amp;gt; = RegistryObject.create(ResourceLocation(&amp;quot;examplemod&amp;quot;, &amp;quot;example_item&amp;quot;), ForgeRegistries.ITEMS)&lt;br /&gt;
&lt;br /&gt;
// Assume that 'examplemod:example_registry' is a valid registry, and 'examplemod:example_object' is a valid object within that registry&lt;br /&gt;
val EXAMPLE_OBJECT: RegistryObject&amp;lt;ExampleRegistry&amp;gt; = RegistryObject.create(ResourceLocation(&amp;quot;examplemod&amp;quot;, &amp;quot;example_object&amp;quot;), new ResourceLocation(&amp;quot;examplemod&amp;quot;, &amp;quot;example_registry&amp;quot;), &amp;quot;examplemod&amp;quot;)&lt;br /&gt;
|scala=final val EXAMPLE_ITEM = RegistryObject.create(new ResourceLocation(&amp;quot;examplemod&amp;quot;, &amp;quot;example_item&amp;quot;), ForgeRegistries.ITEMS)&lt;br /&gt;
&lt;br /&gt;
// Assume that 'examplemod:example_registry' is a valid registry, and 'examplemod:example_object' is a valid object within that registry&lt;br /&gt;
final val EXAMPLE_OBJECT = RegistryObject.create(new ResourceLocation(&amp;quot;examplemod&amp;quot;, &amp;quot;example_object&amp;quot;), new ResourceLocation(&amp;quot;examplemod&amp;quot;, &amp;quot;example_registry&amp;quot;), &amp;quot;examplemod&amp;quot;); &lt;br /&gt;
|}}&lt;br /&gt;
&lt;br /&gt;
{{Tip/Important|All vanilla objects are bootstrapped and registered before mods are loaded. As such, they can be referenced as is without any issues.}}&lt;br /&gt;
&lt;br /&gt;
=== Using @ObjectHolder ===&lt;br /&gt;
&lt;br /&gt;
Forge registry objects can also be injected into &amp;lt;code&amp;gt;public static final&amp;lt;/code&amp;gt; fields by annotating each field with &amp;lt;code&amp;gt;@ObjectHolder&amp;lt;/code&amp;gt;. Note that using &amp;lt;code&amp;gt;RegistryObject&amp;lt;/code&amp;gt;s is the preferred strategy as ObjectHolders are verbose, clunky, and easy to mess up.&lt;br /&gt;
&lt;br /&gt;
ObjectHolders can only be applied to fields and require 2 pieces of information: the registry name of your target registry and the name of your object entry inside the registry.&lt;br /&gt;
&lt;br /&gt;
The registry name can be found inside of &amp;lt;code&amp;gt;ForgeRegistries.Keys&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;Registry&amp;lt;/code&amp;gt;.&lt;br /&gt;
For blocks, this would be &amp;lt;code&amp;gt;&amp;quot;minecraft:block&amp;quot;&amp;lt;/code&amp;gt;.&lt;br /&gt;
For items, this would be &amp;lt;code&amp;gt;&amp;quot;minecraft:item&amp;quot;&amp;lt;/code&amp;gt;, etc.&lt;br /&gt;
&lt;br /&gt;
The name of your entry is dependent on what you called it and requires your modid to be prefixed.&lt;br /&gt;
When using &amp;lt;code&amp;gt;@ObjectHolder&amp;lt;/code&amp;gt; inside of your main mod class annotated with &amp;lt;code&amp;gt;@Mod&amp;lt;/code&amp;gt;, the modid namespace can be omitted.&lt;br /&gt;
&lt;br /&gt;
The rules for &amp;lt;code&amp;gt;@ObjectHolder&amp;lt;/code&amp;gt; are as follows:&lt;br /&gt;
&lt;br /&gt;
* If the class is annotated with &amp;lt;code&amp;gt;@Mod&amp;lt;/code&amp;gt;, the modid will be the default namespace for all annotated fields within if not explicitly defined &lt;br /&gt;
* A field is considered for injection if:&lt;br /&gt;
** it has at least the modifiers &amp;lt;code&amp;gt;public static&amp;lt;/code&amp;gt; and optionally &amp;lt;code&amp;gt;final&amp;lt;/code&amp;gt;, and&lt;br /&gt;
** the '''field''' is annotated with &amp;lt;code&amp;gt;@ObjectHolder&amp;lt;/code&amp;gt;, and:&lt;br /&gt;
*** the entry name value is explicitly defined, and&lt;br /&gt;
*** the registry name value is explicitly defined&lt;br /&gt;
* ''An exception is thrown if the resulting &amp;lt;code&amp;gt;ResourceLocation&amp;lt;/code&amp;gt; is incomplete or invalid (non-valid characters in path)''&lt;br /&gt;
* If no other errors or exceptions occur, the field will be injected&lt;br /&gt;
* If all of the above rules do not apply, no action will be taken (and a message may be logged)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;@ObjectHolder&amp;lt;/code&amp;gt; annotated fields are injected with their associated object values after &amp;lt;code&amp;gt;RegisterEvent&amp;lt;/code&amp;gt; is fired for their registry, the same time that &amp;lt;code&amp;gt;RegistryObject&amp;lt;/code&amp;gt;s are filled. ObjectHolders will remain empty if the associated registry does not exist.&lt;br /&gt;
&lt;br /&gt;
{{Tip/Warning|If the object does not exist in the registry when it is to be injected, a debug message will be logged, and no value will be injected. If the object is found, but the field cannot be set, a warning message will be logged instead.}}&lt;br /&gt;
&lt;br /&gt;
As these rules are rather complicated, here are some examples:&lt;br /&gt;
&amp;lt;div class=&amp;quot;mw-collapsible mw-collapsed&amp;quot; style=&amp;quot;border: solid 2px; padding: 2px 5px; margin-top: 3px&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;div style=&amp;quot;font-weight:bold;line-height:1.6;&amp;quot;&amp;gt;Example uses of &amp;lt;code&amp;gt;@ObjectHolder&amp;lt;/code&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;div class=&amp;quot;mw-collapsible-content&amp;quot; style=&amp;quot;overflow: auto; white-space: nowrap;&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
class Holder {&lt;br /&gt;
    @ObjectHolder(registryName = &amp;quot;minecraft:enchantment&amp;quot;, value = &amp;quot;minecraft:flame&amp;quot;)&lt;br /&gt;
    public static final Enchantment flame = null;     // Annotation present. [public static] is required. [final] is optional.&lt;br /&gt;
                                                      // Registry name is explicitly defined: &amp;quot;minecraft:enchantment&amp;quot;&lt;br /&gt;
                                                      // Resource location is explicitly defined: &amp;quot;minecraft:flame&amp;quot;&lt;br /&gt;
                                                      // To inject: &amp;quot;minecraft:flame&amp;quot; from the [Enchantment] registry&lt;br /&gt;
&lt;br /&gt;
    public static final Biome ice_flat = null;        // No annotation on the field.&lt;br /&gt;
                                                      // Therefore, the field is ignored.&lt;br /&gt;
&lt;br /&gt;
    @ObjectHolder(&amp;quot;minecraft:creeper&amp;quot;)&lt;br /&gt;
    public static final Entity creeper = null;        // Annotation present. [public static] is required. [final] is optional.&lt;br /&gt;
                                                      // The registry name has not been specified on the field.&lt;br /&gt;
                                                      // Therefore, this will not compile.&lt;br /&gt;
&lt;br /&gt;
    @ObjectHolder(registryName = &amp;quot;minecraft:potion&amp;quot;)&lt;br /&gt;
    public static final Potion levitation = null;     // Annotation present. [public static] is required. [final] is optional.&lt;br /&gt;
                                                      // Registry name is explicitly defined: &amp;quot;minecraft:potion&amp;quot;&lt;br /&gt;
                                                      // The entry's name value has not been specified on the field.&lt;br /&gt;
                                                      // Therefore, this will not compile.&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Creating Custom Registries ==&lt;br /&gt;
&lt;br /&gt;
Creating custom registries for your mod might be useful if you want other mods to add new things to your system. For example, you might have magic spells and want to allow other mods to add new spells. For this you will want to make a registry (eg. &amp;quot;mymagicmod:spells&amp;quot;). This way, other mods will be able to register things to that list, and you won't have to do anything else.&lt;br /&gt;
&lt;br /&gt;
Just like with registering a new item or block you have two ways of making a new registry. Each method takes in a &amp;lt;code&amp;gt;RegistryBuilder&amp;lt;/code&amp;gt; which is used to build an &amp;lt;code&amp;gt;IForgeRegistry&amp;lt;/code&amp;gt;. Each builder should have its name set via &amp;lt;code&amp;gt;#setName&amp;lt;/code&amp;gt; before being created.&lt;br /&gt;
&lt;br /&gt;
=== With DeferredRegister ===&lt;br /&gt;
&lt;br /&gt;
The first method involves the second static constructor: &amp;lt;code&amp;gt;DeferredRegister#create(ResourceLocation, String)&amp;lt;/code&amp;gt;. From there, we can construct the registry using &amp;lt;code&amp;gt;#makeRegistry&amp;lt;/code&amp;gt;. This will already populate &amp;lt;code&amp;gt;#setName&amp;lt;/code&amp;gt; for us. This method also returns a supplier of the registry which we can use after the &amp;lt;code&amp;gt;NewRegistryEvent&amp;lt;/code&amp;gt; is called.&lt;br /&gt;
&lt;br /&gt;
Here is an example:&lt;br /&gt;
&lt;br /&gt;
{{Template:Tabs/Code_Snippets&lt;br /&gt;
|java=public static final DeferredRegister&amp;lt;ExampleRegistry&amp;gt; EXAMPLE = DeferredRegister.create(new ResourceLocation(MODID, &amp;quot;example_registry&amp;quot;), MODID);&lt;br /&gt;
&lt;br /&gt;
public static final Supplier&amp;lt;IForgeRegistry&amp;lt;ExampleRegistry&amp;gt;&amp;gt; REGISTRY = EXAMPLE.makeRegistry(RegistryBuilder::new);&lt;br /&gt;
|kotlin=val EXAMPLE: DeferredRegister&amp;lt;ExampleRegistry&amp;gt; = DeferredRegister.create(ResourceLocation(MODID, &amp;quot;example_registry&amp;quot;), MODID)&lt;br /&gt;
&lt;br /&gt;
val REGISTRY: IForgeRegistry&amp;lt;ExampleRegistry&amp;gt; by EXAMPLE.makeRegistry(::RegistryBuilder).let {&lt;br /&gt;
    lazy {&lt;br /&gt;
        it.get()&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
|scala=final val EXAMPLE = DeferredRegister.create(new ResourceLocation(MODID, &amp;quot;example_registry&amp;quot;), MODID)&lt;br /&gt;
&lt;br /&gt;
private final val PRIVATE_REGISTRY = EXAMPLE.makeRegistry(() =&amp;gt; new RegistryBuilder)&lt;br /&gt;
final lazy val REGISTRY = PRIVATE_REGISTRY.get&lt;br /&gt;
|}}&lt;br /&gt;
&lt;br /&gt;
=== Using &amp;lt;code&amp;gt;NewRegistryEvent&amp;lt;/code&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
The second method can be done during the &amp;lt;code&amp;gt;NewRegistryEvent&amp;lt;/code&amp;gt; event. Using &amp;lt;code&amp;gt;NewRegistryEvent#create&amp;lt;/code&amp;gt;, you can pass in a &amp;lt;code&amp;gt;RegistryBuilder&amp;lt;/code&amp;gt; directly. This method will return a &amp;lt;code&amp;gt;Supplier&amp;lt;IForgeRegistry&amp;lt;V&amp;gt;&amp;gt;&amp;lt;/code&amp;gt; that can be stored and queried after the event is fired to gain access to your &amp;lt;code&amp;gt;IForgeRegistry&amp;lt;/code&amp;gt; instance.&lt;br /&gt;
&lt;br /&gt;
Here is an example: (the event handler is registered on the '''mod event bus''')&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;Java&amp;quot;&amp;gt;&lt;br /&gt;
public static Supplier&amp;lt;IForgeRegistry&amp;lt;ExampleRegistry&amp;gt;&amp;gt; registrySupplier = null;&lt;br /&gt;
&lt;br /&gt;
@SubscribeEvent&lt;br /&gt;
public void onNewRegistry(NewRegistryEvent event){&lt;br /&gt;
    RegistryBuilder&amp;lt;ExampleRegistry&amp;gt; registryBuilder = new RegistryBuilder&amp;lt;&amp;gt;();&lt;br /&gt;
    registryBuilder.setName(new ResourceLocation(MODID, &amp;quot;example_registry&amp;quot;);&lt;br /&gt;
    registrySupplier = event.create(registryBuilder);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Handling Missing Entries ==&lt;br /&gt;
&lt;br /&gt;
When loading a pre-existing world after removing mods or updating versions, there are cases where certain registry objects will cease to exist. In these cases, it is possible to specify actions to remove a mapping, prevent the world from loading, or remap the name as needed. This can be done through the third of the registry events: &amp;lt;code&amp;gt;MissingMappingsEvent&amp;lt;/code&amp;gt;. Within the event, you can grab an immutable list of missing mappings associated with a mod id for a given registry via &amp;lt;code&amp;gt;#getMappings&amp;lt;/code&amp;gt; or a list of all mappings via &amp;lt;code&amp;gt;#getAllMappings&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
For each &amp;lt;code&amp;gt;Mapping&amp;lt;/code&amp;gt;, you can either execute one of the following methods:&lt;br /&gt;
* &amp;lt;code&amp;gt;#ignore&amp;lt;/code&amp;gt; which abandons the entry when loading&lt;br /&gt;
* &amp;lt;code&amp;gt;#warn&amp;lt;/code&amp;gt; which warns the user about the missing entry but continues loading&lt;br /&gt;
* &amp;lt;code&amp;gt;#fail&amp;lt;/code&amp;gt; which prevents the world from loading&lt;br /&gt;
* &amp;lt;code&amp;gt;#remap&amp;lt;/code&amp;gt; which remaps the entry to the specified non-null object in the same registry&lt;br /&gt;
&lt;br /&gt;
If none of the above are specified, then the default action of notifying the user about the missing mappings occur.&lt;br /&gt;
&lt;br /&gt;
Here is an example:  (the event handler is registered on the '''forge event bus''')&lt;br /&gt;
&lt;br /&gt;
{{Template:Tabs/Code_Snippets&lt;br /&gt;
|java=// This will ignore any missing test items from the specified world&lt;br /&gt;
@SubscribeEvent&lt;br /&gt;
public void onMissing(final MissingMappingsEvent event) {&lt;br /&gt;
    event.getMappings(ForgeRegistries.Keys.ITEMS, MODID).stream()&lt;br /&gt;
        .filter(mapping -&amp;gt; mapping.key.getPath().contains(&amp;quot;test&amp;quot;))&lt;br /&gt;
            .forEach(Mapping::ignore);&lt;br /&gt;
}&lt;br /&gt;
|groovy=// This will ignore any missing test items from the specified world&lt;br /&gt;
@SubscribeEvent&lt;br /&gt;
void onMissing(final MissingMappingsEvent event) {&lt;br /&gt;
    event.getMappings(ForgeRegistries.Keys.ITEMS, MODID).stream()&lt;br /&gt;
        .filter(mapping -&amp;gt; mapping.key.path.contains(&amp;quot;test&amp;quot;))&lt;br /&gt;
            .forEach(Mapping::ignore);&lt;br /&gt;
}&lt;br /&gt;
|}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Common Concepts]]&lt;/div&gt;</summary>
		<author><name>SizableShrimp</name></author>
	</entry>
	<entry>
		<id>https://forge.gemwire.uk/index.php?title=Biome_Modifiers&amp;diff=3312</id>
		<title>Biome Modifiers</title>
		<link rel="alternate" type="text/html" href="https://forge.gemwire.uk/index.php?title=Biome_Modifiers&amp;diff=3312"/>
		<updated>2022-08-16T02:16:58Z</updated>

		<summary type="html">&lt;p&gt;SizableShrimp: &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;
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;/div&gt;</summary>
		<author><name>SizableShrimp</name></author>
	</entry>
	<entry>
		<id>https://forge.gemwire.uk/index.php?title=Biome_Modifiers&amp;diff=3311</id>
		<title>Biome Modifiers</title>
		<link rel="alternate" type="text/html" href="https://forge.gemwire.uk/index.php?title=Biome_Modifiers&amp;diff=3311"/>
		<updated>2022-08-13T20:40:08Z</updated>

		<summary type="html">&lt;p&gt;SizableShrimp: /* Biome Modifier Types */&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;
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;&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;
== 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>SizableShrimp</name></author>
	</entry>
	<entry>
		<id>https://forge.gemwire.uk/index.php?title=Holder&amp;diff=3307</id>
		<title>Holder</title>
		<link rel="alternate" type="text/html" href="https://forge.gemwire.uk/index.php?title=Holder&amp;diff=3307"/>
		<updated>2022-08-13T20:31:14Z</updated>

		<summary type="html">&lt;p&gt;SizableShrimp: Redirect to Holders&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;#REDIRECT [[Holders]]&lt;/div&gt;</summary>
		<author><name>SizableShrimp</name></author>
	</entry>
	<entry>
		<id>https://forge.gemwire.uk/index.php?title=HolderSet&amp;diff=3306</id>
		<title>HolderSet</title>
		<link rel="alternate" type="text/html" href="https://forge.gemwire.uk/index.php?title=HolderSet&amp;diff=3306"/>
		<updated>2022-08-13T20:30:15Z</updated>

		<summary type="html">&lt;p&gt;SizableShrimp: Redirect to Holders#HolderSets&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;#REDIRECT [[Holders#HolderSets]]&lt;/div&gt;</summary>
		<author><name>SizableShrimp</name></author>
	</entry>
	<entry>
		<id>https://forge.gemwire.uk/index.php?title=HolderSets&amp;diff=3305</id>
		<title>HolderSets</title>
		<link rel="alternate" type="text/html" href="https://forge.gemwire.uk/index.php?title=HolderSets&amp;diff=3305"/>
		<updated>2022-08-13T20:29:28Z</updated>

		<summary type="html">&lt;p&gt;SizableShrimp: Redirect to Holders#HolderSets&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;#REDIRECT [[Holders#HolderSets]]&lt;/div&gt;</summary>
		<author><name>SizableShrimp</name></author>
	</entry>
	<entry>
		<id>https://forge.gemwire.uk/index.php?title=Holders&amp;diff=3303</id>
		<title>Holders</title>
		<link rel="alternate" type="text/html" href="https://forge.gemwire.uk/index.php?title=Holders&amp;diff=3303"/>
		<updated>2022-08-13T16:36:28Z</updated>

		<summary type="html">&lt;p&gt;SizableShrimp: /* Builtin Custom HolderSet Types */&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>SizableShrimp</name></author>
	</entry>
	<entry>
		<id>https://forge.gemwire.uk/index.php?title=Item_Overrides/1.18&amp;diff=3282</id>
		<title>Item Overrides/1.18</title>
		<link rel="alternate" type="text/html" href="https://forge.gemwire.uk/index.php?title=Item_Overrides/1.18&amp;diff=3282"/>
		<updated>2022-06-16T01:26:42Z</updated>

		<summary type="html">&lt;p&gt;SizableShrimp: Redirect to Item Properties/1.18&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;#REDIRECT [[Item Properties/1.18]]&lt;/div&gt;</summary>
		<author><name>SizableShrimp</name></author>
	</entry>
	<entry>
		<id>https://forge.gemwire.uk/index.php?title=Item_Overrides&amp;diff=3281</id>
		<title>Item Overrides</title>
		<link rel="alternate" type="text/html" href="https://forge.gemwire.uk/index.php?title=Item_Overrides&amp;diff=3281"/>
		<updated>2022-06-16T01:26:17Z</updated>

		<summary type="html">&lt;p&gt;SizableShrimp: Redirect to Item Properties&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;#REDIRECT [[Item Properties]]&lt;/div&gt;</summary>
		<author><name>SizableShrimp</name></author>
	</entry>
	<entry>
		<id>https://forge.gemwire.uk/index.php?title=Registration&amp;diff=3263</id>
		<title>Registration</title>
		<link rel="alternate" type="text/html" href="https://forge.gemwire.uk/index.php?title=Registration&amp;diff=3263"/>
		<updated>2022-06-13T00:50:13Z</updated>

		<summary type="html">&lt;p&gt;SizableShrimp: Clarify non-vanilla registries tip&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Registration is the process of making an object (such as an item or block) known to the game during runtime. If some objects are not registered, this could cause crashes even before the game is fully loaded or arbitrary behaviors such as bottlenecking mod compatibility for world generation.&lt;br /&gt;
&lt;br /&gt;
Most objects that are known within the game are handled by a &amp;lt;code&amp;gt;Registry&amp;lt;/code&amp;gt;. Each registry uniquely defines each object through a &amp;quot;registry name&amp;quot; via a [[Using Resources#ResourceLocation|ResourceLocation]].&lt;br /&gt;
&lt;br /&gt;
{{Tip|In a global context, each object is universally unique through its &amp;lt;code&amp;gt;ResourceKey&amp;lt;/code&amp;gt;: a concatenation of its registry's id and the object's registry name.}}&lt;br /&gt;
&lt;br /&gt;
Due to the inconsistent ordering and registration process vanilla uses, Forge wraps most vanilla registries using &amp;lt;code&amp;gt;IForgeRegistry&amp;lt;/code&amp;gt;. This guarantees that the loading order for these wrapped registries will be &amp;lt;code&amp;gt;Block&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;Item&amp;lt;/code&amp;gt;, and then the rest of the wrapped registries in alphabetical order. All registries supported by Forge can be found within the &amp;lt;code&amp;gt;ForgeRegistries&amp;lt;/code&amp;gt; class. Since all registry names are unique to a specific registry, different registry objects within different registries can have the same name (e.g. a &amp;lt;code&amp;gt;Block&amp;lt;/code&amp;gt; and an &amp;lt;code&amp;gt;Item&amp;lt;/code&amp;gt; each hold a registry object named &amp;lt;code&amp;gt;examplemod:object&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
{{Tip/Warning|If two registry objects within the same registry have the same name, the second object will override the first. The only registry that will throw an &amp;lt;code&amp;gt;IllegalArgumentException&amp;lt;/code&amp;gt; is the &amp;lt;code&amp;gt;DataSerializerEntry&amp;lt;/code&amp;gt; registry.}}&lt;br /&gt;
&lt;br /&gt;
== Methods for Registering ==&lt;br /&gt;
&lt;br /&gt;
There are two proper ways to register objects within an associated wrapped Forge registry: the &amp;lt;code&amp;gt;DeferredRegister&amp;lt;/code&amp;gt; class, and the &amp;lt;code&amp;gt;RegisterEvent&amp;lt;/code&amp;gt; lifecycle event.&lt;br /&gt;
&lt;br /&gt;
=== DeferredRegister ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;DeferredRegister&amp;lt;/code&amp;gt; is an abstraction layer over the registry event used to register objects. It maintains a map of &amp;quot;registry name&amp;quot; to their associated suppliers and resolves those suppliers during &amp;lt;code&amp;gt;RegisterEvent&amp;lt;/code&amp;gt; for the associated registry. This method is the currently recommended, and documented, way to handle these objects as it provides convenience and safety for those who want to statically initialize objects while avoiding some issues associated with it.&lt;br /&gt;
&lt;br /&gt;
{{Tip/Important|When using &amp;lt;code&amp;gt;DeferredRegister&amp;lt;/code&amp;gt;s with non-vanilla registries, the registry key or the registry name should be supplied to the &amp;lt;code&amp;gt;create&amp;lt;/code&amp;gt; method. These include the custom Forge registries for entity data serializers, global loot modifier serializers, world presets, and biome modifier serializers. Calling &amp;lt;code&amp;gt;Supplier#get&amp;lt;/code&amp;gt; on a &amp;lt;code&amp;gt;Supplier&amp;lt;IForgeRegistry&amp;lt;?&amp;gt;&amp;gt;&amp;lt;/code&amp;gt; when making a DeferredRegister will return null because the registry does not exist yet.}}&lt;br /&gt;
&lt;br /&gt;
An example of a mod registering a custom block:&lt;br /&gt;
&lt;br /&gt;
{{Template:Tabs/Code_Snippets&lt;br /&gt;
|java=private static final DeferredRegister&amp;lt;Block&amp;gt; BLOCKS = DeferredRegister.create(ForgeRegistries.BLOCKS, MODID);&lt;br /&gt;
&lt;br /&gt;
public static final RegistryObject&amp;lt;Block&amp;gt; EXAMPLE_BLOCK = BLOCKS.register(&amp;quot;example_block&amp;quot;, () -&amp;gt; new Block(BlockBehaviour.Properties.of(Material.STONE)));&lt;br /&gt;
&lt;br /&gt;
public ExampleMod() {&lt;br /&gt;
    BLOCKS.register(FMLJavaModLoadingContext.get().getModEventBus());&lt;br /&gt;
}&lt;br /&gt;
|kotlin=private val BLOCKS = DeferredRegister.create(ForgeRegistries.BLOCKS, MODID)&lt;br /&gt;
&lt;br /&gt;
val EXAMPLE_BLOCK: RegistryObject&amp;lt;Block&amp;gt; = BLOCKS.register(&amp;quot;example_block&amp;quot;) { Block(BlockBehaviour.Properties.of(Material.ROCK)) }&lt;br /&gt;
&lt;br /&gt;
internal class ExampleMod {&lt;br /&gt;
    init {&lt;br /&gt;
        BLOCKS.register(FMLJavaModLoadingContext.get().modEventBus)&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
|scala=object ExampleMod {&lt;br /&gt;
    private final val BLOCKS = DeferredRegister.create(ForgeRegistries.BLOCKS, MODID)&lt;br /&gt;
&lt;br /&gt;
    final val EXAMPLE_BLOCK = registerBlock(&amp;quot;example_block&amp;quot;, () =&amp;gt; new Block(BlockBehaviour.Properties.of(Material.ROCK)))&lt;br /&gt;
}&lt;br /&gt;
class ExampleMod {&lt;br /&gt;
    BLOCKS.register(FMLJavaModLoadingContext.get.getModEventBus)&lt;br /&gt;
}&lt;br /&gt;
|groovy=private static final DeferredRegister&amp;lt;Block&amp;gt; BLOCKS = DeferredRegister.create(ForgeRegistries.BLOCKS, MODID);&lt;br /&gt;
&lt;br /&gt;
public static final RegistryObject&amp;lt;Block&amp;gt; EXAMPLE_BLOCK = BLOCKS.register(&amp;quot;example_block&amp;quot;, () -&amp;gt; new Block(BlockBehaviour.Properties.of(Material.STONE)));&lt;br /&gt;
&lt;br /&gt;
ExampleMod() {&lt;br /&gt;
    BLOCKS.register(FMLJavaModLoadingContext.get().modEventBus);&lt;br /&gt;
}&lt;br /&gt;
|}}&lt;br /&gt;
&lt;br /&gt;
{{Tip|When using a &amp;lt;code&amp;gt;DeferredRegister&amp;lt;/code&amp;gt; to register any object, the name inputted will be automatically prefixed with the mod id passed in, giving the above object a &amp;quot;registry name&amp;quot; of &amp;lt;code&amp;gt;examplemod:example_block&amp;lt;/code&amp;gt;.}}&lt;br /&gt;
&lt;br /&gt;
=== RegisterEvent ===&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;RegisterEvent&amp;lt;/code&amp;gt; is the second way register objects. This [[Events|event]] is fired for each registry synchronously in vanilla registry order after &amp;lt;code&amp;gt;FMLConstructModEvent&amp;lt;/code&amp;gt; and before the configs are loaded. Objects are registered using &amp;lt;code&amp;gt;#register&amp;lt;/code&amp;gt; by passing in the registry key, the name of the registry object, and the object itself. There is an additional &amp;lt;code&amp;gt;#register&amp;lt;/code&amp;gt; overload which takes in a consumed helper to register an object with a given name. It is recommended to use this method to avoid unnecessary object creation.&lt;br /&gt;
&lt;br /&gt;
Here is an example: (the event handler is registered on the '''mod event bus''')&lt;br /&gt;
&lt;br /&gt;
{{Template:Tabs/Code_Snippets&lt;br /&gt;
|java=@SubscribeEvent&lt;br /&gt;
public void register(RegisterEvent event) {&lt;br /&gt;
    event.register(ForgeRegistries.Keys.BLOCKS,&lt;br /&gt;
        helper -&amp;gt; helper.register(new ResourceLocation(MODID, &amp;quot;example_block&amp;quot;), new Block(...))&lt;br /&gt;
    );&lt;br /&gt;
}&lt;br /&gt;
|kotlin=@JvmStatic&lt;br /&gt;
@SubscribeEvent&lt;br /&gt;
private fun register(event: RegisterEvent) =&lt;br /&gt;
    event.register(ForgeRegistries.Keys.BLOCKS) {&lt;br /&gt;
        helper -&amp;gt; helper.register(ResourceLocation(MODID, &amp;quot;example_block&amp;quot;), Block(...))&lt;br /&gt;
    }&lt;br /&gt;
|scala=@SubscribeEvent&lt;br /&gt;
def register(event: RegisterEvent): Unit =&lt;br /&gt;
    event.register(ForgeRegistries.Keys.BLOCKS,&lt;br /&gt;
        helper =&amp;gt; helper.register(new ResourceLocation(MODID, &amp;quot;example_block&amp;quot;), new Block(...))&lt;br /&gt;
    )&lt;br /&gt;
|}}&lt;br /&gt;
&lt;br /&gt;
{{Tip/Important|Since all objects registered must be singleton, some classes cannot by themselves be registered. Instead, &amp;lt;code&amp;gt;*Type&amp;lt;/code&amp;gt; classes are registered and used in the formers' constructors to wrap the flyweight objects. For example, a [[Basics_of_Block_Entities|&amp;lt;code&amp;gt;BlockEntity&amp;lt;/code&amp;gt;]] is wrapped via &amp;lt;code&amp;gt;BlockEntityType&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;Entity&amp;lt;/code&amp;gt; is wrapped via &amp;lt;code&amp;gt;EntityType&amp;lt;/code&amp;gt;. These &amp;lt;code&amp;gt;*Type&amp;lt;/code&amp;gt; classes hold factories that simply create the containing type on demand.&lt;br /&gt;
&lt;br /&gt;
These factory holders are created through the use of their &amp;lt;code&amp;gt;*Type$Builder&amp;lt;/code&amp;gt; classes. An example: (&amp;lt;code&amp;gt;REGISTER&amp;lt;/code&amp;gt; here refers to a &amp;lt;code&amp;gt;DeferredRegister&amp;lt;BlockEntityType&amp;lt;?&amp;gt;&amp;gt;&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
{{Template:Tabs/Code_Snippets&lt;br /&gt;
|java=public static final RegistryObject&amp;lt;BlockEntityType&amp;lt;ExampleBlockEntity&amp;gt;&amp;gt; EXAMPLE_BLOCK_ENTITY = REGISTER.register(&lt;br /&gt;
    &amp;quot;example_block_entity&amp;quot;, () -&amp;gt; BlockEntityType.Builder.of(ExampleBlockEntity::new, EXAMPLE_BLOCK.get()).build(null)&lt;br /&gt;
);&lt;br /&gt;
|kotlin=val EXAMPLE_BLOCK_ENTITY: RegistryObject&amp;lt;BlockEntityType&amp;lt;ExampleBlockEntity&amp;gt;&amp;gt; = REGISTER.register(&amp;quot;example_block_entity&amp;quot;) { BlockEntityType.Builder.of(::ExampleBlockEntity, EXAMPLE_BLOCK.get()).build(null)) }&lt;br /&gt;
|scala=final val EXAMPLE_BLOCK_ENTITY = REGISTER.register(&amp;quot;example_block_entity&amp;quot;, () =&amp;gt; BlockEntityType.Builder.of(() =&amp;gt; new ExampleBlockEntity(), GeneralRegistrar.EXAMPLE_BLOCK.get).build(null))&lt;br /&gt;
|}}&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
=== Non-Forge Registries ===&lt;br /&gt;
&lt;br /&gt;
Not all vanilla registries are wrapped as a Forge registry. To register objects to any one of these registries, create a &amp;lt;code&amp;gt;DeferredRegister&amp;lt;/code&amp;gt; via the &amp;lt;code&amp;gt;#create&amp;lt;/code&amp;gt; overload which takes in a resource key of the registry and the mod id to register the entries for. Then simply call &amp;lt;code&amp;gt;#register&amp;lt;/code&amp;gt; like any other &amp;lt;code&amp;gt;DeferredRegister&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
{{Template:Tabs/Code_Snippets&lt;br /&gt;
|java=private static final DeferredRegister&amp;lt;LootItemConditionType&amp;gt; REGISTER = DeferredRegister.create(Registry.LOOT_ITEM_REGISTRY, MODID);&lt;br /&gt;
&lt;br /&gt;
public static final RegistryObject&amp;lt;LootItemConditionType&amp;gt; EXAMPLE_LOOT_ITEM_CONDITION_TYPE = REGISTER.register(&amp;quot;example_loot_item_condition_type&amp;quot;, () -&amp;gt; new LootItemConditionType(...));&lt;br /&gt;
|kotlin=private val REGISTER = DeferredRegister.create(Registry.LOOT_ITEM_REGISTRY, MODID)&lt;br /&gt;
&lt;br /&gt;
val EXAMPLE_LOOT_ITEM_CONDITION_TYPE : RegistryObject&amp;lt;LootItemConditionType&amp;gt; = REGISTER.register(&amp;quot;example_loot_item_condition_type&amp;quot;) {&lt;br /&gt;
    LootItemConditionType(...)&lt;br /&gt;
}&lt;br /&gt;
|scala=private final val REGISTER = DeferredRegister.create(Registry.LOOT_ITEM_REGISTRY, MODID)&lt;br /&gt;
&lt;br /&gt;
final val EXAMPLE_LOOT_ITEM_CONDITION_TYPE = REGISTER.register(&amp;quot;example_loot_item_condition_type&amp;quot;, () =&amp;gt; new LootItemConditionType(...))&lt;br /&gt;
|groovy=private static final DeferredRegister&amp;lt;LootItemConditionType&amp;gt; REGISTER = DeferredRegister.create(Registry.LOOT_ITEM_REGISTRY, MODID);&lt;br /&gt;
&lt;br /&gt;
public static final RegistryObject&amp;lt;LootItemConditionType&amp;gt; EXAMPLE_LOOT_ITEM_CONDITION_TYPE = REGISTER.register(&amp;quot;example_loot_item_condition_type&amp;quot;, () -&amp;gt; new LootItemConditionType(...));&lt;br /&gt;
|}}&lt;br /&gt;
&lt;br /&gt;
If you attempt to make one of these instances require an instance of another registry object, you should use the lazy initialization method mentioned above to register the object in the correct order.&lt;br /&gt;
&lt;br /&gt;
=== Data Driven Entries ===&lt;br /&gt;
&lt;br /&gt;
Registries are considered to be data driven if they are located within &amp;lt;code&amp;gt;RegistryAccess&amp;lt;/code&amp;gt; with the exception of &amp;lt;code&amp;gt;LevelStem&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;Level&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
These registry objects only need to be registered within code if they are to be used within a pre-existing registry object (e.g. a &amp;lt;code&amp;gt;PlacedFeature&amp;lt;/code&amp;gt; for ore generation within an overworld &amp;lt;code&amp;gt;Biome&amp;lt;/code&amp;gt;). Otherwise, their instance can be purely registered using a JSON file.&lt;br /&gt;
&lt;br /&gt;
If a data driven registry object has to be registered within code, a dummy object should be supplied to hold a &amp;quot;registry name&amp;quot; and then constructed within a JSON file.&lt;br /&gt;
&lt;br /&gt;
== Referencing Registered Objects ==&lt;br /&gt;
&lt;br /&gt;
Each forge registered object should not be statically initialized nor reference another instance being registered. They must always be a new, singleton instance that is resolved during when &amp;lt;code&amp;gt;RegisterEvent&amp;lt;/code&amp;gt; is called for their registry. This is to maintain a sane loading order for registries and their objects along with dynamic loading/unloading of mods.&lt;br /&gt;
&lt;br /&gt;
Forge registered objects must always be referenced through a &amp;lt;code&amp;gt;RegistryObject&amp;lt;/code&amp;gt; or a field with &amp;lt;code&amp;gt;@ObjectHolder&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
===Using RegistryObjects===&lt;br /&gt;
&amp;lt;code&amp;gt;RegistryObject&amp;lt;/code&amp;gt;s can be used to retrieve references to registered objects once they become available. Their references are updated along with all &amp;lt;code&amp;gt;@ObjectHolder&amp;lt;/code&amp;gt; annotations after the registry that &amp;lt;code&amp;gt;RegisterEvent&amp;lt;/code&amp;gt; is called for is dispatched and frozen.&lt;br /&gt;
&lt;br /&gt;
A &amp;lt;code&amp;gt;RegistryObject&amp;lt;/code&amp;gt; can be retrieved as a result of using &amp;lt;code&amp;gt;DeferredRegister&amp;lt;/code&amp;gt; or calling the static factory &amp;lt;code&amp;gt;RegistryObject#create&amp;lt;/code&amp;gt;. Each static factory takes in the &amp;quot;registry name&amp;quot; of the object being referenced and one of the following: a &amp;lt;code&amp;gt;IForgeRegistry&amp;lt;/code&amp;gt;, a registry name of the type &amp;lt;code&amp;gt;ResourceLocation&amp;lt;/code&amp;gt;, or a registry key of the type &amp;lt;code&amp;gt;ResourceKey&amp;lt;? extends Registry&amp;lt;?&amp;gt;&amp;gt;&amp;lt;/code&amp;gt;. The &amp;lt;code&amp;gt;RegistryObject&amp;lt;/code&amp;gt; can be stored within some field and retrieve the registered object using &amp;lt;code&amp;gt;#get&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
An example using &amp;lt;code&amp;gt;RegistryObject&amp;lt;/code&amp;gt;:&lt;br /&gt;
{{Template:Tabs/Code_Snippets&lt;br /&gt;
|java=public static final RegistryObject&amp;lt;Item&amp;gt; EXAMPLE_ITEM = RegistryObject.create(new ResourceLocation(&amp;quot;examplemod&amp;quot;, &amp;quot;example_item&amp;quot;), ForgeRegistries.ITEMS);&lt;br /&gt;
&lt;br /&gt;
// Assume that 'examplemod:example_registry' is a valid registry, and 'examplemod:example_object' is a valid object within that registry&lt;br /&gt;
public static final RegistryObject&amp;lt;ExampleRegistry&amp;gt; EXAMPLE_OBJECT = RegistryObject.create(new ResourceLocation(&amp;quot;examplemod&amp;quot;, &amp;quot;example_object&amp;quot;), new ResourceLocation(&amp;quot;examplemod&amp;quot;, &amp;quot;example_registry&amp;quot;), &amp;quot;examplemod&amp;quot;); &lt;br /&gt;
|kotlin=val EXAMPLE_ITEM: RegistryObject&amp;lt;Item&amp;gt; = RegistryObject.create(ResourceLocation(&amp;quot;examplemod&amp;quot;, &amp;quot;example_item&amp;quot;), ForgeRegistries.ITEMS)&lt;br /&gt;
&lt;br /&gt;
// Assume that 'examplemod:example_registry' is a valid registry, and 'examplemod:example_object' is a valid object within that registry&lt;br /&gt;
val EXAMPLE_OBJECT: RegistryObject&amp;lt;ExampleRegistry&amp;gt; = RegistryObject.create(ResourceLocation(&amp;quot;examplemod&amp;quot;, &amp;quot;example_object&amp;quot;), new ResourceLocation(&amp;quot;examplemod&amp;quot;, &amp;quot;example_registry&amp;quot;), &amp;quot;examplemod&amp;quot;)&lt;br /&gt;
|scala=final val EXAMPLE_ITEM = RegistryObject.create(new ResourceLocation(&amp;quot;examplemod&amp;quot;, &amp;quot;example_item&amp;quot;), ForgeRegistries.ITEMS)&lt;br /&gt;
&lt;br /&gt;
// Assume that 'examplemod:example_registry' is a valid registry, and 'examplemod:example_object' is a valid object within that registry&lt;br /&gt;
final val EXAMPLE_OBJECT = RegistryObject.create(new ResourceLocation(&amp;quot;examplemod&amp;quot;, &amp;quot;example_object&amp;quot;), new ResourceLocation(&amp;quot;examplemod&amp;quot;, &amp;quot;example_registry&amp;quot;), &amp;quot;examplemod&amp;quot;); &lt;br /&gt;
|}}&lt;br /&gt;
&lt;br /&gt;
{{Tip/Important|All vanilla objects are bootstrapped and registered before mods are loaded. As such, they can be referenced as is without any issues.}}&lt;br /&gt;
&lt;br /&gt;
=== Using @ObjectHolder ===&lt;br /&gt;
&lt;br /&gt;
Forge registry objects can also be injected into &amp;lt;code&amp;gt;public static&amp;lt;/code&amp;gt; fields with either their class or that field annotated with &amp;lt;code&amp;gt;@ObjectHolder&amp;lt;/code&amp;gt;. There must be enough information to construct a &amp;lt;code&amp;gt;ResourceLocation&amp;lt;/code&amp;gt; to identify a single object within a specific registry.&lt;br /&gt;
&lt;br /&gt;
The rules for &amp;lt;code&amp;gt;@ObjectHolder&amp;lt;/code&amp;gt; are as follows:&lt;br /&gt;
&lt;br /&gt;
* If the class is annotated with &amp;lt;code&amp;gt;@ObjectHolder&amp;lt;/code&amp;gt;, its value will be the default namespace for all fields within if not explicitly defined&lt;br /&gt;
* If the class is annotated with &amp;lt;code&amp;gt;@Mod&amp;lt;/code&amp;gt;, the modid will be the default namespace for all annotated fields within if not explicitly defined &lt;br /&gt;
* A field is considered for injection if:&lt;br /&gt;
** it has at least the modifiers &amp;lt;code&amp;gt;public static&amp;lt;/code&amp;gt;; and&lt;br /&gt;
** one of the following conditions are true:&lt;br /&gt;
*** the '''enclosing class''' has an &amp;lt;code&amp;gt;@ObjectHolder&amp;lt;/code&amp;gt; annotation, and the field is &amp;lt;code&amp;gt;final&amp;lt;/code&amp;gt;, and:&lt;br /&gt;
**** the name value is the field's name; and&lt;br /&gt;
**** the namespace value is the enclosing class's namespace&lt;br /&gt;
**** ''An exception is thrown if the namespace value cannot be found and inherited''&lt;br /&gt;
*** the '''field''' is annotated with &amp;lt;code&amp;gt;@ObjectHolder&amp;lt;/code&amp;gt;, and:&lt;br /&gt;
**** the name value is explicitly defined; and&lt;br /&gt;
**** the namespace value is either explicitly defined or the enclosing class's namespace&lt;br /&gt;
** the field type or one of its supertypes corresponds to a valid registry (e.g. &amp;lt;code&amp;gt;Item&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;ArrowItem&amp;lt;/code&amp;gt; for the &amp;lt;code&amp;gt;Item&amp;lt;/code&amp;gt; registry)&lt;br /&gt;
** ''An exception is thrown if a field does not have a corresponding registry.''&lt;br /&gt;
* ''An exception is thrown if the resulting &amp;lt;code&amp;gt;ResourceLocation&amp;lt;/code&amp;gt; is incomplete or invalid (non-valid characters in path)''&lt;br /&gt;
* If no other errors or exceptions occur, the field will be injected&lt;br /&gt;
* If all of the above rules do not apply, no action will be taken (and a message may be logged)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;@ObjectHolder&amp;lt;/code&amp;gt; annotated fields are injected with their associated object values after &amp;lt;code&amp;gt;RegisterEvent&amp;lt;/code&amp;gt; is fired for their registry, along with &amp;lt;code&amp;gt;RegistryObject&amp;lt;/code&amp;gt;s.&lt;br /&gt;
&lt;br /&gt;
{{Tip/Warning|If the object does not exist in the registry when it is to be injected, a debug message will be logged, and no value will be injected. If the object is found, but the field cannot be set, a warning message will be logged instead.}}&lt;br /&gt;
&lt;br /&gt;
As these rules are rather complicated, here are some examples:&lt;br /&gt;
&amp;lt;div class=&amp;quot;mw-collapsible mw-collapsed&amp;quot; style=&amp;quot;border: solid 2px; padding: 2px 5px; margin-top: 3px&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;div style=&amp;quot;font-weight:bold;line-height:1.6;&amp;quot;&amp;gt;Example uses of &amp;lt;code&amp;gt;@ObjectHolder&amp;lt;/code&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;div class=&amp;quot;mw-collapsible-content&amp;quot; style=&amp;quot;overflow: auto; white-space: nowrap;&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
@ObjectHolder(&amp;quot;minecraft&amp;quot;) // Inheritable resource namespace: &amp;quot;minecraft&amp;quot;&lt;br /&gt;
class AnnotatedHolder {&lt;br /&gt;
    public static final Block diamond_block = null;   // No annotation. [public static final] is required.&lt;br /&gt;
                                                      // Block has a corresponding registry: [Block]&lt;br /&gt;
                                                      // Name path is the name of the field: &amp;quot;diamond_block&amp;quot;&lt;br /&gt;
                                                      // Namespace is not explicitly defined.&lt;br /&gt;
                                                      // So, namespace is inherited from class annotation: &amp;quot;minecraft&amp;quot;&lt;br /&gt;
                                                      // To inject: &amp;quot;minecraft:diamond_block&amp;quot; from the [Block] registry&lt;br /&gt;
&lt;br /&gt;
    @ObjectHolder(&amp;quot;ambient.cave&amp;quot;)&lt;br /&gt;
    public static SoundEvent ambient_sound = null;    // Annotation present. [public static] is required.&lt;br /&gt;
                                                      // SoundEvent has a corresponding registry: [SoundEvent]&lt;br /&gt;
                                                      // Name path is the value of the annotation: &amp;quot;ambient.cave&amp;quot;&lt;br /&gt;
                                                      // Namespace is not explicitly defined.&lt;br /&gt;
                                                      // So, namespace is inherited from class annotation: &amp;quot;minecraft&amp;quot;&lt;br /&gt;
                                                      // To inject: &amp;quot;minecraft:ambient.cave&amp;quot; from the [SoundEvent] registry&lt;br /&gt;
&lt;br /&gt;
    // Assume for the next entry that [ManaType] is a valid registry.          &lt;br /&gt;
    @ObjectHolder(&amp;quot;neomagicae:coffeinum&amp;quot;)&lt;br /&gt;
    public static final ManaType coffeinum = null;    // Annotation present. [public static] is required. [final] is optional.&lt;br /&gt;
                                                      // ManaType has a corresponding registry: [ManaType] (custom registry)&lt;br /&gt;
                                                      // Resource location is explicitly defined: &amp;quot;neomagicae:coffeinum&amp;quot;&lt;br /&gt;
                                                      // To inject: &amp;quot;neomagicae:coffeinum&amp;quot; from the [ManaType] registry&lt;br /&gt;
&lt;br /&gt;
    public static final Item ENDER_PEARL = null;      // No annotation. [public static final] is required.&lt;br /&gt;
                                                      // Item has a corresponding registry: [Item].&lt;br /&gt;
                                                      // Name path is the name of the field: &amp;quot;ENDER_PEARL&amp;quot; -&amp;gt; &amp;quot;ender_pearl&amp;quot;&lt;br /&gt;
                                                      // !! ^ Field name is valid, because they are&lt;br /&gt;
                                                      //      converted to lowercase automatically.&lt;br /&gt;
                                                      // Namespace is not explicitly defined.&lt;br /&gt;
                                                      // So, namespace is inherited from class annotation: &amp;quot;minecraft&amp;quot;&lt;br /&gt;
                                                      // To inject: &amp;quot;minecraft:ender_pearl&amp;quot; from the [Item] registry&lt;br /&gt;
&lt;br /&gt;
    @ObjectHolder(&amp;quot;minecraft:arrow&amp;quot;)&lt;br /&gt;
    public static final ArrowItem arrow = null;       // Annotation present. [public static] is required. [final] is optional.&lt;br /&gt;
                                                      // ArrowItem does not have a corresponding registry.&lt;br /&gt;
                                                      // ArrowItem's supertype of Item has a corresponding registry: [Item]&lt;br /&gt;
                                                      // Resource location is explicitly defined: &amp;quot;minecraft:arrow&amp;quot;&lt;br /&gt;
                                                      // To inject: &amp;quot;minecraft:arrow&amp;quot; from the [Item] registry                                                    &lt;br /&gt;
&lt;br /&gt;
    public static Block bedrock = null;               // No annotation, so [public static final] is required.&lt;br /&gt;
                                                      // Therefore, the field is ignored.&lt;br /&gt;
    &lt;br /&gt;
    public static final CreativeModeTab group = null; // No annotation. [public static final] is required.&lt;br /&gt;
                                                      // CreativeModeTab does not have a corresponding registry.&lt;br /&gt;
                                                      // No supertypes of CreativeModeTab has a corresponding registry.&lt;br /&gt;
                                                      // Therefore, THIS WILL PRODUCE AN EXCEPTION.&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
class UnannotatedHolder { // Note the lack of an @ObjectHolder annotation on this class.&lt;br /&gt;
    @ObjectHolder(&amp;quot;minecraft:flame&amp;quot;)&lt;br /&gt;
    public static final Enchantment flame = null;     // Annotation present. [public static] is required. [final] is optional.&lt;br /&gt;
                                                      // Enchantment has corresponding registry: [Enchantment].&lt;br /&gt;
                                                      // Resource location is explicitly defined: &amp;quot;minecraft:flame&amp;quot;&lt;br /&gt;
                                                      // To inject: &amp;quot;minecraft:flame&amp;quot; from the [Enchantment] registry&lt;br /&gt;
&lt;br /&gt;
    public static final Biome ice_flat = null;        // No annotation on the enclosing class.&lt;br /&gt;
                                                      // Therefore, the field is ignored.&lt;br /&gt;
&lt;br /&gt;
    @ObjectHolder(&amp;quot;minecraft:creeper&amp;quot;)&lt;br /&gt;
    public static Entity creeper = null;              // Annotation present. [public static] is required.&lt;br /&gt;
                                                      // Entity does not have a corresponding registry.&lt;br /&gt;
                                                      // No supertypes of Entity has a corresponding registry.&lt;br /&gt;
                                                      // Therefore, THIS WILL PRODUCE AN EXCEPTION.&lt;br /&gt;
&lt;br /&gt;
    @ObjectHolder(&amp;quot;levitation&amp;quot;)&lt;br /&gt;
    public static final Potion levitation = null;     // Annotation present. [public static] is required. [final] is optional.&lt;br /&gt;
                                                      // Potion has a corresponding registry: [Potion].&lt;br /&gt;
                                                      // Name path is the value of the annotation: &amp;quot;levitation&amp;quot;&lt;br /&gt;
                                                      // Namespace is not explicitly defined.&lt;br /&gt;
                                                      // No annotation in enclosing class.&lt;br /&gt;
                                                      // Therefore, THIS WILL PRODUCE AN EXCEPTION.&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Creating Custom Registries ==&lt;br /&gt;
&lt;br /&gt;
Creating custom registries for your mod might be useful if you want other mods to add new things to your system. For example, you might have magic spells and want to allow other mods to add new spells. For this you will want to make a registry (eg. &amp;quot;mymagicmod:spells&amp;quot;). This way, other mods will be able to register things to that list, and you won't have to do anything else.&lt;br /&gt;
&lt;br /&gt;
Just like with registering a new item or block you have two ways of making a new registry. Each method takes in a &amp;lt;code&amp;gt;RegistryBuilder&amp;lt;/code&amp;gt; which is used to build an &amp;lt;code&amp;gt;IForgeRegistry&amp;lt;/code&amp;gt;. Each builder should have its name set via &amp;lt;code&amp;gt;#setName&amp;lt;/code&amp;gt; before being created.&lt;br /&gt;
&lt;br /&gt;
=== With DeferredRegister ===&lt;br /&gt;
&lt;br /&gt;
The first method involves the second static constructor: &amp;lt;code&amp;gt;DeferredRegister#create(ResourceLocation, String)&amp;lt;/code&amp;gt;. From there, we can construct the registry using &amp;lt;code&amp;gt;#makeRegistry&amp;lt;/code&amp;gt;. This will already populate &amp;lt;code&amp;gt;#setName&amp;lt;/code&amp;gt; for us. This method also returns a supplier of the registry which we can use after the &amp;lt;code&amp;gt;NewRegistryEvent&amp;lt;/code&amp;gt; is called.&lt;br /&gt;
&lt;br /&gt;
Here is an example:&lt;br /&gt;
&lt;br /&gt;
{{Template:Tabs/Code_Snippets&lt;br /&gt;
|java=public static final DeferredRegister&amp;lt;ExampleRegistry&amp;gt; EXAMPLE = DeferredRegister.create(new ResourceLocation(MODID, &amp;quot;example_registry&amp;quot;), MODID);&lt;br /&gt;
&lt;br /&gt;
public static final Supplier&amp;lt;IForgeRegistry&amp;lt;ExampleRegistry&amp;gt;&amp;gt; REGISTRY = EXAMPLE.makeRegistry(RegistryBuilder::new);&lt;br /&gt;
|kotlin=val EXAMPLE: DeferredRegister&amp;lt;ExampleRegistry&amp;gt; = DeferredRegister.create(ResourceLocation(MODID, &amp;quot;example_registry&amp;quot;), MODID)&lt;br /&gt;
&lt;br /&gt;
val REGISTRY: IForgeRegistry&amp;lt;ExampleRegistry&amp;gt; by lazy {&lt;br /&gt;
    EXAMPLE.makeRegistry(::RegistryBuilder).get()&lt;br /&gt;
}&lt;br /&gt;
|scala=final val EXAMPLE = DeferredRegister.create(new ResourceLocation(MODID, &amp;quot;example_registry&amp;quot;), MODID)&lt;br /&gt;
&lt;br /&gt;
final lazy val REGISTRY = EXAMPLE.makeRegistry(() =&amp;gt; new RegistryBuilder).get&lt;br /&gt;
|}}&lt;br /&gt;
&lt;br /&gt;
=== Using &amp;lt;code&amp;gt;NewRegistryEvent&amp;lt;/code&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
The second method can be done during the &amp;lt;code&amp;gt;NewRegistryEvent&amp;lt;/code&amp;gt; event. Using &amp;lt;code&amp;gt;NewRegistryEvent#create&amp;lt;/code&amp;gt;, you can pass in a &amp;lt;code&amp;gt;RegistryBuilder&amp;lt;/code&amp;gt; directly. This method will return a &amp;lt;code&amp;gt;Supplier&amp;lt;IForgeRegistry&amp;lt;V&amp;gt;&amp;gt;&amp;lt;/code&amp;gt; that can be stored and queried after the event is fired to gain access to your &amp;lt;code&amp;gt;IForgeRegistry&amp;lt;/code&amp;gt; instance.&lt;br /&gt;
&lt;br /&gt;
Here is an example: (the event handler is registered on the '''mod event bus''')&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;Java&amp;quot;&amp;gt;&lt;br /&gt;
public static Supplier&amp;lt;IForgeRegistry&amp;lt;ExampleRegistry&amp;gt;&amp;gt; registrySupplier = null;&lt;br /&gt;
&lt;br /&gt;
@SubscribeEvent&lt;br /&gt;
public void onNewRegistry(NewRegistryEvent event){&lt;br /&gt;
    RegistryBuilder&amp;lt;ExampleRegistry&amp;gt; registryBuilder = new RegistryBuilder&amp;lt;&amp;gt;();&lt;br /&gt;
    registryBuilder.setName(new ResourceLocation(MODID, &amp;quot;example_registry&amp;quot;);&lt;br /&gt;
    registrySupplier = event.create(registryBuilder);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Handling Missing Entries ==&lt;br /&gt;
&lt;br /&gt;
When loading a pre-existing world after removing mods or updating versions, there are cases where certain registry objects will cease to exist. In these cases, it is possible to specify actions to remove a mapping, prevent the world from loading, or remap the name as needed. This can be done through the third of the registry events: &amp;lt;code&amp;gt;MissingMappingsEvent&amp;lt;/code&amp;gt;. Within the event, you can grab an immutable list of missing mappings associated with a mod id for a given registry via &amp;lt;code&amp;gt;#getMappings&amp;lt;/code&amp;gt; or a list of all mappings via &amp;lt;code&amp;gt;#getAllMappings&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
For each &amp;lt;code&amp;gt;Mapping&amp;lt;/code&amp;gt;, you can either execute one of the following methods:&lt;br /&gt;
* &amp;lt;code&amp;gt;#ignore&amp;lt;/code&amp;gt; which abandons the entry when loading&lt;br /&gt;
* &amp;lt;code&amp;gt;#warn&amp;lt;/code&amp;gt; which warns the user about the missing entry but continues loading&lt;br /&gt;
* &amp;lt;code&amp;gt;#fail&amp;lt;/code&amp;gt; which prevents the world from loading&lt;br /&gt;
* &amp;lt;code&amp;gt;#remap&amp;lt;/code&amp;gt; which remaps the entry to the specified non-null object in the same registry&lt;br /&gt;
&lt;br /&gt;
If none of the above are specified, then the default action of notifying the user about the missing mappings occur.&lt;br /&gt;
&lt;br /&gt;
Here is an example:  (the event handler is registered on the '''forge event bus''')&lt;br /&gt;
&lt;br /&gt;
{{Template:Tabs/Code_Snippets&lt;br /&gt;
|java=// This will ignore any missing test items from the specified world&lt;br /&gt;
@SubscribeEvent&lt;br /&gt;
public void onMissing(final MissingMappingsEvent event) {&lt;br /&gt;
    event.getMappings(ForgeRegistries.Keys.ITEMS, MODID).stream()&lt;br /&gt;
        .filter(mapping -&amp;gt; mapping.key.getPath().contains(&amp;quot;test&amp;quot;))&lt;br /&gt;
            .forEach(Mapping::ignore);&lt;br /&gt;
}&lt;br /&gt;
|groovy=// This will ignore any missing test items from the specified world&lt;br /&gt;
@SubscribeEvent&lt;br /&gt;
void onMissing(final MissingMappingsEvent event) {&lt;br /&gt;
    event.getMappings(ForgeRegistries.Keys.ITEMS, MODID).stream()&lt;br /&gt;
        .filter(mapping -&amp;gt; mapping.key.path.contains(&amp;quot;test&amp;quot;))&lt;br /&gt;
            .forEach(Mapping::ignore);&lt;br /&gt;
}&lt;br /&gt;
|}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Common Concepts]]&lt;/div&gt;</summary>
		<author><name>SizableShrimp</name></author>
	</entry>
	<entry>
		<id>https://forge.gemwire.uk/index.php?title=Registration&amp;diff=3259</id>
		<title>Registration</title>
		<link rel="alternate" type="text/html" href="https://forge.gemwire.uk/index.php?title=Registration&amp;diff=3259"/>
		<updated>2022-06-12T06:23:41Z</updated>

		<summary type="html">&lt;p&gt;SizableShrimp: /* Using `NewRegistryEvent` */ Fix header&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Registration is the process of making an object (such as an item or block) known to the game during runtime. If some objects are not registered, this could cause crashes even before the game is fully loaded or arbitrary behaviors such as bottlenecking mod compatibility for world generation.&lt;br /&gt;
&lt;br /&gt;
Most objects that are known within the game are handled by a &amp;lt;code&amp;gt;Registry&amp;lt;/code&amp;gt;. Each registry uniquely defines each object through a &amp;quot;registry name&amp;quot; via a [[Using Resources#ResourceLocation|ResourceLocation]].&lt;br /&gt;
&lt;br /&gt;
{{Tip|In a global context, each object is universally unique through its &amp;lt;code&amp;gt;ResourceKey&amp;lt;/code&amp;gt;: a concatenation of its registry's id and the object's registry name.}}&lt;br /&gt;
&lt;br /&gt;
Due to the inconsistent ordering and registration process vanilla uses, Forge wraps most vanilla registries using &amp;lt;code&amp;gt;IForgeRegistry&amp;lt;/code&amp;gt;. This guarantees that the loading order for these wrapped registries will be &amp;lt;code&amp;gt;Block&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;Item&amp;lt;/code&amp;gt;, and then the rest of the wrapped registries in alphabetical order. All registries supported by Forge can be found within the &amp;lt;code&amp;gt;ForgeRegistries&amp;lt;/code&amp;gt; class. Since all registry names are unique to a specific registry, different registry objects within different registries can have the same name (e.g. a &amp;lt;code&amp;gt;Block&amp;lt;/code&amp;gt; and an &amp;lt;code&amp;gt;Item&amp;lt;/code&amp;gt; each hold a registry object named &amp;lt;code&amp;gt;examplemod:object&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
{{Tip/Warning|If two registry objects within the same registry have the same name, the second object will override the first. The only registry that will throw an &amp;lt;code&amp;gt;IllegalArgumentException&amp;lt;/code&amp;gt; is the &amp;lt;code&amp;gt;DataSerializerEntry&amp;lt;/code&amp;gt; registry.}}&lt;br /&gt;
&lt;br /&gt;
== Methods for Registering ==&lt;br /&gt;
&lt;br /&gt;
There are two proper ways to register objects within an associated wrapped Forge registry: the &amp;lt;code&amp;gt;DeferredRegister&amp;lt;/code&amp;gt; class, and the &amp;lt;code&amp;gt;RegisterEvent&amp;lt;/code&amp;gt; lifecycle event.&lt;br /&gt;
&lt;br /&gt;
=== DeferredRegister ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;DeferredRegister&amp;lt;/code&amp;gt; is an abstraction layer over the registry event used to register objects. It maintains a map of &amp;quot;registry name&amp;quot; to their associated suppliers and resolves those suppliers during &amp;lt;code&amp;gt;RegisterEvent&amp;lt;/code&amp;gt; for the associated registry. This method is the currently recommended, and documented, way to handle these objects as it provides convenience and safety for those who want to statically initialize objects while avoiding some issues associated with it. &lt;br /&gt;
&lt;br /&gt;
An example of a mod registering a custom block:&lt;br /&gt;
&lt;br /&gt;
{{Template:Tabs/Code_Snippets&lt;br /&gt;
|java=private static final DeferredRegister&amp;lt;Block&amp;gt; BLOCKS = DeferredRegister.create(ForgeRegistries.BLOCKS, MODID);&lt;br /&gt;
&lt;br /&gt;
public static final RegistryObject&amp;lt;Block&amp;gt; EXAMPLE_BLOCK = BLOCKS.register(&amp;quot;example_block&amp;quot;, () -&amp;gt; new Block(BlockBehaviour.Properties.of(Material.STONE)));&lt;br /&gt;
&lt;br /&gt;
public ExampleMod() {&lt;br /&gt;
    BLOCKS.register(FMLJavaModLoadingContext.get().getModEventBus());&lt;br /&gt;
}&lt;br /&gt;
|kotlin=private val BLOCKS = DeferredRegister.create(ForgeRegistries.BLOCKS, MODID)&lt;br /&gt;
&lt;br /&gt;
val EXAMPLE_BLOCK: RegistryObject&amp;lt;Block&amp;gt; = BLOCKS.register(&amp;quot;example_block&amp;quot;) { Block(BlockBehaviour.Properties.of(Material.ROCK)) }&lt;br /&gt;
&lt;br /&gt;
internal class ExampleMod {&lt;br /&gt;
    init {&lt;br /&gt;
        BLOCKS.register(FMLJavaModLoadingContext.get().modEventBus)&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
|scala=object ExampleMod {&lt;br /&gt;
    private final val BLOCKS = DeferredRegister.create(ForgeRegistries.BLOCKS, MODID)&lt;br /&gt;
&lt;br /&gt;
    final val EXAMPLE_BLOCK = registerBlock(&amp;quot;example_block&amp;quot;, () =&amp;gt; new Block(BlockBehaviour.Properties.of(Material.ROCK)))&lt;br /&gt;
}&lt;br /&gt;
class ExampleMod {&lt;br /&gt;
    BLOCKS.register(FMLJavaModLoadingContext.get.getModEventBus)&lt;br /&gt;
}&lt;br /&gt;
|groovy=private static final DeferredRegister&amp;lt;Block&amp;gt; BLOCKS = DeferredRegister.create(ForgeRegistries.BLOCKS, MODID);&lt;br /&gt;
&lt;br /&gt;
public static final RegistryObject&amp;lt;Block&amp;gt; EXAMPLE_BLOCK = BLOCKS.register(&amp;quot;example_block&amp;quot;, () -&amp;gt; new Block(BlockBehaviour.Properties.of(Material.STONE)));&lt;br /&gt;
&lt;br /&gt;
ExampleMod() {&lt;br /&gt;
    BLOCKS.register(FMLJavaModLoadingContext.get().modEventBus);&lt;br /&gt;
}&lt;br /&gt;
|}}&lt;br /&gt;
&lt;br /&gt;
{{Tip|When using a &amp;lt;code&amp;gt;DeferredRegister&amp;lt;/code&amp;gt; to register any object, the name inputted will be automatically prefixed with the mod id passed in, giving the above object a &amp;quot;registry name&amp;quot; of &amp;lt;code&amp;gt;examplemod:example_block&amp;lt;/code&amp;gt;.}}&lt;br /&gt;
&lt;br /&gt;
=== RegisterEvent ===&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;RegisterEvent&amp;lt;/code&amp;gt; is the second way register objects. This [[Events|event]] is fired for each registry synchronously in vanilla registry order after &amp;lt;code&amp;gt;FMLConstructModEvent&amp;lt;/code&amp;gt; and before the configs are loaded. Objects are registered using &amp;lt;code&amp;gt;#register&amp;lt;/code&amp;gt; by passing in the registry key, the name of the registry object, and the object itself. There is an additional &amp;lt;code&amp;gt;#register&amp;lt;/code&amp;gt; overload which takes in a consumed helper to register an object with a given name. It is recommended to use this method to avoid unnecessary object creation.&lt;br /&gt;
&lt;br /&gt;
Here is an example: (the event handler is registered on the '''mod event bus''')&lt;br /&gt;
&lt;br /&gt;
{{Template:Tabs/Code_Snippets&lt;br /&gt;
|java=@SubscribeEvent&lt;br /&gt;
public void register(RegisterEvent event) {&lt;br /&gt;
    event.register(ForgeRegistries.Keys.BLOCKS,&lt;br /&gt;
        helper -&amp;gt; helper.register(new ResourceLocation(MODID, &amp;quot;example_block&amp;quot;), new Block(...))&lt;br /&gt;
    );&lt;br /&gt;
}&lt;br /&gt;
|kotlin=@JvmStatic&lt;br /&gt;
@SubscribeEvent&lt;br /&gt;
private fun register(event: RegisterEvent) =&lt;br /&gt;
    event.register(ForgeRegistries.Keys.BLOCKS) {&lt;br /&gt;
        helper -&amp;gt; helper.register(ResourceLocation(MODID, &amp;quot;example_block&amp;quot;), Block(...))&lt;br /&gt;
    }&lt;br /&gt;
|scala=@SubscribeEvent&lt;br /&gt;
def register(event: RegisterEvent): Unit =&lt;br /&gt;
    event.register(ForgeRegistries.Keys.BLOCKS,&lt;br /&gt;
        helper =&amp;gt; helper.register(new ResourceLocation(MODID, &amp;quot;example_block&amp;quot;), new Block(...))&lt;br /&gt;
    )&lt;br /&gt;
|}}&lt;br /&gt;
&lt;br /&gt;
{{Tip/Important|Since all objects registered must be singleton, some classes cannot by themselves be registered. Instead, &amp;lt;code&amp;gt;*Type&amp;lt;/code&amp;gt; classes are registered and used in the formers' constructors to wrap the flyweight objects. For example, a [[Basics_of_Block_Entities|&amp;lt;code&amp;gt;BlockEntity&amp;lt;/code&amp;gt;]] is wrapped via &amp;lt;code&amp;gt;BlockEntityType&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;Entity&amp;lt;/code&amp;gt; is wrapped via &amp;lt;code&amp;gt;EntityType&amp;lt;/code&amp;gt;. These &amp;lt;code&amp;gt;*Type&amp;lt;/code&amp;gt; classes hold factories that simply create the containing type on demand.&lt;br /&gt;
&lt;br /&gt;
These factory holders are created through the use of their &amp;lt;code&amp;gt;*Type$Builder&amp;lt;/code&amp;gt; classes. An example: (&amp;lt;code&amp;gt;REGISTER&amp;lt;/code&amp;gt; here refers to a &amp;lt;code&amp;gt;DeferredRegister&amp;lt;BlockEntityType&amp;lt;?&amp;gt;&amp;gt;&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
{{Template:Tabs/Code_Snippets&lt;br /&gt;
|java=public static final RegistryObject&amp;lt;BlockEntityType&amp;lt;ExampleBlockEntity&amp;gt;&amp;gt; EXAMPLE_BLOCK_ENTITY = REGISTER.register(&lt;br /&gt;
    &amp;quot;example_block_entity&amp;quot;, () -&amp;gt; BlockEntityType.Builder.of(ExampleBlockEntity::new, EXAMPLE_BLOCK.get()).build(null)&lt;br /&gt;
);&lt;br /&gt;
|kotlin=val EXAMPLE_BLOCK_ENTITY: RegistryObject&amp;lt;BlockEntityType&amp;lt;ExampleBlockEntity&amp;gt;&amp;gt; = REGISTER.register(&amp;quot;example_block_entity&amp;quot;) { BlockEntityType.Builder.of(::ExampleBlockEntity, EXAMPLE_BLOCK.get()).build(null)) }&lt;br /&gt;
|scala=final val EXAMPLE_BLOCK_ENTITY = REGISTER.register(&amp;quot;example_block_entity&amp;quot;, () =&amp;gt; BlockEntityType.Builder.of(() =&amp;gt; new ExampleBlockEntity(), GeneralRegistrar.EXAMPLE_BLOCK.get).build(null))&lt;br /&gt;
|}}&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
=== Non-Forge Registries ===&lt;br /&gt;
&lt;br /&gt;
Not all vanilla registries are wrapped as a Forge registry. To register objects to any one of these registries, create a &amp;lt;code&amp;gt;DeferredRegister&amp;lt;/code&amp;gt; via the &amp;lt;code&amp;gt;#create&amp;lt;/code&amp;gt; overload which takes in a resource key of the registry and the mod id to register the entries for. Then simply call &amp;lt;code&amp;gt;#register&amp;lt;/code&amp;gt; like any other &amp;lt;code&amp;gt;DeferredRegister&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
{{Template:Tabs/Code_Snippets&lt;br /&gt;
|java=private static final DeferredRegister&amp;lt;LootItemConditionType&amp;gt; REGISTER = DeferredRegister.create(Registry.LOOT_ITEM_REGISTRY, MODID);&lt;br /&gt;
&lt;br /&gt;
public static final RegistryObject&amp;lt;LootItemConditionType&amp;gt; EXAMPLE_LOOT_ITEM_CONDITION_TYPE = REGISTER.register(&amp;quot;example_loot_item_condition_type&amp;quot;, () -&amp;gt; new LootItemConditionType(...));&lt;br /&gt;
|kotlin=private val REGISTER = DeferredRegister.create(Registry.LOOT_ITEM_REGISTRY, MODID)&lt;br /&gt;
&lt;br /&gt;
val EXAMPLE_LOOT_ITEM_CONDITION_TYPE : RegistryObject&amp;lt;LootItemConditionType&amp;gt; = REGISTER.register(&amp;quot;example_loot_item_condition_type&amp;quot;) {&lt;br /&gt;
    LootItemConditionType(...)&lt;br /&gt;
}&lt;br /&gt;
|scala=private final val REGISTER = DeferredRegister.create(Registry.LOOT_ITEM_REGISTRY, MODID)&lt;br /&gt;
&lt;br /&gt;
final val EXAMPLE_LOOT_ITEM_CONDITION_TYPE = REGISTER.register(&amp;quot;example_loot_item_condition_type&amp;quot;, () =&amp;gt; new LootItemConditionType(...))&lt;br /&gt;
|groovy=private static final DeferredRegister&amp;lt;LootItemConditionType&amp;gt; REGISTER = DeferredRegister.create(Registry.LOOT_ITEM_REGISTRY, MODID);&lt;br /&gt;
&lt;br /&gt;
public static final RegistryObject&amp;lt;LootItemConditionType&amp;gt; EXAMPLE_LOOT_ITEM_CONDITION_TYPE = REGISTER.register(&amp;quot;example_loot_item_condition_type&amp;quot;, () -&amp;gt; new LootItemConditionType(...));&lt;br /&gt;
|}}&lt;br /&gt;
&lt;br /&gt;
If you attempt to make one of these instances require an instance of another registry object, you should use the lazy initialization method mentioned above to register the object in the correct order.&lt;br /&gt;
&lt;br /&gt;
=== Data Driven Entries ===&lt;br /&gt;
&lt;br /&gt;
Registries are considered to be data driven if they are located within &amp;lt;code&amp;gt;RegistryAccess&amp;lt;/code&amp;gt; with the exception of &amp;lt;code&amp;gt;LevelStem&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;Level&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
These registry objects only need to be registered within code if they are to be used within a pre-existing registry object (e.g. a &amp;lt;code&amp;gt;PlacedFeature&amp;lt;/code&amp;gt; for ore generation within an overworld &amp;lt;code&amp;gt;Biome&amp;lt;/code&amp;gt;). Otherwise, their instance can be purely registered using a JSON file.&lt;br /&gt;
&lt;br /&gt;
If a data driven registry object has to be registered within code, a dummy object should be supplied to hold a &amp;quot;registry name&amp;quot; and then constructed within a JSON file.&lt;br /&gt;
&lt;br /&gt;
== Referencing Registered Objects ==&lt;br /&gt;
&lt;br /&gt;
Each forge registered object should not be statically initialized nor reference another instance being registered. They must always be a new, singleton instance that is resolved during when &amp;lt;code&amp;gt;RegisterEvent&amp;lt;/code&amp;gt; is called for their registry. This is to maintain a sane loading order for registries and their objects along with dynamic loading/unloading of mods.&lt;br /&gt;
&lt;br /&gt;
Forge registered objects must always be referenced through a &amp;lt;code&amp;gt;RegistryObject&amp;lt;/code&amp;gt; or a field with &amp;lt;code&amp;gt;@ObjectHolder&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
===Using RegistryObjects===&lt;br /&gt;
&amp;lt;code&amp;gt;RegistryObject&amp;lt;/code&amp;gt;s can be used to retrieve references to registered objects once they become available. Their references are updated along with all &amp;lt;code&amp;gt;@ObjectHolder&amp;lt;/code&amp;gt; annotations after the registry that &amp;lt;code&amp;gt;RegisterEvent&amp;lt;/code&amp;gt; is called for is dispatched and frozen.&lt;br /&gt;
&lt;br /&gt;
A &amp;lt;code&amp;gt;RegistryObject&amp;lt;/code&amp;gt; can be retrieved as a result of using &amp;lt;code&amp;gt;DeferredRegister&amp;lt;/code&amp;gt; or calling the static factory &amp;lt;code&amp;gt;RegistryObject#create&amp;lt;/code&amp;gt;. Each static factory takes in the &amp;quot;registry name&amp;quot; of the object being referenced and one of the following: a &amp;lt;code&amp;gt;IForgeRegistry&amp;lt;/code&amp;gt;, a registry name of the type &amp;lt;code&amp;gt;ResourceLocation&amp;lt;/code&amp;gt;, or a registry key of the type &amp;lt;code&amp;gt;ResourceKey&amp;lt;? extends Registry&amp;lt;?&amp;gt;&amp;gt;&amp;lt;/code&amp;gt;. The &amp;lt;code&amp;gt;RegistryObject&amp;lt;/code&amp;gt; can be stored within some field and retrieve the registered object using &amp;lt;code&amp;gt;#get&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
An example using &amp;lt;code&amp;gt;RegistryObject&amp;lt;/code&amp;gt;:&lt;br /&gt;
{{Template:Tabs/Code_Snippets&lt;br /&gt;
|java=public static final RegistryObject&amp;lt;Item&amp;gt; EXAMPLE_ITEM = RegistryObject.create(new ResourceLocation(&amp;quot;examplemod&amp;quot;, &amp;quot;example_item&amp;quot;), ForgeRegistries.ITEMS);&lt;br /&gt;
&lt;br /&gt;
// Assume that 'examplemod:example_registry' is a valid registry, and 'examplemod:example_object' is a valid object within that registry&lt;br /&gt;
public static final RegistryObject&amp;lt;ExampleRegistry&amp;gt; EXAMPLE_OBJECT = RegistryObject.create(new ResourceLocation(&amp;quot;examplemod&amp;quot;, &amp;quot;example_object&amp;quot;), new ResourceLocation(&amp;quot;examplemod&amp;quot;, &amp;quot;example_registry&amp;quot;), &amp;quot;examplemod&amp;quot;); &lt;br /&gt;
|kotlin=val EXAMPLE_ITEM: RegistryObject&amp;lt;Item&amp;gt; = RegistryObject.create(ResourceLocation(&amp;quot;examplemod&amp;quot;, &amp;quot;example_item&amp;quot;), ForgeRegistries.ITEMS)&lt;br /&gt;
&lt;br /&gt;
// Assume that 'examplemod:example_registry' is a valid registry, and 'examplemod:example_object' is a valid object within that registry&lt;br /&gt;
val EXAMPLE_OBJECT: RegistryObject&amp;lt;ExampleRegistry&amp;gt; = RegistryObject.create(ResourceLocation(&amp;quot;examplemod&amp;quot;, &amp;quot;example_object&amp;quot;), new ResourceLocation(&amp;quot;examplemod&amp;quot;, &amp;quot;example_registry&amp;quot;), &amp;quot;examplemod&amp;quot;)&lt;br /&gt;
|scala=final val EXAMPLE_ITEM = RegistryObject.create(new ResourceLocation(&amp;quot;examplemod&amp;quot;, &amp;quot;example_item&amp;quot;), ForgeRegistries.ITEMS)&lt;br /&gt;
&lt;br /&gt;
// Assume that 'examplemod:example_registry' is a valid registry, and 'examplemod:example_object' is a valid object within that registry&lt;br /&gt;
final val EXAMPLE_OBJECT = RegistryObject.create(new ResourceLocation(&amp;quot;examplemod&amp;quot;, &amp;quot;example_object&amp;quot;), new ResourceLocation(&amp;quot;examplemod&amp;quot;, &amp;quot;example_registry&amp;quot;), &amp;quot;examplemod&amp;quot;); &lt;br /&gt;
|}}&lt;br /&gt;
&lt;br /&gt;
{{Tip/Important|All vanilla objects are bootstrapped and registered before mods are loaded. As such, they can be referenced as is without any issues.}}&lt;br /&gt;
&lt;br /&gt;
=== Using @ObjectHolder ===&lt;br /&gt;
&lt;br /&gt;
Forge registry objects can also be injected into &amp;lt;code&amp;gt;public static&amp;lt;/code&amp;gt; fields with either their class or that field annotated with &amp;lt;code&amp;gt;@ObjectHolder&amp;lt;/code&amp;gt;. There must be enough information to construct a &amp;lt;code&amp;gt;ResourceLocation&amp;lt;/code&amp;gt; to identify a single object within a specific registry.&lt;br /&gt;
&lt;br /&gt;
The rules for &amp;lt;code&amp;gt;@ObjectHolder&amp;lt;/code&amp;gt; are as follows:&lt;br /&gt;
&lt;br /&gt;
* If the class is annotated with &amp;lt;code&amp;gt;@ObjectHolder&amp;lt;/code&amp;gt;, its value will be the default namespace for all fields within if not explicitly defined&lt;br /&gt;
* If the class is annotated with &amp;lt;code&amp;gt;@Mod&amp;lt;/code&amp;gt;, the modid will be the default namespace for all annotated fields within if not explicitly defined &lt;br /&gt;
* A field is considered for injection if:&lt;br /&gt;
** it has at least the modifiers &amp;lt;code&amp;gt;public static&amp;lt;/code&amp;gt;; and&lt;br /&gt;
** one of the following conditions are true:&lt;br /&gt;
*** the '''enclosing class''' has an &amp;lt;code&amp;gt;@ObjectHolder&amp;lt;/code&amp;gt; annotation, and the field is &amp;lt;code&amp;gt;final&amp;lt;/code&amp;gt;, and:&lt;br /&gt;
**** the name value is the field's name; and&lt;br /&gt;
**** the namespace value is the enclosing class's namespace&lt;br /&gt;
**** ''An exception is thrown if the namespace value cannot be found and inherited''&lt;br /&gt;
*** the '''field''' is annotated with &amp;lt;code&amp;gt;@ObjectHolder&amp;lt;/code&amp;gt;, and:&lt;br /&gt;
**** the name value is explicitly defined; and&lt;br /&gt;
**** the namespace value is either explicitly defined or the enclosing class's namespace&lt;br /&gt;
** the field type or one of its supertypes corresponds to a valid registry (e.g. &amp;lt;code&amp;gt;Item&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;ArrowItem&amp;lt;/code&amp;gt; for the &amp;lt;code&amp;gt;Item&amp;lt;/code&amp;gt; registry)&lt;br /&gt;
** ''An exception is thrown if a field does not have a corresponding registry.''&lt;br /&gt;
* ''An exception is thrown if the resulting &amp;lt;code&amp;gt;ResourceLocation&amp;lt;/code&amp;gt; is incomplete or invalid (non-valid characters in path)''&lt;br /&gt;
* If no other errors or exceptions occur, the field will be injected&lt;br /&gt;
* If all of the above rules do not apply, no action will be taken (and a message may be logged)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;@ObjectHolder&amp;lt;/code&amp;gt; annotated fields are injected with their associated object values after &amp;lt;code&amp;gt;RegisterEvent&amp;lt;/code&amp;gt; is fired for their registry, along with &amp;lt;code&amp;gt;RegistryObject&amp;lt;/code&amp;gt;s.&lt;br /&gt;
&lt;br /&gt;
{{Tip/Warning|If the object does not exist in the registry when it is to be injected, a debug message will be logged, and no value will be injected. If the object is found, but the field cannot be set, a warning message will be logged instead.}}&lt;br /&gt;
&lt;br /&gt;
As these rules are rather complicated, here are some examples:&lt;br /&gt;
&amp;lt;div class=&amp;quot;mw-collapsible mw-collapsed&amp;quot; style=&amp;quot;border: solid 2px; padding: 2px 5px; margin-top: 3px&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;div style=&amp;quot;font-weight:bold;line-height:1.6;&amp;quot;&amp;gt;Example uses of &amp;lt;code&amp;gt;@ObjectHolder&amp;lt;/code&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;div class=&amp;quot;mw-collapsible-content&amp;quot; style=&amp;quot;overflow: auto; white-space: nowrap;&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
@ObjectHolder(&amp;quot;minecraft&amp;quot;) // Inheritable resource namespace: &amp;quot;minecraft&amp;quot;&lt;br /&gt;
class AnnotatedHolder {&lt;br /&gt;
    public static final Block diamond_block = null;   // No annotation. [public static final] is required.&lt;br /&gt;
                                                      // Block has a corresponding registry: [Block]&lt;br /&gt;
                                                      // Name path is the name of the field: &amp;quot;diamond_block&amp;quot;&lt;br /&gt;
                                                      // Namespace is not explicitly defined.&lt;br /&gt;
                                                      // So, namespace is inherited from class annotation: &amp;quot;minecraft&amp;quot;&lt;br /&gt;
                                                      // To inject: &amp;quot;minecraft:diamond_block&amp;quot; from the [Block] registry&lt;br /&gt;
&lt;br /&gt;
    @ObjectHolder(&amp;quot;ambient.cave&amp;quot;)&lt;br /&gt;
    public static SoundEvent ambient_sound = null;    // Annotation present. [public static] is required.&lt;br /&gt;
                                                      // SoundEvent has a corresponding registry: [SoundEvent]&lt;br /&gt;
                                                      // Name path is the value of the annotation: &amp;quot;ambient.cave&amp;quot;&lt;br /&gt;
                                                      // Namespace is not explicitly defined.&lt;br /&gt;
                                                      // So, namespace is inherited from class annotation: &amp;quot;minecraft&amp;quot;&lt;br /&gt;
                                                      // To inject: &amp;quot;minecraft:ambient.cave&amp;quot; from the [SoundEvent] registry&lt;br /&gt;
&lt;br /&gt;
    // Assume for the next entry that [ManaType] is a valid registry.          &lt;br /&gt;
    @ObjectHolder(&amp;quot;neomagicae:coffeinum&amp;quot;)&lt;br /&gt;
    public static final ManaType coffeinum = null;    // Annotation present. [public static] is required. [final] is optional.&lt;br /&gt;
                                                      // ManaType has a corresponding registry: [ManaType] (custom registry)&lt;br /&gt;
                                                      // Resource location is explicitly defined: &amp;quot;neomagicae:coffeinum&amp;quot;&lt;br /&gt;
                                                      // To inject: &amp;quot;neomagicae:coffeinum&amp;quot; from the [ManaType] registry&lt;br /&gt;
&lt;br /&gt;
    public static final Item ENDER_PEARL = null;      // No annotation. [public static final] is required.&lt;br /&gt;
                                                      // Item has a corresponding registry: [Item].&lt;br /&gt;
                                                      // Name path is the name of the field: &amp;quot;ENDER_PEARL&amp;quot; -&amp;gt; &amp;quot;ender_pearl&amp;quot;&lt;br /&gt;
                                                      // !! ^ Field name is valid, because they are&lt;br /&gt;
                                                      //      converted to lowercase automatically.&lt;br /&gt;
                                                      // Namespace is not explicitly defined.&lt;br /&gt;
                                                      // So, namespace is inherited from class annotation: &amp;quot;minecraft&amp;quot;&lt;br /&gt;
                                                      // To inject: &amp;quot;minecraft:ender_pearl&amp;quot; from the [Item] registry&lt;br /&gt;
&lt;br /&gt;
    @ObjectHolder(&amp;quot;minecraft:arrow&amp;quot;)&lt;br /&gt;
    public static final ArrowItem arrow = null;       // Annotation present. [public static] is required. [final] is optional.&lt;br /&gt;
                                                      // ArrowItem does not have a corresponding registry.&lt;br /&gt;
                                                      // ArrowItem's supertype of Item has a corresponding registry: [Item]&lt;br /&gt;
                                                      // Resource location is explicitly defined: &amp;quot;minecraft:arrow&amp;quot;&lt;br /&gt;
                                                      // To inject: &amp;quot;minecraft:arrow&amp;quot; from the [Item] registry                                                    &lt;br /&gt;
&lt;br /&gt;
    public static Block bedrock = null;               // No annotation, so [public static final] is required.&lt;br /&gt;
                                                      // Therefore, the field is ignored.&lt;br /&gt;
    &lt;br /&gt;
    public static final CreativeModeTab group = null; // No annotation. [public static final] is required.&lt;br /&gt;
                                                      // CreativeModeTab does not have a corresponding registry.&lt;br /&gt;
                                                      // No supertypes of CreativeModeTab has a corresponding registry.&lt;br /&gt;
                                                      // Therefore, THIS WILL PRODUCE AN EXCEPTION.&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
class UnannotatedHolder { // Note the lack of an @ObjectHolder annotation on this class.&lt;br /&gt;
    @ObjectHolder(&amp;quot;minecraft:flame&amp;quot;)&lt;br /&gt;
    public static final Enchantment flame = null;     // Annotation present. [public static] is required. [final] is optional.&lt;br /&gt;
                                                      // Enchantment has corresponding registry: [Enchantment].&lt;br /&gt;
                                                      // Resource location is explicitly defined: &amp;quot;minecraft:flame&amp;quot;&lt;br /&gt;
                                                      // To inject: &amp;quot;minecraft:flame&amp;quot; from the [Enchantment] registry&lt;br /&gt;
&lt;br /&gt;
    public static final Biome ice_flat = null;        // No annotation on the enclosing class.&lt;br /&gt;
                                                      // Therefore, the field is ignored.&lt;br /&gt;
&lt;br /&gt;
    @ObjectHolder(&amp;quot;minecraft:creeper&amp;quot;)&lt;br /&gt;
    public static Entity creeper = null;              // Annotation present. [public static] is required.&lt;br /&gt;
                                                      // Entity does not have a corresponding registry.&lt;br /&gt;
                                                      // No supertypes of Entity has a corresponding registry.&lt;br /&gt;
                                                      // Therefore, THIS WILL PRODUCE AN EXCEPTION.&lt;br /&gt;
&lt;br /&gt;
    @ObjectHolder(&amp;quot;levitation&amp;quot;)&lt;br /&gt;
    public static final Potion levitation = null;     // Annotation present. [public static] is required. [final] is optional.&lt;br /&gt;
                                                      // Potion has a corresponding registry: [Potion].&lt;br /&gt;
                                                      // Name path is the value of the annotation: &amp;quot;levitation&amp;quot;&lt;br /&gt;
                                                      // Namespace is not explicitly defined.&lt;br /&gt;
                                                      // No annotation in enclosing class.&lt;br /&gt;
                                                      // Therefore, THIS WILL PRODUCE AN EXCEPTION.&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Creating Custom Registries ==&lt;br /&gt;
&lt;br /&gt;
Creating custom registries for your mod might be useful if you want other mods to add new things to your system. For example, you might have magic spells and want to allow other mods to add new spells. For this you will want to make a registry (eg. &amp;quot;mymagicmod:spells&amp;quot;). This way, other mods will be able to register things to that list, and you won't have to do anything else.&lt;br /&gt;
&lt;br /&gt;
Just like with registering a new item or block you have two ways of making a new registry. Each method takes in a &amp;lt;code&amp;gt;RegistryBuilder&amp;lt;/code&amp;gt; which is used to build an &amp;lt;code&amp;gt;IForgeRegistry&amp;lt;/code&amp;gt;. Each builder should have its name set via &amp;lt;code&amp;gt;#setName&amp;lt;/code&amp;gt; before being created.&lt;br /&gt;
&lt;br /&gt;
=== With DeferredRegister ===&lt;br /&gt;
&lt;br /&gt;
The first method involves the second static constructor: &amp;lt;code&amp;gt;DeferredRegister#create(ResourceLocation, String)&amp;lt;/code&amp;gt;. From there, we can construct the registry using &amp;lt;code&amp;gt;#makeRegistry&amp;lt;/code&amp;gt;. This will already populate &amp;lt;code&amp;gt;#setName&amp;lt;/code&amp;gt; for us. This method also returns a supplier of the registry which we can use after the &amp;lt;code&amp;gt;NewRegistryEvent&amp;lt;/code&amp;gt; is called.&lt;br /&gt;
&lt;br /&gt;
Here is an example:&lt;br /&gt;
&lt;br /&gt;
{{Template:Tabs/Code_Snippets&lt;br /&gt;
|java=public static final DeferredRegister&amp;lt;ExampleRegistry&amp;gt; EXAMPLE = DeferredRegister.create(new ResourceLocation(MODID, &amp;quot;example_registry&amp;quot;), MODID);&lt;br /&gt;
&lt;br /&gt;
public static final Supplier&amp;lt;IForgeRegistry&amp;lt;ExampleRegistry&amp;gt;&amp;gt; REGISTRY = EXAMPLE.makeRegistry(RegistryBuilder::new);&lt;br /&gt;
|kotlin=val EXAMPLE: DeferredRegister&amp;lt;ExampleRegistry&amp;gt; = DeferredRegister.create(ResourceLocation(MODID, &amp;quot;example_registry&amp;quot;), MODID)&lt;br /&gt;
&lt;br /&gt;
val REGISTRY: IForgeRegistry&amp;lt;ExampleRegistry&amp;gt; by lazy {&lt;br /&gt;
    EXAMPLE.makeRegistry(::RegistryBuilder).get()&lt;br /&gt;
}&lt;br /&gt;
|scala=final val EXAMPLE = DeferredRegister.create(new ResourceLocation(MODID, &amp;quot;example_registry&amp;quot;), MODID)&lt;br /&gt;
&lt;br /&gt;
final lazy val REGISTRY = EXAMPLE.makeRegistry(() =&amp;gt; new RegistryBuilder).get&lt;br /&gt;
|}}&lt;br /&gt;
&lt;br /&gt;
=== Using &amp;lt;code&amp;gt;NewRegistryEvent&amp;lt;/code&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
The second method can be done during the &amp;lt;code&amp;gt;NewRegistryEvent&amp;lt;/code&amp;gt; event. Using &amp;lt;code&amp;gt;NewRegistryEvent#create&amp;lt;/code&amp;gt;, you can pass in a &amp;lt;code&amp;gt;RegistryBuilder&amp;lt;/code&amp;gt; directly. This method will return a &amp;lt;code&amp;gt;Supplier&amp;lt;IForgeRegistry&amp;lt;V&amp;gt;&amp;gt;&amp;lt;/code&amp;gt; that can be stored and queried after the event is fired to gain access to your &amp;lt;code&amp;gt;IForgeRegistry&amp;lt;/code&amp;gt; instance.&lt;br /&gt;
&lt;br /&gt;
Here is an example: (the event handler is registered on the '''mod event bus''')&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;Java&amp;quot;&amp;gt;&lt;br /&gt;
public static Supplier&amp;lt;IForgeRegistry&amp;lt;ExampleRegistry&amp;gt;&amp;gt; registrySupplier = null;&lt;br /&gt;
&lt;br /&gt;
@SubscribeEvent&lt;br /&gt;
public void onNewRegistry(NewRegistryEvent event){&lt;br /&gt;
    RegistryBuilder&amp;lt;ExampleRegistry&amp;gt; registryBuilder = new RegistryBuilder&amp;lt;&amp;gt;();&lt;br /&gt;
    registryBuilder.setName(new ResourceLocation(MODID, &amp;quot;example_registry&amp;quot;);&lt;br /&gt;
    registrySupplier = event.create(registryBuilder);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Handling Missing Entries ==&lt;br /&gt;
&lt;br /&gt;
When loading a pre-existing world after removing mods or updating versions, there are cases where certain registry objects will cease to exist. In these cases, it is possible to specify actions to remove a mapping, prevent the world from loading, or remap the name as needed. This can be done through the third of the registry events: &amp;lt;code&amp;gt;MissingMappingsEvent&amp;lt;/code&amp;gt;. Within the event, you can grab an immutable list of missing mappings associated with a mod id for a given registry via &amp;lt;code&amp;gt;#getMappings&amp;lt;/code&amp;gt; or a list of all mappings via &amp;lt;code&amp;gt;#getAllMappings&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
For each &amp;lt;code&amp;gt;Mapping&amp;lt;/code&amp;gt;, you can either execute one of the following methods:&lt;br /&gt;
* &amp;lt;code&amp;gt;#ignore&amp;lt;/code&amp;gt; which abandons the entry when loading&lt;br /&gt;
* &amp;lt;code&amp;gt;#warn&amp;lt;/code&amp;gt; which warns the user about the missing entry but continues loading&lt;br /&gt;
* &amp;lt;code&amp;gt;#fail&amp;lt;/code&amp;gt; which prevents the world from loading&lt;br /&gt;
* &amp;lt;code&amp;gt;#remap&amp;lt;/code&amp;gt; which remaps the entry to the specified non-null object in the same registry&lt;br /&gt;
&lt;br /&gt;
If none of the above are specified, then the default action of notifying the user about the missing mappings occur.&lt;br /&gt;
&lt;br /&gt;
Here is an example:  (the event handler is registered on the '''forge event bus''')&lt;br /&gt;
&lt;br /&gt;
{{Template:Tabs/Code_Snippets&lt;br /&gt;
|java=// This will ignore any missing test items from the specified world&lt;br /&gt;
@SubscribeEvent&lt;br /&gt;
public void onMissing(final MissingMappingsEvent event) {&lt;br /&gt;
    event.getMappings(ForgeRegistries.Keys.ITEMS, MODID).stream()&lt;br /&gt;
        .filter(mapping -&amp;gt; mapping.key.getPath().contains(&amp;quot;test&amp;quot;))&lt;br /&gt;
            .forEach(Mapping::ignore);&lt;br /&gt;
}&lt;br /&gt;
|groovy=// This will ignore any missing test items from the specified world&lt;br /&gt;
@SubscribeEvent&lt;br /&gt;
void onMissing(final MissingMappingsEvent event) {&lt;br /&gt;
    event.getMappings(ForgeRegistries.Keys.ITEMS, MODID).stream()&lt;br /&gt;
        .filter(mapping -&amp;gt; mapping.key.path.contains(&amp;quot;test&amp;quot;))&lt;br /&gt;
            .forEach(Mapping::ignore);&lt;br /&gt;
}&lt;br /&gt;
|}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Common Concepts]]&lt;/div&gt;</summary>
		<author><name>SizableShrimp</name></author>
	</entry>
	<entry>
		<id>https://forge.gemwire.uk/index.php?title=Registration&amp;diff=3258</id>
		<title>Registration</title>
		<link rel="alternate" type="text/html" href="https://forge.gemwire.uk/index.php?title=Registration&amp;diff=3258"/>
		<updated>2022-06-12T06:20:06Z</updated>

		<summary type="html">&lt;p&gt;SizableShrimp: I don't think this page is under construction anymore&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Registration is the process of making an object (such as an item or block) known to the game during runtime. If some objects are not registered, this could cause crashes even before the game is fully loaded or arbitrary behaviors such as bottlenecking mod compatibility for world generation.&lt;br /&gt;
&lt;br /&gt;
Most objects that are known within the game are handled by a &amp;lt;code&amp;gt;Registry&amp;lt;/code&amp;gt;. Each registry uniquely defines each object through a &amp;quot;registry name&amp;quot; via a [[Using Resources#ResourceLocation|ResourceLocation]].&lt;br /&gt;
&lt;br /&gt;
{{Tip|In a global context, each object is universally unique through its &amp;lt;code&amp;gt;ResourceKey&amp;lt;/code&amp;gt;: a concatenation of its registry's id and the object's registry name.}}&lt;br /&gt;
&lt;br /&gt;
Due to the inconsistent ordering and registration process vanilla uses, Forge wraps most vanilla registries using &amp;lt;code&amp;gt;IForgeRegistry&amp;lt;/code&amp;gt;. This guarantees that the loading order for these wrapped registries will be &amp;lt;code&amp;gt;Block&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;Item&amp;lt;/code&amp;gt;, and then the rest of the wrapped registries in alphabetical order. All registries supported by Forge can be found within the &amp;lt;code&amp;gt;ForgeRegistries&amp;lt;/code&amp;gt; class. Since all registry names are unique to a specific registry, different registry objects within different registries can have the same name (e.g. a &amp;lt;code&amp;gt;Block&amp;lt;/code&amp;gt; and an &amp;lt;code&amp;gt;Item&amp;lt;/code&amp;gt; each hold a registry object named &amp;lt;code&amp;gt;examplemod:object&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
{{Tip/Warning|If two registry objects within the same registry have the same name, the second object will override the first. The only registry that will throw an &amp;lt;code&amp;gt;IllegalArgumentException&amp;lt;/code&amp;gt; is the &amp;lt;code&amp;gt;DataSerializerEntry&amp;lt;/code&amp;gt; registry.}}&lt;br /&gt;
&lt;br /&gt;
== Methods for Registering ==&lt;br /&gt;
&lt;br /&gt;
There are two proper ways to register objects within an associated wrapped Forge registry: the &amp;lt;code&amp;gt;DeferredRegister&amp;lt;/code&amp;gt; class, and the &amp;lt;code&amp;gt;RegisterEvent&amp;lt;/code&amp;gt; lifecycle event.&lt;br /&gt;
&lt;br /&gt;
=== DeferredRegister ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;DeferredRegister&amp;lt;/code&amp;gt; is an abstraction layer over the registry event used to register objects. It maintains a map of &amp;quot;registry name&amp;quot; to their associated suppliers and resolves those suppliers during &amp;lt;code&amp;gt;RegisterEvent&amp;lt;/code&amp;gt; for the associated registry. This method is the currently recommended, and documented, way to handle these objects as it provides convenience and safety for those who want to statically initialize objects while avoiding some issues associated with it. &lt;br /&gt;
&lt;br /&gt;
An example of a mod registering a custom block:&lt;br /&gt;
&lt;br /&gt;
{{Template:Tabs/Code_Snippets&lt;br /&gt;
|java=private static final DeferredRegister&amp;lt;Block&amp;gt; BLOCKS = DeferredRegister.create(ForgeRegistries.BLOCKS, MODID);&lt;br /&gt;
&lt;br /&gt;
public static final RegistryObject&amp;lt;Block&amp;gt; EXAMPLE_BLOCK = BLOCKS.register(&amp;quot;example_block&amp;quot;, () -&amp;gt; new Block(BlockBehaviour.Properties.of(Material.STONE)));&lt;br /&gt;
&lt;br /&gt;
public ExampleMod() {&lt;br /&gt;
    BLOCKS.register(FMLJavaModLoadingContext.get().getModEventBus());&lt;br /&gt;
}&lt;br /&gt;
|kotlin=private val BLOCKS = DeferredRegister.create(ForgeRegistries.BLOCKS, MODID)&lt;br /&gt;
&lt;br /&gt;
val EXAMPLE_BLOCK: RegistryObject&amp;lt;Block&amp;gt; = BLOCKS.register(&amp;quot;example_block&amp;quot;) { Block(BlockBehaviour.Properties.of(Material.ROCK)) }&lt;br /&gt;
&lt;br /&gt;
internal class ExampleMod {&lt;br /&gt;
    init {&lt;br /&gt;
        BLOCKS.register(FMLJavaModLoadingContext.get().modEventBus)&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
|scala=object ExampleMod {&lt;br /&gt;
    private final val BLOCKS = DeferredRegister.create(ForgeRegistries.BLOCKS, MODID)&lt;br /&gt;
&lt;br /&gt;
    final val EXAMPLE_BLOCK = registerBlock(&amp;quot;example_block&amp;quot;, () =&amp;gt; new Block(BlockBehaviour.Properties.of(Material.ROCK)))&lt;br /&gt;
}&lt;br /&gt;
class ExampleMod {&lt;br /&gt;
    BLOCKS.register(FMLJavaModLoadingContext.get.getModEventBus)&lt;br /&gt;
}&lt;br /&gt;
|groovy=private static final DeferredRegister&amp;lt;Block&amp;gt; BLOCKS = DeferredRegister.create(ForgeRegistries.BLOCKS, MODID);&lt;br /&gt;
&lt;br /&gt;
public static final RegistryObject&amp;lt;Block&amp;gt; EXAMPLE_BLOCK = BLOCKS.register(&amp;quot;example_block&amp;quot;, () -&amp;gt; new Block(BlockBehaviour.Properties.of(Material.STONE)));&lt;br /&gt;
&lt;br /&gt;
ExampleMod() {&lt;br /&gt;
    BLOCKS.register(FMLJavaModLoadingContext.get().modEventBus);&lt;br /&gt;
}&lt;br /&gt;
|}}&lt;br /&gt;
&lt;br /&gt;
{{Tip|When using a &amp;lt;code&amp;gt;DeferredRegister&amp;lt;/code&amp;gt; to register any object, the name inputted will be automatically prefixed with the mod id passed in, giving the above object a &amp;quot;registry name&amp;quot; of &amp;lt;code&amp;gt;examplemod:example_block&amp;lt;/code&amp;gt;.}}&lt;br /&gt;
&lt;br /&gt;
=== RegisterEvent ===&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;RegisterEvent&amp;lt;/code&amp;gt; is the second way register objects. This [[Events|event]] is fired for each registry synchronously in vanilla registry order after &amp;lt;code&amp;gt;FMLConstructModEvent&amp;lt;/code&amp;gt; and before the configs are loaded. Objects are registered using &amp;lt;code&amp;gt;#register&amp;lt;/code&amp;gt; by passing in the registry key, the name of the registry object, and the object itself. There is an additional &amp;lt;code&amp;gt;#register&amp;lt;/code&amp;gt; overload which takes in a consumed helper to register an object with a given name. It is recommended to use this method to avoid unnecessary object creation.&lt;br /&gt;
&lt;br /&gt;
Here is an example: (the event handler is registered on the '''mod event bus''')&lt;br /&gt;
&lt;br /&gt;
{{Template:Tabs/Code_Snippets&lt;br /&gt;
|java=@SubscribeEvent&lt;br /&gt;
public void register(RegisterEvent event) {&lt;br /&gt;
    event.register(ForgeRegistries.Keys.BLOCKS,&lt;br /&gt;
        helper -&amp;gt; helper.register(new ResourceLocation(MODID, &amp;quot;example_block&amp;quot;), new Block(...))&lt;br /&gt;
    );&lt;br /&gt;
}&lt;br /&gt;
|kotlin=@JvmStatic&lt;br /&gt;
@SubscribeEvent&lt;br /&gt;
private fun register(event: RegisterEvent) =&lt;br /&gt;
    event.register(ForgeRegistries.Keys.BLOCKS) {&lt;br /&gt;
        helper -&amp;gt; helper.register(ResourceLocation(MODID, &amp;quot;example_block&amp;quot;), Block(...))&lt;br /&gt;
    }&lt;br /&gt;
|scala=@SubscribeEvent&lt;br /&gt;
def register(event: RegisterEvent): Unit =&lt;br /&gt;
    event.register(ForgeRegistries.Keys.BLOCKS,&lt;br /&gt;
        helper =&amp;gt; helper.register(new ResourceLocation(MODID, &amp;quot;example_block&amp;quot;), new Block(...))&lt;br /&gt;
    )&lt;br /&gt;
|}}&lt;br /&gt;
&lt;br /&gt;
{{Tip/Important|Since all objects registered must be singleton, some classes cannot by themselves be registered. Instead, &amp;lt;code&amp;gt;*Type&amp;lt;/code&amp;gt; classes are registered and used in the formers' constructors to wrap the flyweight objects. For example, a [[Basics_of_Block_Entities|&amp;lt;code&amp;gt;BlockEntity&amp;lt;/code&amp;gt;]] is wrapped via &amp;lt;code&amp;gt;BlockEntityType&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;Entity&amp;lt;/code&amp;gt; is wrapped via &amp;lt;code&amp;gt;EntityType&amp;lt;/code&amp;gt;. These &amp;lt;code&amp;gt;*Type&amp;lt;/code&amp;gt; classes hold factories that simply create the containing type on demand.&lt;br /&gt;
&lt;br /&gt;
These factory holders are created through the use of their &amp;lt;code&amp;gt;*Type$Builder&amp;lt;/code&amp;gt; classes. An example: (&amp;lt;code&amp;gt;REGISTER&amp;lt;/code&amp;gt; here refers to a &amp;lt;code&amp;gt;DeferredRegister&amp;lt;BlockEntityType&amp;lt;?&amp;gt;&amp;gt;&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
{{Template:Tabs/Code_Snippets&lt;br /&gt;
|java=public static final RegistryObject&amp;lt;BlockEntityType&amp;lt;ExampleBlockEntity&amp;gt;&amp;gt; EXAMPLE_BLOCK_ENTITY = REGISTER.register(&lt;br /&gt;
    &amp;quot;example_block_entity&amp;quot;, () -&amp;gt; BlockEntityType.Builder.of(ExampleBlockEntity::new, EXAMPLE_BLOCK.get()).build(null)&lt;br /&gt;
);&lt;br /&gt;
|kotlin=val EXAMPLE_BLOCK_ENTITY: RegistryObject&amp;lt;BlockEntityType&amp;lt;ExampleBlockEntity&amp;gt;&amp;gt; = REGISTER.register(&amp;quot;example_block_entity&amp;quot;) { BlockEntityType.Builder.of(::ExampleBlockEntity, EXAMPLE_BLOCK.get()).build(null)) }&lt;br /&gt;
|scala=final val EXAMPLE_BLOCK_ENTITY = REGISTER.register(&amp;quot;example_block_entity&amp;quot;, () =&amp;gt; BlockEntityType.Builder.of(() =&amp;gt; new ExampleBlockEntity(), GeneralRegistrar.EXAMPLE_BLOCK.get).build(null))&lt;br /&gt;
|}}&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
=== Non-Forge Registries ===&lt;br /&gt;
&lt;br /&gt;
Not all vanilla registries are wrapped as a Forge registry. To register objects to any one of these registries, create a &amp;lt;code&amp;gt;DeferredRegister&amp;lt;/code&amp;gt; via the &amp;lt;code&amp;gt;#create&amp;lt;/code&amp;gt; overload which takes in a resource key of the registry and the mod id to register the entries for. Then simply call &amp;lt;code&amp;gt;#register&amp;lt;/code&amp;gt; like any other &amp;lt;code&amp;gt;DeferredRegister&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
{{Template:Tabs/Code_Snippets&lt;br /&gt;
|java=private static final DeferredRegister&amp;lt;LootItemConditionType&amp;gt; REGISTER = DeferredRegister.create(Registry.LOOT_ITEM_REGISTRY, MODID);&lt;br /&gt;
&lt;br /&gt;
public static final RegistryObject&amp;lt;LootItemConditionType&amp;gt; EXAMPLE_LOOT_ITEM_CONDITION_TYPE = REGISTER.register(&amp;quot;example_loot_item_condition_type&amp;quot;, () -&amp;gt; new LootItemConditionType(...));&lt;br /&gt;
|kotlin=private val REGISTER = DeferredRegister.create(Registry.LOOT_ITEM_REGISTRY, MODID)&lt;br /&gt;
&lt;br /&gt;
val EXAMPLE_LOOT_ITEM_CONDITION_TYPE : RegistryObject&amp;lt;LootItemConditionType&amp;gt; = REGISTER.register(&amp;quot;example_loot_item_condition_type&amp;quot;) {&lt;br /&gt;
    LootItemConditionType(...)&lt;br /&gt;
}&lt;br /&gt;
|scala=private final val REGISTER = DeferredRegister.create(Registry.LOOT_ITEM_REGISTRY, MODID)&lt;br /&gt;
&lt;br /&gt;
final val EXAMPLE_LOOT_ITEM_CONDITION_TYPE = REGISTER.register(&amp;quot;example_loot_item_condition_type&amp;quot;, () =&amp;gt; new LootItemConditionType(...))&lt;br /&gt;
|groovy=private static final DeferredRegister&amp;lt;LootItemConditionType&amp;gt; REGISTER = DeferredRegister.create(Registry.LOOT_ITEM_REGISTRY, MODID);&lt;br /&gt;
&lt;br /&gt;
public static final RegistryObject&amp;lt;LootItemConditionType&amp;gt; EXAMPLE_LOOT_ITEM_CONDITION_TYPE = REGISTER.register(&amp;quot;example_loot_item_condition_type&amp;quot;, () -&amp;gt; new LootItemConditionType(...));&lt;br /&gt;
|}}&lt;br /&gt;
&lt;br /&gt;
If you attempt to make one of these instances require an instance of another registry object, you should use the lazy initialization method mentioned above to register the object in the correct order.&lt;br /&gt;
&lt;br /&gt;
=== Data Driven Entries ===&lt;br /&gt;
&lt;br /&gt;
Registries are considered to be data driven if they are located within &amp;lt;code&amp;gt;RegistryAccess&amp;lt;/code&amp;gt; with the exception of &amp;lt;code&amp;gt;LevelStem&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;Level&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
These registry objects only need to be registered within code if they are to be used within a pre-existing registry object (e.g. a &amp;lt;code&amp;gt;PlacedFeature&amp;lt;/code&amp;gt; for ore generation within an overworld &amp;lt;code&amp;gt;Biome&amp;lt;/code&amp;gt;). Otherwise, their instance can be purely registered using a JSON file.&lt;br /&gt;
&lt;br /&gt;
If a data driven registry object has to be registered within code, a dummy object should be supplied to hold a &amp;quot;registry name&amp;quot; and then constructed within a JSON file.&lt;br /&gt;
&lt;br /&gt;
== Referencing Registered Objects ==&lt;br /&gt;
&lt;br /&gt;
Each forge registered object should not be statically initialized nor reference another instance being registered. They must always be a new, singleton instance that is resolved during when &amp;lt;code&amp;gt;RegisterEvent&amp;lt;/code&amp;gt; is called for their registry. This is to maintain a sane loading order for registries and their objects along with dynamic loading/unloading of mods.&lt;br /&gt;
&lt;br /&gt;
Forge registered objects must always be referenced through a &amp;lt;code&amp;gt;RegistryObject&amp;lt;/code&amp;gt; or a field with &amp;lt;code&amp;gt;@ObjectHolder&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
===Using RegistryObjects===&lt;br /&gt;
&amp;lt;code&amp;gt;RegistryObject&amp;lt;/code&amp;gt;s can be used to retrieve references to registered objects once they become available. Their references are updated along with all &amp;lt;code&amp;gt;@ObjectHolder&amp;lt;/code&amp;gt; annotations after the registry that &amp;lt;code&amp;gt;RegisterEvent&amp;lt;/code&amp;gt; is called for is dispatched and frozen.&lt;br /&gt;
&lt;br /&gt;
A &amp;lt;code&amp;gt;RegistryObject&amp;lt;/code&amp;gt; can be retrieved as a result of using &amp;lt;code&amp;gt;DeferredRegister&amp;lt;/code&amp;gt; or calling the static factory &amp;lt;code&amp;gt;RegistryObject#create&amp;lt;/code&amp;gt;. Each static factory takes in the &amp;quot;registry name&amp;quot; of the object being referenced and one of the following: a &amp;lt;code&amp;gt;IForgeRegistry&amp;lt;/code&amp;gt;, a registry name of the type &amp;lt;code&amp;gt;ResourceLocation&amp;lt;/code&amp;gt;, or a registry key of the type &amp;lt;code&amp;gt;ResourceKey&amp;lt;? extends Registry&amp;lt;?&amp;gt;&amp;gt;&amp;lt;/code&amp;gt;. The &amp;lt;code&amp;gt;RegistryObject&amp;lt;/code&amp;gt; can be stored within some field and retrieve the registered object using &amp;lt;code&amp;gt;#get&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
An example using &amp;lt;code&amp;gt;RegistryObject&amp;lt;/code&amp;gt;:&lt;br /&gt;
{{Template:Tabs/Code_Snippets&lt;br /&gt;
|java=public static final RegistryObject&amp;lt;Item&amp;gt; EXAMPLE_ITEM = RegistryObject.create(new ResourceLocation(&amp;quot;examplemod&amp;quot;, &amp;quot;example_item&amp;quot;), ForgeRegistries.ITEMS);&lt;br /&gt;
&lt;br /&gt;
// Assume that 'examplemod:example_registry' is a valid registry, and 'examplemod:example_object' is a valid object within that registry&lt;br /&gt;
public static final RegistryObject&amp;lt;ExampleRegistry&amp;gt; EXAMPLE_OBJECT = RegistryObject.create(new ResourceLocation(&amp;quot;examplemod&amp;quot;, &amp;quot;example_object&amp;quot;), new ResourceLocation(&amp;quot;examplemod&amp;quot;, &amp;quot;example_registry&amp;quot;), &amp;quot;examplemod&amp;quot;); &lt;br /&gt;
|kotlin=val EXAMPLE_ITEM: RegistryObject&amp;lt;Item&amp;gt; = RegistryObject.create(ResourceLocation(&amp;quot;examplemod&amp;quot;, &amp;quot;example_item&amp;quot;), ForgeRegistries.ITEMS)&lt;br /&gt;
&lt;br /&gt;
// Assume that 'examplemod:example_registry' is a valid registry, and 'examplemod:example_object' is a valid object within that registry&lt;br /&gt;
val EXAMPLE_OBJECT: RegistryObject&amp;lt;ExampleRegistry&amp;gt; = RegistryObject.create(ResourceLocation(&amp;quot;examplemod&amp;quot;, &amp;quot;example_object&amp;quot;), new ResourceLocation(&amp;quot;examplemod&amp;quot;, &amp;quot;example_registry&amp;quot;), &amp;quot;examplemod&amp;quot;)&lt;br /&gt;
|scala=final val EXAMPLE_ITEM = RegistryObject.create(new ResourceLocation(&amp;quot;examplemod&amp;quot;, &amp;quot;example_item&amp;quot;), ForgeRegistries.ITEMS)&lt;br /&gt;
&lt;br /&gt;
// Assume that 'examplemod:example_registry' is a valid registry, and 'examplemod:example_object' is a valid object within that registry&lt;br /&gt;
final val EXAMPLE_OBJECT = RegistryObject.create(new ResourceLocation(&amp;quot;examplemod&amp;quot;, &amp;quot;example_object&amp;quot;), new ResourceLocation(&amp;quot;examplemod&amp;quot;, &amp;quot;example_registry&amp;quot;), &amp;quot;examplemod&amp;quot;); &lt;br /&gt;
|}}&lt;br /&gt;
&lt;br /&gt;
{{Tip/Important|All vanilla objects are bootstrapped and registered before mods are loaded. As such, they can be referenced as is without any issues.}}&lt;br /&gt;
&lt;br /&gt;
=== Using @ObjectHolder ===&lt;br /&gt;
&lt;br /&gt;
Forge registry objects can also be injected into &amp;lt;code&amp;gt;public static&amp;lt;/code&amp;gt; fields with either their class or that field annotated with &amp;lt;code&amp;gt;@ObjectHolder&amp;lt;/code&amp;gt;. There must be enough information to construct a &amp;lt;code&amp;gt;ResourceLocation&amp;lt;/code&amp;gt; to identify a single object within a specific registry.&lt;br /&gt;
&lt;br /&gt;
The rules for &amp;lt;code&amp;gt;@ObjectHolder&amp;lt;/code&amp;gt; are as follows:&lt;br /&gt;
&lt;br /&gt;
* If the class is annotated with &amp;lt;code&amp;gt;@ObjectHolder&amp;lt;/code&amp;gt;, its value will be the default namespace for all fields within if not explicitly defined&lt;br /&gt;
* If the class is annotated with &amp;lt;code&amp;gt;@Mod&amp;lt;/code&amp;gt;, the modid will be the default namespace for all annotated fields within if not explicitly defined &lt;br /&gt;
* A field is considered for injection if:&lt;br /&gt;
** it has at least the modifiers &amp;lt;code&amp;gt;public static&amp;lt;/code&amp;gt;; and&lt;br /&gt;
** one of the following conditions are true:&lt;br /&gt;
*** the '''enclosing class''' has an &amp;lt;code&amp;gt;@ObjectHolder&amp;lt;/code&amp;gt; annotation, and the field is &amp;lt;code&amp;gt;final&amp;lt;/code&amp;gt;, and:&lt;br /&gt;
**** the name value is the field's name; and&lt;br /&gt;
**** the namespace value is the enclosing class's namespace&lt;br /&gt;
**** ''An exception is thrown if the namespace value cannot be found and inherited''&lt;br /&gt;
*** the '''field''' is annotated with &amp;lt;code&amp;gt;@ObjectHolder&amp;lt;/code&amp;gt;, and:&lt;br /&gt;
**** the name value is explicitly defined; and&lt;br /&gt;
**** the namespace value is either explicitly defined or the enclosing class's namespace&lt;br /&gt;
** the field type or one of its supertypes corresponds to a valid registry (e.g. &amp;lt;code&amp;gt;Item&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;ArrowItem&amp;lt;/code&amp;gt; for the &amp;lt;code&amp;gt;Item&amp;lt;/code&amp;gt; registry)&lt;br /&gt;
** ''An exception is thrown if a field does not have a corresponding registry.''&lt;br /&gt;
* ''An exception is thrown if the resulting &amp;lt;code&amp;gt;ResourceLocation&amp;lt;/code&amp;gt; is incomplete or invalid (non-valid characters in path)''&lt;br /&gt;
* If no other errors or exceptions occur, the field will be injected&lt;br /&gt;
* If all of the above rules do not apply, no action will be taken (and a message may be logged)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;@ObjectHolder&amp;lt;/code&amp;gt; annotated fields are injected with their associated object values after &amp;lt;code&amp;gt;RegisterEvent&amp;lt;/code&amp;gt; is fired for their registry, along with &amp;lt;code&amp;gt;RegistryObject&amp;lt;/code&amp;gt;s.&lt;br /&gt;
&lt;br /&gt;
{{Tip/Warning|If the object does not exist in the registry when it is to be injected, a debug message will be logged, and no value will be injected. If the object is found, but the field cannot be set, a warning message will be logged instead.}}&lt;br /&gt;
&lt;br /&gt;
As these rules are rather complicated, here are some examples:&lt;br /&gt;
&amp;lt;div class=&amp;quot;mw-collapsible mw-collapsed&amp;quot; style=&amp;quot;border: solid 2px; padding: 2px 5px; margin-top: 3px&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;div style=&amp;quot;font-weight:bold;line-height:1.6;&amp;quot;&amp;gt;Example uses of &amp;lt;code&amp;gt;@ObjectHolder&amp;lt;/code&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;div class=&amp;quot;mw-collapsible-content&amp;quot; style=&amp;quot;overflow: auto; white-space: nowrap;&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
@ObjectHolder(&amp;quot;minecraft&amp;quot;) // Inheritable resource namespace: &amp;quot;minecraft&amp;quot;&lt;br /&gt;
class AnnotatedHolder {&lt;br /&gt;
    public static final Block diamond_block = null;   // No annotation. [public static final] is required.&lt;br /&gt;
                                                      // Block has a corresponding registry: [Block]&lt;br /&gt;
                                                      // Name path is the name of the field: &amp;quot;diamond_block&amp;quot;&lt;br /&gt;
                                                      // Namespace is not explicitly defined.&lt;br /&gt;
                                                      // So, namespace is inherited from class annotation: &amp;quot;minecraft&amp;quot;&lt;br /&gt;
                                                      // To inject: &amp;quot;minecraft:diamond_block&amp;quot; from the [Block] registry&lt;br /&gt;
&lt;br /&gt;
    @ObjectHolder(&amp;quot;ambient.cave&amp;quot;)&lt;br /&gt;
    public static SoundEvent ambient_sound = null;    // Annotation present. [public static] is required.&lt;br /&gt;
                                                      // SoundEvent has a corresponding registry: [SoundEvent]&lt;br /&gt;
                                                      // Name path is the value of the annotation: &amp;quot;ambient.cave&amp;quot;&lt;br /&gt;
                                                      // Namespace is not explicitly defined.&lt;br /&gt;
                                                      // So, namespace is inherited from class annotation: &amp;quot;minecraft&amp;quot;&lt;br /&gt;
                                                      // To inject: &amp;quot;minecraft:ambient.cave&amp;quot; from the [SoundEvent] registry&lt;br /&gt;
&lt;br /&gt;
    // Assume for the next entry that [ManaType] is a valid registry.          &lt;br /&gt;
    @ObjectHolder(&amp;quot;neomagicae:coffeinum&amp;quot;)&lt;br /&gt;
    public static final ManaType coffeinum = null;    // Annotation present. [public static] is required. [final] is optional.&lt;br /&gt;
                                                      // ManaType has a corresponding registry: [ManaType] (custom registry)&lt;br /&gt;
                                                      // Resource location is explicitly defined: &amp;quot;neomagicae:coffeinum&amp;quot;&lt;br /&gt;
                                                      // To inject: &amp;quot;neomagicae:coffeinum&amp;quot; from the [ManaType] registry&lt;br /&gt;
&lt;br /&gt;
    public static final Item ENDER_PEARL = null;      // No annotation. [public static final] is required.&lt;br /&gt;
                                                      // Item has a corresponding registry: [Item].&lt;br /&gt;
                                                      // Name path is the name of the field: &amp;quot;ENDER_PEARL&amp;quot; -&amp;gt; &amp;quot;ender_pearl&amp;quot;&lt;br /&gt;
                                                      // !! ^ Field name is valid, because they are&lt;br /&gt;
                                                      //      converted to lowercase automatically.&lt;br /&gt;
                                                      // Namespace is not explicitly defined.&lt;br /&gt;
                                                      // So, namespace is inherited from class annotation: &amp;quot;minecraft&amp;quot;&lt;br /&gt;
                                                      // To inject: &amp;quot;minecraft:ender_pearl&amp;quot; from the [Item] registry&lt;br /&gt;
&lt;br /&gt;
    @ObjectHolder(&amp;quot;minecraft:arrow&amp;quot;)&lt;br /&gt;
    public static final ArrowItem arrow = null;       // Annotation present. [public static] is required. [final] is optional.&lt;br /&gt;
                                                      // ArrowItem does not have a corresponding registry.&lt;br /&gt;
                                                      // ArrowItem's supertype of Item has a corresponding registry: [Item]&lt;br /&gt;
                                                      // Resource location is explicitly defined: &amp;quot;minecraft:arrow&amp;quot;&lt;br /&gt;
                                                      // To inject: &amp;quot;minecraft:arrow&amp;quot; from the [Item] registry                                                    &lt;br /&gt;
&lt;br /&gt;
    public static Block bedrock = null;               // No annotation, so [public static final] is required.&lt;br /&gt;
                                                      // Therefore, the field is ignored.&lt;br /&gt;
    &lt;br /&gt;
    public static final CreativeModeTab group = null; // No annotation. [public static final] is required.&lt;br /&gt;
                                                      // CreativeModeTab does not have a corresponding registry.&lt;br /&gt;
                                                      // No supertypes of CreativeModeTab has a corresponding registry.&lt;br /&gt;
                                                      // Therefore, THIS WILL PRODUCE AN EXCEPTION.&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
class UnannotatedHolder { // Note the lack of an @ObjectHolder annotation on this class.&lt;br /&gt;
    @ObjectHolder(&amp;quot;minecraft:flame&amp;quot;)&lt;br /&gt;
    public static final Enchantment flame = null;     // Annotation present. [public static] is required. [final] is optional.&lt;br /&gt;
                                                      // Enchantment has corresponding registry: [Enchantment].&lt;br /&gt;
                                                      // Resource location is explicitly defined: &amp;quot;minecraft:flame&amp;quot;&lt;br /&gt;
                                                      // To inject: &amp;quot;minecraft:flame&amp;quot; from the [Enchantment] registry&lt;br /&gt;
&lt;br /&gt;
    public static final Biome ice_flat = null;        // No annotation on the enclosing class.&lt;br /&gt;
                                                      // Therefore, the field is ignored.&lt;br /&gt;
&lt;br /&gt;
    @ObjectHolder(&amp;quot;minecraft:creeper&amp;quot;)&lt;br /&gt;
    public static Entity creeper = null;              // Annotation present. [public static] is required.&lt;br /&gt;
                                                      // Entity does not have a corresponding registry.&lt;br /&gt;
                                                      // No supertypes of Entity has a corresponding registry.&lt;br /&gt;
                                                      // Therefore, THIS WILL PRODUCE AN EXCEPTION.&lt;br /&gt;
&lt;br /&gt;
    @ObjectHolder(&amp;quot;levitation&amp;quot;)&lt;br /&gt;
    public static final Potion levitation = null;     // Annotation present. [public static] is required. [final] is optional.&lt;br /&gt;
                                                      // Potion has a corresponding registry: [Potion].&lt;br /&gt;
                                                      // Name path is the value of the annotation: &amp;quot;levitation&amp;quot;&lt;br /&gt;
                                                      // Namespace is not explicitly defined.&lt;br /&gt;
                                                      // No annotation in enclosing class.&lt;br /&gt;
                                                      // Therefore, THIS WILL PRODUCE AN EXCEPTION.&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Creating Custom Registries ==&lt;br /&gt;
&lt;br /&gt;
Creating custom registries for your mod might be useful if you want other mods to add new things to your system. For example, you might have magic spells and want to allow other mods to add new spells. For this you will want to make a registry (eg. &amp;quot;mymagicmod:spells&amp;quot;). This way, other mods will be able to register things to that list, and you won't have to do anything else.&lt;br /&gt;
&lt;br /&gt;
Just like with registering a new item or block you have two ways of making a new registry. Each method takes in a &amp;lt;code&amp;gt;RegistryBuilder&amp;lt;/code&amp;gt; which is used to build an &amp;lt;code&amp;gt;IForgeRegistry&amp;lt;/code&amp;gt;. Each builder should have its name set via &amp;lt;code&amp;gt;#setName&amp;lt;/code&amp;gt; before being created.&lt;br /&gt;
&lt;br /&gt;
=== With DeferredRegister ===&lt;br /&gt;
&lt;br /&gt;
The first method involves the second static constructor: &amp;lt;code&amp;gt;DeferredRegister#create(ResourceLocation, String)&amp;lt;/code&amp;gt;. From there, we can construct the registry using &amp;lt;code&amp;gt;#makeRegistry&amp;lt;/code&amp;gt;. This will already populate &amp;lt;code&amp;gt;#setName&amp;lt;/code&amp;gt; for us. This method also returns a supplier of the registry which we can use after the &amp;lt;code&amp;gt;NewRegistryEvent&amp;lt;/code&amp;gt; is called.&lt;br /&gt;
&lt;br /&gt;
Here is an example:&lt;br /&gt;
&lt;br /&gt;
{{Template:Tabs/Code_Snippets&lt;br /&gt;
|java=public static final DeferredRegister&amp;lt;ExampleRegistry&amp;gt; EXAMPLE = DeferredRegister.create(new ResourceLocation(MODID, &amp;quot;example_registry&amp;quot;), MODID);&lt;br /&gt;
&lt;br /&gt;
public static final Supplier&amp;lt;IForgeRegistry&amp;lt;ExampleRegistry&amp;gt;&amp;gt; REGISTRY = EXAMPLE.makeRegistry(RegistryBuilder::new);&lt;br /&gt;
|kotlin=val EXAMPLE: DeferredRegister&amp;lt;ExampleRegistry&amp;gt; = DeferredRegister.create(ResourceLocation(MODID, &amp;quot;example_registry&amp;quot;), MODID)&lt;br /&gt;
&lt;br /&gt;
val REGISTRY: IForgeRegistry&amp;lt;ExampleRegistry&amp;gt; by lazy {&lt;br /&gt;
    EXAMPLE.makeRegistry(::RegistryBuilder).get()&lt;br /&gt;
}&lt;br /&gt;
|scala=final val EXAMPLE = DeferredRegister.create(new ResourceLocation(MODID, &amp;quot;example_registry&amp;quot;), MODID)&lt;br /&gt;
&lt;br /&gt;
final lazy val REGISTRY = EXAMPLE.makeRegistry(() =&amp;gt; new RegistryBuilder).get&lt;br /&gt;
|}}&lt;br /&gt;
&lt;br /&gt;
=== Using `NewRegistryEvent` ===&lt;br /&gt;
&lt;br /&gt;
The second method can be done during the &amp;lt;code&amp;gt;NewRegistryEvent&amp;lt;/code&amp;gt; event. Using &amp;lt;code&amp;gt;NewRegistryEvent#create&amp;lt;/code&amp;gt;, you can pass in a &amp;lt;code&amp;gt;RegistryBuilder&amp;lt;/code&amp;gt; directly. This method will return a &amp;lt;code&amp;gt;Supplier&amp;lt;IForgeRegistry&amp;lt;V&amp;gt;&amp;gt;&amp;lt;/code&amp;gt; that can be stored and queried after the event is fired to gain access to your &amp;lt;code&amp;gt;IForgeRegistry&amp;lt;/code&amp;gt; instance.&lt;br /&gt;
&lt;br /&gt;
Here is an example: (the event handler is registered on the '''mod event bus''')&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;Java&amp;quot;&amp;gt;&lt;br /&gt;
public static Supplier&amp;lt;IForgeRegistry&amp;lt;ExampleRegistry&amp;gt;&amp;gt; registrySupplier = null;&lt;br /&gt;
&lt;br /&gt;
@SubscribeEvent&lt;br /&gt;
public void onNewRegistry(NewRegistryEvent event){&lt;br /&gt;
    RegistryBuilder&amp;lt;ExampleRegistry&amp;gt; registryBuilder = new RegistryBuilder&amp;lt;&amp;gt;();&lt;br /&gt;
    registryBuilder.setName(new ResourceLocation(MODID, &amp;quot;example_registry&amp;quot;);&lt;br /&gt;
    registrySupplier = event.create(registryBuilder);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Handling Missing Entries ==&lt;br /&gt;
&lt;br /&gt;
When loading a pre-existing world after removing mods or updating versions, there are cases where certain registry objects will cease to exist. In these cases, it is possible to specify actions to remove a mapping, prevent the world from loading, or remap the name as needed. This can be done through the third of the registry events: &amp;lt;code&amp;gt;MissingMappingsEvent&amp;lt;/code&amp;gt;. Within the event, you can grab an immutable list of missing mappings associated with a mod id for a given registry via &amp;lt;code&amp;gt;#getMappings&amp;lt;/code&amp;gt; or a list of all mappings via &amp;lt;code&amp;gt;#getAllMappings&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
For each &amp;lt;code&amp;gt;Mapping&amp;lt;/code&amp;gt;, you can either execute one of the following methods:&lt;br /&gt;
* &amp;lt;code&amp;gt;#ignore&amp;lt;/code&amp;gt; which abandons the entry when loading&lt;br /&gt;
* &amp;lt;code&amp;gt;#warn&amp;lt;/code&amp;gt; which warns the user about the missing entry but continues loading&lt;br /&gt;
* &amp;lt;code&amp;gt;#fail&amp;lt;/code&amp;gt; which prevents the world from loading&lt;br /&gt;
* &amp;lt;code&amp;gt;#remap&amp;lt;/code&amp;gt; which remaps the entry to the specified non-null object in the same registry&lt;br /&gt;
&lt;br /&gt;
If none of the above are specified, then the default action of notifying the user about the missing mappings occur.&lt;br /&gt;
&lt;br /&gt;
Here is an example:  (the event handler is registered on the '''forge event bus''')&lt;br /&gt;
&lt;br /&gt;
{{Template:Tabs/Code_Snippets&lt;br /&gt;
|java=// This will ignore any missing test items from the specified world&lt;br /&gt;
@SubscribeEvent&lt;br /&gt;
public void onMissing(final MissingMappingsEvent event) {&lt;br /&gt;
    event.getMappings(ForgeRegistries.Keys.ITEMS, MODID).stream()&lt;br /&gt;
        .filter(mapping -&amp;gt; mapping.key.getPath().contains(&amp;quot;test&amp;quot;))&lt;br /&gt;
            .forEach(Mapping::ignore);&lt;br /&gt;
}&lt;br /&gt;
|groovy=// This will ignore any missing test items from the specified world&lt;br /&gt;
@SubscribeEvent&lt;br /&gt;
void onMissing(final MissingMappingsEvent event) {&lt;br /&gt;
    event.getMappings(ForgeRegistries.Keys.ITEMS, MODID).stream()&lt;br /&gt;
        .filter(mapping -&amp;gt; mapping.key.path.contains(&amp;quot;test&amp;quot;))&lt;br /&gt;
            .forEach(Mapping::ignore);&lt;br /&gt;
}&lt;br /&gt;
|}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Common Concepts]]&lt;/div&gt;</summary>
		<author><name>SizableShrimp</name></author>
	</entry>
	<entry>
		<id>https://forge.gemwire.uk/index.php?title=Main_Page/1.18&amp;diff=3248</id>
		<title>Main Page/1.18</title>
		<link rel="alternate" type="text/html" href="https://forge.gemwire.uk/index.php?title=Main_Page/1.18&amp;diff=3248"/>
		<updated>2022-06-10T08:03:34Z</updated>

		<summary type="html">&lt;p&gt;SizableShrimp: Biome modifiers do not exist on 1.18&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/1.18|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/1.18|Getting Started]]&lt;br /&gt;
* [[Proper Mod Structuring/1.18|Proper Mod Structuring]]&lt;br /&gt;
* [[Mods.toml file/1.18|Mods.toml file]]&lt;br /&gt;
* [[Debug Profiler/1.18|The Debug Profiler]]&lt;br /&gt;
* [[Version Checker/1.18|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/1.18|Understanding Sides]]&lt;br /&gt;
* [[Events/1.18|Understanding Events]]&lt;br /&gt;
* [[Registration/1.18|Registration]]&lt;br /&gt;
* [[Internationalization/1.18|Internationalization]]&lt;br /&gt;
* [[Configs/1.18|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/1.18|Semantic Versioning]]&lt;br /&gt;
* [[Stages of Modloading/1.18|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/1.18|Introduction]]&lt;br /&gt;
* [[Recipes/1.18|Recipes]]&lt;br /&gt;
* [[Tags/1.18|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/1.18|Creating Blocks]]&lt;br /&gt;
* [[Understanding Blockstates/1.18|Understanding Blockstates]] &lt;br /&gt;
* [[Interacting With Blocks/1.18|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/1.18|Making Items]]&lt;br /&gt;
* [[Making Tools/1.18|Making Tools]]&lt;br /&gt;
* [[BlockEntityWithoutLevelRenderer/1.18|&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/1.18|Introduction]]&lt;br /&gt;
* [[Datageneration/Recipes/1.18|Recipes]]&lt;br /&gt;
* [[Datageneration/Tags/1.18|Tags]]&lt;br /&gt;
* [[Datageneration/Loot Tables/1.18|Loot Tables]]&lt;br /&gt;
* [[Datageneration/I18n/1.18|Localization]]&lt;br /&gt;
* [[Datageneration/States and Models/1.18|&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/1.18|Introduction]]&lt;br /&gt;
* [[Block Entity Renderer/1.18|&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/1.18|Introduction]]&lt;br /&gt;
* [[Model JSONs/1.18|Model JSONs]]&lt;br /&gt;
* [[BlockState JSONs/1.18|BlockState JSONs]]&lt;br /&gt;
* [[Coloring textures dynamically/1.18|Dynamically Colored Textures]]&lt;br /&gt;
* [[Item Properties/1.18|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/1.18|Introduction]]&lt;br /&gt;
* [[Using NBT/1.18|Named Binary Tag (NBT)]]&lt;br /&gt;
* [[Using FriendlyByteBuf/1.18|Using &amp;lt;tt&amp;gt;FriendlyByteBuf&amp;lt;/tt&amp;gt;]]&lt;br /&gt;
* [[Sending Packets/1.18|Sending and Receiving Packets]]&lt;br /&gt;
* [[Using SimpleChannel/1.18|Using &amp;lt;tt&amp;gt;SimpleChannel&amp;lt;/tt&amp;gt;]]&lt;br /&gt;
* [[Networking with Entities/1.18|Networking with Entities]]&lt;br /&gt;
* [[DynamicOps/1.18|Using DynamicOps]]&lt;br /&gt;
* [[Codecs/1.18|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/1.18|Understanding Capabilities]] &lt;br /&gt;
* [[Capabilities/Attaching/1.18|Attaching Capabilities]]&lt;br /&gt;
* [[Saved Data/1.18|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/1.18|Mob Effects]]&lt;br /&gt;
* [[Potions/1.18|Potions]]&lt;br /&gt;
* [[Particles/1.18|Particles]]&lt;br /&gt;
* [[Sounds/1.18|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/1.18|Understanding Events]]&lt;br /&gt;
* [[Entity Events/1.18|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/1.18|Dependencies]]&lt;br /&gt;
* [[Dynamic Loot Modification/1.18|Dynamic Loot Modification]]&lt;br /&gt;
* [[Components/1.18|Components and Translation Keys]]&lt;br /&gt;
* [[Key Mappings/1.18|Key Mappings]]&lt;br /&gt;
* [[Access Transformers/1.18|Access Transformers]]&lt;br /&gt;
* [[Toolchain/1.18|Toolchain]]&lt;br /&gt;
* [[Game Tests/1.18|Game Tests]]&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/1.18|Recipes]]&lt;br /&gt;
* [[Custom Recipes/1.18|Custom Recipe Types]]&lt;br /&gt;
* [[Datageneration/Recipes/1.18|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>SizableShrimp</name></author>
	</entry>
	<entry>
		<id>https://forge.gemwire.uk/index.php?title=Template:Supported_versions&amp;diff=3247</id>
		<title>Template:Supported versions</title>
		<link rel="alternate" type="text/html" href="https://forge.gemwire.uk/index.php?title=Template:Supported_versions&amp;diff=3247"/>
		<updated>2022-06-10T08:02:08Z</updated>

		<summary type="html">&lt;p&gt;SizableShrimp: Add 1.19 to support box&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{#if:{{{text|}}}&lt;br /&gt;
|The current ''Latest'' version is '''1.19'''. The current ''Long Term Support (LTS)'' version is '''1.18.2'''.&lt;br /&gt;
|{{#vardefine: page | Main Page }}&lt;br /&gt;
{{Colored box&lt;br /&gt;
|border-color=#3498db&lt;br /&gt;
|title={{{title|This wiki hosts information for the following Minecraft versions:}}}&lt;br /&gt;
|{{{1|* [[{{#var:page}}|1.19]]&lt;br /&gt;
* [[{{#var:page}}/1.18|1.18]]&lt;br /&gt;
* [[{{#var:page}}/1.17|1.17]]&lt;br /&gt;
* [[{{#var:page}}/1.16|1.16]]}}}&lt;br /&gt;
}}}}&lt;/div&gt;</summary>
		<author><name>SizableShrimp</name></author>
	</entry>
	<entry>
		<id>https://forge.gemwire.uk/index.php?title=Template:Supported_versions&amp;diff=3142</id>
		<title>Template:Supported versions</title>
		<link rel="alternate" type="text/html" href="https://forge.gemwire.uk/index.php?title=Template:Supported_versions&amp;diff=3142"/>
		<updated>2022-06-10T01:09:32Z</updated>

		<summary type="html">&lt;p&gt;SizableShrimp: 1.19, still need to copy all pages&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{#if:{{{text|}}}&lt;br /&gt;
|The current ''Latest'' version is '''1.19'''. The current ''Long Term Support (LTS)'' version is '''1.18.2'''.&lt;br /&gt;
|{{#vardefine: page | Main Page }}&lt;br /&gt;
{{Colored box&lt;br /&gt;
|border-color=#3498db&lt;br /&gt;
|title={{{title|This wiki hosts information for the following Minecraft versions:}}}&lt;br /&gt;
|{{{1|* [[{{#var:page}}|1.18]]&lt;br /&gt;
* [[{{#var:page}}/1.17|1.17]]&lt;br /&gt;
* [[{{#var:page}}/1.16|1.16]]}}}&lt;br /&gt;
}}}}&lt;/div&gt;</summary>
		<author><name>SizableShrimp</name></author>
	</entry>
	<entry>
		<id>https://forge.gemwire.uk/index.php?title=Registration&amp;diff=3137</id>
		<title>Registration</title>
		<link rel="alternate" type="text/html" href="https://forge.gemwire.uk/index.php?title=Registration&amp;diff=3137"/>
		<updated>2022-04-03T18:26:44Z</updated>

		<summary type="html">&lt;p&gt;SizableShrimp: Some cleanup based on #8527 vanilla Deferred Registers&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Under construction}}&lt;br /&gt;
&lt;br /&gt;
Registration is the process of making an object (such as an item or block) known to the game during runtime. If some objects are not registered, this could cause crashes even before the game is fully loaded or arbitrary behaviors such as bottlenecking mod compatibility for world generation.&lt;br /&gt;
&lt;br /&gt;
Most objects that are known within the game are handled by a &amp;lt;code&amp;gt;Registry&amp;lt;/code&amp;gt;. Each registry uniquely defines each object through a &amp;quot;registry name&amp;quot; via a [[Using Resources#ResourceLocation|ResourceLocation]]. This &amp;quot;registry name&amp;quot; can be accessed with its respective getter and setter: &amp;lt;code&amp;gt;#getRegistryName&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;#setRegistryName&amp;lt;/code&amp;gt;. You can only set the &amp;quot;registry name&amp;quot; of a given object once; otherwise, an exception will be thrown.&lt;br /&gt;
&lt;br /&gt;
{{Tip|In a global context, each object is universally unique through its &amp;lt;code&amp;gt;ResourceKey&amp;lt;/code&amp;gt;: a concatenation of its registry's id and the object's registry name.}}&lt;br /&gt;
&lt;br /&gt;
Due to the inconsistent ordering and registration process vanilla uses, Forge wraps most vanilla registries using &amp;lt;code&amp;gt;IForgeRegistry&amp;lt;/code&amp;gt;. This guarantees that the loading order for these wrapped registries will be &amp;lt;code&amp;gt;Block&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;Item&amp;lt;/code&amp;gt;, and then the rest of the wrapped registries in alphabetical order. All registries supported by Forge can be found within the &amp;lt;code&amp;gt;ForgeRegistries&amp;lt;/code&amp;gt; class. Since all registry names are unique to a specific registry, different registry objects within different registries can have the same name (e.g. a &amp;lt;code&amp;gt;Block&amp;lt;/code&amp;gt; and an &amp;lt;code&amp;gt;Item&amp;lt;/code&amp;gt; each hold a registry object named &amp;lt;code&amp;gt;examplemod:object&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
{{Tip/Warning|If two registry objects within the same registry have the same name, the second object will override the first. The only registry that will throw an &amp;lt;code&amp;gt;IllegalArgumentException&amp;lt;/code&amp;gt; is the &amp;lt;code&amp;gt;DataSerializerEntry&amp;lt;/code&amp;gt; registry.}}&lt;br /&gt;
&lt;br /&gt;
== Methods for Registering ==&lt;br /&gt;
&lt;br /&gt;
There are two proper ways to register objects within an associated wrapped Forge registry: the &amp;lt;code&amp;gt;DeferredRegister&amp;lt;/code&amp;gt; class, and the &amp;lt;code&amp;gt;RegistryEvent$Register&amp;lt;/code&amp;gt; lifecycle event.&lt;br /&gt;
&lt;br /&gt;
For objects with '''no''' associated Forge registry, you can register the associated entry during the &amp;lt;code&amp;gt;FMLCommonSetupEvent&amp;lt;/code&amp;gt; lifecycle event. In some cases, although not recommended, you may also statically initialize and register these entries.&lt;br /&gt;
&lt;br /&gt;
=== DeferredRegister ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;DeferredRegister&amp;lt;/code&amp;gt; is an abstraction layer over the registry event used to register objects. It maintains a map of &amp;quot;registry name&amp;quot; to their associated suppliers and resolves those suppliers during the proper &amp;lt;code&amp;gt;RegistryEvent$Register&amp;lt;/code&amp;gt; event. This method is the currently recommended, and documented, way to handle these objects as it provides convenience and safety for those who want to statically initialize objects while avoiding some issues associated with it. &lt;br /&gt;
&lt;br /&gt;
An example of a mod registering a custom block:&lt;br /&gt;
&lt;br /&gt;
{{Template:Tabs/Code_Snippets&lt;br /&gt;
|java=private static final DeferredRegister&amp;lt;Block&amp;gt; BLOCKS = DeferredRegister.create(ForgeRegistries.BLOCKS, MODID);&lt;br /&gt;
&lt;br /&gt;
public static final RegistryObject&amp;lt;Block&amp;gt; EXAMPLE_BLOCK = BLOCKS.register(&amp;quot;example_block&amp;quot;, () -&amp;gt; new Block(BlockBehaviour.Properties.of(Material.STONE)));&lt;br /&gt;
&lt;br /&gt;
public ExampleMod() {&lt;br /&gt;
    BLOCKS.register(FMLJavaModLoadingContext.get().getModEventBus());&lt;br /&gt;
}&lt;br /&gt;
|kotlin=private val BLOCKS = DeferredRegister.create(ForgeRegistries.BLOCKS, MODID)&lt;br /&gt;
&lt;br /&gt;
val EXAMPLE_BLOCK: RegistryObject&amp;lt;Block&amp;gt; = BLOCKS.register(&amp;quot;example_block&amp;quot;) { Block(BlockBehaviour.Properties.of(Material.ROCK)) }&lt;br /&gt;
&lt;br /&gt;
internal class ExampleMod {&lt;br /&gt;
    init {&lt;br /&gt;
        BLOCKS.register(FMLJavaModLoadingContext.get().modEventBus)&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
|scala=object ExampleMod {&lt;br /&gt;
    private final val BLOCKS = DeferredRegister.create(ForgeRegistries.BLOCKS, MODID)&lt;br /&gt;
&lt;br /&gt;
    final val EXAMPLE_BLOCK = registerBlock(&amp;quot;example_block&amp;quot;, () =&amp;gt; new Block(BlockBehaviour.Properties.of(Material.ROCK)))&lt;br /&gt;
}&lt;br /&gt;
class ExampleMod {&lt;br /&gt;
    BLOCKS.register(FMLJavaModLoadingContext.get.getModEventBus)&lt;br /&gt;
}&lt;br /&gt;
|groovy=private static final DeferredRegister&amp;lt;Block&amp;gt; BLOCKS = DeferredRegister.create(ForgeRegistries.BLOCKS, MODID);&lt;br /&gt;
&lt;br /&gt;
public static final RegistryObject&amp;lt;Block&amp;gt; EXAMPLE_BLOCK = BLOCKS.register(&amp;quot;example_block&amp;quot;, () -&amp;gt; new Block(BlockBehaviour.Properties.of(Material.STONE)));&lt;br /&gt;
&lt;br /&gt;
ExampleMod() {&lt;br /&gt;
    BLOCKS.register(FMLJavaModLoadingContext.get().modEventBus);&lt;br /&gt;
}&lt;br /&gt;
|}}&lt;br /&gt;
&lt;br /&gt;
{{Tip|When using a &amp;lt;code&amp;gt;DeferredRegister&amp;lt;/code&amp;gt; to register any object, the name inputted will be automatically prefixed with the mod id passed in, giving the above object a &amp;quot;registry name&amp;quot; of &amp;lt;code&amp;gt;examplemod:example_block&amp;lt;/code&amp;gt;.}}&lt;br /&gt;
&lt;br /&gt;
=== RegistryEvent.Register ===&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;RegistryEvent&amp;lt;/code&amp;gt;s are another, more slightly flexible way to register objects. These [[Events|events]] are fired synchronously after &amp;lt;code&amp;gt;FMLConstructModEvent&amp;lt;/code&amp;gt; and before the configs are loaded.&lt;br /&gt;
&lt;br /&gt;
The event used to register objects is &amp;lt;code&amp;gt;RegistryEvent.Register&amp;lt;T&amp;gt;&amp;lt;/code&amp;gt;, where the type parameter &amp;lt;code&amp;gt;T&amp;lt;/code&amp;gt; is the object type being registered. You can grab the associated registry using &amp;lt;code&amp;gt;#getRegistry&amp;lt;/code&amp;gt; and register the objects within using either &amp;lt;code&amp;gt;#register&amp;lt;/code&amp;gt; (pass in a single object) or &amp;lt;code&amp;gt;#registerAll&amp;lt;/code&amp;gt; (pass in ''varargs'' or an array of objects). The latter is useful for minimizing calls to &amp;lt;code&amp;gt;#register&amp;lt;/code&amp;gt;, although it provides no benefit time-complexity wise.&lt;br /&gt;
&lt;br /&gt;
{{Tip/Important|The type parameter specified must be the exact class used within the Forge registry, not its superclass nor its subclass. If the class specified is not referenced as a type parameter within the associated Forge registries, then the event will not be called.}}&lt;br /&gt;
&lt;br /&gt;
Here is an example: (the event handler is registered on the '''mod event bus''')&lt;br /&gt;
&lt;br /&gt;
{{Template:Tabs/Code_Snippets&lt;br /&gt;
|java=@SubscribeEvent&lt;br /&gt;
public void registerBlocks(RegistryEvent.Register&amp;lt;Block&amp;gt; event) {&lt;br /&gt;
    event.getRegistry().registerAll(new Block(...).setRegistryName(new ResourceLocation(MODID, &amp;quot;example_block1&amp;quot;)), new Block(...).setRegistryName(new ResourceLocation(MODID, &amp;quot;example_block2&amp;quot;)), ...);&lt;br /&gt;
}&lt;br /&gt;
|kotlin=@JvmStatic&lt;br /&gt;
@SubscribeEvent&lt;br /&gt;
private fun registerBlocks(event: RegistryEvent.Register&amp;lt;Block&amp;gt;) =&lt;br /&gt;
    event.registry.registerAll(Block(...).setRegistryName(new ResourceLocation(MODID, &amp;quot;example_block1&amp;quot;)), Block(...).setRegistryName(new ResourceLocation(MODID, &amp;quot;example_block2&amp;quot;)), ...)&lt;br /&gt;
|scala=@SubscribeEvent&lt;br /&gt;
def registerBlocks(event: RegistryEvent.Register[Block]): Unit =&lt;br /&gt;
    event.getRegistry.registerAll(new Block(...).setRegistryName(new ResourceLocation(MODID, &amp;quot;example_block1&amp;quot;)), new Block(...).setRegistryName(new ResourceLocation(MODID, &amp;quot;example_block2&amp;quot;)), ...)&lt;br /&gt;
|}}&lt;br /&gt;
&lt;br /&gt;
{{Tip/Important|Since all objects registered must be singleton, some classes cannot by themselves be registered. Instead, &amp;lt;code&amp;gt;*Type&amp;lt;/code&amp;gt; classes are registered and used in the formers' constructors to wrap the flyweight objects. For example, a [[Basics_of_Block_Entities|&amp;lt;code&amp;gt;BlockEntity&amp;lt;/code&amp;gt;]] is wrapped via &amp;lt;code&amp;gt;BlockEntityType&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;Entity&amp;lt;/code&amp;gt; is wrapped via &amp;lt;code&amp;gt;EntityType&amp;lt;/code&amp;gt;. These &amp;lt;code&amp;gt;*Type&amp;lt;/code&amp;gt; classes hold factories that simply create the containing type on demand.&lt;br /&gt;
&lt;br /&gt;
These factory holders are created through the use of their &amp;lt;code&amp;gt;*Type$Builder&amp;lt;/code&amp;gt; classes. An example: (&amp;lt;code&amp;gt;REGISTER&amp;lt;/code&amp;gt; here refers to a &amp;lt;code&amp;gt;DeferredRegister&amp;lt;BlockEntityType&amp;lt;?&amp;gt;&amp;gt;&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
{{Template:Tabs/Code_Snippets&lt;br /&gt;
|java=public static final RegistryObject&amp;lt;BlockEntityType&amp;lt;ExampleBlockEntity&amp;gt;&amp;gt; EXAMPLE_BLOCK_ENTITY = REGISTER.register(&lt;br /&gt;
    &amp;quot;example_block_entity&amp;quot;, () -&amp;gt; BlockEntityType.Builder.of(ExampleBlockEntity::new, EXAMPLE_BLOCK.get()).build(null)&lt;br /&gt;
);&lt;br /&gt;
|kotlin=val EXAMPLE_BLOCK_ENTITY: RegistryObject&amp;lt;BlockEntityType&amp;lt;ExampleBlockEntity&amp;gt;&amp;gt; = REGISTER.register(&amp;quot;example_block_entity&amp;quot;) { BlockEntityType.Builder.of(::ExampleBlockEntity, EXAMPLE_BLOCK.get()).build(null)) }&lt;br /&gt;
|scala=final val EXAMPLE_BLOCK_ENTITY = REGISTER.register(&amp;quot;example_block_entity&amp;quot;, () =&amp;gt; BlockEntityType.Builder.of(() =&amp;gt; new ExampleBlockEntity(), GeneralRegistrar.EXAMPLE_BLOCK.get).build(null))&lt;br /&gt;
|}}&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
=== Non-Forge Registries ===&lt;br /&gt;
&lt;br /&gt;
Not all vanilla registries are wrapped as a Forge registry. This is because the registry is fully independent from any other registry, completely data driven, or just has not been wrapped yet.&lt;br /&gt;
&lt;br /&gt;
These registries include:&lt;br /&gt;
* Custom Stats (a &amp;lt;code&amp;gt;ResourceLocation&amp;lt;/code&amp;gt; registry)&lt;br /&gt;
* &amp;lt;code&amp;gt;RuleTestType&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;PosRuleTestType&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;RecipeType&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;GameEvent&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;PositionSourceType&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;VillagerType&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;LootPoolEntryType&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;LootItemFunctionType&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;LootItemConditionType&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;LootNumberProviderType&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;LootNbtProviderType&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;LootScoreProviderType&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;FloatProviderType&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;IntProviderType&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;HeightProviderType&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;StructurePieceType&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;TrunkPlacerType&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;FeatureSizeType&amp;lt;/code&amp;gt;&lt;br /&gt;
* A &amp;lt;code&amp;gt;Codec&amp;lt;/code&amp;gt; of &amp;lt;code&amp;gt;BiomeSource&amp;lt;/code&amp;gt;&lt;br /&gt;
* A &amp;lt;code&amp;gt;Codec&amp;lt;/code&amp;gt; of &amp;lt;code&amp;gt;ChunkGenerator&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;StructureProcessorType&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;StructurePoolElementType&amp;lt;/code&amp;gt;&lt;br /&gt;
* All registries within &amp;lt;code&amp;gt;BuiltinRegistries&amp;lt;/code&amp;gt; excluding &amp;lt;code&amp;gt;Biome&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To register objects to any one of these registries, create a &amp;lt;code&amp;gt;DeferredRegister&amp;lt;/code&amp;gt; via the &amp;lt;code&amp;gt;#create&amp;lt;/code&amp;gt; overload which takes in a resource key of the registry and the mod id to register the entries for. Then simply call &amp;lt;code&amp;gt;#register&amp;lt;/code&amp;gt; like any other &amp;lt;code&amp;gt;DeferredRegister&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
{{Template:Tabs/Code_Snippets&lt;br /&gt;
|java=private static final DeferredRegister&amp;lt;RecipeType&amp;lt;?&amp;gt;&amp;gt; RECIPE_TYPES = DeferredRegister.create(Registry.RECIPE_TYPE_REGISTRY, MODID);&lt;br /&gt;
&lt;br /&gt;
public static final RegistryObject&amp;lt;RecipeType&amp;lt;ExampleRecipe&amp;gt;&amp;gt; EXAMPLE_RECIPE = RECIPE_TYPES.register(&amp;quot;example_recipe&amp;quot;, () -&amp;gt; new RecipeType&amp;lt;&amp;gt;() {});&lt;br /&gt;
|kotlin=private val RECIPE_TYPES = DeferredRegister.create(Registry.RECIPE_TYPE_REGISTRY, MODID)&lt;br /&gt;
&lt;br /&gt;
val EXAMPLE_RECIPE: RegistryObject&amp;lt;RecipeType&amp;lt;ExampleRecipe&amp;gt;&amp;gt; = RECIPE_TYPES.register(&amp;quot;example_recipe&amp;quot;) {&lt;br /&gt;
    RecipeType&amp;lt;&amp;gt;() {}&lt;br /&gt;
}&lt;br /&gt;
|scala=private final val RECIPE_TYPES = DeferredRegister.create(Registry.RECIPE_TYPE_REGISTRY, MODID)&lt;br /&gt;
&lt;br /&gt;
final val EXAMPLE_RECIPE = RECIPE_TYPES.register(&amp;quot;example_recipe&amp;quot;, () =&amp;gt; new RecipeType&amp;lt;&amp;gt;() {})&lt;br /&gt;
|groovy=private static final DeferredRegister&amp;lt;RecipeType&amp;lt;?&amp;gt;&amp;gt; RECIPE_TYPES = DeferredRegister.create(Registry.RECIPE_TYPE_REGISTRY, MODID);&lt;br /&gt;
&lt;br /&gt;
public static final RegistryObject&amp;lt;RecipeType&amp;lt;ExampleRecipe&amp;gt;&amp;gt; EXAMPLE_RECIPE = RECIPE_TYPES.register(&amp;quot;example_recipe&amp;quot;, () -&amp;gt; new RecipeType&amp;lt;&amp;gt;() {});&lt;br /&gt;
|}}&lt;br /&gt;
&lt;br /&gt;
If you attempt to make one of these instances require an instance of another registry object, you must use the lazy initialization method mentioned above to register the object in the correct order.&lt;br /&gt;
&lt;br /&gt;
=== Data Driven Entries ===&lt;br /&gt;
&lt;br /&gt;
Registries are considered to be data driven if they are located within &amp;lt;code&amp;gt;RegistryAccess&amp;lt;/code&amp;gt; with the exception of &amp;lt;code&amp;gt;LevelStem&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;Level&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
The following registries are data driven:&lt;br /&gt;
* &amp;lt;code&amp;gt;ConfiguredSurfaceBuilder&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;ConfiguredWorldCarver&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;ConfiguredFeature&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;ConfiguredStructureFeature&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;StructureProcessorList&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;StructureTemplatePool&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;Biome&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;NoiseGeneratorSettings&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;DimensionType&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;LevelStem&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;Level&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
These registry objects only need to be registered within code if they are to be used within a pre-existing registry object (e.g. a &amp;lt;code&amp;gt;ConfiguredFeature&amp;lt;/code&amp;gt; for ore generation within an overworld &amp;lt;code&amp;gt;Biome&amp;lt;/code&amp;gt;). Otherwise, their instance can be purely registered using a JSON file.&lt;br /&gt;
&lt;br /&gt;
If a data driven registry object has to be registered within code, a dummy object should be supplied to hold a &amp;quot;registry name&amp;quot; and then constructed within a JSON file.&lt;br /&gt;
&lt;br /&gt;
== Referencing Registered Objects ==&lt;br /&gt;
&lt;br /&gt;
Each forge registered object should not be statically initialized nor reference another instance being registered. They must always be a new, singleton instance that is resolved during their respective &amp;lt;code&amp;gt;RegistryEvent$Register&amp;lt;/code&amp;gt; event. This is to maintain a sane loading order for registries and their objects along with dynamic loading/unloading of mods.&lt;br /&gt;
&lt;br /&gt;
Forge registered objects must always be referenced through a &amp;lt;code&amp;gt;RegistryObject&amp;lt;/code&amp;gt; or a field with &amp;lt;code&amp;gt;@ObjectHolder&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
===Using RegistryObjects===&lt;br /&gt;
&amp;lt;code&amp;gt;RegistryObject&amp;lt;/code&amp;gt;s can be used to retrieve references to registered objects once they become available. Their references are updated along with all &amp;lt;code&amp;gt;@ObjectHolder&amp;lt;/code&amp;gt; annotations after the associated &amp;lt;code&amp;gt;RegistryEvent$Register&amp;lt;/code&amp;gt; has been dispatched and frozen.&lt;br /&gt;
&lt;br /&gt;
A &amp;lt;code&amp;gt;RegistryObject&amp;lt;/code&amp;gt; can be retrieved as a result of using &amp;lt;code&amp;gt;DeferredRegister&amp;lt;/code&amp;gt; or calling the static factory &amp;lt;code&amp;gt;RegistryObject#create&amp;lt;/code&amp;gt;. Each static factory takes in the &amp;quot;registry name&amp;quot; of the object being referenced and one of the following: a &amp;lt;code&amp;gt;IForgeRegistry&amp;lt;/code&amp;gt;, a registry name of the type &amp;lt;code&amp;gt;ResourceLocation&amp;lt;/code&amp;gt;, or a registry key of the type &amp;lt;code&amp;gt;ResourceKey&amp;lt;? extends Registry&amp;lt;?&amp;gt;&amp;gt;&amp;lt;/code&amp;gt;. The &amp;lt;code&amp;gt;RegistryObject&amp;lt;/code&amp;gt; can be stored within some field and retrieve the registered object using &amp;lt;code&amp;gt;#get&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
An example using &amp;lt;code&amp;gt;RegistryObject&amp;lt;/code&amp;gt;:&lt;br /&gt;
{{Template:Tabs/Code_Snippets&lt;br /&gt;
|java=public static final RegistryObject&amp;lt;Item&amp;gt; EXAMPLE_ITEM = RegistryObject.create(new ResourceLocation(&amp;quot;examplemod&amp;quot;, &amp;quot;example_item&amp;quot;), ForgeRegistries.ITEMS);&lt;br /&gt;
&lt;br /&gt;
// Assume that 'examplemod:example_registry' is a valid registry, and 'examplemod:example_object' is a valid object within that registry&lt;br /&gt;
public static final RegistryObject&amp;lt;ExampleRegistry&amp;gt; EXAMPLE_OBJECT = RegistryObject.create(new ResourceLocation(&amp;quot;examplemod&amp;quot;, &amp;quot;example_object&amp;quot;), new ResourceLocation(&amp;quot;examplemod&amp;quot;, &amp;quot;example_registry&amp;quot;), &amp;quot;examplemod&amp;quot;); &lt;br /&gt;
|kotlin=val EXAMPLE_ITEM: RegistryObject&amp;lt;Item&amp;gt; = RegistryObject.create(ResourceLocation(&amp;quot;examplemod&amp;quot;, &amp;quot;example_item&amp;quot;), ForgeRegistries.ITEMS)&lt;br /&gt;
&lt;br /&gt;
// Assume that 'examplemod:example_registry' is a valid registry, and 'examplemod:example_object' is a valid object within that registry&lt;br /&gt;
val EXAMPLE_OBJECT: RegistryObject&amp;lt;ExampleRegistry&amp;gt; = RegistryObject.create(ResourceLocation(&amp;quot;examplemod&amp;quot;, &amp;quot;example_object&amp;quot;), new ResourceLocation(&amp;quot;examplemod&amp;quot;, &amp;quot;example_registry&amp;quot;), &amp;quot;examplemod&amp;quot;)&lt;br /&gt;
|scala=final val EXAMPLE_ITEM = RegistryObject.create(new ResourceLocation(&amp;quot;examplemod&amp;quot;, &amp;quot;example_item&amp;quot;), ForgeRegistries.ITEMS)&lt;br /&gt;
&lt;br /&gt;
// Assume that 'examplemod:example_registry' is a valid registry, and 'examplemod:example_object' is a valid object within that registry&lt;br /&gt;
final val EXAMPLE_OBJECT = RegistryObject.create(new ResourceLocation(&amp;quot;examplemod&amp;quot;, &amp;quot;example_object&amp;quot;), new ResourceLocation(&amp;quot;examplemod&amp;quot;, &amp;quot;example_registry&amp;quot;), &amp;quot;examplemod&amp;quot;); &lt;br /&gt;
|}}&lt;br /&gt;
&lt;br /&gt;
{{Tip/Important|All vanilla objects are bootstrapped and registered before mods are loaded. As such, they can be referenced as is without any issues.}}&lt;br /&gt;
&lt;br /&gt;
=== Using @ObjectHolder ===&lt;br /&gt;
&lt;br /&gt;
Forge registry objects can also be injected into &amp;lt;code&amp;gt;public static&amp;lt;/code&amp;gt; fields with either their class or that field annotated with &amp;lt;code&amp;gt;@ObjectHolder&amp;lt;/code&amp;gt;. There must be enough information to construct a &amp;lt;code&amp;gt;ResourceLocation&amp;lt;/code&amp;gt; to identify a single object within a specific registry.&lt;br /&gt;
&lt;br /&gt;
The rules for &amp;lt;code&amp;gt;@ObjectHolder&amp;lt;/code&amp;gt; are as follows:&lt;br /&gt;
&lt;br /&gt;
* If the class is annotated with &amp;lt;code&amp;gt;@ObjectHolder&amp;lt;/code&amp;gt;, its value will be the default namespace for all fields within if not explicitly defined&lt;br /&gt;
* If the class is annotated with &amp;lt;code&amp;gt;@Mod&amp;lt;/code&amp;gt;, the modid will be the default namespace for all annotated fields within if not explicitly defined &lt;br /&gt;
* A field is considered for injection if:&lt;br /&gt;
** it has at least the modifiers &amp;lt;code&amp;gt;public static&amp;lt;/code&amp;gt;; and&lt;br /&gt;
** one of the following conditions are true:&lt;br /&gt;
*** the '''enclosing class''' has an &amp;lt;code&amp;gt;@ObjectHolder&amp;lt;/code&amp;gt; annotation, and the field is &amp;lt;code&amp;gt;final&amp;lt;/code&amp;gt;, and:&lt;br /&gt;
**** the name value is the field's name; and&lt;br /&gt;
**** the namespace value is the enclosing class's namespace&lt;br /&gt;
**** ''An exception is thrown if the namespace value cannot be found and inherited''&lt;br /&gt;
*** the '''field''' is annotated with &amp;lt;code&amp;gt;@ObjectHolder&amp;lt;/code&amp;gt;, and:&lt;br /&gt;
**** the name value is explicitly defined; and&lt;br /&gt;
**** the namespace value is either explicitly defined or the enclosing class's namespace&lt;br /&gt;
** the field type or one of its supertypes corresponds to a valid registry (e.g. &amp;lt;code&amp;gt;Item&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;ArrowItem&amp;lt;/code&amp;gt; for the &amp;lt;code&amp;gt;Item&amp;lt;/code&amp;gt; registry)&lt;br /&gt;
** ''An exception is thrown if a field does not have a corresponding registry.''&lt;br /&gt;
* ''An exception is thrown if the resulting &amp;lt;code&amp;gt;ResourceLocation&amp;lt;/code&amp;gt; is incomplete or invalid (non-valid characters in path)''&lt;br /&gt;
* If no other errors or exceptions occur, the field will be injected&lt;br /&gt;
* If all of the above rules do not apply, no action will be taken (and a message may be logged)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;@ObjectHolder&amp;lt;/code&amp;gt; annotated fields are injected with their associated object values after their corresponding registry's &amp;lt;code&amp;gt;RegistryEvent$Register&amp;lt;/code&amp;gt; event is fired, along with &amp;lt;code&amp;gt;RegistryObject&amp;lt;/code&amp;gt;s.&lt;br /&gt;
&lt;br /&gt;
{{Tip/Warning|If the object does not exist in the registry when it is to be injected, a debug message will be logged, and no value will be injected. If the object is found, but the field cannot be set, a warning message will be logged instead.}}&lt;br /&gt;
&lt;br /&gt;
As these rules are rather complicated, here are some examples:&lt;br /&gt;
&amp;lt;div class=&amp;quot;mw-collapsible mw-collapsed&amp;quot; style=&amp;quot;border: solid 2px; padding: 2px 5px; margin-top: 3px&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;div style=&amp;quot;font-weight:bold;line-height:1.6;&amp;quot;&amp;gt;Example uses of &amp;lt;code&amp;gt;@ObjectHolder&amp;lt;/code&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;div class=&amp;quot;mw-collapsible-content&amp;quot; style=&amp;quot;overflow: auto; white-space: nowrap;&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
@ObjectHolder(&amp;quot;minecraft&amp;quot;) // Inheritable resource namespace: &amp;quot;minecraft&amp;quot;&lt;br /&gt;
class AnnotatedHolder {&lt;br /&gt;
    public static final Block diamond_block = null;   // No annotation. [public static final] is required.&lt;br /&gt;
                                                      // Block has a corresponding registry: [Block]&lt;br /&gt;
                                                      // Name path is the name of the field: &amp;quot;diamond_block&amp;quot;&lt;br /&gt;
                                                      // Namespace is not explicitly defined.&lt;br /&gt;
                                                      // So, namespace is inherited from class annotation: &amp;quot;minecraft&amp;quot;&lt;br /&gt;
                                                      // To inject: &amp;quot;minecraft:diamond_block&amp;quot; from the [Block] registry&lt;br /&gt;
&lt;br /&gt;
    @ObjectHolder(&amp;quot;ambient.cave&amp;quot;)&lt;br /&gt;
    public static SoundEvent ambient_sound = null;    // Annotation present. [public static] is required.&lt;br /&gt;
                                                      // SoundEvent has a corresponding registry: [SoundEvent]&lt;br /&gt;
                                                      // Name path is the value of the annotation: &amp;quot;ambient.cave&amp;quot;&lt;br /&gt;
                                                      // Namespace is not explicitly defined.&lt;br /&gt;
                                                      // So, namespace is inherited from class annotation: &amp;quot;minecraft&amp;quot;&lt;br /&gt;
                                                      // To inject: &amp;quot;minecraft:ambient.cave&amp;quot; from the [SoundEvent] registry&lt;br /&gt;
&lt;br /&gt;
    // Assume for the next entry that [ManaType] is a valid registry.          &lt;br /&gt;
    @ObjectHolder(&amp;quot;neomagicae:coffeinum&amp;quot;)&lt;br /&gt;
    public static final ManaType coffeinum = null;    // Annotation present. [public static] is required. [final] is optional.&lt;br /&gt;
                                                      // ManaType has a corresponding registry: [ManaType] (custom registry)&lt;br /&gt;
                                                      // Resource location is explicitly defined: &amp;quot;neomagicae:coffeinum&amp;quot;&lt;br /&gt;
                                                      // To inject: &amp;quot;neomagicae:coffeinum&amp;quot; from the [ManaType] registry&lt;br /&gt;
&lt;br /&gt;
    public static final Item ENDER_PEARL = null;      // No annotation. [public static final] is required.&lt;br /&gt;
                                                      // Item has a corresponding registry: [Item].&lt;br /&gt;
                                                      // Name path is the name of the field: &amp;quot;ENDER_PEARL&amp;quot; -&amp;gt; &amp;quot;ender_pearl&amp;quot;&lt;br /&gt;
                                                      // !! ^ Field name is valid, because they are&lt;br /&gt;
                                                      //      converted to lowercase automatically.&lt;br /&gt;
                                                      // Namespace is not explicitly defined.&lt;br /&gt;
                                                      // So, namespace is inherited from class annotation: &amp;quot;minecraft&amp;quot;&lt;br /&gt;
                                                      // To inject: &amp;quot;minecraft:ender_pearl&amp;quot; from the [Item] registry&lt;br /&gt;
&lt;br /&gt;
    @ObjectHolder(&amp;quot;minecraft:arrow&amp;quot;)&lt;br /&gt;
    public static final ArrowItem arrow = null;       // Annotation present. [public static] is required. [final] is optional.&lt;br /&gt;
                                                      // ArrowItem does not have a corresponding registry.&lt;br /&gt;
                                                      // ArrowItem's supertype of Item has a corresponding registry: [Item]&lt;br /&gt;
                                                      // Resource location is explicitly defined: &amp;quot;minecraft:arrow&amp;quot;&lt;br /&gt;
                                                      // To inject: &amp;quot;minecraft:arrow&amp;quot; from the [Item] registry                                                    &lt;br /&gt;
&lt;br /&gt;
    public static Block bedrock = null;               // No annotation, so [public static final] is required.&lt;br /&gt;
                                                      // Therefore, the field is ignored.&lt;br /&gt;
    &lt;br /&gt;
    public static final CreativeModeTab group = null; // No annotation. [public static final] is required.&lt;br /&gt;
                                                      // CreativeModeTab does not have a corresponding registry.&lt;br /&gt;
                                                      // No supertypes of CreativeModeTab has a corresponding registry.&lt;br /&gt;
                                                      // Therefore, THIS WILL PRODUCE AN EXCEPTION.&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
class UnannotatedHolder { // Note the lack of an @ObjectHolder annotation on this class.&lt;br /&gt;
    @ObjectHolder(&amp;quot;minecraft:flame&amp;quot;)&lt;br /&gt;
    public static final Enchantment flame = null;     // Annotation present. [public static] is required. [final] is optional.&lt;br /&gt;
                                                      // Enchantment has corresponding registry: [Enchantment].&lt;br /&gt;
                                                      // Resource location is explicitly defined: &amp;quot;minecraft:flame&amp;quot;&lt;br /&gt;
                                                      // To inject: &amp;quot;minecraft:flame&amp;quot; from the [Enchantment] registry&lt;br /&gt;
&lt;br /&gt;
    public static final Biome ice_flat = null;        // No annotation on the enclosing class.&lt;br /&gt;
                                                      // Therefore, the field is ignored.&lt;br /&gt;
&lt;br /&gt;
    @ObjectHolder(&amp;quot;minecraft:creeper&amp;quot;)&lt;br /&gt;
    public static Entity creeper = null;              // Annotation present. [public static] is required.&lt;br /&gt;
                                                      // Entity does not have a corresponding registry.&lt;br /&gt;
                                                      // No supertypes of Entity has a corresponding registry.&lt;br /&gt;
                                                      // Therefore, THIS WILL PRODUCE AN EXCEPTION.&lt;br /&gt;
&lt;br /&gt;
    @ObjectHolder(&amp;quot;levitation&amp;quot;)&lt;br /&gt;
    public static final Potion levitation = null;     // Annotation present. [public static] is required. [final] is optional.&lt;br /&gt;
                                                      // Potion has a corresponding registry: [Potion].&lt;br /&gt;
                                                      // Name path is the value of the annotation: &amp;quot;levitation&amp;quot;&lt;br /&gt;
                                                      // Namespace is not explicitly defined.&lt;br /&gt;
                                                      // No annotation in enclosing class.&lt;br /&gt;
                                                      // Therefore, THIS WILL PRODUCE AN EXCEPTION.&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Creating Custom Registries ==&lt;br /&gt;
&lt;br /&gt;
Creating custom registries for your mod might be useful if you want other mods to add new things to your system. For example, you might have magic spells and want to allow other mods to add new spells. For this you will want to make a registry (eg. &amp;quot;mymagicmod:spells&amp;quot;). This way, other mods will be able to register things to that list, and you won't have to do anything else.&lt;br /&gt;
&lt;br /&gt;
Just like with registering a new item or block you have two ways of making a new registry. Each method takes in a &amp;lt;code&amp;gt;RegistryBuilder&amp;lt;/code&amp;gt; which is used to build an &amp;lt;code&amp;gt;IForgeRegistry&amp;lt;/code&amp;gt; for an object class that implements &amp;lt;code&amp;gt;IForgeRegistryEntry&amp;lt;/code&amp;gt;. Each builder should have its name and type set via &amp;lt;code&amp;gt;#setName&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;#setType&amp;lt;/code&amp;gt; respectively before being created.&lt;br /&gt;
&lt;br /&gt;
For the class that implements &amp;lt;code&amp;gt;IForgeRegistryEntry&amp;lt;/code&amp;gt;, it is recommended in most cases to extend the default implementation of &amp;lt;code&amp;gt;ForgeRegistryEntry&amp;lt;/code&amp;gt;. For interfaces, it should extend &amp;lt;code&amp;gt;IForgeRegistryEntry&amp;lt;/code&amp;gt; with its implementations extending &amp;lt;code&amp;gt;ForgeRegistryEntry&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== With DeferredRegister ===&lt;br /&gt;
&lt;br /&gt;
The first method involves the second static constructor: &amp;lt;code&amp;gt;DeferredRegister#create(ResourceLocation, String)&amp;lt;/code&amp;gt;. From there, we can construct the registry using &amp;lt;code&amp;gt;#makeRegistry&amp;lt;/code&amp;gt;. This will already populate &amp;lt;code&amp;gt;#setName&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;#setType&amp;lt;/code&amp;gt; for us. This method also returns a supplier of the registry which we can use after the &amp;lt;code&amp;gt;NewRegistryEvent&amp;lt;/code&amp;gt; is called.&lt;br /&gt;
&lt;br /&gt;
Here is an example:&lt;br /&gt;
&lt;br /&gt;
{{Template:Tabs/Code_Snippets&lt;br /&gt;
|java=public static final DeferredRegister&amp;lt;ExampleRegistry&amp;gt; EXAMPLE = DeferredRegister.create(new ResourceLocation(MODID, &amp;quot;example_registry&amp;quot;), MODID);&lt;br /&gt;
&lt;br /&gt;
public static final Supplier&amp;lt;IForgeRegistry&amp;lt;ExampleRegistry&amp;gt;&amp;gt; REGISTRY = EXAMPLE.makeRegistry(ExampleRegistry.class, RegistryBuilder::new);&lt;br /&gt;
|kotlin=val EXAMPLE: DeferredRegister&amp;lt;ExampleRegistry&amp;gt; = DeferredRegister.create(ResourceLocation(MODID, &amp;quot;example_registry&amp;quot;), MODID)&lt;br /&gt;
&lt;br /&gt;
val REGISTRY: IForgeRegistry&amp;lt;ExampleRegistry&amp;gt; by lazy {&lt;br /&gt;
    EXAMPLE.makeRegistry(ExampleRegistry::class.java, ::RegistryBuilder).get()&lt;br /&gt;
}&lt;br /&gt;
|scala=final val EXAMPLE = DeferredRegister.create(new ResourceLocation(MODID, &amp;quot;example_registry&amp;quot;), MODID)&lt;br /&gt;
&lt;br /&gt;
final lazy val REGISTRY = EXAMPLE.makeRegistry(classOf[ExampleRegistry], () =&amp;gt; new RegistryBuilder).get&lt;br /&gt;
|}}&lt;br /&gt;
&lt;br /&gt;
=== Using `NewRegistryEvent` ===&lt;br /&gt;
&lt;br /&gt;
The second method can be done during the &amp;lt;code&amp;gt;NewRegistryEvent&amp;lt;/code&amp;gt; event. Using &amp;lt;code&amp;gt;NewRegistryEvent#create&amp;lt;/code&amp;gt;, you can pass in a &amp;lt;code&amp;gt;RegistryBuilder&amp;lt;/code&amp;gt; directly. This method will return a &amp;lt;code&amp;gt;Supplier&amp;lt;IForgeRegistry&amp;lt;V&amp;gt;&amp;gt;&amp;lt;/code&amp;gt; that can be stored and queried after the event is fired to gain access to your &amp;lt;code&amp;gt;IForgeRegistry&amp;lt;/code&amp;gt; instance.&lt;br /&gt;
&lt;br /&gt;
Here is an example: (the event handler is registered on the '''mod event bus''')&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;Java&amp;quot;&amp;gt;&lt;br /&gt;
public static Supplier&amp;lt;IForgeRegistry&amp;lt;ExampleRegistry&amp;gt;&amp;gt; registrySupplier = null;&lt;br /&gt;
&lt;br /&gt;
@SubscribeEvent&lt;br /&gt;
public void onNewRegistry(NewRegistryEvent event){&lt;br /&gt;
    RegistryBuilder&amp;lt;ExampleRegistry&amp;gt; registryBuilder = new RegistryBuilder&amp;lt;&amp;gt;();&lt;br /&gt;
    registryBuilder.setName(new ResourceLocation(MODID, &amp;quot;example_registry&amp;quot;);&lt;br /&gt;
    registryBuilder.setType(ExampleRegistry.class);&lt;br /&gt;
    registrySupplier = event.create(registryBuilder);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Handling Missing Entries ==&lt;br /&gt;
&lt;br /&gt;
When loading a pre-existing world after removing mods or updating versions, there are cases where certain registry objects will cease to exist. In these cases, it is possible to specify actions to remove a mapping, prevent the world from loading, or remap the name as needed. This can be done through the third of the registry events: &amp;lt;code&amp;gt;RegistryEvent$MissingMappings&amp;lt;T&amp;gt;&amp;lt;/code&amp;gt;, where the type parameter &amp;lt;code&amp;gt;T&amp;lt;/code&amp;gt; is the object type being registered. Within the event, you can grab an immutable list of missing mappings associated with a mod id via &amp;lt;code&amp;gt;#getMappings&amp;lt;/code&amp;gt; or a list of all mappings via &amp;lt;code&amp;gt;#getAllMappings&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
For each &amp;lt;code&amp;gt;Mapping&amp;lt;/code&amp;gt;, you can either execute one of the following methods:&lt;br /&gt;
* &amp;lt;code&amp;gt;#ignore&amp;lt;/code&amp;gt; which abandons the entry when loading&lt;br /&gt;
* &amp;lt;code&amp;gt;#warn&amp;lt;/code&amp;gt; which warns the user about the missing entry but continues loading&lt;br /&gt;
* &amp;lt;code&amp;gt;#fail&amp;lt;/code&amp;gt; which prevents the world from loading&lt;br /&gt;
* &amp;lt;code&amp;gt;#remap&amp;lt;/code&amp;gt; which remaps the entry to the specified non-null object in the same registry&lt;br /&gt;
&lt;br /&gt;
If none of the above are specified, then the default action of notifying the user about the missing mappings occur.&lt;br /&gt;
&lt;br /&gt;
Here is an example:  (the event handler is registered on the '''mod event bus''')&lt;br /&gt;
&lt;br /&gt;
{{Template:Tabs/Code_Snippets&lt;br /&gt;
|java=// This will ignore any missing test items from the specified world&lt;br /&gt;
@SubscribeEvent&lt;br /&gt;
public void onMissingItems(final RegistryEvent.MissingMappings&amp;lt;Item&amp;gt; event) {&lt;br /&gt;
    event.getMappings(MODID).stream()&lt;br /&gt;
        .filter(mapping -&amp;gt; mapping.key.getPath().contains(&amp;quot;test&amp;quot;))&lt;br /&gt;
            .forEach(Mapping::ignore);&lt;br /&gt;
}&lt;br /&gt;
|groovy=// This will ignore any missing test items from the specified world&lt;br /&gt;
@SubscribeEvent&lt;br /&gt;
void onMissingItems(final RegistryEvent.MissingMappings&amp;lt;Item&amp;gt; event) {&lt;br /&gt;
    event.getMappings(MODID).stream()&lt;br /&gt;
        .filter(mapping -&amp;gt; mapping.key.path.contains(&amp;quot;test&amp;quot;))&lt;br /&gt;
            .forEach(Mapping::ignore);&lt;br /&gt;
}&lt;br /&gt;
|}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Common Concepts]]&lt;/div&gt;</summary>
		<author><name>SizableShrimp</name></author>
	</entry>
	<entry>
		<id>https://forge.gemwire.uk/index.php?title=ISTER&amp;diff=3123</id>
		<title>ISTER</title>
		<link rel="alternate" type="text/html" href="https://forge.gemwire.uk/index.php?title=ISTER&amp;diff=3123"/>
		<updated>2022-02-02T02:19:18Z</updated>

		<summary type="html">&lt;p&gt;SizableShrimp: Redirect to ItemStack_TileEntityRenderer/1.16&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;#REDIRECT [[ItemStack_TileEntityRenderer/1.16]]&lt;/div&gt;</summary>
		<author><name>SizableShrimp</name></author>
	</entry>
	<entry>
		<id>https://forge.gemwire.uk/index.php?title=BEWLR&amp;diff=3122</id>
		<title>BEWLR</title>
		<link rel="alternate" type="text/html" href="https://forge.gemwire.uk/index.php?title=BEWLR&amp;diff=3122"/>
		<updated>2022-02-02T02:17:44Z</updated>

		<summary type="html">&lt;p&gt;SizableShrimp: Redirect to BlockEntityWithoutLevelRenderer&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;#REDIRECT [[BlockEntityWithoutLevelRenderer]]&lt;/div&gt;</summary>
		<author><name>SizableShrimp</name></author>
	</entry>
	<entry>
		<id>https://forge.gemwire.uk/index.php?title=Saved_Data/1.16&amp;diff=3120</id>
		<title>Saved Data/1.16</title>
		<link rel="alternate" type="text/html" href="https://forge.gemwire.uk/index.php?title=Saved_Data/1.16&amp;diff=3120"/>
		<updated>2022-01-30T01:30:54Z</updated>

		<summary type="html">&lt;p&gt;SizableShrimp: Redirect to World Saved Data/1.16&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;#REDIRECT [[World Saved Data/1.16]]&lt;/div&gt;</summary>
		<author><name>SizableShrimp</name></author>
	</entry>
	<entry>
		<id>https://forge.gemwire.uk/index.php?title=Components/1.16&amp;diff=3119</id>
		<title>Components/1.16</title>
		<link rel="alternate" type="text/html" href="https://forge.gemwire.uk/index.php?title=Components/1.16&amp;diff=3119"/>
		<updated>2022-01-19T21:04:46Z</updated>

		<summary type="html">&lt;p&gt;SizableShrimp: Redirect to Text Components/1.16&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;#REDIRECT [[Text Components/1.16]]&lt;/div&gt;</summary>
		<author><name>SizableShrimp</name></author>
	</entry>
	<entry>
		<id>https://forge.gemwire.uk/index.php?title=Capabilities&amp;diff=3117</id>
		<title>Capabilities</title>
		<link rel="alternate" type="text/html" href="https://forge.gemwire.uk/index.php?title=Capabilities&amp;diff=3117"/>
		<updated>2022-01-12T15:41:07Z</updated>

		<summary type="html">&lt;p&gt;SizableShrimp: /* Forge-provided Capabilities and Providers */ Remove ref to IAnimationStateMachine&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Capabilities''' are a Forge system that allows cross-mod interactions by allowing capability ''providers'' to&lt;br /&gt;
dynamically respect contracts and provide specialized behavior without requiring the implementation of many interfaces&lt;br /&gt;
or hard dependencies on mods.&lt;br /&gt;
&lt;br /&gt;
== History ==&lt;br /&gt;
In an ideal world, all that would be needed for a mod to provide the equivalent of a capability would be implementing an&lt;br /&gt;
interface. This is in fact how cross-mod interaction used to work prior to the introduction of capabilities.&lt;br /&gt;
&lt;br /&gt;
The real world, though, is often much more complicated: users wanted to be free to combine mods the way they wanted and&lt;br /&gt;
saw fit, and developers wanted to be able to declare ''soft'' dependencies on other mods, thus reducing the need of&lt;br /&gt;
having a huge mod pack just for testing.&lt;br /&gt;
&lt;br /&gt;
The first approach used by Forge was conditional stripping of interfaces and methods, but this proved to be problematic.&lt;br /&gt;
While the idea works well in theory, in practice the ASM editing of classes relied on complex mechanics and could lead&lt;br /&gt;
to hard to spot bugs.&lt;br /&gt;
&lt;br /&gt;
For this reason, the entire system was redesigned and the concept of '''capabilities''' was born.&lt;br /&gt;
&lt;br /&gt;
== The Concept ==&lt;br /&gt;
A capability allows any capability provider to conditionally expose a certain ability to do something, e.g. accepting&lt;br /&gt;
power or handling items. A capability provider, moreover, can decide to expose a capability only on certain sides,&lt;br /&gt;
allowing for easy interactions with hoppers, cables, etc.&lt;br /&gt;
&lt;br /&gt;
Capabilities may also be added and removed dynamically both from the &amp;quot;owner&amp;quot; of the capability provider and other mods,&lt;br /&gt;
allowing even easier cross-mod interaction. For example, a mod that isn't compatible with Forge Energy could be&lt;br /&gt;
converted into one by dynamically attaching the Forge Energy capability and handling the conversion to a third-party&lt;br /&gt;
energy system without having to alter the original mod.&lt;br /&gt;
&lt;br /&gt;
== Terminology ==&lt;br /&gt;
The high flexibility of the system comes with a cost, though, which is terminology. The following section wants to be a&lt;br /&gt;
dictionary of sorts, defining all the terms that you may come across when dealing with capabilities.&lt;br /&gt;
&lt;br /&gt;
In the rest of this article, we will refer to these terms frequently, so make sure you are familiar with them.&lt;br /&gt;
&lt;br /&gt;
; Capability&lt;br /&gt;
: the ability to perform something. In-code this is represented by the &amp;lt;code&amp;gt;Capability&amp;lt;/code&amp;gt; class.&lt;br /&gt;
; Capability Provider&lt;br /&gt;
: something that is able to support capabilities and provides a mean of accessing them. In-code they are represented by implementations of &amp;lt;code&amp;gt;ICapabilityProvider&amp;lt;/code&amp;gt;. There are multiple kinds of capability providers:&lt;br /&gt;
:; Volatile Provider&lt;br /&gt;
:: a provider that doesn't persist data to disk; once the provider ceases to exist for any number of reasons, all capability data gets deleted.&lt;br /&gt;
:; Persistent Provider&lt;br /&gt;
:: a provider that requires all capabilities to serialize data to disk, in order to persist data even across game restarts. They implement the &amp;lt;code&amp;gt;INBTSerializable&amp;lt;/code&amp;gt; interface.&lt;br /&gt;
:; Agnostic Provider&lt;br /&gt;
:: a provider that isn't neither volatile nor persistent, rather delegates the decision either to the capability directly or to sub-implementations. They also implement the &amp;lt;code&amp;gt;INBTSerializable&amp;lt;/code&amp;gt; interface.&lt;br /&gt;
; Capability Interface&lt;br /&gt;
: the interface that defines the contract of the capability, so what operations the capability exposes.&lt;br /&gt;
; Capability Implementation&lt;br /&gt;
: one of the possibly many implementations of the capability interface, that actually carries out the work.&lt;br /&gt;
&lt;br /&gt;
The wary reader may note that both ''persistent'' and ''agnostic'' providers are represented the same way in code. In&lt;br /&gt;
fact, the only difference between them comes from pure semantics in how their serialization methods are designed. This&lt;br /&gt;
will be further discussed in their respective sections.&lt;br /&gt;
&lt;br /&gt;
Moreover, it is also common to refer to the capability interface as simply the ''capability''. While not strictly&lt;br /&gt;
correct, due to common usage we will also use this convention. So, to refer to the capability interface&lt;br /&gt;
&amp;lt;code&amp;gt;MyCapability&amp;lt;/code&amp;gt;, we will usually talk about the &amp;quot;&amp;lt;code&amp;gt;MyCapability&amp;lt;/code&amp;gt; capability&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
== Forge-provided Capabilities and Providers ==&lt;br /&gt;
In order to ensure mods can work together seamlessly, Forge provides a set of default capabilities and capability&lt;br /&gt;
providers.&lt;br /&gt;
&lt;br /&gt;
The default capability providers in a Forge environment are: &amp;lt;code&amp;gt;BlockEntity&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;Entity&amp;lt;/code&amp;gt;,&lt;br /&gt;
&amp;lt;code&amp;gt;ItemStack&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;Level&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;LevelChunk&amp;lt;/code&amp;gt;. These are all agnostic providers, since they don't&lt;br /&gt;
mandate any sort of capability persistency requirements. Rather, it is the job of whoever subclasses these providers to&lt;br /&gt;
deal with either volatile or non-volatile capabilities.&lt;br /&gt;
&lt;br /&gt;
The default capabilities that forge provides are represented by the interfaces &amp;lt;code&amp;gt;IItemHandler&amp;lt;/code&amp;gt;,&lt;br /&gt;
&amp;lt;code&amp;gt;IFluidHandler&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;IFluidHandlerItem&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;IEnergyStorage&amp;lt;/code&amp;gt;. Each one of these capabilities will be discussed in the corresponding section.&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;IItemHandler&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;IItemHandler&amp;lt;/code&amp;gt; capability refers to the ability for any capability provider to have some sort of internal&lt;br /&gt;
'''inventory''' with a certain number of slots, from which items can be inserted and extracted. It is also possible,&lt;br /&gt;
though, to expose this capability even if no such inventory is present as long as the capability provider can emulate&lt;br /&gt;
its presence (e.g. tools that allow accessing remote inventories).&lt;br /&gt;
&lt;br /&gt;
This effectively '''replaces''' the vanilla interfaces &amp;lt;code&amp;gt;Container&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;WorldlyContainer&amp;lt;/code&amp;gt;. These&lt;br /&gt;
interfaces are in fact retained only to allow vanilla code to compile and should not be used in mod code. This extends&lt;br /&gt;
to anything that implements those vanilla interfaces, such as &amp;lt;code&amp;gt;RandomizableContainerBlockEntity&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
A default reference implementation for this capability interface is provided in &amp;lt;code&amp;gt;ItemStackHandler&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;IFluidHandler&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;IFluidHandler&amp;lt;/code&amp;gt; capability refers to the ability for any capability provider to handle and store fluids&lt;br /&gt;
in one or multiple fluid tanks. It is effectively the equivalent in terms of fluids of the &amp;lt;code&amp;gt;IItemHandler&amp;lt;/code&amp;gt;&lt;br /&gt;
capability.&lt;br /&gt;
&lt;br /&gt;
A default reference implementation for this capability interface is provided in &amp;lt;code&amp;gt;TileFluidHandler&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;IFluidHandlerItem&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;IFluidHandlerItem&amp;lt;/code&amp;gt; capability refers to the ability for an &amp;lt;code&amp;gt;ItemStack&amp;lt;/code&amp;gt; capability provider&lt;br /&gt;
to handle and store fluids in one or multiple fluid tanks. It is basically a specialized version of the&lt;br /&gt;
&amp;lt;code&amp;gt;IFluidHandler&amp;lt;/code&amp;gt; capability that allows &amp;lt;code&amp;gt;ItemStack&amp;lt;/code&amp;gt;s to define a custom container.&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;IEnergyStorage&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;IEnergyStorage&amp;lt;/code&amp;gt; capability refers to the ability for any capability provider to store, consume, and&lt;br /&gt;
produce energy. This capability is the base capability for what's commonly known in the modded world as Forge Energy (or&lt;br /&gt;
FE), i.e. the energy system most mods use. Its internal design is heavily based on the (now defunct) Redstone Flux&lt;br /&gt;
Energy API, supporting both a push and pull system.&lt;br /&gt;
&lt;br /&gt;
A default reference implementation for this capability interface is provided in &amp;lt;code&amp;gt;EnergyStorage&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Working with Capabilities ==&lt;br /&gt;
&lt;br /&gt;
Both capability providers and users need to be able to provide and access capabilities through a common framework,&lt;br /&gt;
otherwise the ideal of dynamic and mod-agnostic would not really exist. For this reason, both capability providers and&lt;br /&gt;
capability ''accessors'' (which we define as everything that wants to access a capability), also known as '''clients''' or '''users''',&lt;br /&gt;
need to work together and with Forge to ensure that the common interface is used sensibly and correctly by all parties.&lt;br /&gt;
&lt;br /&gt;
=== Obtaining a Capability ===&lt;br /&gt;
&lt;br /&gt;
Before being able to work with a capability, it is necessary to obtain an instance of the &amp;lt;code&amp;gt;Capability&amp;lt;/code&amp;gt; object itself.&lt;br /&gt;
&lt;br /&gt;
A &amp;lt;code&amp;gt;Capability&amp;lt;/code&amp;gt; can obtained at any time using &amp;lt;code&amp;gt;CapabilityManager#get&amp;lt;/code&amp;gt;. This takes in an anonymous &amp;lt;code&amp;gt;CapabilityToken&amp;lt;/code&amp;gt; to still allow for a soft dependency system while also keeping hold of any generic information needed. As such, you can always obtain a non-null capability.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
public static Capability&amp;lt;IItemHandler&amp;gt; ITEM_HANDLER_CAPABILITY = CapabilityManager.get(new CapabilityToken&amp;lt;&amp;gt;(){});&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The above code will let Forge know that the field &amp;lt;code&amp;gt;ITEM_HANDLER_CAPABILITY&amp;lt;/code&amp;gt; should be analogous with the &amp;lt;code&amp;gt;IItemHandler&amp;lt;/code&amp;gt; capability. Note that this does not mean the capability is accessible or registered. To check if it is, call &amp;lt;code&amp;gt;Capability#isRegistered&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
This is, for obvious reasons, redundant, since that capability is also available through&lt;br /&gt;
&amp;lt;code&amp;gt;CapabilityItemHandler&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Exposing a Capability ===&lt;br /&gt;
&lt;br /&gt;
Exposing a capability is a voluntary act by a capability provider that allows the capability to be discovered and&lt;br /&gt;
accessed by users.&lt;br /&gt;
&lt;br /&gt;
To do so, a capability provider needs to juggle a couple more moving pieces to ensure that the capability state remains&lt;br /&gt;
consistent and that the lookup remains fast. It is in fact possible for a capability provider to be asked to provide&lt;br /&gt;
many capabilities many times in the same tick. For this reason, a provider is asked to do the following:&lt;br /&gt;
&lt;br /&gt;
* the &amp;lt;code&amp;gt;LazyOptional&amp;lt;/code&amp;gt;s that get returned '''must be cached''';&lt;br /&gt;
* if a capability changes exposure state (more on this later), all listeners '''must be notified''';&lt;br /&gt;
* if a capability gets invalidated (more on this later), all listeners '''must be notified'''&lt;br /&gt;
* the lookup inside &amp;lt;code&amp;gt;getCapability&amp;lt;/code&amp;gt; must be performed with '''an &amp;lt;code&amp;gt;if&amp;lt;/code&amp;gt;-&amp;lt;code&amp;gt;else&amp;lt;/code&amp;gt; chain''';&lt;br /&gt;
* all unexposed but still present capabilities '''should be available''' if the provider is queried with a &amp;lt;code&amp;gt;null&amp;lt;/code&amp;gt; direction (see ''Accessing a Capability'' for more information);&lt;br /&gt;
* if no capability of a given type is available or accessible, the provider '''must call &amp;lt;code&amp;gt;super&amp;lt;/code&amp;gt; as long as it is possible to do so'''.&lt;br /&gt;
&lt;br /&gt;
Capability providers must also reflect changes in the ''exposure state'' of a capability, meaning that if the&lt;br /&gt;
accessibility of a capability from a certain &amp;lt;code&amp;gt;Direction&amp;lt;/code&amp;gt; changes (refer to&lt;br /&gt;
[[#Accessing a Capability|Accessing a Capability]] for more information), it is the provider's responsibility to trigger&lt;br /&gt;
a state response by invalidating the returned &amp;lt;code&amp;gt;LazyOptional&amp;lt;/code&amp;gt; and caching a new one. This should also be&lt;br /&gt;
performed when a capability gets ''invalidated'', such as when a capability provider gets removed.&lt;br /&gt;
&lt;br /&gt;
With all of the above in mind, part of a capability provider implementation may be similar to the following snippet:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
// suppose the presence of a field 'inventory' of type 'IItemHandler'&lt;br /&gt;
&lt;br /&gt;
private final LazyOptional&amp;lt;IItemhandler&amp;gt; inventoryOptional = LazyOptional.of(() -&amp;gt; this.inventory);&lt;br /&gt;
&lt;br /&gt;
@Override&lt;br /&gt;
public &amp;lt;T&amp;gt; LazyOptional&amp;lt;T&amp;gt; getCapability(Capability&amp;lt;T&amp;gt; capability, @Nullable Direction direction) {&lt;br /&gt;
    if (capability == CapabilityItemHandler.ITEM_HANDLER_CAPABILITY&lt;br /&gt;
            &amp;amp;&amp;amp; (direction == null || direction == Direction.UP || direction == Direction.DOWN)) {&lt;br /&gt;
        return this.inventoryOptional.cast();&lt;br /&gt;
    }&lt;br /&gt;
    return super.getCapability(capability, direction); // See note after snippet&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
@Override&lt;br /&gt;
protected void invalidateCaps() {&lt;br /&gt;
    super.invalidateCaps();&lt;br /&gt;
    this.inventoryOptional.invalidate();&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This possible implementation of a capability provider exposes an &amp;lt;code&amp;gt;IItemHandler&amp;lt;/code&amp;gt; capability and restricts&lt;br /&gt;
access only to the &amp;lt;code&amp;gt;UP&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;DOWN&amp;lt;/code&amp;gt; directions. If we assume this capability provider is a&lt;br /&gt;
&amp;lt;code&amp;gt;BlockEntity&amp;lt;/code&amp;gt;, then we may also say that the inventory is only accessible from the top and the bottom of the&lt;br /&gt;
block.&lt;br /&gt;
&lt;br /&gt;
Moreover, the capability gets automatically invalidated when the provider gets invalidated. Assuming this is a&lt;br /&gt;
&amp;lt;code&amp;gt;BlockEntity&amp;lt;/code&amp;gt;, this usually happens when the block gets removed from the level or unloaded due to distance.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;super&amp;lt;/code&amp;gt; call at the end of the &amp;lt;code&amp;gt;getCapability&amp;lt;/code&amp;gt; method is extremely important, since it's what&lt;br /&gt;
allows Attaching external Capabilities to capability providers. Nevertheless, it is not always possible to invoke&lt;br /&gt;
&amp;lt;code&amp;gt;super&amp;lt;/code&amp;gt;: in those cases, an empty &amp;lt;code&amp;gt;LazyOptional&amp;lt;/code&amp;gt; should be returned.&lt;br /&gt;
&lt;br /&gt;
=== Attaching a Capability ===&lt;br /&gt;
&lt;br /&gt;
Attaching a Capability is a process by which external agents &amp;quot;modify&amp;quot; a Capability Provider, making it expose additional&lt;br /&gt;
capabilities other than the already available ones.&lt;br /&gt;
&lt;br /&gt;
To do so, the '''attaching agent''' (which means the thing that wants to attach a capability to another provider) must&lt;br /&gt;
listen to the &amp;lt;code&amp;gt;AttachCapabilitiesEvent&amp;amp;lt;T&amp;amp;gt;&amp;lt;/code&amp;gt;. The &amp;lt;code&amp;gt;T&amp;lt;/code&amp;gt; in this case represents the capability&lt;br /&gt;
provider you want to attach the capability to. Note that the type of &amp;lt;code&amp;gt;T&amp;lt;/code&amp;gt; '''must''' be the base type of the&lt;br /&gt;
capability provider, not a subclass. As an example, if you want to attach a capability to a &amp;lt;code&amp;gt;MyBlockEntity&amp;lt;/code&amp;gt;,&lt;br /&gt;
which extends &amp;lt;code&amp;gt;BlockEntity&amp;lt;/code&amp;gt;, you'll have to listen to &amp;lt;code&amp;gt;AttachCapabilitiesEvent&amp;amp;lt;BlockEntity&amp;amp;gt;&amp;lt;/code&amp;gt;,&lt;br /&gt;
'''NOT''' to &amp;lt;code&amp;gt;AttachCapabilitiesEvent&amp;amp;lt;MyBlockEntity&amp;amp;gt;&amp;lt;/code&amp;gt;, since the latter will never fire.&lt;br /&gt;
&lt;br /&gt;
The attaching agent can use the provided methods &amp;lt;code&amp;gt;getObject&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;addCapability&amp;lt;/code&amp;gt;, and &lt;br /&gt;
&amp;lt;code&amp;gt;addListener&amp;lt;/code&amp;gt; to check whether the capability should be attached to the current object and perform the&lt;br /&gt;
desired action.&lt;br /&gt;
&lt;br /&gt;
When attaching a capability, the attaching agent should also provide a name in the form of a&lt;br /&gt;
&amp;lt;code&amp;gt;ResourceLocation&amp;lt;/code&amp;gt;. The name '''must''' be under the attaching agent's namespace, but no restrictions are&lt;br /&gt;
placed on the actual name, as long as it is unique inside the given namespace.&lt;br /&gt;
&lt;br /&gt;
Maybe a little counter-intuitively, the process of attaching does not attach a capability nor a capability interface&lt;br /&gt;
directly. Rather, the attaching agent should create its own implementation of a '''Capability Provider''' and attach it&lt;br /&gt;
via the event. This is done so that the attaching agent can have control over when, how, and where its capabilities are&lt;br /&gt;
exposed, instead of relying on the game itself deciding these parameters. For this reason, all considerations given in&lt;br /&gt;
the [[#Exposing a Capability|Exposing a Capability]] section on how to correctly create a Capability Provider.&lt;br /&gt;
&lt;br /&gt;
With the above in mind, part of an attaching agent may be similar to the following snippet of code:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
@SubscribeEvent&lt;br /&gt;
public void onAttachingCapabilities(final AttachCapabilitiesEvent&amp;lt;BlockEntity&amp;gt; event) {&lt;br /&gt;
    if (!(event.getObject() instanceof EnergyBasedBlockEntity)) return;&lt;br /&gt;
&lt;br /&gt;
    EnergyStorage backend = new EnergyStorage(((EnergyBasedBlockEntity) event.getObject()).capacity);&lt;br /&gt;
    LazyOptional&amp;lt;IEnergyStorage&amp;gt; optionalStorage = LazyOptional.of(() -&amp;gt; backend);&lt;br /&gt;
&lt;br /&gt;
    ICapabilityProvider provider = new ICapabilityProvider() {&lt;br /&gt;
        @Override&lt;br /&gt;
        public &amp;lt;T&amp;gt; LazyOptional&amp;lt;T&amp;gt; getCapability(Capability&amp;lt;T&amp;gt; cap, @Nullable Direction direction) {&lt;br /&gt;
            if (cap == CapabilityEnergy.ENERGY) {&lt;br /&gt;
                return optionalStorage.cast();&lt;br /&gt;
            }&lt;br /&gt;
            return LazyOptional.empty();&lt;br /&gt;
        }&lt;br /&gt;
    };&lt;br /&gt;
&lt;br /&gt;
    event.addCapability(new ResourceLocation(&amp;quot;examplemod&amp;quot;, &amp;quot;fe_compatibility&amp;quot;), provider);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This example implementation of an attaching agent attaches a &amp;lt;code&amp;gt;IEnergyStorage&amp;lt;/code&amp;gt; capability to all&lt;br /&gt;
&amp;lt;code&amp;gt;BlockEntity&amp;lt;/code&amp;gt; instance that are a subclass of &amp;lt;code&amp;gt;EnergyBasedBlockEntity&amp;lt;/code&amp;gt;. It also sets up the&lt;br /&gt;
&amp;lt;code&amp;gt;LazyOptional&amp;lt;/code&amp;gt; for invalidation if the parent capability provider gets invalidated.&lt;br /&gt;
&lt;br /&gt;
Note also the call of &amp;lt;code&amp;gt;LazyOptional.empty()&amp;lt;/code&amp;gt; rather than a &amp;lt;code&amp;gt;super&amp;lt;/code&amp;gt;. This is needed because when&lt;br /&gt;
attaching a capability, the parent capability provider isn't known. For this reason, it is necessary to return an empty&lt;br /&gt;
&amp;lt;code&amp;gt;LazyOptional&amp;lt;/code&amp;gt;. The game will then handle automatic merging of the various different providers into a single&lt;br /&gt;
one.&lt;br /&gt;
&lt;br /&gt;
The above example is one of a '''Volatile''' Capability Provider. On the other hand, mods may want to persist their&lt;br /&gt;
data across sessions. In this case, they should attach a '''Persistent''' Capability Provider: this can be done either&lt;br /&gt;
by implementing the &amp;lt;code&amp;gt;INBTSerializable&amp;lt;/code&amp;gt; interface along with &amp;lt;code&amp;gt;ICapabilityProvider&amp;lt;/code&amp;gt; or by&lt;br /&gt;
implementing the &amp;lt;code&amp;gt;ICapabilitySerializable&amp;lt;/code&amp;gt; interface.&lt;br /&gt;
&lt;br /&gt;
The previous example reworked to use a Persistent Capability Provider may be similar to the following snippet:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
@SubscribeEvent&lt;br /&gt;
public void onAttachingCapabilities(final AttachCapabilitiesEvent&amp;lt;BlockEntity&amp;gt; event) {&lt;br /&gt;
    if (!(event.getObject() instanceof EnergyBasedBlockEntity)) return;&lt;br /&gt;
&lt;br /&gt;
    EnergyStorage backend = new EnergyStorage(((EnergyBasedBlockEntity) event.getObject()).capacity);&lt;br /&gt;
    LazyOptional&amp;lt;IEnergyStorage&amp;gt; optionalStorage = LazyOptional.of(() -&amp;gt; backend);&lt;br /&gt;
    Capability&amp;lt;IEnergyStorage&amp;gt; capability = CapabilityEnergy.ENERGY;&lt;br /&gt;
&lt;br /&gt;
    ICapabilityProvider provider = new ICapabilitySerializable&amp;lt;IntTag&amp;gt;() {&lt;br /&gt;
        @Override&lt;br /&gt;
        public &amp;lt;T&amp;gt; LazyOptional&amp;lt;T&amp;gt; getCapability(Capability&amp;lt;T&amp;gt; cap, @Nullable Direction direction) {&lt;br /&gt;
            if (cap == capability) {&lt;br /&gt;
                return optionalStorage.cast();&lt;br /&gt;
            }&lt;br /&gt;
            return LazyOptional.empty();&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        @Override&lt;br /&gt;
        public IntTag serializeNBT() {&lt;br /&gt;
            return backend.serializeNBT();&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        @Override&lt;br /&gt;
        public void deserializeNBT(IntTag tag) {&lt;br /&gt;
            backend.deserializeNBT(tag);&lt;br /&gt;
        }&lt;br /&gt;
    };&lt;br /&gt;
&lt;br /&gt;
    event.addCapabilities(new ResourceLocation(&amp;quot;examplemod&amp;quot;, &amp;quot;fe_compatibility&amp;quot;), provider);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that when using capabilities on entities, you should manually invalidate the capability via &amp;lt;code&amp;gt;invalidateCaps()&amp;lt;/code&amp;gt;, via etc. &amp;lt;code&amp;gt;PlayerEvent.Clone&amp;lt;/code&amp;gt;. This is due to the fact that players are recreated &amp;amp; copied when moving across dimensions, not simply moved.&lt;br /&gt;
&lt;br /&gt;
=== Accessing a Capability ===&lt;br /&gt;
&lt;br /&gt;
Accessing a Capability is the process by which a user is able to '''query''' a Capability Provider for a specific&lt;br /&gt;
instance of a capability.&lt;br /&gt;
&lt;br /&gt;
This is perhaps the second most important part of the entire capability system, since it is what allows cross-mod&lt;br /&gt;
interaction. To obtain an instance of a Capability, the user must first get a hold of the Capability Provider that&lt;br /&gt;
should be queried. This can be done in a variety of ways and is outside the scope of this article. The user should&lt;br /&gt;
then invoke the &amp;lt;code&amp;gt;getCapability&amp;lt;/code&amp;gt; method passing the unique instance of the capability that should be queried&lt;br /&gt;
(see [[#Obtaining a Capability|Obtaining a Capability]] for more information) and the querying &amp;lt;code&amp;gt;Direction&amp;lt;/code&amp;gt;,&lt;br /&gt;
if applicable.&lt;br /&gt;
&lt;br /&gt;
The returned object is a &amp;lt;code&amp;gt;LazyOptional&amp;lt;/code&amp;gt; wrapping the queried Capability, if the capability provider exposes&lt;br /&gt;
it, otherwise it will be empty. The &amp;lt;code&amp;gt;LazyOptional&amp;lt;/code&amp;gt; can be either unwrapped via an &amp;lt;code&amp;gt;orElse&amp;lt;/code&amp;gt; or&lt;br /&gt;
used directly via &amp;lt;code&amp;gt;ifPresent&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
It is '''highly suggested''' to cache the returned &amp;lt;code&amp;gt;LazyOptional&amp;lt;/code&amp;gt; to avoid querying the same provider every&lt;br /&gt;
time, in order to improve performance. The user should thus register itself to the invalidation listener via the&lt;br /&gt;
&amp;lt;code&amp;gt;addListener&amp;lt;/code&amp;gt; method. This ensures that the user will be able to react to the invalidation of the&lt;br /&gt;
&amp;lt;code&amp;gt;LazyOptional&amp;lt;/code&amp;gt; and remove it from the cache.&lt;br /&gt;
&lt;br /&gt;
With the above in mind, part of an user may be similar to the following snippet of code:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
// note the use of EnumMap, which is much more performant than HashMap for enum keys&lt;br /&gt;
private final Map&amp;lt;Direction, LazyOptional&amp;lt;IEnergyStorage&amp;gt;&amp;gt; cache = new EnumMap&amp;lt;&amp;gt;(Direction.class);&lt;br /&gt;
&lt;br /&gt;
private void sendPowerTo(int power, Direction direction) {&lt;br /&gt;
    LazyOptional&amp;lt;IEnergyStorage&amp;gt; targetCapability = cache.get(direction);&lt;br /&gt;
&lt;br /&gt;
    if (targetCapability == null) {&lt;br /&gt;
        ICapabilityProvider provider = level.getBlockEntity(pos.relative(direction));&lt;br /&gt;
        targetCapability = provider.getCapability(CapabilityEnergy.ENERGY, direction.getOpposite());&lt;br /&gt;
        cache.put(direction, targetCapability);&lt;br /&gt;
        targetCapability.addListener(self -&amp;gt; cache.put(direction, null));&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    targetCapability.ifPresent(storage -&amp;gt; storage.receiveEnergy(power, false));&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This example implementation of an user is querying via a &amp;lt;code&amp;gt;BlockEntity&amp;lt;/code&amp;gt; the neighboring capability provider&lt;br /&gt;
for an &amp;lt;code&amp;gt;IEnergyStorage&amp;lt;/code&amp;gt; capability. Before obtaining the provider, the code performs a cache lookup for the&lt;br /&gt;
targeted capability. If the check succeeds, then no lookup is performed; if the check fails, the targeted Capability&lt;br /&gt;
Provider is obtained and queried for the Capability. The obtained &amp;lt;code&amp;gt;LazyOptional&amp;lt;/code&amp;gt; is then cached and a&lt;br /&gt;
listener is attached to it so that the cache would be emptied on invalidation. The code then continues with the&lt;br /&gt;
interaction with the capability, which is outside the scope of this article.&lt;br /&gt;
&lt;br /&gt;
== Creating Custom Capabilities ==&lt;br /&gt;
&lt;br /&gt;
While the various capabilities provided by Forge may satisfy the most common use cases, there is always the chance that&lt;br /&gt;
a mod may require a custom solution. For this reason, Forge provides a way to define a custom Capability.&lt;br /&gt;
&lt;br /&gt;
Defining a custom Capability requires the user to provide one main component: the Capability Interface. Optionally, a &lt;br /&gt;
Capability Implementation and Capability Provider can also be created. In this&lt;br /&gt;
case, the provider will be used as described in [[#Attaching a Capability|Attaching a Capability]]. The various details &lt;br /&gt;
for all these components are described in the respective sections of this article.&lt;br /&gt;
&lt;br /&gt;
In this section, we will refer to the implementation of a &amp;lt;code&amp;gt;MyCapability&amp;lt;/code&amp;gt; capability, that can be used to&lt;br /&gt;
store a single mutable &amp;lt;code&amp;gt;String&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Refer also to [[#Code Examples|Code Examples]] for an example on how the various components may be implemented in a&lt;br /&gt;
real-world scenario.&lt;br /&gt;
&lt;br /&gt;
=== The Capability Interface and the Capability Implementation ===&lt;br /&gt;
&lt;br /&gt;
The Capability Interface is one of the most important parts of a Capability: without it, the Capability effectively does&lt;br /&gt;
not exist. Designing a Capability Interface is exactly like designing any Java interface, so the particular details will&lt;br /&gt;
be glossed over in this section.&lt;br /&gt;
&lt;br /&gt;
The Capability Implementation, on the other hand, is the implementation of the previously defined Capability Interface.&lt;br /&gt;
Usual rules for interface implementations follow. There can be more than one Capability Implementation for each&lt;br /&gt;
capability. &lt;br /&gt;
&lt;br /&gt;
Note that a '''well-formed''' capability implementation should '''not store''' the Capability Provider inside of it: we&lt;br /&gt;
call the capability implementation ''provider-agnostic''. This is not a hard-requirement, though, rather it should act&lt;br /&gt;
more as a guideline. There are in fact certain situations where this cannot be avoided (e.g. attaching a client-synced&lt;br /&gt;
capability to an &amp;lt;code&amp;gt;ItemStack&amp;lt;/code&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
Given all of the above information, this may be an example implementation of both a Capability Interface and a&lt;br /&gt;
Capability Implementation:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
public interface MyCapability {&lt;br /&gt;
    String getValue();&lt;br /&gt;
    void setValue(String value);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
public class MyCapabilityImplementation implements MyCapability {&lt;br /&gt;
    private String value;&lt;br /&gt;
&lt;br /&gt;
    @Override&lt;br /&gt;
    public String getValue() {&lt;br /&gt;
        return this.value;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    @Override&lt;br /&gt;
    public void setValue(String value) {&lt;br /&gt;
        this.value = value;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that in this case, only a single implementation is provided.&lt;br /&gt;
&lt;br /&gt;
=== The Capability Provider ===&lt;br /&gt;
&lt;br /&gt;
The Capability Provider is an optional component of the capability that allows the Capability to be attached to a&lt;br /&gt;
component. The details on how a Capability Provider should behave have already been discussed in the two previous&lt;br /&gt;
sections [[#Exposing a Capability|Exposing a Capability]] and [[#Attaching a Capability|Attaching a Capability]]: refer&lt;br /&gt;
to those for more information.&lt;br /&gt;
&lt;br /&gt;
=== Tying it All Together ===&lt;br /&gt;
&lt;br /&gt;
Once all components of a Capability have been created, they must be registered so that the game is aware of the&lt;br /&gt;
capability's presence. The registration requires specifying only the Capability Interface.&lt;br /&gt;
&lt;br /&gt;
The registration can be performed by calling the &amp;lt;code&amp;gt;register&amp;lt;/code&amp;gt; method within the &amp;lt;code&amp;gt;RegisterCapabilitiesEvent&amp;lt;/code&amp;gt; which is fired on the &amp;lt;code&amp;gt;MOD&amp;lt;/code&amp;gt; event bus. The&lt;br /&gt;
registration will also automatically inject the created Capability into all relevant fields and methods: refer to&lt;br /&gt;
[[#Obtaining a Capability|Obtaining a Capability]] for more information.&lt;br /&gt;
&lt;br /&gt;
An example of registration can be found in the snippet that follows:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
@SubscribeEvent&lt;br /&gt;
public void registerCaps(RegisterCapabilitiesEvent event) {&lt;br /&gt;
    event.register(MyCapability.class);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Class Diagram ===&lt;br /&gt;
&lt;br /&gt;
[[File:Custom Capability Class Diagram.svg|800px|thumb|center|Custom Capability Class Diagram]]&lt;br /&gt;
&lt;br /&gt;
In the above diagram the green and red marked areas are classes from Minecraft and Forge respectively. The classes inside the purple area are only needed if you want to [[#Attaching a Capability|Attach a Capability]]. Furthermore this diagram models a persistent provider and its most basic form, for more information on how to create a more complex provider see [[#Custom Capability Providers|Custom Capability Providers]]. To create a volatile provider instead just do not implement &amp;lt;code&amp;gt;INBTSerializable&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Custom Capability Providers ==&lt;br /&gt;
&lt;br /&gt;
Much like custom Capabilities, Forge also allows the creation of custom Capability Providers. The main advantage of this&lt;br /&gt;
is allowing mods to create custom providers for their custom objects, in order to promote not only cross-mod&lt;br /&gt;
compatibility, but also uniformity in the way users may interact with different mod APIs.&lt;br /&gt;
&lt;br /&gt;
This section will only give the basic outline of what is necessary to implement a custom Capability Provider: for more&lt;br /&gt;
in-depth explanation, people are referred to the game code.&lt;br /&gt;
&lt;br /&gt;
By definition, a custom Capability Provider is everything that implements the &amp;lt;code&amp;gt;ICapabilityProvider&amp;lt;/code&amp;gt;&lt;br /&gt;
interface. In this section, though, we will only cover people that may want to replicate the functionality of one of&lt;br /&gt;
the default providers, such as &amp;lt;code&amp;gt;BlockEntity&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;LevelChunk&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
The easiest way of doing this is extending the &amp;lt;code&amp;gt;CapabilityProvider&amp;lt;/code&amp;gt; class provided by Forge. This will&lt;br /&gt;
automatically set up an ''agnostic'' Capability Provider. To fully initialize the capability provider, the subclass&lt;br /&gt;
should then invoke the &amp;lt;code&amp;gt;gatherCapabilities&amp;lt;/code&amp;gt; method as the last instruction in its constructor, to ensure that&lt;br /&gt;
the game is able to recollect and attach all capabilities that other mods may want to attach to the capability provider.&lt;br /&gt;
&lt;br /&gt;
== Code Examples ==&lt;br /&gt;
&lt;br /&gt;
* [https://gist.github.com/TheCurle/6db954d680f6f067dcdc791355c32c89 A Gist showing a quick and dirty example on how to implement a Capability effectively]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Data Storage]]&lt;/div&gt;</summary>
		<author><name>SizableShrimp</name></author>
	</entry>
	<entry>
		<id>https://forge.gemwire.uk/index.php?title=Template:Supported_versions&amp;diff=3106</id>
		<title>Template:Supported versions</title>
		<link rel="alternate" type="text/html" href="https://forge.gemwire.uk/index.php?title=Template:Supported_versions&amp;diff=3106"/>
		<updated>2022-01-08T19:21:45Z</updated>

		<summary type="html">&lt;p&gt;SizableShrimp: Update Latest version to 1.18.1&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{#if:{{{text|}}}&lt;br /&gt;
|The current ''Latest'' version is '''1.18.1'''. The current ''Long Term Support (LTS)'' version is '''1.16.5'''.&lt;br /&gt;
|{{#vardefine: page | Main Page }}&lt;br /&gt;
{{Colored box&lt;br /&gt;
|border-color=#3498db&lt;br /&gt;
|title={{{title|This wiki hosts information for the following Minecraft versions:}}}&lt;br /&gt;
|{{{1|* [[{{#var:page}}|1.18]]&lt;br /&gt;
* [[{{#var:page}}/1.17|1.17]]&lt;br /&gt;
* [[{{#var:page}}/1.16|1.16]]}}}&lt;br /&gt;
}}}}&lt;/div&gt;</summary>
		<author><name>SizableShrimp</name></author>
	</entry>
	<entry>
		<id>https://forge.gemwire.uk/index.php?title=Config&amp;diff=3105</id>
		<title>Config</title>
		<link rel="alternate" type="text/html" href="https://forge.gemwire.uk/index.php?title=Config&amp;diff=3105"/>
		<updated>2022-01-08T19:20:56Z</updated>

		<summary type="html">&lt;p&gt;SizableShrimp: Redirect to Configs&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;#REDIRECT [[Configs]]&lt;/div&gt;</summary>
		<author><name>SizableShrimp</name></author>
	</entry>
	<entry>
		<id>https://forge.gemwire.uk/index.php?title=Template:Supported_versions&amp;diff=3090</id>
		<title>Template:Supported versions</title>
		<link rel="alternate" type="text/html" href="https://forge.gemwire.uk/index.php?title=Template:Supported_versions&amp;diff=3090"/>
		<updated>2021-12-07T14:48:13Z</updated>

		<summary type="html">&lt;p&gt;SizableShrimp: Use Main Page for now&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{#if:{{{text|}}}&lt;br /&gt;
|The current ''Latest'' version is '''1.18'''. The current ''Long Term Support (LTS)'' version is '''1.16.5'''.&lt;br /&gt;
|{{#vardefine: page | Main Page }}&lt;br /&gt;
{{Colored box&lt;br /&gt;
|border-color=#3498db&lt;br /&gt;
|title={{{title|This wiki hosts information for the following Minecraft versions:}}}&lt;br /&gt;
|{{{1|* [[{{#var:page}}|1.18]]&lt;br /&gt;
* [[{{#var:page}}/1.17|1.17]]&lt;br /&gt;
* [[{{#var:page}}/1.16|1.16]]}}}&lt;br /&gt;
}}}}&lt;/div&gt;</summary>
		<author><name>SizableShrimp</name></author>
	</entry>
	<entry>
		<id>https://forge.gemwire.uk/index.php?title=Template:Supported_versions&amp;diff=3089</id>
		<title>Template:Supported versions</title>
		<link rel="alternate" type="text/html" href="https://forge.gemwire.uk/index.php?title=Template:Supported_versions&amp;diff=3089"/>
		<updated>2021-12-07T14:09:06Z</updated>

		<summary type="html">&lt;p&gt;SizableShrimp: Try {{BASEPAGENAME}}&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{#if:{{{text|}}}|The current ''Latest'' version is '''1.18'''. The current ''Long Term Support (LTS)'' version is '''1.16.5'''.|{{Colored box&lt;br /&gt;
|border-color=#3498db&lt;br /&gt;
|title={{{title|This wiki hosts information for the following Minecraft versions:}}}&lt;br /&gt;
|{{{1|* [[{{{page|{{NAMESPACE}}:{{BASEPAGENAME}}}}}|1.18]]&lt;br /&gt;
* [[{{{page|{{NAMESPACE}}:{{BASEPAGENAME}}}}}/1.17|1.17]]&lt;br /&gt;
* [[{{{page|{{NAMESPACE}}:{{BASEPAGENAME}}}}}/1.16|1.16]]}}}&lt;br /&gt;
}}}}&lt;/div&gt;</summary>
		<author><name>SizableShrimp</name></author>
	</entry>
	<entry>
		<id>https://forge.gemwire.uk/index.php?title=Template:Supported_versions&amp;diff=3088</id>
		<title>Template:Supported versions</title>
		<link rel="alternate" type="text/html" href="https://forge.gemwire.uk/index.php?title=Template:Supported_versions&amp;diff=3088"/>
		<updated>2021-12-07T14:01:16Z</updated>

		<summary type="html">&lt;p&gt;SizableShrimp: Allow specifying linked page&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{#if:{{{text|}}}|The current ''Latest'' version is '''1.18'''. The current ''Long Term Support (LTS)'' version is '''1.16.5'''.|{{Colored box&lt;br /&gt;
|border-color=#3498db&lt;br /&gt;
|title={{{title|This wiki hosts information for the following Minecraft versions:}}}&lt;br /&gt;
|{{{1|* [[{{{page|{{NAMESPACE}}:{{ROOTPAGENAME}}}}}|1.18]]&lt;br /&gt;
* [[{{{page|{{NAMESPACE}}:{{ROOTPAGENAME}}}}}/1.17|1.17]]&lt;br /&gt;
* [[{{{page|{{NAMESPACE}}:{{ROOTPAGENAME}}}}}/1.16|1.16]]}}}&lt;br /&gt;
}}}}&lt;/div&gt;</summary>
		<author><name>SizableShrimp</name></author>
	</entry>
	<entry>
		<id>https://forge.gemwire.uk/index.php?title=Main_Page/1.16&amp;diff=3087</id>
		<title>Main Page/1.16</title>
		<link rel="alternate" type="text/html" href="https://forge.gemwire.uk/index.php?title=Main_Page/1.16&amp;diff=3087"/>
		<updated>2021-12-07T13:59:15Z</updated>

		<summary type="html">&lt;p&gt;SizableShrimp: Use Template:Supported versions with text=1&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/1.16|Getting Started]]&lt;br /&gt;
* [[Proper Mod Structuring/1.16|Proper Mod Structuring]]&lt;br /&gt;
* [[Debug Profiler/1.16|The Debug Profiler]]&lt;br /&gt;
* [[Version Checker/1.16|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/1.16|Understanding Sides]]&lt;br /&gt;
* [[Events/1.16|Understanding Events]]&lt;br /&gt;
* [[Registration/1.16|Registration]]&lt;br /&gt;
* [[Internationalization/1.16|Internationalization]]&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/1.16|Semantic Versioning]]&lt;br /&gt;
* [[Stages of Modloading/1.16|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/1.16|Introduction]]&lt;br /&gt;
* [[Recipes/1.16|Recipes]]&lt;br /&gt;
* [[Tags/1.16|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/1.16|Creating Blocks]]&lt;br /&gt;
* [[Understanding Blockstates/1.16|Understanding Blockstates]] &lt;br /&gt;
* [[Interacting With Blocks/1.16|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/1.16|Making Items]]&lt;br /&gt;
* [[Making Tools/1.16|Making Tools]]&lt;br /&gt;
* [[ItemStack TileEntityRenderer/1.16|&amp;lt;tt&amp;gt;ItemStackTileEntityRenderer&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/1.16|Introduction]]&lt;br /&gt;
* [[Datageneration/Recipes/1.16|Recipes]]&lt;br /&gt;
* [[Datageneration/Tags/1.16|Tags]]&lt;br /&gt;
* [[Datageneration/Loot Tables/1.16|Loot Tables]]&lt;br /&gt;
* [[Datageneration/I18n/1.16|Localization]]&lt;br /&gt;
* [[Datageneration/States and Models/1.16|&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;Tile Entities&amp;lt;/h3&amp;gt;&lt;br /&gt;
* [[Basics of Tile Entities/1.16|Introduction]]&lt;br /&gt;
* [[Using Tile Entity Renderers/1.16|Using Tile Entity Renderers]]&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/1.16|Introduction]]&lt;br /&gt;
* [[Model JSONs/1.16|Model JSONs]]&lt;br /&gt;
* [[BlockState JSONs/1.16|BlockState JSONs]]&lt;br /&gt;
* [[Coloring textures dynamically/1.16|Dynamically Colored Textures]]&lt;br /&gt;
* [[Item Overrides/1.16|Item Overrides]]&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/1.16|Introduction]]&lt;br /&gt;
* [[Using NBT/1.16|Named Binary Tag (NBT)]]&lt;br /&gt;
* [[Using PacketBuffer/1.16|Using &amp;lt;tt&amp;gt;PacketBuffer&amp;lt;/tt&amp;gt;]]&lt;br /&gt;
* [[Sending Packets/1.16|Sending and Receiving Packets]]&lt;br /&gt;
* [[Using SimpleChannel/1.16|Using &amp;lt;tt&amp;gt;SimpleChannel&amp;lt;/tt&amp;gt;]]&lt;br /&gt;
* [[Networking with Entities/1.16|Networking with Entities]]&lt;br /&gt;
* [[DynamicOps/1.16|Using DynamicOps]]&lt;br /&gt;
* [[Codecs/1.16|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/1.16|Understanding Capabilities]] &lt;br /&gt;
* [[Capabilities/Attaching/1.16|Attaching Capabilities]]&lt;br /&gt;
* [[World Saved Data/1.16|World 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;
* [[Effects/1.16|Effects]]&lt;br /&gt;
* [[Potions/1.16|Potions]]&lt;br /&gt;
* [[Particles/1.16|Particles]]&lt;br /&gt;
* [[Sounds/1.16|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/1.16|Understanding Events]]&lt;br /&gt;
* [[Entity Events/1.16|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/1.16|Dependencies]]&lt;br /&gt;
* [[Dynamic Loot Modification/1.16|Dynamic Loot Modification]]&lt;br /&gt;
* [[Text Components/1.16|Text Components and Translation Keys]]&lt;br /&gt;
* [[Key Bindings/1.16|Key Bindings]]&lt;br /&gt;
* [[Access Transformers/1.16|Access Transformers]]&lt;br /&gt;
* [[Toolchain/1.16|Toolchain]]&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/1.16|Recipes]]&lt;br /&gt;
* [[Custom Recipes/1.16|Custom Recipe Types]]&lt;br /&gt;
* [[Datageneration/Recipes/1.16|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>SizableShrimp</name></author>
	</entry>
	<entry>
		<id>https://forge.gemwire.uk/index.php?title=Main_Page/1.17&amp;diff=3086</id>
		<title>Main Page/1.17</title>
		<link rel="alternate" type="text/html" href="https://forge.gemwire.uk/index.php?title=Main_Page/1.17&amp;diff=3086"/>
		<updated>2021-12-07T13:58:29Z</updated>

		<summary type="html">&lt;p&gt;SizableShrimp: Use Template:Supported versions with text=1&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/1.17|Getting Started]]&lt;br /&gt;
* [[Proper Mod Structuring/1.17|Proper Mod Structuring]]&lt;br /&gt;
* [[Mods.toml file/1.17|Mods.toml file]]&lt;br /&gt;
* [[Debug Profiler/1.17|The Debug Profiler]]&lt;br /&gt;
* [[Version Checker/1.17|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/1.17|Understanding Sides]]&lt;br /&gt;
* [[Events/1.17|Understanding Events]]&lt;br /&gt;
* [[Registration/1.17|Registration]]&lt;br /&gt;
* [[Internationalization/1.17|Internationalization]]&lt;br /&gt;
* [[Configs/1.17|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/1.17|Semantic Versioning]]&lt;br /&gt;
* [[Stages of Modloading/1.17|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/1.17|Introduction]]&lt;br /&gt;
* [[Recipes/1.17|Recipes]]&lt;br /&gt;
* [[Tags/1.17|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/1.17|Creating Blocks]]&lt;br /&gt;
* [[Understanding Blockstates/1.17|Understanding Blockstates]] &lt;br /&gt;
* [[Interacting With Blocks/1.17|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/1.17|Making Items]]&lt;br /&gt;
* [[Making Tools/1.17|Making Tools]]&lt;br /&gt;
* [[BlockEntityWithoutLevelRenderer/1.17|&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/1.17|Introduction]]&lt;br /&gt;
* [[Datageneration/Recipes/1.17|Recipes]]&lt;br /&gt;
* [[Datageneration/Tags/1.17|Tags]]&lt;br /&gt;
* [[Datageneration/Loot Tables/1.17|Loot Tables]]&lt;br /&gt;
* [[Datageneration/I18n/1.17|Localization]]&lt;br /&gt;
* [[Datageneration/States and Models/1.17|&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/1.17|Introduction]]&lt;br /&gt;
* [[Block Entity Renderer/1.17|&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/1.17|Introduction]]&lt;br /&gt;
* [[Model JSONs/1.17|Model JSONs]]&lt;br /&gt;
* [[BlockState JSONs/1.17|BlockState JSONs]]&lt;br /&gt;
* [[Coloring textures dynamically/1.17|Dynamically Colored Textures]]&lt;br /&gt;
* [[Item Properties/1.17|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/1.17|Introduction]]&lt;br /&gt;
* [[Using NBT/1.17|Named Binary Tag (NBT)]]&lt;br /&gt;
* [[Using FriendlyByteBuf/1.17|Using &amp;lt;tt&amp;gt;FriendlyByteBuf&amp;lt;/tt&amp;gt;]]&lt;br /&gt;
* [[Sending Packets/1.17|Sending and Receiving Packets]]&lt;br /&gt;
* [[Using SimpleChannel/1.17|Using &amp;lt;tt&amp;gt;SimpleChannel&amp;lt;/tt&amp;gt;]]&lt;br /&gt;
* [[Networking with Entities/1.17|Networking with Entities]]&lt;br /&gt;
* [[DynamicOps/1.17|Using DynamicOps]]&lt;br /&gt;
* [[Codecs/1.17|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/1.17|Understanding Capabilities]] &lt;br /&gt;
* [[Capabilities/Attaching/1.17|Attaching Capabilities]]&lt;br /&gt;
* [[Saved Data/1.17|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/1.17|Mob Effects]]&lt;br /&gt;
* [[Potions/1.17|Potions]]&lt;br /&gt;
* [[Particles/1.17|Particles]]&lt;br /&gt;
* [[Sounds/1.17|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/1.17|Understanding Events]]&lt;br /&gt;
* [[Entity Events/1.17|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/1.17|Dependencies]]&lt;br /&gt;
* [[Dynamic Loot Modification/1.17|Dynamic Loot Modification]]&lt;br /&gt;
* [[Components/1.17|Components and Translation Keys]]&lt;br /&gt;
* [[Key Mappings/1.17|Key Mappings]]&lt;br /&gt;
* [[Access Transformers/1.17|Access Transformers]]&lt;br /&gt;
* [[Toolchain/1.17|Toolchain]]&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/1.17|Recipes]]&lt;br /&gt;
* [[Custom Recipes/1.17|Custom Recipe Types]]&lt;br /&gt;
* [[Datageneration/Recipes/1.17|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>SizableShrimp</name></author>
	</entry>
	<entry>
		<id>https://forge.gemwire.uk/index.php?title=Main_Page&amp;diff=3085</id>
		<title>Main Page</title>
		<link rel="alternate" type="text/html" href="https://forge.gemwire.uk/index.php?title=Main_Page&amp;diff=3085"/>
		<updated>2021-12-07T13:57:51Z</updated>

		<summary type="html">&lt;p&gt;SizableShrimp: Use Template:Supported versions with text=1&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;
&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>SizableShrimp</name></author>
	</entry>
	<entry>
		<id>https://forge.gemwire.uk/index.php?title=Template:Supported_versions&amp;diff=3084</id>
		<title>Template:Supported versions</title>
		<link rel="alternate" type="text/html" href="https://forge.gemwire.uk/index.php?title=Template:Supported_versions&amp;diff=3084"/>
		<updated>2021-12-07T13:57:07Z</updated>

		<summary type="html">&lt;p&gt;SizableShrimp: Add text=1 to show different info&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{#if:{{{text|}}}|The current ''Latest'' version is '''1.18'''. The current ''Long Term Support (LTS)'' version is '''1.16.5'''.|{{Colored box&lt;br /&gt;
|border-color=#3498db&lt;br /&gt;
|title={{{title|This wiki hosts information for the following Minecraft versions:}}}&lt;br /&gt;
|{{{1|* [[Main Page|1.18]]&lt;br /&gt;
* [[Main Page/1.17|1.17]]&lt;br /&gt;
* [[Main Page/1.16|1.16]]}}}&lt;br /&gt;
}}}}&lt;/div&gt;</summary>
		<author><name>SizableShrimp</name></author>
	</entry>
	<entry>
		<id>https://forge.gemwire.uk/index.php?title=Template:Supported_versions&amp;diff=3083</id>
		<title>Template:Supported versions</title>
		<link rel="alternate" type="text/html" href="https://forge.gemwire.uk/index.php?title=Template:Supported_versions&amp;diff=3083"/>
		<updated>2021-12-06T05:54:24Z</updated>

		<summary type="html">&lt;p&gt;SizableShrimp: Update info for Forge 1.18&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Colored box&lt;br /&gt;
|border-color=#3498db&lt;br /&gt;
|title={{{title|This wiki hosts information for the following Minecraft versions:}}}&lt;br /&gt;
|{{{1|* [[Main Page|1.18]]&lt;br /&gt;
* [[Main Page/1.17|1.17]]&lt;br /&gt;
* [[Main Page/1.16|1.16]]}}}&lt;br /&gt;
}}&lt;/div&gt;</summary>
		<author><name>SizableShrimp</name></author>
	</entry>
	<entry>
		<id>https://forge.gemwire.uk/index.php?title=Main_Page&amp;diff=3082</id>
		<title>Main Page</title>
		<link rel="alternate" type="text/html" href="https://forge.gemwire.uk/index.php?title=Main_Page&amp;diff=3082"/>
		<updated>2021-12-06T05:53:38Z</updated>

		<summary type="html">&lt;p&gt;SizableShrimp: Update info for Forge 1.18&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;
The current ''Latest'' version is '''1.18'''. The current ''Long Term Support (LTS)'' version is '''1.16.5'''.&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;
&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>SizableShrimp</name></author>
	</entry>
	<entry>
		<id>https://forge.gemwire.uk/index.php?title=Codec&amp;diff=2981</id>
		<title>Codec</title>
		<link rel="alternate" type="text/html" href="https://forge.gemwire.uk/index.php?title=Codec&amp;diff=2981"/>
		<updated>2021-11-27T05:36:25Z</updated>

		<summary type="html">&lt;p&gt;SizableShrimp: Redirect to Codecs&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;#REDIRECT [[Codecs]]&lt;/div&gt;</summary>
		<author><name>SizableShrimp</name></author>
	</entry>
	<entry>
		<id>https://forge.gemwire.uk/index.php?title=Main_Page/1.16&amp;diff=2815</id>
		<title>Main Page/1.16</title>
		<link rel="alternate" type="text/html" href="https://forge.gemwire.uk/index.php?title=Main_Page/1.16&amp;diff=2815"/>
		<updated>2021-07-28T02:11:16Z</updated>

		<summary type="html">&lt;p&gt;SizableShrimp: Update info for Forge 1.17.1&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;
The current ''Latest'' version is '''1.17.1'''. The current ''Long Term Support (LTS)'' version is '''1.16.5'''. '''1.15.2''' is currently in ''grace/LTS''.&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/1.16|Getting Started]]&lt;br /&gt;
* [[Proper Mod Structuring/1.16|Proper Mod Structuring]]&lt;br /&gt;
* [[Debug Profiler/1.16|The Debug Profiler]]&lt;br /&gt;
* [[Version Checker/1.16|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/1.16|Understanding Sides]]&lt;br /&gt;
* [[Events/1.16|Understanding Events]]&lt;br /&gt;
* [[Registration/1.16|Registration]]&lt;br /&gt;
* [[Internationalization/1.16|Internationalization]]&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/1.16|Semantic Versioning]]&lt;br /&gt;
* [[Stages of Modloading/1.16|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/1.16|Introduction]]&lt;br /&gt;
* [[Recipes/1.16|Recipes]]&lt;br /&gt;
* [[Tags/1.16|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/1.16|Creating Blocks]]&lt;br /&gt;
* [[Understanding Blockstates/1.16|Understanding Blockstates]] &lt;br /&gt;
* [[Interacting With Blocks/1.16|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/1.16|Making Items]]&lt;br /&gt;
* [[Making Tools/1.16|Making Tools]]&lt;br /&gt;
* [[ItemStack TileEntityRenderer/1.16|&amp;lt;tt&amp;gt;ItemStackTileEntityRenderer&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/1.16|Introduction]]&lt;br /&gt;
* [[Datageneration/Recipes/1.16|Recipes]]&lt;br /&gt;
* [[Datageneration/Tags/1.16|Tags]]&lt;br /&gt;
* [[Datageneration/Loot Tables/1.16|Loot Tables]]&lt;br /&gt;
* [[Datageneration/I18n/1.16|Localization]]&lt;br /&gt;
* [[Datageneration/States and Models/1.16|&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;Tile Entities&amp;lt;/h3&amp;gt;&lt;br /&gt;
* [[Basics of Tile Entities/1.16|Introduction]]&lt;br /&gt;
* [[Using Tile Entity Renderers/1.16|Using Tile Entity Renderers]]&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/1.16|Introduction]]&lt;br /&gt;
* [[Model JSONs/1.16|Model JSONs]]&lt;br /&gt;
* [[BlockState JSONs/1.16|BlockState JSONs]]&lt;br /&gt;
* [[Coloring textures dynamically/1.16|Dynamically Colored Textures]]&lt;br /&gt;
* [[Item Overrides/1.16|Item Overrides]]&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/1.16|Introduction]]&lt;br /&gt;
* [[Using NBT/1.16|Named Binary Tag (NBT)]]&lt;br /&gt;
* [[Using PacketBuffer/1.16|Using &amp;lt;tt&amp;gt;PacketBuffer&amp;lt;/tt&amp;gt;]]&lt;br /&gt;
* [[Sending Packets/1.16|Sending and Receiving Packets]]&lt;br /&gt;
* [[Using SimpleChannel/1.16|Using &amp;lt;tt&amp;gt;SimpleChannel&amp;lt;/tt&amp;gt;]]&lt;br /&gt;
* [[Networking with Entities/1.16|Networking with Entities]]&lt;br /&gt;
* [[DynamicOps/1.16|Using DynamicOps]]&lt;br /&gt;
* [[Codecs/1.16|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/1.16|Understanding Capabilities]] &lt;br /&gt;
* [[Capabilities/Attaching/1.16|Attaching Capabilities]]&lt;br /&gt;
* [[World Saved Data/1.16|World 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;
* [[Effects/1.16|Effects]]&lt;br /&gt;
* [[Potions/1.16|Potions]]&lt;br /&gt;
* [[Particles/1.16|Particles]]&lt;br /&gt;
* [[Sounds/1.16|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/1.16|Understanding Events]]&lt;br /&gt;
* [[Entity Events/1.16|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/1.16|Dependencies]]&lt;br /&gt;
* [[Dynamic Loot Modification/1.16|Dynamic Loot Modification]]&lt;br /&gt;
* [[Text Components/1.16|Text Components and Translation Keys]]&lt;br /&gt;
* [[Key Bindings/1.16|Key Bindings]]&lt;br /&gt;
* [[Access Transformers/1.16|Access Transformers]]&lt;br /&gt;
* [[Toolchain/1.16|Toolchain]]&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/1.16|Recipes]]&lt;br /&gt;
* [[Custom Recipes/1.16|Custom Recipe Types]]&lt;br /&gt;
* [[Datageneration/Recipes/1.16|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>SizableShrimp</name></author>
	</entry>
	<entry>
		<id>https://forge.gemwire.uk/index.php?title=Main_Page&amp;diff=2814</id>
		<title>Main Page</title>
		<link rel="alternate" type="text/html" href="https://forge.gemwire.uk/index.php?title=Main_Page&amp;diff=2814"/>
		<updated>2021-07-28T02:10:14Z</updated>

		<summary type="html">&lt;p&gt;SizableShrimp: Update info for Forge 1.17.1&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;
The current ''Latest'' version is '''1.17.1'''. The current ''Long Term Support (LTS)'' version is '''1.16.5'''. '''1.15.2''' is currently in ''grace/LTS''.&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;
* [[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;
&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;
* [[ItemStack TileEntityRenderer|&amp;lt;tt&amp;gt;ItemStackTileEntityRenderer&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;Tile Entities&amp;lt;/h3&amp;gt;&lt;br /&gt;
* [[Basics of Tile Entities|Introduction]]&lt;br /&gt;
* [[Using Tile Entity Renderers]]&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 Overrides]]&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 PacketBuffer|Using &amp;lt;tt&amp;gt;PacketBuffer&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;
* [[World 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;
* [[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;
* [[Text Components|Text Components and Translation Keys]]&lt;br /&gt;
* [[Key Bindings]]&lt;br /&gt;
* [[Access Transformers]]&lt;br /&gt;
* [[Toolchain]]&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>SizableShrimp</name></author>
	</entry>
	<entry>
		<id>https://forge.gemwire.uk/index.php?title=Template:Supported_versions&amp;diff=2813</id>
		<title>Template:Supported versions</title>
		<link rel="alternate" type="text/html" href="https://forge.gemwire.uk/index.php?title=Template:Supported_versions&amp;diff=2813"/>
		<updated>2021-07-28T02:09:29Z</updated>

		<summary type="html">&lt;p&gt;SizableShrimp: grammar change&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Colored box&lt;br /&gt;
|border-color=#3498db&lt;br /&gt;
|title={{{title|This wiki hosts information for the following Minecraft versions:}}}&lt;br /&gt;
|{{{1|* [[Main Page|1.17]]&lt;br /&gt;
* [[Main Page/1.16|1.16]]}}}&lt;br /&gt;
}}&lt;/div&gt;</summary>
		<author><name>SizableShrimp</name></author>
	</entry>
	<entry>
		<id>https://forge.gemwire.uk/index.php?title=Template:Supported_versions&amp;diff=2812</id>
		<title>Template:Supported versions</title>
		<link rel="alternate" type="text/html" href="https://forge.gemwire.uk/index.php?title=Template:Supported_versions&amp;diff=2812"/>
		<updated>2021-07-28T02:07:02Z</updated>

		<summary type="html">&lt;p&gt;SizableShrimp: Create initial template&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Colored box&lt;br /&gt;
|border-color=#3498db&lt;br /&gt;
|title={{{title|This wiki supports the following Minecraft versions:}}}&lt;br /&gt;
|{{{1|* [[Main Page|1.17]]&lt;br /&gt;
* [[Main Page/1.16|1.16]]}}}&lt;br /&gt;
}}&lt;/div&gt;</summary>
		<author><name>SizableShrimp</name></author>
	</entry>
	<entry>
		<id>https://forge.gemwire.uk/index.php?title=Main_Page/1.16&amp;diff=2811</id>
		<title>Main Page/1.16</title>
		<link rel="alternate" type="text/html" href="https://forge.gemwire.uk/index.php?title=Main_Page/1.16&amp;diff=2811"/>
		<updated>2021-07-27T04:21:04Z</updated>

		<summary type="html">&lt;p&gt;SizableShrimp: Small fix&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;
''The wiki is still under heavy construction. Pages may move around, so if you bookmark a page, beware when the page is moved and your bookmarked link dies.''&lt;br /&gt;
&lt;br /&gt;
Please note that we only maintain wiki entries for the Latest and Long Term Support (LTS) releases. Once a documented release is no longer under LTS, it will be removed.&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;
The current ''Latest'' version is '''1.16.5'''. The current ''Long Term Support (LTS)'' version is '''1.15.2'''.&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/1.16|Getting Started]]&lt;br /&gt;
* [[Proper Mod Structuring/1.16|Proper Mod Structuring]]&lt;br /&gt;
* [[Debug Profiler/1.16|The Debug Profiler]]&lt;br /&gt;
* [[Version Checker/1.16|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/1.16|Understanding Sides]]&lt;br /&gt;
* [[Events/1.16|Understanding Events]]&lt;br /&gt;
* [[Registration/1.16|Registration]]&lt;br /&gt;
* [[Internationalization/1.16|Internationalization]]&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/1.16|Semantic Versioning]]&lt;br /&gt;
* [[Stages of Modloading/1.16|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/1.16|Introduction]]&lt;br /&gt;
* [[Recipes/1.16|Recipes]]&lt;br /&gt;
* [[Tags/1.16|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/1.16|Creating Blocks]]&lt;br /&gt;
* [[Understanding Blockstates/1.16|Understanding Blockstates]] &lt;br /&gt;
* [[Interacting With Blocks/1.16|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/1.16|Making Items]]&lt;br /&gt;
* [[Making Tools/1.16|Making Tools]]&lt;br /&gt;
* [[ItemStack TileEntityRenderer/1.16|&amp;lt;tt&amp;gt;ItemStackTileEntityRenderer&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/1.16|Introduction]]&lt;br /&gt;
* [[Datageneration/Recipes/1.16|Recipes]]&lt;br /&gt;
* [[Datageneration/Tags/1.16|Tags]]&lt;br /&gt;
* [[Datageneration/Loot Tables/1.16|Loot Tables]]&lt;br /&gt;
* [[Datageneration/I18n/1.16|Localization]]&lt;br /&gt;
* [[Datageneration/States and Models/1.16|&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;Tile Entities&amp;lt;/h3&amp;gt;&lt;br /&gt;
* [[Basics of Tile Entities/1.16|Introduction]]&lt;br /&gt;
* [[Using Tile Entity Renderers/1.16|Using Tile Entity Renderers]]&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/1.16|Introduction]]&lt;br /&gt;
* [[Model JSONs/1.16|Model JSONs]]&lt;br /&gt;
* [[BlockState JSONs/1.16|BlockState JSONs]]&lt;br /&gt;
* [[Coloring textures dynamically/1.16|Dynamically Colored Textures]]&lt;br /&gt;
* [[Item Overrides/1.16|Item Overrides]]&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/1.16|Introduction]]&lt;br /&gt;
* [[Using NBT/1.16|Named Binary Tag (NBT)]]&lt;br /&gt;
* [[Using PacketBuffer/1.16|Using &amp;lt;tt&amp;gt;PacketBuffer&amp;lt;/tt&amp;gt;]]&lt;br /&gt;
* [[Sending Packets/1.16|Sending and Receiving Packets]]&lt;br /&gt;
* [[Using SimpleChannel/1.16|Using &amp;lt;tt&amp;gt;SimpleChannel&amp;lt;/tt&amp;gt;]]&lt;br /&gt;
* [[Networking with Entities/1.16|Networking with Entities]]&lt;br /&gt;
* [[DynamicOps/1.16|Using DynamicOps]]&lt;br /&gt;
* [[Codecs/1.16|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/1.16|Understanding Capabilities]] &lt;br /&gt;
* [[Capabilities/Attaching/1.16|Attaching Capabilities]]&lt;br /&gt;
* [[World Saved Data/1.16|World 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;
* [[Effects/1.16|Effects]]&lt;br /&gt;
* [[Potions/1.16|Potions]]&lt;br /&gt;
* [[Particles/1.16|Particles]]&lt;br /&gt;
* [[Sounds/1.16|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/1.16|Understanding Events]]&lt;br /&gt;
* [[Entity Events/1.16|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/1.16|Dependencies]]&lt;br /&gt;
* [[Dynamic Loot Modification/1.16|Dynamic Loot Modification]]&lt;br /&gt;
* [[Text Components/1.16|Text Components and Translation Keys]]&lt;br /&gt;
* [[Key Bindings/1.16|Key Bindings]]&lt;br /&gt;
* [[Access Transformers/1.16|Access Transformers]]&lt;br /&gt;
* [[Toolchain/1.16|Toolchain]]&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/1.16|Recipes]]&lt;br /&gt;
* [[Custom Recipes/1.16|Custom Recipe Types]]&lt;br /&gt;
* [[Datageneration/Recipes/1.16|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>SizableShrimp</name></author>
	</entry>
	<entry>
		<id>https://forge.gemwire.uk/index.php?title=Components&amp;diff=2648</id>
		<title>Components</title>
		<link rel="alternate" type="text/html" href="https://forge.gemwire.uk/index.php?title=Components&amp;diff=2648"/>
		<updated>2021-05-30T00:27:38Z</updated>

		<summary type="html">&lt;p&gt;SizableShrimp: Wording changes and updates&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Text components''' (base interface &amp;lt;code&amp;gt;ITextComponent&amp;lt;/code&amp;gt;) are forms of text used by Minecraft and Forge to concisely hold data relating to text. They form the basis of the chat system used in Minecraft. They are used for serializing and sending text data over network to players, displaying on clients, and styling for how the text appears with modifiers like bold and coloration.&lt;br /&gt;
&lt;br /&gt;
There are two main types of text components: &amp;lt;code&amp;gt;StringTextComponent&amp;lt;/code&amp;gt;s and &amp;lt;code&amp;gt;TranslationTextComponent&amp;lt;/code&amp;gt;s. Both serve different purposes, although you should prefer the latter one for most general mod development. Both of these also extend from a base class of &amp;lt;code&amp;gt;TextComponent&amp;lt;/code&amp;gt;, which has some important properties.&lt;br /&gt;
&lt;br /&gt;
== TextComponent ==&lt;br /&gt;
Text components at their most basic level hold a &amp;lt;code&amp;gt;Style&amp;lt;/code&amp;gt; object and a list of &amp;quot;sibling&amp;quot; text components named &amp;lt;code&amp;gt;siblings&amp;lt;/code&amp;gt;. In reality, these &amp;quot;siblings&amp;quot; are actually children of the main text component, and are treated as such when formatting with the &amp;lt;code&amp;gt;Style&amp;lt;/code&amp;gt; object. A style can be applied to a text component by calling &amp;lt;code&amp;gt;withStyle&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;setStyle&amp;lt;/code&amp;gt;. &amp;lt;code&amp;gt;withStyle&amp;lt;/code&amp;gt; modifies the existing &amp;lt;code&amp;gt;Style&amp;lt;/code&amp;gt; object with the given property, while &amp;lt;code&amp;gt;setStyle&amp;lt;/code&amp;gt; replaces the current &amp;lt;code&amp;gt;Style&amp;lt;/code&amp;gt; object. By default, text components use a style of &amp;lt;code&amp;gt;Style.EMPTY&amp;lt;/code&amp;gt;, with an empty color representing white and empty properties meaning no special text formatting. To add a light blue color for example, one could simple call &amp;lt;code&amp;gt;theTextComponent.withStyle(TextFormatting.BLUE)&amp;lt;/code&amp;gt;. This will merge the &amp;lt;code&amp;gt;BLUE&amp;lt;/code&amp;gt; color with the existing &amp;lt;code&amp;gt;Style&amp;lt;/code&amp;gt; object. When applying a parent text component's &amp;lt;code&amp;gt;Style&amp;lt;/code&amp;gt; to its children text components, a non-null property of a child &amp;lt;code&amp;gt;Style&amp;lt;/code&amp;gt; will take precedence over its parent &amp;lt;code&amp;gt;Style&amp;lt;/code&amp;gt;. This means that if the color is set for both a child and parent text component, the child's color will be displayed. Otherwise, non-null properties from a parent text component's &amp;lt;code&amp;gt;Style&amp;lt;/code&amp;gt; override properties from the child &amp;lt;code&amp;gt;Style&amp;lt;/code&amp;gt; if they are null.&lt;br /&gt;
&lt;br /&gt;
=== Appending siblings ===&lt;br /&gt;
Siblings can be appended to text components similar to the plus (+) operator with Strings. Either &amp;lt;code&amp;gt;TextComponent#append(ITextComponent)&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;TextComponent#append(String)&amp;lt;/code&amp;gt; can be called. The latter is an overload for the first function, and simply creates a new &amp;lt;code&amp;gt;StringTextComponent&amp;lt;/code&amp;gt; with the provided String.&lt;br /&gt;
&lt;br /&gt;
== StringTextComponent ==&lt;br /&gt;
String text components are the most basic form of text components. They are raw text components that contain a single String object. These are not preferred for general mod development as they cannot be translated into other languages. All properties of the base &amp;lt;code&amp;gt;TextComponent&amp;lt;/code&amp;gt; apply to string text components.&lt;br /&gt;
&lt;br /&gt;
=== Creating ===&lt;br /&gt;
String text components are instantiated in the form &amp;lt;code&amp;gt;new StringTextComponent(&amp;quot;Hello, world!&amp;quot;)&amp;lt;/code&amp;gt;. In practice, when sent to a player, this would simply be displayed as declared: &amp;lt;code&amp;gt;Hello, world!&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Usage ===&lt;br /&gt;
String text components are most commonly used to create empty or space-filling text components, which can then link multiple text components together using &amp;lt;code&amp;gt;appendSibling&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== TranslationTextComponent ==&lt;br /&gt;
Translation text components are a more advanced form of text components that support String formatting and translation into multiple languages. Translation text components hold a '''translation key''', which is integral to translation into other languages. Translation keys are then mapped with a language file (commonly know as a lang file) to their appropriate entry for each translated language. It is important to note that the translation key is translated by the client, not the server. The server sends the translation key to the player, and the player's client converts the translation key into its fully expanded form when rendering depending on the player's selected language. If a player selects a specific language for which a translation key is not mapped, it will default to English.&lt;br /&gt;
&lt;br /&gt;
=== Format modifiers ===&lt;br /&gt;
Translation text components also support format modifiers like used in &amp;lt;code&amp;gt;String#format&amp;lt;/code&amp;gt;. These format modifiers are declared by using the string &amp;lt;code&amp;gt;%s&amp;lt;/code&amp;gt; when creating a translation entry for a given translation key. This format modifier will then be expanded and replaced with the provided object when rendered by the client. Any other format modifiers like &amp;lt;code&amp;gt;%d&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;%n&amp;lt;/code&amp;gt; are ''not supported'' and will throw a formatting error. To get a normal percentage, a double percentage sign must be used (&amp;lt;code&amp;gt;%%&amp;lt;/code&amp;gt;). A number can also be inserted, and it will be used as a 1-based index to select the argument. This is useful for choosing a specific argument out of order, or using the same argument twice. This looks like &amp;lt;code&amp;gt;%1$s&amp;lt;/code&amp;gt;. The list of arguments to expand these format modifiers are passed to the constructor of the &amp;lt;code&amp;gt;TranslationTextComponent&amp;lt;/code&amp;gt; using an Object varargs parameter, similar to &amp;lt;code&amp;gt;String#format&amp;lt;/code&amp;gt;. The arguments passed in the constructor of a &amp;lt;code&amp;gt;TranslationTextComponent&amp;lt;/code&amp;gt; can be either an Object or another &amp;lt;code&amp;gt;ITextComponent&amp;lt;/code&amp;gt;. Any &amp;lt;code&amp;gt;ITextComponent&amp;lt;/code&amp;gt;s will be expanded and have any declared &amp;lt;code&amp;gt;Style&amp;lt;/code&amp;gt;s properties preserved in the final output. Any objects that are not an instance of &amp;lt;code&amp;gt;ITextComponent&amp;lt;/code&amp;gt; will have &amp;lt;code&amp;gt;Object#toString&amp;lt;/code&amp;gt; called during expansion.&lt;br /&gt;
&lt;br /&gt;
=== Creating ===&lt;br /&gt;
Translation text components are instantiated in the form &amp;lt;code&amp;gt;new TranslationTextComponent(&amp;quot;your.translation_key.here&amp;quot;, new StringTextComponent(&amp;quot;thing1&amp;quot;).withStyle(TextFormatting.RED), new StringTextComponent(&amp;quot;thing1&amp;quot;).withStyle(TextFormatting.BLUE))&amp;lt;/code&amp;gt;. In your lang file, the entry would look something like: &amp;lt;syntaxhighlight lang=&amp;quot;json&amp;quot;&amp;gt;{&lt;br /&gt;
    &amp;quot;your.translation_key.here&amp;quot;: &amp;quot;I like using %1$s and %2$s!&amp;quot;&lt;br /&gt;
}&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
In practice, when sent to a player, this would be displayed as &amp;lt;code&amp;gt;I like using thing1 and thing2!&amp;lt;/code&amp;gt;, where &amp;lt;code&amp;gt;thing1&amp;lt;/code&amp;gt; would be colored as red and &amp;lt;code&amp;gt;thing2&amp;lt;/code&amp;gt; would be colored as blue. Normal &amp;lt;code&amp;gt;String&amp;lt;/code&amp;gt;s can also be passed in, and they will inherit the &amp;lt;code&amp;gt;Style&amp;lt;/code&amp;gt; object of the main text component. Note that any more values in the language file must be declared as comma-separated key-value pairs as required by the JSON specification, with the last key-value pair not ending with a comment.&lt;br /&gt;
&lt;br /&gt;
=== Usage ===&lt;br /&gt;
Translation text components are used for sending anything visual to the player. Using them provides a benefit of format modifiers and the ability to be translated into different languages. This means that, given a translator, one could translate the English translation file (by default, &amp;lt;code&amp;gt;en_us.json&amp;lt;/code&amp;gt;) into another language for a given mod. This system is also used by Minecraft itself and has been used to translate the game into hundreds of langauges. Translation keys are also required for declaring the names of items, blocks, and entities in the game.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Translations]]&lt;/div&gt;</summary>
		<author><name>SizableShrimp</name></author>
	</entry>
	<entry>
		<id>https://forge.gemwire.uk/index.php?title=Template:See_also&amp;diff=2647</id>
		<title>Template:See also</title>
		<link rel="alternate" type="text/html" href="https://forge.gemwire.uk/index.php?title=Template:See_also&amp;diff=2647"/>
		<updated>2021-05-29T03:02:12Z</updated>

		<summary type="html">&lt;p&gt;SizableShrimp: Adds template data&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;See also: [[{{{1}}}]]{{#if:{{{2|}}}|{{#if:{{{3|}}}|,&amp;amp;nbsp;|&amp;amp;nbsp;and&amp;amp;nbsp;}}[[{{{2}}}]]{{#if:{{{3|}}}|{{#if:{{{4|}}}|,&amp;amp;nbsp;|&amp;amp;nbsp;and&amp;amp;nbsp;}}[[{{{3}}}]]{{#if:{{{4|}}}|{{#if:{{{5|}}}|,&amp;amp;nbsp;|&amp;amp;nbsp;and&amp;amp;nbsp;}}[[{{{4}}}]]{{#if:{{{5|}}}|{{#if:{{{6|}}}|,&amp;amp;nbsp;|&amp;amp;nbsp;and&amp;amp;nbsp;}}[[{{{5}}}]]{{#if:{{{6|}}}|{{#if:{{{7|}}}|,&amp;amp;nbsp;|&amp;amp;nbsp;and&amp;amp;nbsp;}}[[{{{6}}}]]{{#if:{{{7|}}}|{{#if:{{{8|}}}|,&amp;amp;nbsp;|&amp;amp;nbsp;and&amp;amp;nbsp;}}[[{{{7}}}]]{{#if:{{{8|}}}|{{#if:{{{9|}}}|,&amp;amp;nbsp;|&amp;amp;nbsp;and&amp;amp;nbsp;}}[[{{{8}}}]]{{#if:{{{9|}}}|&amp;amp;nbsp;and [[{{{9}}}]]}} |}} |}} |}} |}} |}} |}} |}}''&lt;br /&gt;
&amp;lt;noinclude&amp;gt;&lt;br /&gt;
&amp;lt;templatedata&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
	&amp;quot;params&amp;quot;: {&lt;br /&gt;
		&amp;quot;1&amp;quot;: {&lt;br /&gt;
			&amp;quot;description&amp;quot;: &amp;quot;The first article to see also&amp;quot;,&lt;br /&gt;
			&amp;quot;required&amp;quot;: true,&lt;br /&gt;
			&amp;quot;suggested&amp;quot;: true&lt;br /&gt;
		},&lt;br /&gt;
		&amp;quot;2&amp;quot;: {},&lt;br /&gt;
		&amp;quot;3&amp;quot;: {},&lt;br /&gt;
		&amp;quot;4&amp;quot;: {},&lt;br /&gt;
		&amp;quot;5&amp;quot;: {},&lt;br /&gt;
		&amp;quot;6&amp;quot;: {},&lt;br /&gt;
		&amp;quot;7&amp;quot;: {},&lt;br /&gt;
		&amp;quot;8&amp;quot;: {},&lt;br /&gt;
		&amp;quot;9&amp;quot;: {}&lt;br /&gt;
	},&lt;br /&gt;
	&amp;quot;description&amp;quot;: &amp;quot;Adds a hatnote linking to similar or related articles. Used on section headers&amp;quot;,&lt;br /&gt;
	&amp;quot;format&amp;quot;: &amp;quot;inline&amp;quot;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/templatedata&amp;gt;&lt;br /&gt;
&amp;lt;/noinclude&amp;gt;&lt;/div&gt;</summary>
		<author><name>SizableShrimp</name></author>
	</entry>
	<entry>
		<id>https://forge.gemwire.uk/index.php?title=Template:See_also&amp;diff=2646</id>
		<title>Template:See also</title>
		<link rel="alternate" type="text/html" href="https://forge.gemwire.uk/index.php?title=Template:See_also&amp;diff=2646"/>
		<updated>2021-05-29T02:59:20Z</updated>

		<summary type="html">&lt;p&gt;SizableShrimp: Create template&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;See also: [[{{{1}}}]]{{#if:{{{2|}}}|{{#if:{{{3|}}}|,&amp;amp;nbsp;|&amp;amp;nbsp;and&amp;amp;nbsp;}}[[{{{2}}}]]{{#if:{{{3|}}}|{{#if:{{{4|}}}|,&amp;amp;nbsp;|&amp;amp;nbsp;and&amp;amp;nbsp;}}[[{{{3}}}]]{{#if:{{{4|}}}|{{#if:{{{5|}}}|,&amp;amp;nbsp;|&amp;amp;nbsp;and&amp;amp;nbsp;}}[[{{{4}}}]]{{#if:{{{5|}}}|{{#if:{{{6|}}}|,&amp;amp;nbsp;|&amp;amp;nbsp;and&amp;amp;nbsp;}}[[{{{5}}}]]{{#if:{{{6|}}}|{{#if:{{{7|}}}|,&amp;amp;nbsp;|&amp;amp;nbsp;and&amp;amp;nbsp;}}[[{{{6}}}]]{{#if:{{{7|}}}|{{#if:{{{8|}}}|,&amp;amp;nbsp;|&amp;amp;nbsp;and&amp;amp;nbsp;}}[[{{{7}}}]]{{#if:{{{8|}}}|{{#if:{{{9|}}}|,&amp;amp;nbsp;|&amp;amp;nbsp;and&amp;amp;nbsp;}}[[{{{8}}}]]{{#if:{{{9|}}}|&amp;amp;nbsp;and [[{{{9}}}]]}} |}} |}} |}} |}} |}} |}} |}}''&lt;/div&gt;</summary>
		<author><name>SizableShrimp</name></author>
	</entry>
	<entry>
		<id>https://forge.gemwire.uk/index.php?title=Template:About&amp;diff=2643</id>
		<title>Template:About</title>
		<link rel="alternate" type="text/html" href="https://forge.gemwire.uk/index.php?title=Template:About&amp;diff=2643"/>
		<updated>2021-05-19T01:36:48Z</updated>

		<summary type="html">&lt;p&gt;SizableShrimp: Create {{About}} template&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;:''This page is about {{{1}}}. For {{{2|other uses}}}, see &amp;lt;span class=&amp;quot;about-dis-link&amp;quot;&amp;gt;[[{{{3|{{PAGENAME}} (Disambiguation)}}}]]&amp;lt;/span&amp;gt;''.&amp;lt;noinclude&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;templatedata&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
	&amp;quot;params&amp;quot;: {&lt;br /&gt;
		&amp;quot;1&amp;quot;: {&lt;br /&gt;
			&amp;quot;description&amp;quot;: &amp;quot;The use of the page&amp;quot;,&lt;br /&gt;
			&amp;quot;example&amp;quot;: &amp;quot;This page is about forge modloading.&amp;quot;,&lt;br /&gt;
			&amp;quot;type&amp;quot;: &amp;quot;string&amp;quot;,&lt;br /&gt;
			&amp;quot;required&amp;quot;: true&lt;br /&gt;
		},&lt;br /&gt;
		&amp;quot;2&amp;quot;: {&lt;br /&gt;
			&amp;quot;description&amp;quot;: &amp;quot;The use of the similar page&amp;quot;,&lt;br /&gt;
			&amp;quot;example&amp;quot;: &amp;quot;For minecraft loading, see Minecraft Loading.&amp;quot;,&lt;br /&gt;
			&amp;quot;type&amp;quot;: &amp;quot;string&amp;quot;,&lt;br /&gt;
			&amp;quot;default&amp;quot;: &amp;quot;other uses&amp;quot;,&lt;br /&gt;
			&amp;quot;autovalue&amp;quot;: &amp;quot;other uses&amp;quot;&lt;br /&gt;
		},&lt;br /&gt;
		&amp;quot;3&amp;quot;: {&lt;br /&gt;
			&amp;quot;description&amp;quot;: &amp;quot;The disambiguation page or other page. Automatically converted into a wikilink.&amp;quot;,&lt;br /&gt;
			&amp;quot;example&amp;quot;: &amp;quot;Minecraft Loading&amp;quot;,&lt;br /&gt;
			&amp;quot;type&amp;quot;: &amp;quot;string&amp;quot;,&lt;br /&gt;
			&amp;quot;default&amp;quot;: &amp;quot;{{PAGENAME}} (Disambiguation)&amp;quot;,&lt;br /&gt;
			&amp;quot;autovalue&amp;quot;: &amp;quot;{{subst:PAGENAME}} (Disambiguation)&amp;quot;&lt;br /&gt;
		}&lt;br /&gt;
	},&lt;br /&gt;
	&amp;quot;description&amp;quot;: &amp;quot;Used to inform readers about the content on a page and provide them with similarly named pages.&amp;quot;,&lt;br /&gt;
	&amp;quot;format&amp;quot;: &amp;quot;inline&amp;quot;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/templatedata&amp;gt;&lt;br /&gt;
&amp;lt;/noinclude&amp;gt;&lt;/div&gt;</summary>
		<author><name>SizableShrimp</name></author>
	</entry>
</feed>