<?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=Curle</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=Curle"/>
	<link rel="alternate" type="text/html" href="https://forge.gemwire.uk/wiki/Special:Contributions/Curle"/>
	<updated>2026-06-02T06:42:53Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.35.0</generator>
	<entry>
		<id>https://forge.gemwire.uk/index.php?title=Capabilities&amp;diff=3335</id>
		<title>Capabilities</title>
		<link rel="alternate" type="text/html" href="https://forge.gemwire.uk/index.php?title=Capabilities&amp;diff=3335"/>
		<updated>2022-09-24T19:30:08Z</updated>

		<summary type="html">&lt;p&gt;Curle: fix factual errors related to ForgeCapabilities vs the capability provider implementations&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;
@AutoRegisterCapability&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>Curle</name></author>
	</entry>
	<entry>
		<id>https://forge.gemwire.uk/index.php?title=Capabilities&amp;diff=3334</id>
		<title>Capabilities</title>
		<link rel="alternate" type="text/html" href="https://forge.gemwire.uk/index.php?title=Capabilities&amp;diff=3334"/>
		<updated>2022-09-24T19:22:44Z</updated>

		<summary type="html">&lt;p&gt;Curle: Undo revision 3332 by Nexus-Dino&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 = 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&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 all capabilities are 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;
&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 LazyOptional&amp;lt;IItemhandler&amp;gt; inventoryOptional = LazyOptional.empty();&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;
public void invalidateCaps()&lt;br /&gt;
{&lt;br /&gt;
    this.inventoryOptional = LazyOptional.of(() -&amp;gt; this.inventory);&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 == 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;
&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 = 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;
&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(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;
&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;
@AutoRegisterCapability&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>Curle</name></author>
	</entry>
	<entry>
		<id>https://forge.gemwire.uk/index.php?title=Capabilities&amp;diff=3101</id>
		<title>Capabilities</title>
		<link rel="alternate" type="text/html" href="https://forge.gemwire.uk/index.php?title=Capabilities&amp;diff=3101"/>
		<updated>2021-12-18T00:00:18Z</updated>

		<summary type="html">&lt;p&gt;Curle: Change example gist to one hosted by a Wiki admin (to fix invalidation problem)&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;, &amp;lt;code&amp;gt;IEnergyStorage&amp;lt;/code&amp;gt;, and&lt;br /&gt;
&amp;lt;code&amp;gt;IAnimationStateMachine&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;
=== &amp;lt;tt&amp;gt;IAnimationStateMachine&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;IAnimationStateMachine&amp;lt;/code&amp;gt; capability refers to the ability for any capability provider to leverage the Forge Animation State Machine API for animations. This api does not work post 1.12 at the moment.&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>Curle</name></author>
	</entry>
	<entry>
		<id>https://forge.gemwire.uk/index.php?title=Capabilities&amp;diff=3100</id>
		<title>Capabilities</title>
		<link rel="alternate" type="text/html" href="https://forge.gemwire.uk/index.php?title=Capabilities&amp;diff=3100"/>
		<updated>2021-12-17T23:58:00Z</updated>

		<summary type="html">&lt;p&gt;Curle: Add note on invalidation, remove invalidation listener from example code.&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;, &amp;lt;code&amp;gt;IEnergyStorage&amp;lt;/code&amp;gt;, and&lt;br /&gt;
&amp;lt;code&amp;gt;IAnimationStateMachine&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;
=== &amp;lt;tt&amp;gt;IAnimationStateMachine&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;IAnimationStateMachine&amp;lt;/code&amp;gt; capability refers to the ability for any capability provider to leverage the Forge Animation State Machine API for animations. This api does not work post 1.12 at the moment.&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/N1K-x/a17812bac9de4cf064baa789e9ccb96a 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>Curle</name></author>
	</entry>
	<entry>
		<id>https://forge.gemwire.uk/index.php?title=Events&amp;diff=3094</id>
		<title>Events</title>
		<link rel="alternate" type="text/html" href="https://forge.gemwire.uk/index.php?title=Events&amp;diff=3094"/>
		<updated>2021-12-08T18:04:04Z</updated>

		<summary type="html">&lt;p&gt;Curle: Spacing&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Under construction}}&lt;br /&gt;
&lt;br /&gt;
An '''event''' is a signal that is fired on an '''event bus''' to inform registered listeners about some type of action or state. This is the primary way by which Forge allows mods to hook into vanilla and game behavior; Forge has an array of different events which are fired when different actions happen within the game, and mods may act upon receiving these events.  &lt;br /&gt;
&lt;br /&gt;
Additionally, mods may create their own events and fire them for other mods to listen for, allowing for higher compatibility. For a class to be considered an event, it must be a subclass of &amp;lt;code&amp;gt;Event&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Generic Events ==&lt;br /&gt;
'''Generic events''' are events which supply additional generic type information, allowing event listeners to filter based on that secondary type. Generic events must implement &amp;lt;code&amp;gt;IGenericEvent&amp;lt;T&amp;gt;&amp;lt;/code&amp;gt;, and return their generic type from the &amp;lt;code&amp;gt;IGenericEvent#getType()&amp;lt;/code&amp;gt; method. As a convenience, events that wish to be generic events may extend the &amp;lt;code&amp;gt;GenericEvent&amp;lt;T&amp;gt;&amp;lt;/code&amp;gt; instead of manually implementing the interface.&lt;br /&gt;
&lt;br /&gt;
For generic events, the generic type must be an exact match with the listener's generic type filter to pass; if an &amp;lt;code&amp;gt;AttachCapabilitiesEvent&amp;lt;ItemStack&amp;gt;&amp;lt;/code&amp;gt; is fired and a listener is listening for &amp;lt;code&amp;gt;AttachCapabilitiesEvent&amp;lt;Object&amp;gt;&amp;lt;/code&amp;gt;, the listener does not receive the event. A event listener may listen to events with any generic type by supplying a wildcard generic (&amp;lt;code&amp;gt;&amp;lt;?&amp;gt;&amp;lt;/code&amp;gt;). Nested generic types are ignored.&lt;br /&gt;
&lt;br /&gt;
== Cancellable Events ==&lt;br /&gt;
An event may be marked as '''cancellable''', which allows event listeners to cancel the event.&lt;br /&gt;
&lt;br /&gt;
A cancellable event may be cancelled by using &amp;lt;code&amp;gt;Event#setCanceled(true)&amp;lt;/code&amp;gt;. Attempting to call this method on a non-cancellable event will result in a &amp;lt;code&amp;gt;UnsupportedOperationException&amp;lt;/code&amp;gt;. A cancelled event behaves similarly to a regular noncancelled event, with one main difference: an event listener will not receive cancelled events unless they are explicitly registered to listen for cancelled events.&lt;br /&gt;
&lt;br /&gt;
To mark an event as cancellable, the event class should be annotated with &amp;lt;code&amp;gt;@Cancelable&amp;lt;/code&amp;gt;. This will automatically make &amp;lt;code&amp;gt;Event#isCancelable()&amp;lt;/code&amp;gt; return &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt;. Modders may check if an event has a result through the presence of the annotation or by calling the given method.&lt;br /&gt;
&lt;br /&gt;
== Events with Results ==&lt;br /&gt;
An event may have a '''result''', which is an enum of &amp;lt;code&amp;gt;Event.Result&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;Event.Result&amp;lt;/code&amp;gt; enum has three values: &amp;lt;code&amp;gt;ALLOW&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;DEFAULT&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;DENY&amp;lt;/code&amp;gt;. The meaning of these result values is entirely dependent on the event itself.&lt;br /&gt;
 &lt;br /&gt;
An event's current result can be retrieved through &amp;lt;code&amp;gt;Event#getResult()&amp;lt;/code&amp;gt;. The result on an event can be set through &amp;lt;code&amp;gt;Event#setResult(Event.Result)&amp;lt;/code&amp;gt;. You can set the result for an event which is not marked as having a result, however this will cause nothing to happen if the event does not use the result value.&lt;br /&gt;
&lt;br /&gt;
To mark an event as having a result, the event class should be annotated with &amp;lt;code&amp;gt;@Event.HasResult&amp;lt;/code&amp;gt;. This will automatically make &amp;lt;code&amp;gt;Event#hasResult&amp;lt;/code&amp;gt; return &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt;. Modders may check if an event has a result through the presence of the annotation or by calling the given method.&lt;br /&gt;
&lt;br /&gt;
==Event Bus==&lt;br /&gt;
An '''event bus''' is an object which holds a list of event listeners, and the logic for firing the events. Events may be posted on these event buses, which then invokes the handlers. The main class for event buses is &amp;lt;code&amp;gt;IEventBus&amp;lt;/code&amp;gt;, and a bus is created using &amp;lt;code&amp;gt;BusBuilder&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
You can find a more detailed explanation on the Event Bus pattern [https://dzone.com/articles/design-patterns-event-bus here.] &lt;br /&gt;
===Existing Buses===&lt;br /&gt;
Forge exposes three main families of event buses: the main Forge event bus, the mod-specific event buses, and the network channel event buses.&lt;br /&gt;
====Main Forge Event Bus====&lt;br /&gt;
The '''main Forge event bus''' is located at &amp;lt;code&amp;gt;MinecraftForge#EVENT_BUS&amp;lt;/code&amp;gt;, and is where most events relating to ingame actions or events are fired on, such as events for ticking, block interactions, and entity interactions. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
List of events fired on the main Forge event bus{{:Events/Forge bus}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====Mod-Specific Event Buses====&lt;br /&gt;
The '''mod-specific event buses''' are the family of event buses where mod-related initialization and registration events are fired, such as the events for [[Registration|registering objects]] or setup on different physical sides. Only events which implement &amp;lt;code&amp;gt;IModBusEvent&amp;lt;/code&amp;gt; may be fired or listened for on these event buses.&lt;br /&gt;
&lt;br /&gt;
Each loaded mod has their own instance of a mod-specific event bus. The mod-specific event bus for the currently loading mod can be retrieved from &amp;lt;code&amp;gt;FMLModContainer#getEventBus()&amp;lt;/code&amp;gt;, which is also accessible from &amp;lt;code&amp;gt;FMLJavaModLoadingContext#getModEventBus()&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
{{Tip|title=Tip|The mod-specific event buses are provided by the &amp;lt;code&amp;gt;javafml&amp;lt;/code&amp;gt; language provider which is builtin to Forge Mod Loader. Custom language providers may provide other ways for mods to receive the different mod-related initialization and registration events; see the documentation of your custom language provider for details.}}&lt;br /&gt;
====Network Channel Event Buses====&lt;br /&gt;
The '''network channel event buses''' are the family of event buses where different network-related events are fired. Each registered [[Networking|networking channel]] has their own instance of an event-bus in &amp;lt;code&amp;gt;NetworkInstance&amp;lt;/code&amp;gt;, where only events pertinent to that channel are fired on.&lt;br /&gt;
&lt;br /&gt;
The network channel event buses cannot be accessed directly; &amp;lt;code&amp;gt;EventNetworkChannel&amp;lt;/code&amp;gt; provides methods to register events listeners to the event bus.&lt;br /&gt;
&lt;br /&gt;
== Event Listeners ==&lt;br /&gt;
An '''event listener''' (also known as an '''event handler''') is a class, object, or method registered to an event bus to capture for specific events (and their subclasses).&lt;br /&gt;
&lt;br /&gt;
[[File:Guide to Event Handlers.png|thumb|upright 0.9|A visual guide on how event listeners are registered.]]&lt;br /&gt;
&lt;br /&gt;
An event listener may be registered in three ways:&lt;br /&gt;
* The &amp;lt;code&amp;gt;IEventBus#register(Object)&amp;lt;/code&amp;gt; method on a class or instance;&lt;br /&gt;
* The &amp;lt;code&amp;gt;@EventBusSubscriber&amp;lt;/code&amp;gt; annotation on a class; or&lt;br /&gt;
* The &amp;lt;code&amp;gt;IEventBus#addListener&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;IEventBus#addGenericListener&amp;lt;/code&amp;gt; on a method reference or lambda.&lt;br /&gt;
&lt;br /&gt;
=== Priority and Receiving Cancelled Events ===&lt;br /&gt;
An event listener may be registered to a specific '''event priority''' and whether to '''receive cancelled events'''.&lt;br /&gt;
&lt;br /&gt;
The event priority levels allows a listener to react to an event before other event listeners of a lower level, such as to change the values within an event or cancel it outright.&lt;br /&gt;
&lt;br /&gt;
There are five levels of event listeners priority; in descending order from first to receive an event to last: &amp;lt;code&amp;gt;HIGHEST&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;HIGH&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;NORMAL&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;LOW&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;LOWEST&amp;lt;/code&amp;gt;. Event listeners are registered by default on a priority of &amp;lt;code&amp;gt;NORMAL&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
An event listener normally never receives a cancelled event, however they may change this by being registered to receive these cancelled events. Non-cancellable events are unaffected by this, and will always be sent to all event listeners (in the order specified by their priority).&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;IEventBus.register&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
The &amp;lt;code&amp;gt;IEventBus#register(Object)&amp;lt;/code&amp;gt; method allows for registering an object instance or a &amp;lt;code&amp;gt;Class&amp;lt;?&amp;gt;&amp;lt;/code&amp;gt; to the event bus. The method exhibits two different behaviors, depending on what is passed into it:&lt;br /&gt;
&lt;br /&gt;
* '''an object instance''' - registers all ''instance or non-&amp;lt;code&amp;gt;static&amp;lt;/code&amp;gt;'' methods annotated with &amp;lt;code&amp;gt;@SubscribeEvent&amp;lt;/code&amp;gt; from the object&lt;br /&gt;
* '''a &amp;lt;code&amp;gt;Class&amp;lt;?&amp;gt;&amp;lt;/code&amp;gt; instance''' - registers all ''class or &amp;lt;code&amp;gt;static&amp;lt;/code&amp;gt;'' methods annotated with &amp;lt;code&amp;gt;@SubscribeEvent&amp;lt;/code&amp;gt; from the class which is represented by the passed in &amp;lt;code&amp;gt;Class&amp;lt;?&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tab collapsed name=&amp;quot;Example of how event listeners are registered with the IEventBus.register method&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
class EventHandler {&lt;br /&gt;
	public static void nonAnnotatedStatic(Event event) {}&lt;br /&gt;
&lt;br /&gt;
	@SubscribeEvent&lt;br /&gt;
	public static void annotatedStatic(Event event) {}&lt;br /&gt;
&lt;br /&gt;
	public void nonAnnotatedInstance(Event event) {}&lt;br /&gt;
&lt;br /&gt;
	@SubscribeEvent&lt;br /&gt;
	public void annotatedInstance(Event event) {}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// Within the execution of the program&lt;br /&gt;
IEventBus bus = ...;&lt;br /&gt;
&lt;br /&gt;
// This will register the &amp;quot;annotatedStatic&amp;quot; method from the class&lt;br /&gt;
bus.register(EventHandler.class);&lt;br /&gt;
// This would register &amp;quot;annotatedStatic&amp;quot;, but it is already registered&lt;br /&gt;
bus.register(EventHandler.class);&lt;br /&gt;
&lt;br /&gt;
EventHandler instanceA = new EventHandler();&lt;br /&gt;
EventHandler instanceB = new EventHandler();&lt;br /&gt;
&lt;br /&gt;
// This will register the &amp;quot;annotatedInstance&amp;quot; method from the instanceA object, and will not touch the instanceB object&lt;br /&gt;
bus.register(instanceA);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
If an &amp;lt;code&amp;gt;Event&amp;lt;/code&amp;gt; were to be fired on the event bus in the example above, the &amp;lt;code&amp;gt;EventHandler#annotatedStatic&amp;lt;/code&amp;gt; would receive the event, and the &amp;lt;code&amp;gt;annotatedInstance&amp;lt;/code&amp;gt; method from the &amp;lt;code&amp;gt;instanceA&amp;lt;/code&amp;gt; object instance would receive the event.&lt;br /&gt;
&lt;br /&gt;
Neither the unnannotated methods will receive the event, nor will the &amp;lt;code&amp;gt;annotatedInstance&amp;lt;/code&amp;gt; method from the &amp;lt;code&amp;gt;instanceB&amp;lt;/code&amp;gt; object instance.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/tab&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;tt&amp;gt;@SubscribeEvent&amp;lt;/tt&amp;gt; ====&lt;br /&gt;
The &amp;lt;code&amp;gt;@SubscribeEvent&amp;lt;/code&amp;gt; annotation is used to mark a method as an event listener when its containing class or object is registered using &amp;lt;code&amp;gt;IEventBus#register&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
They have two fields: &amp;lt;code&amp;gt;EventPriority priority&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;boolean receiveCancelled&amp;lt;/code&amp;gt;, which sets the event priority for the listener and whether the listener receives cancelled events, respectively.&lt;br /&gt;
&lt;br /&gt;
= WIP =&lt;br /&gt;
TODO: @EventBusSubscriber, addListener, Generic Events? (probably higher up)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tab name=&amp;quot;Partial previous content of page, to be removed&amp;quot; collapsed&amp;gt;&lt;br /&gt;
== Forge and Mod Buses ==&lt;br /&gt;
There are two event buses of note to a mod: the '''main Forge event bus''', and the '''mod-specific event bus'''.&lt;br /&gt;
&lt;br /&gt;
The Forge event bus, which can be referenced through &amp;lt;code&amp;gt;MinecraftForge.EVENT_BUS&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;EventBusSubscriber.Bus.FORGE&amp;lt;/code&amp;gt; (the latter being an enum that provides handy references to both busses), fires events that depend solely on the game state. This means that:&lt;br /&gt;
* Entity Events&lt;br /&gt;
* Ticking Events&lt;br /&gt;
* Server Events&lt;br /&gt;
and more, are fired on the Forge bus.&lt;br /&gt;
&lt;br /&gt;
The Mod bus, referenced through &amp;lt;code&amp;gt;FMLJavaModLoadingContext.get().getModEventBus()&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;EventBusSubscriber.Bus.MOD&amp;lt;/code&amp;gt;, fires events that depend solely on mod state, or which are used to initialise such.&lt;br /&gt;
This means that:&lt;br /&gt;
* Registration Events&lt;br /&gt;
* Mod Lifecycle Events&lt;br /&gt;
* Model Events (bake and register)&lt;br /&gt;
* Config Events&lt;br /&gt;
* Data Provider Events&lt;br /&gt;
and more, are fired on the Mod bus. See [[Stages of Modloading|mod loading events]]. Note that some of these are fired in parallel.&lt;br /&gt;
&lt;br /&gt;
== Sub Events ==&lt;br /&gt;
&lt;br /&gt;
Many events have different variations of themselves, these can be different but all based around one common factor (e.g. &amp;lt;code&amp;gt;PlayerEvent&amp;lt;/code&amp;gt;) or can be an event that has multiple phases (e.g. &amp;lt;code&amp;gt;PotionBrewEvent&amp;lt;/code&amp;gt;). Take note that if you listen to the parent event class, you will receive calls to your method for ''all'' subclasses.&lt;br /&gt;
&lt;br /&gt;
== Event Handlers ==&lt;br /&gt;
Event handlers are methods, which have four main properties. They are communicated to the event bus you want them to listen on, and when the event is posted on that bus, the hander is invoked.&lt;br /&gt;
&lt;br /&gt;
Event handlers' properties are as such:&lt;br /&gt;
- Registered to an event bus&lt;br /&gt;
- May be static or instance&lt;br /&gt;
- Have a single argument, which is used to determine the event that is being listened for&lt;br /&gt;
- The argument given is the instance of the Event being posted.&lt;br /&gt;
&lt;br /&gt;
Note that handlers may take the form of anonymous functions - lambdas.&lt;br /&gt;
&lt;br /&gt;
== Registering Event Handlers ==&lt;br /&gt;
Event handlers are registered typically one of four ways:&lt;br /&gt;
* &amp;lt;code&amp;gt;EventBusSubscriber&amp;lt;/code&amp;gt; (which requires a static, annotated handler method)&lt;br /&gt;
* &amp;lt;code&amp;gt;EventBus#register(T.class)&amp;lt;/code&amp;gt; (which requires a static, annotated handler method)&lt;br /&gt;
* &amp;lt;code&amp;gt;EventBus#register(new X())&amp;lt;/code&amp;gt; (which requires an instance, annotated handler method)&lt;br /&gt;
* &amp;lt;code&amp;gt;EventBus#addListener(Class::function)&amp;lt;/code&amp;gt; (which requires an instance, non-annotated handler method)&lt;br /&gt;
* as an extension of the above: &amp;lt;code&amp;gt;EventBus#&amp;lt;LivingHurtEvent&amp;gt;addListener(event -&amp;gt; { code })&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Each of these will be explained in detail as follows.&lt;br /&gt;
&lt;br /&gt;
=== Annotated Event Handlers ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
public class MyForgeEventHandler {&lt;br /&gt;
    @SubscribeEvent&lt;br /&gt;
    public void pickupItem(EntityItemPickupEvent event) {&lt;br /&gt;
        System.out.println(&amp;quot;Item picked up!&amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This event handler listens for the &amp;lt;code&amp;gt;EntityItemPickupEvent&amp;lt;/code&amp;gt;, which is, as the name states, posted to the event bus whenever an &amp;lt;code&amp;gt;Entity&amp;lt;/code&amp;gt; picks up an item.&lt;br /&gt;
&lt;br /&gt;
This function would be registered with &amp;lt;code&amp;gt;EventBus#register(new X())&amp;lt;/code&amp;gt; in the above examples.&lt;br /&gt;
&lt;br /&gt;
=== Static Event Handlers ===&lt;br /&gt;
&lt;br /&gt;
An event handler may also be static. The handling method is still annotated with &amp;lt;code&amp;gt;@SubscribeEvent&amp;lt;/code&amp;gt; with the only difference from an instance handler is that it is also marked static. In order to register a static event handler, an instance of the class won’t do, the Class itself has to be passed in. An example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
public class MyStaticForgeEventHandler {&lt;br /&gt;
    @SubscribeEvent&lt;br /&gt;
    public static void arrowNocked(ArrowNockEvent event) {&lt;br /&gt;
        System.out.println(&amp;quot;Arrow nocked!&amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
which must be registered &amp;lt;code&amp;gt;EventBus#register(MyStaticForgeEventHandler.class)&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;h3 id=&amp;quot;eventbussubscriber&amp;quot;&amp;gt;Using &amp;lt;tt style=&amp;quot;font-size: 100%&amp;quot;&amp;gt;@Mod.EventBusSubscriber&amp;lt;/tt&amp;gt;&amp;lt;/h3&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A class may be annotated with the &amp;lt;code&amp;gt;@Mod.EventBusSubscriber&amp;lt;/code&amp;gt; annotation. Such a class is automatically registered to the configured bus when the &amp;lt;code&amp;gt;@Mod&amp;lt;/code&amp;gt; class itself is constructed. This is essentially equivalent to adding &amp;lt;code&amp;gt;EventBus#register(AnnotatedClass.class);&amp;lt;/code&amp;gt; at the end of the &amp;lt;code&amp;gt;@Mod&amp;lt;/code&amp;gt; class's constructor.&lt;br /&gt;
&lt;br /&gt;
The mod ID must be specified unless your class is already annotated with an &amp;lt;code&amp;gt;@Mod&amp;lt;/code&amp;gt; annotation. You can pass the bus you want to listen to inside the &amp;lt;code&amp;gt;@Mod.EventBusSubscriber&amp;lt;/code&amp;gt; annotation.&lt;br /&gt;
&lt;br /&gt;
The bus registered with &amp;lt;code&amp;gt;EventBusSubscriber&amp;lt;/code&amp;gt; defaults to the Forge event bus.&lt;br /&gt;
&lt;br /&gt;
You can also specify the &amp;lt;code&amp;gt;Dist&amp;lt;/code&amp;gt;s to load this event subscriber on. This can be used to not load client specific event subscribers on the dedicated server.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
An example for a static event listener listening to &amp;lt;code&amp;gt;RenderWorldLastEvent&amp;lt;/code&amp;gt; which will only be called on the physical client: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
@Mod.EventBusSubscriber(modid = &amp;quot;examplemod&amp;quot;, dist = Dist.CLIENT)&lt;br /&gt;
public class MyStaticClientOnlyEventHandler {&lt;br /&gt;
    @SubscribeEvent&lt;br /&gt;
    public static void drawLast(RenderWorldLastEvent event) {&lt;br /&gt;
        System.out.println(&amp;quot;Drawing!&amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Tip/Important|This does not register an instance of the class; it registers the class itself (i.e. the event handling methods must be static).}}&lt;br /&gt;
&lt;br /&gt;
=== Non-Annotated Event Handlers ===&lt;br /&gt;
&lt;br /&gt;
Event handlers do not need to be annotated if they are directly referred to using &amp;lt;code&amp;gt;EventBus#addListener&amp;lt;/code&amp;gt; (or &amp;lt;code&amp;gt;EventBus#addGenericListener&amp;lt;/code&amp;gt; for generic events).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
@Mod(&amp;quot;examplemod&amp;quot;)&lt;br /&gt;
public class MyMainModClass {&lt;br /&gt;
&lt;br /&gt;
  public MyMainModClass() {&lt;br /&gt;
    FMLJavaModLoadingContext.get().getModEventBus().addGenericListener(Entity.class, this::entityCap);&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  private void entityCap(AttachCapabilitiesEvent&amp;lt;Entity&amp;gt; event) {&lt;br /&gt;
    System.out.println(&amp;quot;Capability attached!&amp;quot;);&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Tip/Important|The generic passed into the event must be referenced directly within the code itself. Otherwise, the event will not be called whatsoever. For example, if you use &amp;lt;code&amp;gt;AttachCapabilitiesEvent&amp;lt;LivingEntity&amp;gt;&amp;lt;/code&amp;gt;, the event will never be called as no call of this event uses &amp;lt;code&amp;gt;LivingEntity&amp;lt;/code&amp;gt;, only &amp;lt;code&amp;gt;Entity&amp;lt;/code&amp;gt;.}}&lt;br /&gt;
&lt;br /&gt;
== Cancelling ==&lt;br /&gt;
&lt;br /&gt;
If an event can be cancelled, it will be marked with the &amp;lt;code&amp;gt;@Cancelable&amp;lt;/code&amp;gt; annotation, and the method &amp;lt;code&amp;gt;Event#isCancelable()&amp;lt;/code&amp;gt; will return &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt;. The cancel state of a cancellable event may be modified by calling &amp;lt;code&amp;gt;Event#setCanceled(boolean canceled)&amp;lt;/code&amp;gt;, wherein passing the boolean value &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt; is interpreted as cancelling the event, and passing the boolean value &amp;lt;code&amp;gt;false&amp;lt;/code&amp;gt; is interpreted as “un-cancelling” the event.&lt;br /&gt;
&lt;br /&gt;
{{Tip/Important|Not all events can be cancelled! Attempting to cancel an event that is not cancellable will result in an unchecked &amp;lt;code&amp;gt;UnsupportedOperationException&amp;lt;/code&amp;gt; being thrown, which is expected to result in the game crashing. Always check that an event can be cancelled using &amp;lt;code&amp;gt;Event#isCancelable()&amp;lt;/code&amp;gt; before attempting to cancel it.}}&lt;br /&gt;
&lt;br /&gt;
== Results ==&lt;br /&gt;
&lt;br /&gt;
Some events have an &amp;lt;code&amp;gt;Event.Result&amp;lt;/code&amp;gt; as denoted by &amp;lt;code&amp;gt;@HasResult&amp;lt;/code&amp;gt;. A result can be one of three things: &amp;lt;code&amp;gt;DENY&amp;lt;/code&amp;gt; which stops the event, &amp;lt;code&amp;gt;DEFAULT&amp;lt;/code&amp;gt; which uses the Vanilla behavior, and &amp;lt;code&amp;gt;ALLOW&amp;lt;/code&amp;gt; which forces the action to take place, regardless of if it would have originally. The result of an event can be set by calling &amp;lt;code&amp;gt;setResult&amp;lt;/code&amp;gt; with an Event.Result on the event.&lt;br /&gt;
&lt;br /&gt;
{{Colored box|title=Information|content=Different events may use results in different ways, refer to the event's JavaDoc before using the result.}}&lt;br /&gt;
&lt;br /&gt;
== Priority ==&lt;br /&gt;
&lt;br /&gt;
Event handler methods have a priority. You can set the &amp;lt;code&amp;gt;priority&amp;lt;/code&amp;gt; of an event handler method by setting the priority value of the annotation or the listener. The priority can be any value of the &amp;lt;code&amp;gt;EventPriority&amp;lt;/code&amp;gt; enum (&amp;lt;code&amp;gt;HIGHEST&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;HIGH&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;NORMAL&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;LOW&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;LOWEST&amp;lt;/code&amp;gt;). Event handlers with priority &amp;lt;code&amp;gt;HIGHEST&amp;lt;/code&amp;gt; are executed first and from there in descending order until &amp;lt;code&amp;gt;LOWEST&amp;lt;/code&amp;gt; events which are executed last.&lt;br /&gt;
&lt;br /&gt;
== Mod Event Bus ==&lt;br /&gt;
The mod event bus is primarily used for listening to lifecycle events in which mods should initialize. Many of these events are also ran in parallel so mods can be initialized at the same time. This does mean you cannot directly execute code from other mods in these events. Use the &amp;lt;code&amp;gt;InterModComms&amp;lt;/code&amp;gt; system for that.&lt;br /&gt;
&lt;br /&gt;
It is impossible for an event to be posted on the Mod bus that does not inherit the IModBusEvent interface.&lt;br /&gt;
Thus, this provides a good, easy way to tell which events are fired on this bus.&lt;br /&gt;
&lt;br /&gt;
These are the four most commonly used lifecycle events that are called during mod initialization on the mod event bus: &lt;br /&gt;
* &amp;lt;code&amp;gt;FMLCommonSetupEvent&amp;lt;/code&amp;gt; &lt;br /&gt;
* &amp;lt;code&amp;gt;FMLClientSetupEvent&amp;lt;/code&amp;gt; &amp;amp; &amp;lt;code&amp;gt;FMLDedicatedServerSetupEvent&amp;lt;/code&amp;gt; (''These events are only called on their respective [[Sides#Different_Kinds_of_Sides|physical side]].'')&lt;br /&gt;
* &amp;lt;code&amp;gt;InterModEnqueueEvent&amp;lt;/code&amp;gt; &lt;br /&gt;
* &amp;lt;code&amp;gt;InterModProcessEvent&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
These four lifecycle events are all ran in parallel. If you want to run code on the main thread during these events you can use the &amp;lt;code&amp;gt;enqueueWork&amp;lt;/code&amp;gt; methods within the events to do so.&lt;br /&gt;
&lt;br /&gt;
Next to the lifecycle events there are a few miscellaneous events that are fired on the mod event bus where you can register, set up, or initialize various things. Most of these events are not ran in parallel in contrast to the lifecycle events:&lt;br /&gt;
* &amp;lt;code&amp;gt;ColorHandlerEvent&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;ModelBakeEvent&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;TextureStitchEvent&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;RegistryEvent&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;GatherDataEvent&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;SoundLoadEvent&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;ParticleFactoryRegisterEvent&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;ModConfigEvent&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A good rule of thumb: events are fired on the mod event bus when they should be handled during initialization of a mod. or where they are used to set state (eg. the config event.)&lt;br /&gt;
&lt;br /&gt;
Detailed information about these events will be found in their respective pages, once they are ready.&lt;br /&gt;
&lt;br /&gt;
== Forge Event Bus ==&lt;br /&gt;
The Forge event bus is where game state events are fired. If anything changes to do with the game, or anything happens that you would need to know about, there's a good chance it's sent here.&lt;br /&gt;
&lt;br /&gt;
A full list of the events fired here is as follows, split into discrete categories:&lt;br /&gt;
&lt;br /&gt;
{{Tree list}}&lt;br /&gt;
* &amp;lt;code&amp;gt;Event&amp;lt;/code&amp;gt; - ''The root event class''&lt;br /&gt;
** '''Rendering events''' ('''client-only''')&lt;br /&gt;
*** &amp;lt;code&amp;gt;RenderWorldLastEvent&amp;lt;/code&amp;gt; - Fired after world rendering to allow mods to add custom renders&lt;br /&gt;
*** &amp;lt;code&amp;gt;RenderHandEvent&amp;lt;/code&amp;gt; - Fired before and after the hand of the player is rendered in the first person POV&lt;br /&gt;
*** &amp;lt;code&amp;gt;RenderLivingEvent&amp;lt;/code&amp;gt; - Fired before and after a &amp;lt;code&amp;gt;LivingRenderer&amp;lt;/code&amp;gt; is executed&lt;br /&gt;
*** &amp;lt;code&amp;gt;RenderItemInFrameEvent&amp;lt;/code&amp;gt; - Fired before the item in an &amp;lt;code&amp;gt;ItemFrameEntity&amp;lt;/code&amp;gt; is rendered&lt;br /&gt;
*** &amp;lt;code&amp;gt;RenderBlockOverlayEvent&amp;lt;/code&amp;gt; - Fired before the block overlay for the player's screen is rendered&lt;br /&gt;
*** &amp;lt;code&amp;gt;DrawHighlightEvent&amp;lt;/code&amp;gt; - Fired before the block highlight outline is rendered&lt;br /&gt;
*** &amp;lt;code&amp;gt;RenderTooltipEvent&amp;lt;/code&amp;gt; - Fired before and during rendering of a text tooltip on a screen&lt;br /&gt;
*** &amp;lt;code&amp;gt;EntityViewRenderEvent&amp;lt;/code&amp;gt; - Superclass for events relating to the player's viewpoint&lt;br /&gt;
*** &amp;lt;code&amp;gt;RenderGameOverlayEvent&amp;lt;/code&amp;gt; - Superclass, fired for each element on the player's HUD or game overlay&lt;br /&gt;
*** &amp;lt;code&amp;gt;FOVUpdateEvent&amp;lt;/code&amp;gt; - Fired when the FOV of the player is requested (?)&lt;br /&gt;
** '''GUI/Screen events''' ('''client-only''')&lt;br /&gt;
*** &amp;lt;code&amp;gt;GuiScreenEvent&amp;lt;/code&amp;gt; - Superclass for events relating to &amp;lt;code&amp;gt;Screen&amp;lt;/code&amp;gt;s&lt;br /&gt;
*** &amp;lt;code&amp;gt;GuiContainerEvent&amp;lt;/code&amp;gt; - Superclsas for events relating to &amp;lt;code&amp;gt;ContainerScreen&amp;lt;/code&amp;gt;s&lt;br /&gt;
*** &amp;lt;code&amp;gt;GuiOpenEvent&amp;lt;/code&amp;gt; - Fired before a new screen is opened on the game window&lt;br /&gt;
** '''Superclass events''' - ''These events exist to be superclasses of other events''&lt;br /&gt;
*** &amp;lt;code&amp;gt;GenericEvent&amp;lt;/code&amp;gt; - ''from EventBus'', superclass of events which have a generic type&lt;br /&gt;
*** &amp;lt;code&amp;gt;BlockEvent&amp;lt;/code&amp;gt; - Superclass for events relating to a block within the world&lt;br /&gt;
*** &amp;lt;code&amp;gt;WorldEvent&amp;lt;/code&amp;gt; - Superclass for events relating to the world&lt;br /&gt;
*** &amp;lt;code&amp;gt;InputEvent&amp;lt;/code&amp;gt; - ('''client-only''') Superclass for events relating to the player's keyboard and mouse inputs&lt;br /&gt;
*** &amp;lt;code&amp;gt;NetworkEvent&amp;lt;/code&amp;gt; - Superclass for events relating to networking&lt;br /&gt;
*** &amp;lt;code&amp;gt;ExplosionEvent&amp;lt;/code&amp;gt; - Fired before an explosion explodes in the world&lt;br /&gt;
*** &amp;lt;code&amp;gt;SoundEvent&amp;lt;/code&amp;gt; - ('''client-only''') Superclass for events related to sounds&lt;br /&gt;
*** &amp;lt;code&amp;gt;EntityEvent&amp;lt;/code&amp;gt; - Superclass for events relating to entities&lt;br /&gt;
*** &amp;lt;code&amp;gt;TickEvent&amp;lt;/code&amp;gt; - Superclass for events fired before and after ticking&lt;br /&gt;
** '''Chat events'''&lt;br /&gt;
*** &amp;lt;code&amp;gt;ServerChatEvent&amp;lt;/code&amp;gt; ('''server-only''') - Fired when the server receives a chat message and before it relays the message&lt;br /&gt;
*** &amp;lt;code&amp;gt;ClientChatEvent&amp;lt;/code&amp;gt; ('''client-only''') - Fired before the client is about to send a chat message&lt;br /&gt;
*** &amp;lt;code&amp;gt;ClientChatReceivedEvent&amp;lt;/code&amp;gt; ('''client-only''') - Fired when the client receives a chat message from the server&lt;br /&gt;
** '''Data loading events'''&lt;br /&gt;
*** &amp;lt;code&amp;gt;RecipesUpdatedEvent&amp;lt;/code&amp;gt;&lt;br /&gt;
*** &amp;lt;code&amp;gt;BiomeLoadingEvent&amp;lt;/code&amp;gt;&lt;br /&gt;
*** &amp;lt;code&amp;gt;LootTableLoadEvent&amp;lt;/code&amp;gt;&lt;br /&gt;
*** &amp;lt;code&amp;gt;StructureSpawnListGatherEvent&amp;lt;/code&amp;gt;&lt;br /&gt;
** '''Startup events'''&lt;br /&gt;
*** &amp;lt;code&amp;gt;AddReloadListenerEvent&amp;lt;/code&amp;gt;&lt;br /&gt;
*** &amp;lt;code&amp;gt;RegisterCommandsEvent&amp;lt;/code&amp;gt;&lt;br /&gt;
*** &amp;lt;code&amp;gt;ServerLifecycleEvent&amp;lt;/code&amp;gt;&lt;br /&gt;
** '''Gamemode events'''&lt;br /&gt;
*** &amp;lt;code&amp;gt;DifficultyChangeEvent&amp;lt;/code&amp;gt;&lt;br /&gt;
*** &amp;lt;code&amp;gt;ClientPlayerChangeGamemodeEvent&amp;lt;/code&amp;gt;&lt;br /&gt;
**'''Trade events'''&lt;br /&gt;
*** &amp;lt;code&amp;gt;WandererTradesEvent&amp;lt;/code&amp;gt;&lt;br /&gt;
*** &amp;lt;code&amp;gt;VillagerTradesEvent&amp;lt;/code&amp;gt;&lt;br /&gt;
** '''Other events'''&lt;br /&gt;
*** &amp;lt;code&amp;gt;FurnaceFuelBurnTimeEvent&amp;lt;/code&amp;gt;&lt;br /&gt;
*** &amp;lt;code&amp;gt;BabyEntitySpawnEvent&amp;lt;/code&amp;gt;&lt;br /&gt;
*** &amp;lt;code&amp;gt;VillageSiegeEvent&amp;lt;/code&amp;gt;&lt;br /&gt;
*** &amp;lt;code&amp;gt;TagsUpdatedEvent&amp;lt;/code&amp;gt;&lt;br /&gt;
*** &amp;lt;code&amp;gt;PotionBrewEvent&amp;lt;/code&amp;gt;&lt;br /&gt;
*** &amp;lt;code&amp;gt;ScreenshotEvent&amp;lt;/code&amp;gt;&lt;br /&gt;
*** &amp;lt;code&amp;gt;EnchantmentLevelSetEvent&amp;lt;/code&amp;gt;&lt;br /&gt;
*** &amp;lt;code&amp;gt;CommandEvent&amp;lt;/code&amp;gt;&lt;br /&gt;
*** &amp;lt;code&amp;gt;AnvilUpdateEvent&amp;lt;/code&amp;gt;&lt;br /&gt;
*** &amp;lt;code&amp;gt;ItemAttributeModifierEvent&amp;lt;/code&amp;gt;&lt;br /&gt;
*** &amp;lt;code&amp;gt;ClientPlayerNetworkEvent&amp;lt;/code&amp;gt;&lt;br /&gt;
*** &amp;lt;code&amp;gt;ChunkWatchEvent&amp;lt;/code&amp;gt;&lt;br /&gt;
{{Tree list/end}}&lt;br /&gt;
&lt;br /&gt;
Like before, each of these events (especially the Super Events, which contain most of the useful events in the game) will have their own article explaining their purpose and usefulness.&lt;br /&gt;
&amp;lt;/tab&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Events]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Common Concepts]]&lt;/div&gt;</summary>
		<author><name>Curle</name></author>
	</entry>
	<entry>
		<id>https://forge.gemwire.uk/index.php?title=Events&amp;diff=3093</id>
		<title>Events</title>
		<link rel="alternate" type="text/html" href="https://forge.gemwire.uk/index.php?title=Events&amp;diff=3093"/>
		<updated>2021-12-08T18:03:23Z</updated>

		<summary type="html">&lt;p&gt;Curle: Event bus grammar&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Under construction}}&lt;br /&gt;
&lt;br /&gt;
An '''event''' is a signal that is fired on an '''event bus''' to inform registered listeners about some type of action or state. This is the primary way by which Forge allows mods to hook into vanilla and game behavior; Forge has an array of different events which are fired when different actions happen within the game, and mods may act upon receiving these events.  &lt;br /&gt;
&lt;br /&gt;
Additionally, mods may create their own events and fire them for other mods to listen for, allowing for higher compatibility. For a class to be considered an event, it must be a subclass of &amp;lt;code&amp;gt;Event&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Generic Events ==&lt;br /&gt;
'''Generic events''' are events which supply additional generic type information, allowing event listeners to filter based on that secondary type. Generic events must implement &amp;lt;code&amp;gt;IGenericEvent&amp;lt;T&amp;gt;&amp;lt;/code&amp;gt;, and return their generic type from the &amp;lt;code&amp;gt;IGenericEvent#getType()&amp;lt;/code&amp;gt; method. As a convenience, events that wish to be generic events may extend the &amp;lt;code&amp;gt;GenericEvent&amp;lt;T&amp;gt;&amp;lt;/code&amp;gt; instead of manually implementing the interface.&lt;br /&gt;
&lt;br /&gt;
For generic events, the generic type must be an exact match with the listener's generic type filter to pass; if an &amp;lt;code&amp;gt;AttachCapabilitiesEvent&amp;lt;ItemStack&amp;gt;&amp;lt;/code&amp;gt; is fired and a listener is listening for &amp;lt;code&amp;gt;AttachCapabilitiesEvent&amp;lt;Object&amp;gt;&amp;lt;/code&amp;gt;, the listener does not receive the event. A event listener may listen to events with any generic type by supplying a wildcard generic (&amp;lt;code&amp;gt;&amp;lt;?&amp;gt;&amp;lt;/code&amp;gt;). Nested generic types are ignored.&lt;br /&gt;
&lt;br /&gt;
== Cancellable Events ==&lt;br /&gt;
An event may be marked as '''cancellable''', which allows event listeners to cancel the event.&lt;br /&gt;
&lt;br /&gt;
A cancellable event may be cancelled by using &amp;lt;code&amp;gt;Event#setCanceled(true)&amp;lt;/code&amp;gt;. Attempting to call this method on a non-cancellable event will result in a &amp;lt;code&amp;gt;UnsupportedOperationException&amp;lt;/code&amp;gt;. A cancelled event behaves similarly to a regular noncancelled event, with one main difference: an event listener will not receive cancelled events unless they are explicitly registered to listen for cancelled events.&lt;br /&gt;
&lt;br /&gt;
To mark an event as cancellable, the event class should be annotated with &amp;lt;code&amp;gt;@Cancelable&amp;lt;/code&amp;gt;. This will automatically make &amp;lt;code&amp;gt;Event#isCancelable()&amp;lt;/code&amp;gt; return &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt;. Modders may check if an event has a result through the presence of the annotation or by calling the given method.&lt;br /&gt;
&lt;br /&gt;
== Events with Results ==&lt;br /&gt;
An event may have a '''result''', which is an enum of &amp;lt;code&amp;gt;Event.Result&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;Event.Result&amp;lt;/code&amp;gt; enum has three values: &amp;lt;code&amp;gt;ALLOW&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;DEFAULT&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;DENY&amp;lt;/code&amp;gt;. The meaning of these result values is entirely dependent on the event itself.&lt;br /&gt;
 &lt;br /&gt;
An event's current result can be retrieved through &amp;lt;code&amp;gt;Event#getResult()&amp;lt;/code&amp;gt;. The result on an event can be set through &amp;lt;code&amp;gt;Event#setResult(Event.Result)&amp;lt;/code&amp;gt;. You can set the result for an event which is not marked as having a result, however this will cause nothing to happen if the event does not use the result value.&lt;br /&gt;
&lt;br /&gt;
To mark an event as having a result, the event class should be annotated with &amp;lt;code&amp;gt;@Event.HasResult&amp;lt;/code&amp;gt;. This will automatically make &amp;lt;code&amp;gt;Event#hasResult&amp;lt;/code&amp;gt; return &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt;. Modders may check if an event has a result through the presence of the annotation or by calling the given method.&lt;br /&gt;
&lt;br /&gt;
==Event Bus==&lt;br /&gt;
An '''event bus''' is an object which holds a list of event listeners, and the logic for firing the events. Events may be posted on these event buses, which then invokes the handlers. The main class for event buses is &amp;lt;code&amp;gt;IEventBus&amp;lt;/code&amp;gt;, and a bus is created using &amp;lt;code&amp;gt;BusBuilder&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
You can find a more detailed explanation on the Event Bus pattern[https://dzone.com/articles/design-patterns-event-bus here.] &lt;br /&gt;
===Existing Buses===&lt;br /&gt;
Forge exposes three main families of event buses: the main Forge event bus, the mod-specific event buses, and the network channel event buses.&lt;br /&gt;
====Main Forge Event Bus====&lt;br /&gt;
The '''main Forge event bus''' is located at &amp;lt;code&amp;gt;MinecraftForge#EVENT_BUS&amp;lt;/code&amp;gt;, and is where most events relating to ingame actions or events are fired on, such as events for ticking, block interactions, and entity interactions. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
List of events fired on the main Forge event bus{{:Events/Forge bus}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====Mod-Specific Event Buses====&lt;br /&gt;
The '''mod-specific event buses''' are the family of event buses where mod-related initialization and registration events are fired, such as the events for [[Registration|registering objects]] or setup on different physical sides. Only events which implement &amp;lt;code&amp;gt;IModBusEvent&amp;lt;/code&amp;gt; may be fired or listened for on these event buses.&lt;br /&gt;
&lt;br /&gt;
Each loaded mod has their own instance of a mod-specific event bus. The mod-specific event bus for the currently loading mod can be retrieved from &amp;lt;code&amp;gt;FMLModContainer#getEventBus()&amp;lt;/code&amp;gt;, which is also accessible from &amp;lt;code&amp;gt;FMLJavaModLoadingContext#getModEventBus()&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
{{Tip|title=Tip|The mod-specific event buses are provided by the &amp;lt;code&amp;gt;javafml&amp;lt;/code&amp;gt; language provider which is builtin to Forge Mod Loader. Custom language providers may provide other ways for mods to receive the different mod-related initialization and registration events; see the documentation of your custom language provider for details.}}&lt;br /&gt;
====Network Channel Event Buses====&lt;br /&gt;
The '''network channel event buses''' are the family of event buses where different network-related events are fired. Each registered [[Networking|networking channel]] has their own instance of an event-bus in &amp;lt;code&amp;gt;NetworkInstance&amp;lt;/code&amp;gt;, where only events pertinent to that channel are fired on.&lt;br /&gt;
&lt;br /&gt;
The network channel event buses cannot be accessed directly; &amp;lt;code&amp;gt;EventNetworkChannel&amp;lt;/code&amp;gt; provides methods to register events listeners to the event bus.&lt;br /&gt;
&lt;br /&gt;
== Event Listeners ==&lt;br /&gt;
An '''event listener''' (also known as an '''event handler''') is a class, object, or method registered to an event bus to capture for specific events (and their subclasses).&lt;br /&gt;
&lt;br /&gt;
[[File:Guide to Event Handlers.png|thumb|upright 0.9|A visual guide on how event listeners are registered.]]&lt;br /&gt;
&lt;br /&gt;
An event listener may be registered in three ways:&lt;br /&gt;
* The &amp;lt;code&amp;gt;IEventBus#register(Object)&amp;lt;/code&amp;gt; method on a class or instance;&lt;br /&gt;
* The &amp;lt;code&amp;gt;@EventBusSubscriber&amp;lt;/code&amp;gt; annotation on a class; or&lt;br /&gt;
* The &amp;lt;code&amp;gt;IEventBus#addListener&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;IEventBus#addGenericListener&amp;lt;/code&amp;gt; on a method reference or lambda.&lt;br /&gt;
&lt;br /&gt;
=== Priority and Receiving Cancelled Events ===&lt;br /&gt;
An event listener may be registered to a specific '''event priority''' and whether to '''receive cancelled events'''.&lt;br /&gt;
&lt;br /&gt;
The event priority levels allows a listener to react to an event before other event listeners of a lower level, such as to change the values within an event or cancel it outright.&lt;br /&gt;
&lt;br /&gt;
There are five levels of event listeners priority; in descending order from first to receive an event to last: &amp;lt;code&amp;gt;HIGHEST&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;HIGH&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;NORMAL&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;LOW&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;LOWEST&amp;lt;/code&amp;gt;. Event listeners are registered by default on a priority of &amp;lt;code&amp;gt;NORMAL&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
An event listener normally never receives a cancelled event, however they may change this by being registered to receive these cancelled events. Non-cancellable events are unaffected by this, and will always be sent to all event listeners (in the order specified by their priority).&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;IEventBus.register&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
The &amp;lt;code&amp;gt;IEventBus#register(Object)&amp;lt;/code&amp;gt; method allows for registering an object instance or a &amp;lt;code&amp;gt;Class&amp;lt;?&amp;gt;&amp;lt;/code&amp;gt; to the event bus. The method exhibits two different behaviors, depending on what is passed into it:&lt;br /&gt;
&lt;br /&gt;
* '''an object instance''' - registers all ''instance or non-&amp;lt;code&amp;gt;static&amp;lt;/code&amp;gt;'' methods annotated with &amp;lt;code&amp;gt;@SubscribeEvent&amp;lt;/code&amp;gt; from the object&lt;br /&gt;
* '''a &amp;lt;code&amp;gt;Class&amp;lt;?&amp;gt;&amp;lt;/code&amp;gt; instance''' - registers all ''class or &amp;lt;code&amp;gt;static&amp;lt;/code&amp;gt;'' methods annotated with &amp;lt;code&amp;gt;@SubscribeEvent&amp;lt;/code&amp;gt; from the class which is represented by the passed in &amp;lt;code&amp;gt;Class&amp;lt;?&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tab collapsed name=&amp;quot;Example of how event listeners are registered with the IEventBus.register method&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
class EventHandler {&lt;br /&gt;
	public static void nonAnnotatedStatic(Event event) {}&lt;br /&gt;
&lt;br /&gt;
	@SubscribeEvent&lt;br /&gt;
	public static void annotatedStatic(Event event) {}&lt;br /&gt;
&lt;br /&gt;
	public void nonAnnotatedInstance(Event event) {}&lt;br /&gt;
&lt;br /&gt;
	@SubscribeEvent&lt;br /&gt;
	public void annotatedInstance(Event event) {}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// Within the execution of the program&lt;br /&gt;
IEventBus bus = ...;&lt;br /&gt;
&lt;br /&gt;
// This will register the &amp;quot;annotatedStatic&amp;quot; method from the class&lt;br /&gt;
bus.register(EventHandler.class);&lt;br /&gt;
// This would register &amp;quot;annotatedStatic&amp;quot;, but it is already registered&lt;br /&gt;
bus.register(EventHandler.class);&lt;br /&gt;
&lt;br /&gt;
EventHandler instanceA = new EventHandler();&lt;br /&gt;
EventHandler instanceB = new EventHandler();&lt;br /&gt;
&lt;br /&gt;
// This will register the &amp;quot;annotatedInstance&amp;quot; method from the instanceA object, and will not touch the instanceB object&lt;br /&gt;
bus.register(instanceA);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
If an &amp;lt;code&amp;gt;Event&amp;lt;/code&amp;gt; were to be fired on the event bus in the example above, the &amp;lt;code&amp;gt;EventHandler#annotatedStatic&amp;lt;/code&amp;gt; would receive the event, and the &amp;lt;code&amp;gt;annotatedInstance&amp;lt;/code&amp;gt; method from the &amp;lt;code&amp;gt;instanceA&amp;lt;/code&amp;gt; object instance would receive the event.&lt;br /&gt;
&lt;br /&gt;
Neither the unnannotated methods will receive the event, nor will the &amp;lt;code&amp;gt;annotatedInstance&amp;lt;/code&amp;gt; method from the &amp;lt;code&amp;gt;instanceB&amp;lt;/code&amp;gt; object instance.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/tab&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;tt&amp;gt;@SubscribeEvent&amp;lt;/tt&amp;gt; ====&lt;br /&gt;
The &amp;lt;code&amp;gt;@SubscribeEvent&amp;lt;/code&amp;gt; annotation is used to mark a method as an event listener when its containing class or object is registered using &amp;lt;code&amp;gt;IEventBus#register&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
They have two fields: &amp;lt;code&amp;gt;EventPriority priority&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;boolean receiveCancelled&amp;lt;/code&amp;gt;, which sets the event priority for the listener and whether the listener receives cancelled events, respectively.&lt;br /&gt;
&lt;br /&gt;
= WIP =&lt;br /&gt;
TODO: @EventBusSubscriber, addListener, Generic Events? (probably higher up)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tab name=&amp;quot;Partial previous content of page, to be removed&amp;quot; collapsed&amp;gt;&lt;br /&gt;
== Forge and Mod Buses ==&lt;br /&gt;
There are two event buses of note to a mod: the '''main Forge event bus''', and the '''mod-specific event bus'''.&lt;br /&gt;
&lt;br /&gt;
The Forge event bus, which can be referenced through &amp;lt;code&amp;gt;MinecraftForge.EVENT_BUS&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;EventBusSubscriber.Bus.FORGE&amp;lt;/code&amp;gt; (the latter being an enum that provides handy references to both busses), fires events that depend solely on the game state. This means that:&lt;br /&gt;
* Entity Events&lt;br /&gt;
* Ticking Events&lt;br /&gt;
* Server Events&lt;br /&gt;
and more, are fired on the Forge bus.&lt;br /&gt;
&lt;br /&gt;
The Mod bus, referenced through &amp;lt;code&amp;gt;FMLJavaModLoadingContext.get().getModEventBus()&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;EventBusSubscriber.Bus.MOD&amp;lt;/code&amp;gt;, fires events that depend solely on mod state, or which are used to initialise such.&lt;br /&gt;
This means that:&lt;br /&gt;
* Registration Events&lt;br /&gt;
* Mod Lifecycle Events&lt;br /&gt;
* Model Events (bake and register)&lt;br /&gt;
* Config Events&lt;br /&gt;
* Data Provider Events&lt;br /&gt;
and more, are fired on the Mod bus. See [[Stages of Modloading|mod loading events]]. Note that some of these are fired in parallel.&lt;br /&gt;
&lt;br /&gt;
== Sub Events ==&lt;br /&gt;
&lt;br /&gt;
Many events have different variations of themselves, these can be different but all based around one common factor (e.g. &amp;lt;code&amp;gt;PlayerEvent&amp;lt;/code&amp;gt;) or can be an event that has multiple phases (e.g. &amp;lt;code&amp;gt;PotionBrewEvent&amp;lt;/code&amp;gt;). Take note that if you listen to the parent event class, you will receive calls to your method for ''all'' subclasses.&lt;br /&gt;
&lt;br /&gt;
== Event Handlers ==&lt;br /&gt;
Event handlers are methods, which have four main properties. They are communicated to the event bus you want them to listen on, and when the event is posted on that bus, the hander is invoked.&lt;br /&gt;
&lt;br /&gt;
Event handlers' properties are as such:&lt;br /&gt;
- Registered to an event bus&lt;br /&gt;
- May be static or instance&lt;br /&gt;
- Have a single argument, which is used to determine the event that is being listened for&lt;br /&gt;
- The argument given is the instance of the Event being posted.&lt;br /&gt;
&lt;br /&gt;
Note that handlers may take the form of anonymous functions - lambdas.&lt;br /&gt;
&lt;br /&gt;
== Registering Event Handlers ==&lt;br /&gt;
Event handlers are registered typically one of four ways:&lt;br /&gt;
* &amp;lt;code&amp;gt;EventBusSubscriber&amp;lt;/code&amp;gt; (which requires a static, annotated handler method)&lt;br /&gt;
* &amp;lt;code&amp;gt;EventBus#register(T.class)&amp;lt;/code&amp;gt; (which requires a static, annotated handler method)&lt;br /&gt;
* &amp;lt;code&amp;gt;EventBus#register(new X())&amp;lt;/code&amp;gt; (which requires an instance, annotated handler method)&lt;br /&gt;
* &amp;lt;code&amp;gt;EventBus#addListener(Class::function)&amp;lt;/code&amp;gt; (which requires an instance, non-annotated handler method)&lt;br /&gt;
* as an extension of the above: &amp;lt;code&amp;gt;EventBus#&amp;lt;LivingHurtEvent&amp;gt;addListener(event -&amp;gt; { code })&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Each of these will be explained in detail as follows.&lt;br /&gt;
&lt;br /&gt;
=== Annotated Event Handlers ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
public class MyForgeEventHandler {&lt;br /&gt;
    @SubscribeEvent&lt;br /&gt;
    public void pickupItem(EntityItemPickupEvent event) {&lt;br /&gt;
        System.out.println(&amp;quot;Item picked up!&amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This event handler listens for the &amp;lt;code&amp;gt;EntityItemPickupEvent&amp;lt;/code&amp;gt;, which is, as the name states, posted to the event bus whenever an &amp;lt;code&amp;gt;Entity&amp;lt;/code&amp;gt; picks up an item.&lt;br /&gt;
&lt;br /&gt;
This function would be registered with &amp;lt;code&amp;gt;EventBus#register(new X())&amp;lt;/code&amp;gt; in the above examples.&lt;br /&gt;
&lt;br /&gt;
=== Static Event Handlers ===&lt;br /&gt;
&lt;br /&gt;
An event handler may also be static. The handling method is still annotated with &amp;lt;code&amp;gt;@SubscribeEvent&amp;lt;/code&amp;gt; with the only difference from an instance handler is that it is also marked static. In order to register a static event handler, an instance of the class won’t do, the Class itself has to be passed in. An example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
public class MyStaticForgeEventHandler {&lt;br /&gt;
    @SubscribeEvent&lt;br /&gt;
    public static void arrowNocked(ArrowNockEvent event) {&lt;br /&gt;
        System.out.println(&amp;quot;Arrow nocked!&amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
which must be registered &amp;lt;code&amp;gt;EventBus#register(MyStaticForgeEventHandler.class)&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;h3 id=&amp;quot;eventbussubscriber&amp;quot;&amp;gt;Using &amp;lt;tt style=&amp;quot;font-size: 100%&amp;quot;&amp;gt;@Mod.EventBusSubscriber&amp;lt;/tt&amp;gt;&amp;lt;/h3&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A class may be annotated with the &amp;lt;code&amp;gt;@Mod.EventBusSubscriber&amp;lt;/code&amp;gt; annotation. Such a class is automatically registered to the configured bus when the &amp;lt;code&amp;gt;@Mod&amp;lt;/code&amp;gt; class itself is constructed. This is essentially equivalent to adding &amp;lt;code&amp;gt;EventBus#register(AnnotatedClass.class);&amp;lt;/code&amp;gt; at the end of the &amp;lt;code&amp;gt;@Mod&amp;lt;/code&amp;gt; class's constructor.&lt;br /&gt;
&lt;br /&gt;
The mod ID must be specified unless your class is already annotated with an &amp;lt;code&amp;gt;@Mod&amp;lt;/code&amp;gt; annotation. You can pass the bus you want to listen to inside the &amp;lt;code&amp;gt;@Mod.EventBusSubscriber&amp;lt;/code&amp;gt; annotation.&lt;br /&gt;
&lt;br /&gt;
The bus registered with &amp;lt;code&amp;gt;EventBusSubscriber&amp;lt;/code&amp;gt; defaults to the Forge event bus.&lt;br /&gt;
&lt;br /&gt;
You can also specify the &amp;lt;code&amp;gt;Dist&amp;lt;/code&amp;gt;s to load this event subscriber on. This can be used to not load client specific event subscribers on the dedicated server.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
An example for a static event listener listening to &amp;lt;code&amp;gt;RenderWorldLastEvent&amp;lt;/code&amp;gt; which will only be called on the physical client: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
@Mod.EventBusSubscriber(modid = &amp;quot;examplemod&amp;quot;, dist = Dist.CLIENT)&lt;br /&gt;
public class MyStaticClientOnlyEventHandler {&lt;br /&gt;
    @SubscribeEvent&lt;br /&gt;
    public static void drawLast(RenderWorldLastEvent event) {&lt;br /&gt;
        System.out.println(&amp;quot;Drawing!&amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Tip/Important|This does not register an instance of the class; it registers the class itself (i.e. the event handling methods must be static).}}&lt;br /&gt;
&lt;br /&gt;
=== Non-Annotated Event Handlers ===&lt;br /&gt;
&lt;br /&gt;
Event handlers do not need to be annotated if they are directly referred to using &amp;lt;code&amp;gt;EventBus#addListener&amp;lt;/code&amp;gt; (or &amp;lt;code&amp;gt;EventBus#addGenericListener&amp;lt;/code&amp;gt; for generic events).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
@Mod(&amp;quot;examplemod&amp;quot;)&lt;br /&gt;
public class MyMainModClass {&lt;br /&gt;
&lt;br /&gt;
  public MyMainModClass() {&lt;br /&gt;
    FMLJavaModLoadingContext.get().getModEventBus().addGenericListener(Entity.class, this::entityCap);&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  private void entityCap(AttachCapabilitiesEvent&amp;lt;Entity&amp;gt; event) {&lt;br /&gt;
    System.out.println(&amp;quot;Capability attached!&amp;quot;);&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Tip/Important|The generic passed into the event must be referenced directly within the code itself. Otherwise, the event will not be called whatsoever. For example, if you use &amp;lt;code&amp;gt;AttachCapabilitiesEvent&amp;lt;LivingEntity&amp;gt;&amp;lt;/code&amp;gt;, the event will never be called as no call of this event uses &amp;lt;code&amp;gt;LivingEntity&amp;lt;/code&amp;gt;, only &amp;lt;code&amp;gt;Entity&amp;lt;/code&amp;gt;.}}&lt;br /&gt;
&lt;br /&gt;
== Cancelling ==&lt;br /&gt;
&lt;br /&gt;
If an event can be cancelled, it will be marked with the &amp;lt;code&amp;gt;@Cancelable&amp;lt;/code&amp;gt; annotation, and the method &amp;lt;code&amp;gt;Event#isCancelable()&amp;lt;/code&amp;gt; will return &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt;. The cancel state of a cancellable event may be modified by calling &amp;lt;code&amp;gt;Event#setCanceled(boolean canceled)&amp;lt;/code&amp;gt;, wherein passing the boolean value &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt; is interpreted as cancelling the event, and passing the boolean value &amp;lt;code&amp;gt;false&amp;lt;/code&amp;gt; is interpreted as “un-cancelling” the event.&lt;br /&gt;
&lt;br /&gt;
{{Tip/Important|Not all events can be cancelled! Attempting to cancel an event that is not cancellable will result in an unchecked &amp;lt;code&amp;gt;UnsupportedOperationException&amp;lt;/code&amp;gt; being thrown, which is expected to result in the game crashing. Always check that an event can be cancelled using &amp;lt;code&amp;gt;Event#isCancelable()&amp;lt;/code&amp;gt; before attempting to cancel it.}}&lt;br /&gt;
&lt;br /&gt;
== Results ==&lt;br /&gt;
&lt;br /&gt;
Some events have an &amp;lt;code&amp;gt;Event.Result&amp;lt;/code&amp;gt; as denoted by &amp;lt;code&amp;gt;@HasResult&amp;lt;/code&amp;gt;. A result can be one of three things: &amp;lt;code&amp;gt;DENY&amp;lt;/code&amp;gt; which stops the event, &amp;lt;code&amp;gt;DEFAULT&amp;lt;/code&amp;gt; which uses the Vanilla behavior, and &amp;lt;code&amp;gt;ALLOW&amp;lt;/code&amp;gt; which forces the action to take place, regardless of if it would have originally. The result of an event can be set by calling &amp;lt;code&amp;gt;setResult&amp;lt;/code&amp;gt; with an Event.Result on the event.&lt;br /&gt;
&lt;br /&gt;
{{Colored box|title=Information|content=Different events may use results in different ways, refer to the event's JavaDoc before using the result.}}&lt;br /&gt;
&lt;br /&gt;
== Priority ==&lt;br /&gt;
&lt;br /&gt;
Event handler methods have a priority. You can set the &amp;lt;code&amp;gt;priority&amp;lt;/code&amp;gt; of an event handler method by setting the priority value of the annotation or the listener. The priority can be any value of the &amp;lt;code&amp;gt;EventPriority&amp;lt;/code&amp;gt; enum (&amp;lt;code&amp;gt;HIGHEST&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;HIGH&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;NORMAL&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;LOW&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;LOWEST&amp;lt;/code&amp;gt;). Event handlers with priority &amp;lt;code&amp;gt;HIGHEST&amp;lt;/code&amp;gt; are executed first and from there in descending order until &amp;lt;code&amp;gt;LOWEST&amp;lt;/code&amp;gt; events which are executed last.&lt;br /&gt;
&lt;br /&gt;
== Mod Event Bus ==&lt;br /&gt;
The mod event bus is primarily used for listening to lifecycle events in which mods should initialize. Many of these events are also ran in parallel so mods can be initialized at the same time. This does mean you cannot directly execute code from other mods in these events. Use the &amp;lt;code&amp;gt;InterModComms&amp;lt;/code&amp;gt; system for that.&lt;br /&gt;
&lt;br /&gt;
It is impossible for an event to be posted on the Mod bus that does not inherit the IModBusEvent interface.&lt;br /&gt;
Thus, this provides a good, easy way to tell which events are fired on this bus.&lt;br /&gt;
&lt;br /&gt;
These are the four most commonly used lifecycle events that are called during mod initialization on the mod event bus: &lt;br /&gt;
* &amp;lt;code&amp;gt;FMLCommonSetupEvent&amp;lt;/code&amp;gt; &lt;br /&gt;
* &amp;lt;code&amp;gt;FMLClientSetupEvent&amp;lt;/code&amp;gt; &amp;amp; &amp;lt;code&amp;gt;FMLDedicatedServerSetupEvent&amp;lt;/code&amp;gt; (''These events are only called on their respective [[Sides#Different_Kinds_of_Sides|physical side]].'')&lt;br /&gt;
* &amp;lt;code&amp;gt;InterModEnqueueEvent&amp;lt;/code&amp;gt; &lt;br /&gt;
* &amp;lt;code&amp;gt;InterModProcessEvent&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
These four lifecycle events are all ran in parallel. If you want to run code on the main thread during these events you can use the &amp;lt;code&amp;gt;enqueueWork&amp;lt;/code&amp;gt; methods within the events to do so.&lt;br /&gt;
&lt;br /&gt;
Next to the lifecycle events there are a few miscellaneous events that are fired on the mod event bus where you can register, set up, or initialize various things. Most of these events are not ran in parallel in contrast to the lifecycle events:&lt;br /&gt;
* &amp;lt;code&amp;gt;ColorHandlerEvent&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;ModelBakeEvent&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;TextureStitchEvent&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;RegistryEvent&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;GatherDataEvent&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;SoundLoadEvent&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;ParticleFactoryRegisterEvent&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;ModConfigEvent&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A good rule of thumb: events are fired on the mod event bus when they should be handled during initialization of a mod. or where they are used to set state (eg. the config event.)&lt;br /&gt;
&lt;br /&gt;
Detailed information about these events will be found in their respective pages, once they are ready.&lt;br /&gt;
&lt;br /&gt;
== Forge Event Bus ==&lt;br /&gt;
The Forge event bus is where game state events are fired. If anything changes to do with the game, or anything happens that you would need to know about, there's a good chance it's sent here.&lt;br /&gt;
&lt;br /&gt;
A full list of the events fired here is as follows, split into discrete categories:&lt;br /&gt;
&lt;br /&gt;
{{Tree list}}&lt;br /&gt;
* &amp;lt;code&amp;gt;Event&amp;lt;/code&amp;gt; - ''The root event class''&lt;br /&gt;
** '''Rendering events''' ('''client-only''')&lt;br /&gt;
*** &amp;lt;code&amp;gt;RenderWorldLastEvent&amp;lt;/code&amp;gt; - Fired after world rendering to allow mods to add custom renders&lt;br /&gt;
*** &amp;lt;code&amp;gt;RenderHandEvent&amp;lt;/code&amp;gt; - Fired before and after the hand of the player is rendered in the first person POV&lt;br /&gt;
*** &amp;lt;code&amp;gt;RenderLivingEvent&amp;lt;/code&amp;gt; - Fired before and after a &amp;lt;code&amp;gt;LivingRenderer&amp;lt;/code&amp;gt; is executed&lt;br /&gt;
*** &amp;lt;code&amp;gt;RenderItemInFrameEvent&amp;lt;/code&amp;gt; - Fired before the item in an &amp;lt;code&amp;gt;ItemFrameEntity&amp;lt;/code&amp;gt; is rendered&lt;br /&gt;
*** &amp;lt;code&amp;gt;RenderBlockOverlayEvent&amp;lt;/code&amp;gt; - Fired before the block overlay for the player's screen is rendered&lt;br /&gt;
*** &amp;lt;code&amp;gt;DrawHighlightEvent&amp;lt;/code&amp;gt; - Fired before the block highlight outline is rendered&lt;br /&gt;
*** &amp;lt;code&amp;gt;RenderTooltipEvent&amp;lt;/code&amp;gt; - Fired before and during rendering of a text tooltip on a screen&lt;br /&gt;
*** &amp;lt;code&amp;gt;EntityViewRenderEvent&amp;lt;/code&amp;gt; - Superclass for events relating to the player's viewpoint&lt;br /&gt;
*** &amp;lt;code&amp;gt;RenderGameOverlayEvent&amp;lt;/code&amp;gt; - Superclass, fired for each element on the player's HUD or game overlay&lt;br /&gt;
*** &amp;lt;code&amp;gt;FOVUpdateEvent&amp;lt;/code&amp;gt; - Fired when the FOV of the player is requested (?)&lt;br /&gt;
** '''GUI/Screen events''' ('''client-only''')&lt;br /&gt;
*** &amp;lt;code&amp;gt;GuiScreenEvent&amp;lt;/code&amp;gt; - Superclass for events relating to &amp;lt;code&amp;gt;Screen&amp;lt;/code&amp;gt;s&lt;br /&gt;
*** &amp;lt;code&amp;gt;GuiContainerEvent&amp;lt;/code&amp;gt; - Superclsas for events relating to &amp;lt;code&amp;gt;ContainerScreen&amp;lt;/code&amp;gt;s&lt;br /&gt;
*** &amp;lt;code&amp;gt;GuiOpenEvent&amp;lt;/code&amp;gt; - Fired before a new screen is opened on the game window&lt;br /&gt;
** '''Superclass events''' - ''These events exist to be superclasses of other events''&lt;br /&gt;
*** &amp;lt;code&amp;gt;GenericEvent&amp;lt;/code&amp;gt; - ''from EventBus'', superclass of events which have a generic type&lt;br /&gt;
*** &amp;lt;code&amp;gt;BlockEvent&amp;lt;/code&amp;gt; - Superclass for events relating to a block within the world&lt;br /&gt;
*** &amp;lt;code&amp;gt;WorldEvent&amp;lt;/code&amp;gt; - Superclass for events relating to the world&lt;br /&gt;
*** &amp;lt;code&amp;gt;InputEvent&amp;lt;/code&amp;gt; - ('''client-only''') Superclass for events relating to the player's keyboard and mouse inputs&lt;br /&gt;
*** &amp;lt;code&amp;gt;NetworkEvent&amp;lt;/code&amp;gt; - Superclass for events relating to networking&lt;br /&gt;
*** &amp;lt;code&amp;gt;ExplosionEvent&amp;lt;/code&amp;gt; - Fired before an explosion explodes in the world&lt;br /&gt;
*** &amp;lt;code&amp;gt;SoundEvent&amp;lt;/code&amp;gt; - ('''client-only''') Superclass for events related to sounds&lt;br /&gt;
*** &amp;lt;code&amp;gt;EntityEvent&amp;lt;/code&amp;gt; - Superclass for events relating to entities&lt;br /&gt;
*** &amp;lt;code&amp;gt;TickEvent&amp;lt;/code&amp;gt; - Superclass for events fired before and after ticking&lt;br /&gt;
** '''Chat events'''&lt;br /&gt;
*** &amp;lt;code&amp;gt;ServerChatEvent&amp;lt;/code&amp;gt; ('''server-only''') - Fired when the server receives a chat message and before it relays the message&lt;br /&gt;
*** &amp;lt;code&amp;gt;ClientChatEvent&amp;lt;/code&amp;gt; ('''client-only''') - Fired before the client is about to send a chat message&lt;br /&gt;
*** &amp;lt;code&amp;gt;ClientChatReceivedEvent&amp;lt;/code&amp;gt; ('''client-only''') - Fired when the client receives a chat message from the server&lt;br /&gt;
** '''Data loading events'''&lt;br /&gt;
*** &amp;lt;code&amp;gt;RecipesUpdatedEvent&amp;lt;/code&amp;gt;&lt;br /&gt;
*** &amp;lt;code&amp;gt;BiomeLoadingEvent&amp;lt;/code&amp;gt;&lt;br /&gt;
*** &amp;lt;code&amp;gt;LootTableLoadEvent&amp;lt;/code&amp;gt;&lt;br /&gt;
*** &amp;lt;code&amp;gt;StructureSpawnListGatherEvent&amp;lt;/code&amp;gt;&lt;br /&gt;
** '''Startup events'''&lt;br /&gt;
*** &amp;lt;code&amp;gt;AddReloadListenerEvent&amp;lt;/code&amp;gt;&lt;br /&gt;
*** &amp;lt;code&amp;gt;RegisterCommandsEvent&amp;lt;/code&amp;gt;&lt;br /&gt;
*** &amp;lt;code&amp;gt;ServerLifecycleEvent&amp;lt;/code&amp;gt;&lt;br /&gt;
** '''Gamemode events'''&lt;br /&gt;
*** &amp;lt;code&amp;gt;DifficultyChangeEvent&amp;lt;/code&amp;gt;&lt;br /&gt;
*** &amp;lt;code&amp;gt;ClientPlayerChangeGamemodeEvent&amp;lt;/code&amp;gt;&lt;br /&gt;
**'''Trade events'''&lt;br /&gt;
*** &amp;lt;code&amp;gt;WandererTradesEvent&amp;lt;/code&amp;gt;&lt;br /&gt;
*** &amp;lt;code&amp;gt;VillagerTradesEvent&amp;lt;/code&amp;gt;&lt;br /&gt;
** '''Other events'''&lt;br /&gt;
*** &amp;lt;code&amp;gt;FurnaceFuelBurnTimeEvent&amp;lt;/code&amp;gt;&lt;br /&gt;
*** &amp;lt;code&amp;gt;BabyEntitySpawnEvent&amp;lt;/code&amp;gt;&lt;br /&gt;
*** &amp;lt;code&amp;gt;VillageSiegeEvent&amp;lt;/code&amp;gt;&lt;br /&gt;
*** &amp;lt;code&amp;gt;TagsUpdatedEvent&amp;lt;/code&amp;gt;&lt;br /&gt;
*** &amp;lt;code&amp;gt;PotionBrewEvent&amp;lt;/code&amp;gt;&lt;br /&gt;
*** &amp;lt;code&amp;gt;ScreenshotEvent&amp;lt;/code&amp;gt;&lt;br /&gt;
*** &amp;lt;code&amp;gt;EnchantmentLevelSetEvent&amp;lt;/code&amp;gt;&lt;br /&gt;
*** &amp;lt;code&amp;gt;CommandEvent&amp;lt;/code&amp;gt;&lt;br /&gt;
*** &amp;lt;code&amp;gt;AnvilUpdateEvent&amp;lt;/code&amp;gt;&lt;br /&gt;
*** &amp;lt;code&amp;gt;ItemAttributeModifierEvent&amp;lt;/code&amp;gt;&lt;br /&gt;
*** &amp;lt;code&amp;gt;ClientPlayerNetworkEvent&amp;lt;/code&amp;gt;&lt;br /&gt;
*** &amp;lt;code&amp;gt;ChunkWatchEvent&amp;lt;/code&amp;gt;&lt;br /&gt;
{{Tree list/end}}&lt;br /&gt;
&lt;br /&gt;
Like before, each of these events (especially the Super Events, which contain most of the useful events in the game) will have their own article explaining their purpose and usefulness.&lt;br /&gt;
&amp;lt;/tab&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Events]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Common Concepts]]&lt;/div&gt;</summary>
		<author><name>Curle</name></author>
	</entry>
	<entry>
		<id>https://forge.gemwire.uk/index.php?title=Access_Transformers&amp;diff=2911</id>
		<title>Access Transformers</title>
		<link rel="alternate" type="text/html" href="https://forge.gemwire.uk/index.php?title=Access_Transformers&amp;diff=2911"/>
		<updated>2021-08-12T23:48:13Z</updated>

		<summary type="html">&lt;p&gt;Curle: parameters, man.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Under construction}}&lt;br /&gt;
&lt;br /&gt;
Access Transformers are Forge's native way of allowing you to access (read and write) functions that have a lower-than-ideal visibility, and/or removing finality.&lt;br /&gt;
&lt;br /&gt;
== Visibility ==&lt;br /&gt;
&lt;br /&gt;
Here's a quick rundown of the visibility options offered by Java 16:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;public&amp;lt;/code&amp;gt; visible to all classes inside and outside its package&lt;br /&gt;
* &amp;lt;code&amp;gt;protected&amp;lt;/code&amp;gt; visible only to classes inside the package and subclasses&lt;br /&gt;
* &amp;lt;code&amp;gt;default&amp;lt;/code&amp;gt; visible only to classes inside the package&lt;br /&gt;
* &amp;lt;code&amp;gt;private&amp;lt;/code&amp;gt; visible only to inside the class&lt;br /&gt;
&lt;br /&gt;
Additionally, there are final variants of each of these, each represented by the phrase &amp;quot;-f&amp;quot; on the end of the access specifier.&lt;br /&gt;
&lt;br /&gt;
== How It Works ==&lt;br /&gt;
&lt;br /&gt;
As Forge is loading, it scans the jar file for the META-INF/accesstransformers.cfg file. if it's found, it is parsed according to the specification:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code -&amp;gt;NewAccessSpecifier ClassSignature MemberSignature # comment&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you're targetting a class itself, you may omit the Member Signature.&amp;lt;br&amp;gt;&lt;br /&gt;
However, it is required if you're targetting a method or field inside the class.&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;code&amp;gt;MemberSignature&amp;lt;/code&amp;gt;s use the Java specification for parts.&amp;lt;br&amp;gt;&lt;br /&gt;
Importantly, method descriptors are &amp;lt;code&amp;gt;name(parameters)return&amp;lt;/code&amp;gt;, classes in the parameters are in the form &amp;lt;code&amp;gt;Lpath/to/Class;&amp;lt;/code&amp;gt;,and &amp;lt;code&amp;gt;V&amp;lt;/code&amp;gt; is void.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A couple random examples to understand the syntax:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
public net.minecraft.world.level.chunk.PaletteResize # makes the PaletteResize class public&amp;lt;br&amp;gt;&lt;br /&gt;
protected net.minecraft.client.gui.Gui f_168667_ # COLOR_WHITE&amp;lt;br&amp;gt;&lt;br /&gt;
public net.minecraft.client.renderer.GameRenderer m_109128_(Lnet/minecraft/resources/ResourceLocation;)V # loadEffect &amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
If a valid entry is found on a line, Forge will look into the bytecode of the file where that member is defined, and change its access to whatever you desire it to be.&lt;br /&gt;
&lt;br /&gt;
This startup modification means accessing is O(1) for all accesses after this initial change, which makes it a great option for performance if you're looking at something a lot&lt;br /&gt;
&lt;br /&gt;
=== Removing Finality ===&lt;br /&gt;
Access transformers can also be used to remove the '''final''' keyword on code elements. To do this, append &amp;lt;code&amp;gt;-f&amp;lt;/code&amp;gt; to the access specifier.&lt;br /&gt;
&lt;br /&gt;
An example of this in place:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code -&amp;gt;public-f net.minecraft.world.level.chunk.PaletteResize # makes PaletteResize public&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note: You can also use this to ''add'' a final keyword via &amp;lt;code&amp;gt;+f&amp;lt;/code&amp;gt;. This is never recommended however, and should be avoided at all costs unless absolutely necessary.&lt;br /&gt;
&lt;br /&gt;
== Using Access Transformers in your mod ==&lt;br /&gt;
&lt;br /&gt;
{{Tip/Important|You should avoid using ATs if a private variable / function you're looking at has a getter or a setter. Variables are usually private for a reason.}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Step 1: Uncomment the access transformer line in your build.gradle&lt;br /&gt;
&lt;br /&gt;
[[File:Access-transformers-uncomment-this-line-in-build-gradle.png|600px|frameless]]&lt;br /&gt;
&lt;br /&gt;
Step 2: Create a new file called &amp;quot;accesstransformer.cfg&amp;quot; in the &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;src/main/resources/META-INF/&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt; folder.&lt;br /&gt;
&lt;br /&gt;
Step 3: Refresh the Gradle project. This can be done natively in IDEA and Eclipse.&lt;br /&gt;
&lt;br /&gt;
== When not to use Access Transformers ==&lt;br /&gt;
* Unnecessary access transformations (e.g. using ATs to make something &amp;lt;code&amp;gt;public&amp;lt;/code&amp;gt; when it's already &amp;lt;code&amp;gt;public&amp;lt;/code&amp;gt;)&lt;/div&gt;</summary>
		<author><name>Curle</name></author>
	</entry>
	<entry>
		<id>https://forge.gemwire.uk/index.php?title=Access_Transformers&amp;diff=2910</id>
		<title>Access Transformers</title>
		<link rel="alternate" type="text/html" href="https://forge.gemwire.uk/index.php?title=Access_Transformers&amp;diff=2910"/>
		<updated>2021-08-12T23:47:07Z</updated>

		<summary type="html">&lt;p&gt;Curle: Adjust potentially confusing wording&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Under construction}}&lt;br /&gt;
&lt;br /&gt;
Access Transformers are Forge's native way of allowing you to access (read and write) functions that have a lower-than-ideal visibility, and/or removing finality.&lt;br /&gt;
&lt;br /&gt;
== Visibility ==&lt;br /&gt;
&lt;br /&gt;
Here's a quick rundown of the visibility options offered by Java 16:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;public&amp;lt;/code&amp;gt; visible to all classes inside and outside its package&lt;br /&gt;
* &amp;lt;code&amp;gt;protected&amp;lt;/code&amp;gt; visible only to classes inside the package and subclasses&lt;br /&gt;
* &amp;lt;code&amp;gt;default&amp;lt;/code&amp;gt; visible only to classes inside the package&lt;br /&gt;
* &amp;lt;code&amp;gt;private&amp;lt;/code&amp;gt; visible only to inside the class&lt;br /&gt;
&lt;br /&gt;
Additionally, there are final variants of each of these, each represented by the phrase &amp;quot;-f&amp;quot; on the end of the access specifier.&lt;br /&gt;
&lt;br /&gt;
== How It Works ==&lt;br /&gt;
&lt;br /&gt;
As Forge is loading, it scans the jar file for the META-INF/accesstransformers.cfg file. if it's found, it is parsed according to the specification:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code -&amp;gt;NewAccessSpecifier ClassSignature MemberSignature # comment&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you're targetting a class itself, you may omit the Member Signature.&amp;lt;br&amp;gt;&lt;br /&gt;
However, it is required if you're targetting a method or field inside the class.&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;code&amp;gt;MemberSignature&amp;lt;/code&amp;gt;s use the Java specification for parts.&amp;lt;br&amp;gt;&lt;br /&gt;
Importantly, method descriptors are &amp;lt;code&amp;gt;name(parameters)return&amp;lt;/code&amp;gt;, classes in the paramters are in the form &amp;lt;code&amp;gt;Lpath/to/Class;&amp;lt;/code&amp;gt;,and &amp;lt;code&amp;gt;V&amp;lt;/code&amp;gt; is void.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A couple random examples to understand the syntax:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
public net.minecraft.world.level.chunk.PaletteResize # makes the PaletteResize class public&amp;lt;br&amp;gt;&lt;br /&gt;
protected net.minecraft.client.gui.Gui f_168667_ # COLOR_WHITE&amp;lt;br&amp;gt;&lt;br /&gt;
public net.minecraft.client.renderer.GameRenderer m_109128_(Lnet/minecraft/resources/ResourceLocation;)V # loadEffect &amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
If a valid entry is found on a line, Forge will look into the bytecode of the file where that member is defined, and change its access to whatever you desire it to be.&lt;br /&gt;
&lt;br /&gt;
This startup modification means accessing is O(1) for all accesses after this initial change, which makes it a great option for performance if you're looking at something a lot&lt;br /&gt;
&lt;br /&gt;
=== Removing Finality ===&lt;br /&gt;
Access transformers can also be used to remove the '''final''' keyword on code elements. To do this, append &amp;lt;code&amp;gt;-f&amp;lt;/code&amp;gt; to the access specifier.&lt;br /&gt;
&lt;br /&gt;
An example of this in place:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code -&amp;gt;public-f net.minecraft.world.level.chunk.PaletteResize # makes PaletteResize public&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note: You can also use this to ''add'' a final keyword via &amp;lt;code&amp;gt;+f&amp;lt;/code&amp;gt;. This is never recommended however, and should be avoided at all costs unless absolutely necessary.&lt;br /&gt;
&lt;br /&gt;
== Using Access Transformers in your mod ==&lt;br /&gt;
&lt;br /&gt;
{{Tip/Important|You should avoid using ATs if a private variable / function you're looking at has a getter or a setter. Variables are usually private for a reason.}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Step 1: Uncomment the access transformer line in your build.gradle&lt;br /&gt;
&lt;br /&gt;
[[File:Access-transformers-uncomment-this-line-in-build-gradle.png|600px|frameless]]&lt;br /&gt;
&lt;br /&gt;
Step 2: Create a new file called &amp;quot;accesstransformer.cfg&amp;quot; in the &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;src/main/resources/META-INF/&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt; folder.&lt;br /&gt;
&lt;br /&gt;
Step 3: Refresh the Gradle project. This can be done natively in IDEA and Eclipse.&lt;br /&gt;
&lt;br /&gt;
== When not to use Access Transformers ==&lt;br /&gt;
* Unnecessary access transformations (e.g. using ATs to make something &amp;lt;code&amp;gt;public&amp;lt;/code&amp;gt; when it's already &amp;lt;code&amp;gt;public&amp;lt;/code&amp;gt;)&lt;/div&gt;</summary>
		<author><name>Curle</name></author>
	</entry>
	<entry>
		<id>https://forge.gemwire.uk/index.php?title=Access_Transformers&amp;diff=2909</id>
		<title>Access Transformers</title>
		<link rel="alternate" type="text/html" href="https://forge.gemwire.uk/index.php?title=Access_Transformers&amp;diff=2909"/>
		<updated>2021-08-12T23:39:35Z</updated>

		<summary type="html">&lt;p&gt;Curle: &amp;quot;a class or field inside the class&amp;quot; -&amp;gt; &amp;quot;a method or field inside the class&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Under construction}}&lt;br /&gt;
&lt;br /&gt;
Access Transformers are Forge's native way of allowing you to access (read and write) functions that have a lower-than-ideal visibility, and/or removing finality.&lt;br /&gt;
&lt;br /&gt;
== Visibility ==&lt;br /&gt;
&lt;br /&gt;
Here's a quick rundown of the visibility options offered by Java 16:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;public&amp;lt;/code&amp;gt; visible to all classes inside and outside its package&lt;br /&gt;
* &amp;lt;code&amp;gt;protected&amp;lt;/code&amp;gt; visible only to classes inside the package and subclasses&lt;br /&gt;
* &amp;lt;code&amp;gt;default&amp;lt;/code&amp;gt; visible only to classes inside the package&lt;br /&gt;
* &amp;lt;code&amp;gt;private&amp;lt;/code&amp;gt; visible only to inside the class&lt;br /&gt;
&lt;br /&gt;
Additionally, there are final variants of each of these, each represented by the phrase &amp;quot;-f&amp;quot; on the end of the access specifier.&lt;br /&gt;
&lt;br /&gt;
== How It Works ==&lt;br /&gt;
&lt;br /&gt;
As Forge is loading, it scans the jar file for the META-INF/accesstransformers.cfg file. if it's found, it is parsed according to the specification:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code -&amp;gt;NewAccessSpecifier ClassSignature MemberSignature # comment&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you're targetting a class itself, you may omit the Member Signature.&amp;lt;br&amp;gt;&lt;br /&gt;
However, it is required if you're targetting a method or field inside the class.&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;code&amp;gt;MemberSignature&amp;lt;/code&amp;gt;s use the Java specification for parts.&amp;lt;br&amp;gt;&lt;br /&gt;
Importantly, classes are in the form &amp;lt;code&amp;gt;Lpath/to/Class;&amp;lt;/code&amp;gt;, method descriptors are &amp;lt;code&amp;gt;name(parameters)return&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;V&amp;lt;/code&amp;gt; is void.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A couple random examples to understand the syntax:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
public net.minecraft.world.level.chunk.PaletteResize # makes the PaletteResize class public&amp;lt;br&amp;gt;&lt;br /&gt;
protected net.minecraft.client.gui.Gui f_168667_ # COLOR_WHITE&amp;lt;br&amp;gt;&lt;br /&gt;
public net.minecraft.client.renderer.GameRenderer m_109128_(Lnet/minecraft/resources/ResourceLocation;)V # loadEffect &amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
If a valid entry is found on a line, Forge will look into the bytecode of the file where that member is defined, and change its access to whatever you desire it to be.&lt;br /&gt;
&lt;br /&gt;
This startup modification means accessing is O(1) for all accesses after this initial change, which makes it a great option for performance if you're looking at something a lot&lt;br /&gt;
&lt;br /&gt;
=== Removing Finality ===&lt;br /&gt;
Access transformers can also be used to remove the '''final''' keyword on code elements. To do this, append &amp;lt;code&amp;gt;-f&amp;lt;/code&amp;gt; to the access specifier.&lt;br /&gt;
&lt;br /&gt;
An example of this in place:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code -&amp;gt;public-f net.minecraft.world.level.chunk.PaletteResize # makes PaletteResize public&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note: You can also use this to ''add'' a final keyword via &amp;lt;code&amp;gt;+f&amp;lt;/code&amp;gt;. This is never recommended however, and should be avoided at all costs unless absolutely necessary.&lt;br /&gt;
&lt;br /&gt;
== Using Access Transformers in your mod ==&lt;br /&gt;
&lt;br /&gt;
{{Tip/Important|You should avoid using ATs if a private variable / function you're looking at has a getter or a setter. Variables are usually private for a reason.}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Step 1: Uncomment the access transformer line in your build.gradle&lt;br /&gt;
&lt;br /&gt;
[[File:Access-transformers-uncomment-this-line-in-build-gradle.png|600px|frameless]]&lt;br /&gt;
&lt;br /&gt;
Step 2: Create a new file called &amp;quot;accesstransformer.cfg&amp;quot; in the &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;src/main/resources/META-INF/&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt; folder.&lt;br /&gt;
&lt;br /&gt;
Step 3: Refresh the Gradle project. This can be done natively in IDEA and Eclipse.&lt;br /&gt;
&lt;br /&gt;
== When not to use Access Transformers ==&lt;br /&gt;
* Unnecessary access transformations (e.g. using ATs to make something &amp;lt;code&amp;gt;public&amp;lt;/code&amp;gt; when it's already &amp;lt;code&amp;gt;public&amp;lt;/code&amp;gt;)&lt;/div&gt;</summary>
		<author><name>Curle</name></author>
	</entry>
	<entry>
		<id>https://forge.gemwire.uk/index.php?title=Access_Transformers&amp;diff=2908</id>
		<title>Access Transformers</title>
		<link rel="alternate" type="text/html" href="https://forge.gemwire.uk/index.php?title=Access_Transformers&amp;diff=2908"/>
		<updated>2021-08-12T23:38:25Z</updated>

		<summary type="html">&lt;p&gt;Curle: Add information on member signatures. TODO: add a link to the Java specification on signatures&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Under construction}}&lt;br /&gt;
&lt;br /&gt;
Access Transformers are Forge's native way of allowing you to access (read and write) functions that have a lower-than-ideal visibility, and/or removing finality.&lt;br /&gt;
&lt;br /&gt;
== Visibility ==&lt;br /&gt;
&lt;br /&gt;
Here's a quick rundown of the visibility options offered by Java 16:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;public&amp;lt;/code&amp;gt; visible to all classes inside and outside its package&lt;br /&gt;
* &amp;lt;code&amp;gt;protected&amp;lt;/code&amp;gt; visible only to classes inside the package and subclasses&lt;br /&gt;
* &amp;lt;code&amp;gt;default&amp;lt;/code&amp;gt; visible only to classes inside the package&lt;br /&gt;
* &amp;lt;code&amp;gt;private&amp;lt;/code&amp;gt; visible only to inside the class&lt;br /&gt;
&lt;br /&gt;
Additionally, there are final variants of each of these, each represented by the phrase &amp;quot;-f&amp;quot; on the end of the access specifier.&lt;br /&gt;
&lt;br /&gt;
== How It Works ==&lt;br /&gt;
&lt;br /&gt;
As Forge is loading, it scans the jar file for the META-INF/accesstransformers.cfg file. if it's found, it is parsed according to the specification:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code -&amp;gt;NewAccessSpecifier ClassSignature MemberSignature # comment&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you're targetting a class itself, you may omit the Member Signature.&amp;lt;br&amp;gt;&lt;br /&gt;
However, it is required if you're targetting a class or field inside the class.&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;code&amp;gt;MemberSignature&amp;lt;/code&amp;gt;s use the Java specification for parts.&amp;lt;br&amp;gt;&lt;br /&gt;
Importantly, classes are in the form &amp;lt;code&amp;gt;Lpath/to/Class;&amp;lt;/code&amp;gt;, method descriptors are &amp;lt;code&amp;gt;name(parameters)return&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;V&amp;lt;/code&amp;gt; is void.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A couple random examples to understand the syntax:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
public net.minecraft.world.level.chunk.PaletteResize # makes the PaletteResize class public&amp;lt;br&amp;gt;&lt;br /&gt;
protected net.minecraft.client.gui.Gui f_168667_ # COLOR_WHITE&amp;lt;br&amp;gt;&lt;br /&gt;
public net.minecraft.client.renderer.GameRenderer m_109128_(Lnet/minecraft/resources/ResourceLocation;)V # loadEffect &amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
If a valid entry is found on a line, Forge will look into the bytecode of the file where that member is defined, and change its access to whatever you desire it to be.&lt;br /&gt;
&lt;br /&gt;
This startup modification means accessing is O(1) for all accesses after this initial change, which makes it a great option for performance if you're looking at something a lot&lt;br /&gt;
&lt;br /&gt;
=== Removing Finality ===&lt;br /&gt;
Access transformers can also be used to remove the '''final''' keyword on code elements. To do this, append &amp;lt;code&amp;gt;-f&amp;lt;/code&amp;gt; to the access specifier.&lt;br /&gt;
&lt;br /&gt;
An example of this in place:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code -&amp;gt;public-f net.minecraft.world.level.chunk.PaletteResize # makes PaletteResize public&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note: You can also use this to ''add'' a final keyword via &amp;lt;code&amp;gt;+f&amp;lt;/code&amp;gt;. This is never recommended however, and should be avoided at all costs unless absolutely necessary.&lt;br /&gt;
&lt;br /&gt;
== Using Access Transformers in your mod ==&lt;br /&gt;
&lt;br /&gt;
{{Tip/Important|You should avoid using ATs if a private variable / function you're looking at has a getter or a setter. Variables are usually private for a reason.}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Step 1: Uncomment the access transformer line in your build.gradle&lt;br /&gt;
&lt;br /&gt;
[[File:Access-transformers-uncomment-this-line-in-build-gradle.png|600px|frameless]]&lt;br /&gt;
&lt;br /&gt;
Step 2: Create a new file called &amp;quot;accesstransformer.cfg&amp;quot; in the &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;src/main/resources/META-INF/&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt; folder.&lt;br /&gt;
&lt;br /&gt;
Step 3: Refresh the Gradle project. This can be done natively in IDEA and Eclipse.&lt;br /&gt;
&lt;br /&gt;
== When not to use Access Transformers ==&lt;br /&gt;
* Unnecessary access transformations (e.g. using ATs to make something &amp;lt;code&amp;gt;public&amp;lt;/code&amp;gt; when it's already &amp;lt;code&amp;gt;public&amp;lt;/code&amp;gt;)&lt;/div&gt;</summary>
		<author><name>Curle</name></author>
	</entry>
	<entry>
		<id>https://forge.gemwire.uk/index.php?title=Sounds/1.16&amp;diff=2907</id>
		<title>Sounds/1.16</title>
		<link rel="alternate" type="text/html" href="https://forge.gemwire.uk/index.php?title=Sounds/1.16&amp;diff=2907"/>
		<updated>2021-08-08T01:20:59Z</updated>

		<summary type="html">&lt;p&gt;Curle: Add note about mono sounds and attenuation.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Although not essential, sounds bring a greater immersion into the Minecraft world. Their usages within and outside the development environment gives a bit more polish to an already existing mod from background music to a single block break.&lt;br /&gt;
&lt;br /&gt;
== Creating a Sound ==&lt;br /&gt;
&lt;br /&gt;
Sounds in Minecraft are comprised of two things: an audio file and a reference pointer to that audio file.&lt;br /&gt;
&lt;br /&gt;
The reference pointer is known as &amp;lt;code&amp;gt;sounds.json&amp;lt;/code&amp;gt; which should be created at &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;assets/&amp;lt;modid&amp;gt;/sounds.json&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;. This JSON defines resource names to point to the audio files added by a specific mod. The only thing necessary to define a sound is by creating an object, naming it, and then defining the location of the sound within a list.&lt;br /&gt;
&lt;br /&gt;
By default, the only supported audio format is [https://xiph.org/vorbis/ Ogg Vorbis] represented by the extension &amp;lt;code&amp;gt;.ogg&amp;lt;/code&amp;gt;. The file &amp;lt;code&amp;gt;namespace:path&amp;lt;/code&amp;gt; when referenced in the JSON will be located within &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;assets/&amp;lt;namespace&amp;gt;/sounds/&amp;lt;path&amp;gt;.ogg&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;.&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;example_sound&amp;quot;: {&lt;br /&gt;
    &amp;quot;sounds&amp;quot;: [ &amp;quot;examplemod:example_sound_file&amp;quot; ]&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Using the example above, it creates a sound called &amp;lt;code&amp;gt;example_sound&amp;lt;/code&amp;gt; and references the file &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;assets/&amp;lt;modid&amp;gt;/sounds/example_sound_file.ogg&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;.   &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{{Tip/Danger | Due to [https://bugs.mojang.com/browse/MC-146721 the way OpenAL (Minecraft's sound engine) works], for your sound to have attenuation - that is, for it to get quieter as the player walks away, it absolutely MUST be mono (have one audio channel).  &lt;br /&gt;
&lt;br /&gt;
Stereo sounds are always played at the '''player's''' location, making them ideal for ambient sounds and background music.&lt;br /&gt;
&lt;br /&gt;
}}  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Instead of being constructed as a list of strings, each entry could also be an object which allows a greater control over what and how it is played.&lt;br /&gt;
&lt;br /&gt;
Here are some variables that could be defined:&lt;br /&gt;
{| class=&amp;quot;wikitable sortable&amp;quot; border=1&lt;br /&gt;
!Parameter !!Description &lt;br /&gt;
|-&lt;br /&gt;
|   name   ||  Sets the path to the sound file excluding the &amp;lt;code&amp;gt;.ogg&amp;lt;/code&amp;gt; extension. &lt;br /&gt;
|-&lt;br /&gt;
|   stream   ||  Determines whether the sound should be streamed from the file. When true, it reduces the amount of lag from loading a large file; however, it only allows four instances of the sound to be played at once. &lt;br /&gt;
|-&lt;br /&gt;
|   volume   ||  A value between 0 and 1 to determine the volume of the sound played. &lt;br /&gt;
|-&lt;br /&gt;
|}&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;example_sound&amp;quot;: {&lt;br /&gt;
    &amp;quot;sounds&amp;quot;: [ &amp;quot;examplemod:example_sound_file&amp;quot; ]&lt;br /&gt;
  },&lt;br /&gt;
  &amp;quot;example_sound_complex&amp;quot;: {&lt;br /&gt;
    &amp;quot;sounds&amp;quot;:&lt;br /&gt;
    [&lt;br /&gt;
      {&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;examplemod:complex/example_complex&amp;quot;,&lt;br /&gt;
        &amp;quot;pitch&amp;quot;: 0.6,&lt;br /&gt;
        &amp;quot;stream&amp;quot;: true&lt;br /&gt;
      }&lt;br /&gt;
    ]&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now there is a new sound within our JSON called &amp;lt;code&amp;gt;example_sound_complex&amp;lt;/code&amp;gt;. This points to the audio file at &amp;lt;code&amp;gt;assets/examplemod/sounds/complex/example_complex.json&amp;lt;/code&amp;gt;. The sound's pitch is lowered to 0.6 of its original value. The &amp;lt;code&amp;gt;stream&amp;lt;/code&amp;gt; parameter is also set to true.&lt;br /&gt;
&lt;br /&gt;
There are many more parameters that can give greater control on how sounds are played. However, this is left as an exercise to the reader to try and construct with the [https://minecraft.gamepedia.com/Sounds.json wiki].&lt;br /&gt;
&lt;br /&gt;
== Creating &amp;lt;code&amp;gt;SoundEvent&amp;lt;/code&amp;gt;s ==&lt;br /&gt;
&lt;br /&gt;
A &amp;lt;code&amp;gt;sounds.json&amp;lt;/code&amp;gt; left in its current state would only be defined in-game. There is currently no way to reference the sound within a mod. To do this, we utilize the &amp;lt;code&amp;gt;SoundEvent&amp;lt;/code&amp;gt; class. Each &amp;lt;code&amp;gt;SoundEvent&amp;lt;/code&amp;gt; class holds a &amp;lt;code&amp;gt;ResourceLocation&amp;lt;/code&amp;gt; to reference a sound pointer defined in the &amp;lt;code&amp;gt;sounds.json&amp;lt;/code&amp;gt; file. The &amp;lt;code&amp;gt;sounds.json&amp;lt;/code&amp;gt; file used is determined by the namespace or the resource location passed into the class.&lt;br /&gt;
&lt;br /&gt;
For example, to reference &amp;lt;code&amp;gt;example_complex.ogg&amp;lt;/code&amp;gt;, you would store the reference name (e.g. &amp;lt;code&amp;gt;example_sound_complex&amp;lt;/code&amp;gt;) within a &amp;lt;code&amp;gt;new SoundEvent(new ResourceLocation(&amp;quot;examplemod&amp;quot;, &amp;quot;example_sound_complex&amp;quot;))&amp;lt;/code&amp;gt;. This will locate &amp;lt;code&amp;gt;assets/examplemod/sounds.json&amp;lt;/code&amp;gt; and try to find an &amp;lt;code&amp;gt;example_sound_complex&amp;lt;/code&amp;gt; object nested within it.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;SoundEvent&amp;lt;/code&amp;gt;s must be [[Registration/1.16|registered]] to be referenced in code. &lt;br /&gt;
&lt;br /&gt;
== Playing Sounds ==&lt;br /&gt;
&lt;br /&gt;
Vanilla has lots of methods for playing sounds that can be used in different scenarios.&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;code&amp;gt;World&amp;lt;/code&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
# &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;playSound(PlayerEntity, BlockPos, SoundEvent, SoundCategory, volume, pitch)&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
#*Simply forwards to overload (2), adding 0.5 to each coordinate of the BlockPos given.&lt;br /&gt;
# &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;playSound(PlayerEntity, double x, double y, double z, SoundEvent, SoundCategory, volume, pitch)&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
#* &amp;lt;code&amp;gt;Client Behavior&amp;lt;/code&amp;gt;: If the passed in player is the client player, plays the sound event to the client player.&lt;br /&gt;
#* &amp;lt;code&amp;gt;Server Behavior&amp;lt;/code&amp;gt;: Plays the sound event to everyone nearby except the passed in player. Player can be &amp;lt;code&amp;gt;null&amp;lt;/code&amp;gt;.&lt;br /&gt;
#* &amp;lt;code&amp;gt;Usage&amp;lt;/code&amp;gt;: The correspondence between the behaviors implies that these two methods are to be called from some player-initiated code that will be run on both logical sides at the same time - the logical client handles playing it to the user and the logical server handles everyone else hearing it without re-playing it to the original user. They can also be used to play any sound in general at any position server-side by calling it on the logical server and passing in a &amp;lt;code&amp;gt;null&amp;lt;/code&amp;gt; player, thus letting everyone hear it.&lt;br /&gt;
# &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;playSound(double x, double y, double z, SoundEvent, SoundCategory, volume, pitch, distanceDelay)&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
#* &amp;lt;code&amp;gt;Client Behavior&amp;lt;/code&amp;gt;: Just plays the sound event in the client world. If distanceDelay is true, then delays the sound based on how far it is from the player.&lt;br /&gt;
#* &amp;lt;code&amp;gt;Server Behavior&amp;lt;/code&amp;gt;: Does nothing.&lt;br /&gt;
#* &amp;lt;code&amp;gt;Usage&amp;lt;/code&amp;gt;: This method only works client-side, and thus is useful for sounds sent in custom packets, or other client-only effect-type sounds. Used for thunder.&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;code&amp;gt; ClientWorld &amp;lt;/code&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
# &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;playSound(BlockPos, SoundEvent, SoundCategory, volume, pitch, distanceDelay)&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
#* Simply forwards to &amp;lt;code&amp;gt;World&amp;lt;/code&amp;gt;‘s overload (3), adding 0.5 to each coordinate of the &amp;lt;code&amp;gt;BlockPos&amp;lt;/code&amp;gt; given.&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;code&amp;gt; Entity &amp;lt;/code&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
# &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;playSound(SoundEvent, volume, pitch)&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
#* Forwards to &amp;lt;code&amp;gt;World&amp;lt;/code&amp;gt;‘s overload (2), passing in &amp;lt;code&amp;gt;null&amp;lt;/code&amp;gt; as the player.&lt;br /&gt;
#* &amp;lt;code&amp;gt;Client Behavior&amp;lt;/code&amp;gt;: Does nothing.&lt;br /&gt;
#* &amp;lt;code&amp;gt;Server Behavior&amp;lt;/code&amp;gt;: Plays the sound event to everyone at this entity’s position.&lt;br /&gt;
#* &amp;lt;code&amp;gt;Usage&amp;lt;/code&amp;gt;: Emitting any sound from any non-player entity server-side.&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;code&amp;gt; PlayerEntity&amp;lt;/code&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
# &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;playSound(SoundEvent, volume, pitch)&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt; (overriding the one in &amp;lt;code&amp;gt;[[Sounds#Entity/1.16|Entity]]&amp;lt;/code&amp;gt;)&lt;br /&gt;
#* Forwards to &amp;lt;code&amp;gt;World&amp;lt;/code&amp;gt;‘s overload (2), passing in &amp;lt;code&amp;gt;this&amp;lt;/code&amp;gt; as the player.&lt;br /&gt;
#* &amp;lt;code&amp;gt;Client Behavior&amp;lt;/code&amp;gt;: Does nothing, see override in &amp;lt;code&amp;gt;[[Sounds#clientplayerentity/1.16|ClientPlayerEntity]]&amp;lt;/code&amp;gt;.&lt;br /&gt;
#* &amp;lt;code&amp;gt;Server Behavior&amp;lt;/code&amp;gt;: Plays the sound to everyone nearby &amp;lt;code&amp;gt;except&amp;lt;/code&amp;gt; this player.&lt;br /&gt;
#* &amp;lt;code&amp;gt;Usage&amp;lt;/code&amp;gt;: See &amp;lt;code&amp;gt;[[Sounds#clientplayerentity/1.16|ClientPlayerEntity]]&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;code&amp;gt; ClientPlayerEntity&amp;lt;/code&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
# &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;playSound(SoundEvent, volume, pitch)&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt; (overriding the one in &amp;lt;code&amp;gt;[[Sounds#playerentity/1.16|PlayerEntity]]&amp;lt;/code&amp;gt;)&lt;br /&gt;
#* Forwards to &amp;lt;code&amp;gt;World&amp;lt;/code&amp;gt;‘s overload (2), passing in &amp;lt;code&amp;gt;this&amp;lt;/code&amp;gt; as the player.&lt;br /&gt;
#* &amp;lt;code&amp;gt;Client Behavior&amp;lt;/code&amp;gt;: Just plays the Sound Event.&lt;br /&gt;
#* &amp;lt;code&amp;gt;Server Behavior&amp;lt;/code&amp;gt;: Method is client-only.&lt;br /&gt;
#* &amp;lt;code&amp;gt;Usage&amp;lt;/code&amp;gt;: Just like the ones in &amp;lt;code&amp;gt;World&amp;lt;/code&amp;gt;, these two overrides in the player classes seem to be for code that runs together on both sides. The client handles playing the sound to the user, while the server handles everyone else hearing it without re-playing to the original user.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Game Effects/1.16|Category:Game Effects]]&lt;/div&gt;</summary>
		<author><name>Curle</name></author>
	</entry>
	<entry>
		<id>https://forge.gemwire.uk/index.php?title=Sounds&amp;diff=2906</id>
		<title>Sounds</title>
		<link rel="alternate" type="text/html" href="https://forge.gemwire.uk/index.php?title=Sounds&amp;diff=2906"/>
		<updated>2021-08-08T01:20:32Z</updated>

		<summary type="html">&lt;p&gt;Curle: Add note about mono sounds and attenuation.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Although not essential, sounds bring a greater immersion into the Minecraft world. Their usages within and outside the development environment gives a bit more polish to an already existing mod from background music to a single block break.&lt;br /&gt;
&lt;br /&gt;
== Creating a Sound ==&lt;br /&gt;
&lt;br /&gt;
Sounds in Minecraft are comprised of two things: an audio file and a reference pointer to that audio file.&lt;br /&gt;
&lt;br /&gt;
The reference pointer is known as &amp;lt;code&amp;gt;sounds.json&amp;lt;/code&amp;gt; which should be created at &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;assets/&amp;lt;modid&amp;gt;/sounds.json&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;. This JSON defines resource names to point to the audio files added by a specific mod. The only thing necessary to define a sound is by creating an object, naming it, and then defining the location of the sound within a list.&lt;br /&gt;
&lt;br /&gt;
By default, the only supported audio format is [https://xiph.org/vorbis/ Ogg Vorbis] represented by the extension &amp;lt;code&amp;gt;.ogg&amp;lt;/code&amp;gt;. The file &amp;lt;code&amp;gt;namespace:path&amp;lt;/code&amp;gt; when referenced in the JSON will be located within &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;assets/&amp;lt;namespace&amp;gt;/sounds/&amp;lt;path&amp;gt;.ogg&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;.&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;example_sound&amp;quot;: {&lt;br /&gt;
    &amp;quot;sounds&amp;quot;: [ &amp;quot;examplemod:example_sound_file&amp;quot; ]&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Using the example above, it creates a sound called &amp;lt;code&amp;gt;example_sound&amp;lt;/code&amp;gt; and references the file &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;assets/&amp;lt;modid&amp;gt;/sounds/example_sound_file.ogg&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;.  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{{Tip/Danger | Due to [https://bugs.mojang.com/browse/MC-146721 the way OpenAL (Minecraft's sound engine) works], for your sound to have attenuation - that is, for it to get quieter as the player walks away, it absolutely MUST be mono (have one audio channel).  &lt;br /&gt;
&lt;br /&gt;
Stereo sounds are always played at the '''player's''' location, making them ideal for ambient sounds and background music.&lt;br /&gt;
&lt;br /&gt;
}}  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Instead of being constructed as a list of strings, each entry could also be an object which allows a greater control over what and how it is played.&lt;br /&gt;
&lt;br /&gt;
Here are some variables that could be defined:&lt;br /&gt;
{| class=&amp;quot;wikitable sortable&amp;quot; border=1&lt;br /&gt;
!Parameter !!Description &lt;br /&gt;
|-&lt;br /&gt;
|   name   ||  Sets the path to the sound file excluding the &amp;lt;code&amp;gt;.ogg&amp;lt;/code&amp;gt; extension. &lt;br /&gt;
|-&lt;br /&gt;
|   stream   ||  Determines whether the sound should be streamed from the file. When true, it reduces the amount of lag from loading a large file; however, it only allows four instances of the sound to be played at once. &lt;br /&gt;
|-&lt;br /&gt;
|   volume   ||  A value between 0 and 1 to determine the volume of the sound played. &lt;br /&gt;
|-&lt;br /&gt;
|}&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;example_sound&amp;quot;: {&lt;br /&gt;
    &amp;quot;sounds&amp;quot;: [ &amp;quot;examplemod:example_sound_file&amp;quot; ]&lt;br /&gt;
  },&lt;br /&gt;
  &amp;quot;example_sound_complex&amp;quot;: {&lt;br /&gt;
    &amp;quot;sounds&amp;quot;:&lt;br /&gt;
    [&lt;br /&gt;
      {&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;examplemod:complex/example_complex&amp;quot;,&lt;br /&gt;
        &amp;quot;pitch&amp;quot;: 0.6,&lt;br /&gt;
        &amp;quot;stream&amp;quot;: true&lt;br /&gt;
      }&lt;br /&gt;
    ]&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now there is a new sound within our JSON called &amp;lt;code&amp;gt;example_sound_complex&amp;lt;/code&amp;gt;. This points to the audio file at &amp;lt;code&amp;gt;assets/examplemod/sounds/complex/example_complex.json&amp;lt;/code&amp;gt;. The sound's pitch is lowered to 0.6 of its original value. The &amp;lt;code&amp;gt;stream&amp;lt;/code&amp;gt; parameter is also set to true.&lt;br /&gt;
&lt;br /&gt;
There are many more parameters that can give greater control on how sounds are played. However, this is left as an exercise to the reader to try and construct with the [https://minecraft.gamepedia.com/Sounds.json wiki].&lt;br /&gt;
&lt;br /&gt;
== Creating &amp;lt;code&amp;gt;SoundEvent&amp;lt;/code&amp;gt;s ==&lt;br /&gt;
&lt;br /&gt;
A &amp;lt;code&amp;gt;sounds.json&amp;lt;/code&amp;gt; left in its current state would only be defined in-game. There is currently no way to reference the sound within a mod. To do this, we utilize the &amp;lt;code&amp;gt;SoundEvent&amp;lt;/code&amp;gt; class. Each &amp;lt;code&amp;gt;SoundEvent&amp;lt;/code&amp;gt; class holds a &amp;lt;code&amp;gt;ResourceLocation&amp;lt;/code&amp;gt; to reference a sound pointer defined in the &amp;lt;code&amp;gt;sounds.json&amp;lt;/code&amp;gt; file. The &amp;lt;code&amp;gt;sounds.json&amp;lt;/code&amp;gt; file used is determined by the namespace or the resource location passed into the class.&lt;br /&gt;
&lt;br /&gt;
For example, to reference &amp;lt;code&amp;gt;example_complex.ogg&amp;lt;/code&amp;gt;, you would store the reference name (e.g. &amp;lt;code&amp;gt;example_sound_complex&amp;lt;/code&amp;gt;) within a &amp;lt;code&amp;gt;new SoundEvent(new ResourceLocation(&amp;quot;examplemod&amp;quot;, &amp;quot;example_sound_complex&amp;quot;))&amp;lt;/code&amp;gt;. This will locate &amp;lt;code&amp;gt;assets/examplemod/sounds.json&amp;lt;/code&amp;gt; and try to find an &amp;lt;code&amp;gt;example_sound_complex&amp;lt;/code&amp;gt; object nested within it.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;SoundEvent&amp;lt;/code&amp;gt;s must be [[Registration|registered]] to be referenced in code. &lt;br /&gt;
&lt;br /&gt;
== Playing Sounds ==&lt;br /&gt;
&lt;br /&gt;
Vanilla has lots of methods for playing sounds that can be used in different scenarios.&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;code&amp;gt;Level&amp;lt;/code&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
# &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;playSound(Player, BlockPos, SoundEvent, SoundCategory, volume, pitch)&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
#*Simply forwards to overload (2), adding 0.5 to each coordinate of the BlockPos given.&lt;br /&gt;
# &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;playSound(Player, double x, double y, double z, SoundEvent, SoundCategory, volume, pitch)&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
#* &amp;lt;code&amp;gt;Client Behavior&amp;lt;/code&amp;gt;: If the passed in player is the client player, plays the sound event to the client player.&lt;br /&gt;
#* &amp;lt;code&amp;gt;Server Behavior&amp;lt;/code&amp;gt;: Plays the sound event to everyone nearby except the passed in player. Player can be &amp;lt;code&amp;gt;null&amp;lt;/code&amp;gt;.&lt;br /&gt;
#* &amp;lt;code&amp;gt;Usage&amp;lt;/code&amp;gt;: The correspondence between the behaviors implies that these two methods are to be called from some player-initiated code that will be run on both logical sides at the same time - the logical client handles playing it to the user and the logical server handles everyone else hearing it without re-playing it to the original user. They can also be used to play any sound in general at any position server-side by calling it on the logical server and passing in a &amp;lt;code&amp;gt;null&amp;lt;/code&amp;gt; player, thus letting everyone hear it.&lt;br /&gt;
# &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;playSound(double x, double y, double z, SoundEvent, SoundCategory, volume, pitch, distanceDelay)&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
#* &amp;lt;code&amp;gt;Client Behavior&amp;lt;/code&amp;gt;: Just plays the sound event in the client level. If distanceDelay is true, then delays the sound based on how far it is from the player.&lt;br /&gt;
#* &amp;lt;code&amp;gt;Server Behavior&amp;lt;/code&amp;gt;: Does nothing.&lt;br /&gt;
#* &amp;lt;code&amp;gt;Usage&amp;lt;/code&amp;gt;: This method only works client-side, and thus is useful for sounds sent in custom packets, or other client-only effect-type sounds. Used for thunder.&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;code&amp;gt;ClientLevel&amp;lt;/code&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
# &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;playSound(BlockPos, SoundEvent, SoundCategory, volume, pitch, distanceDelay)&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
#* Simply forwards to &amp;lt;code&amp;gt;Level&amp;lt;/code&amp;gt;‘s overload (3), adding 0.5 to each coordinate of the &amp;lt;code&amp;gt;BlockPos&amp;lt;/code&amp;gt; given.&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;code&amp;gt;Entity&amp;lt;/code&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
# &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;playSound(SoundEvent, volume, pitch)&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
#* Forwards to &amp;lt;code&amp;gt;LEvel&amp;lt;/code&amp;gt;‘s overload (2), passing in &amp;lt;code&amp;gt;null&amp;lt;/code&amp;gt; as the player.&lt;br /&gt;
#* &amp;lt;code&amp;gt;Client Behavior&amp;lt;/code&amp;gt;: Does nothing.&lt;br /&gt;
#* &amp;lt;code&amp;gt;Server Behavior&amp;lt;/code&amp;gt;: Plays the sound event to everyone at this entity’s position.&lt;br /&gt;
#* &amp;lt;code&amp;gt;Usage&amp;lt;/code&amp;gt;: Emitting any sound from any non-player entity server-side.&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;code&amp;gt;Player&amp;lt;/code&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
# &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;playSound(SoundEvent, volume, pitch)&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt; (overriding the one in &amp;lt;code&amp;gt;[[Sounds#Entity|Entity]]&amp;lt;/code&amp;gt;)&lt;br /&gt;
#* Forwards to &amp;lt;code&amp;gt;Level&amp;lt;/code&amp;gt;‘s overload (2), passing in &amp;lt;code&amp;gt;this&amp;lt;/code&amp;gt; as the player.&lt;br /&gt;
#* &amp;lt;code&amp;gt;Client Behavior&amp;lt;/code&amp;gt;: Does nothing, see override in &amp;lt;code&amp;gt;[[Sounds#localplayer|LocalPlayer]]&amp;lt;/code&amp;gt;.&lt;br /&gt;
#* &amp;lt;code&amp;gt;Server Behavior&amp;lt;/code&amp;gt;: Plays the sound to everyone nearby &amp;lt;code&amp;gt;except&amp;lt;/code&amp;gt; this player.&lt;br /&gt;
#* &amp;lt;code&amp;gt;Usage&amp;lt;/code&amp;gt;: See &amp;lt;code&amp;gt;[[Sounds#localplayer|LocalPlayer]]&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;code&amp;gt;LocalPlayer&amp;lt;/code&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
# &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;playSound(SoundEvent, volume, pitch)&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt; (overriding the one in &amp;lt;code&amp;gt;[[Sounds#player|Player]&amp;lt;/code&amp;gt;)&lt;br /&gt;
#* Forwards to &amp;lt;code&amp;gt;Level&amp;lt;/code&amp;gt;‘s overload (2), passing in &amp;lt;code&amp;gt;this&amp;lt;/code&amp;gt; as the player.&lt;br /&gt;
#* &amp;lt;code&amp;gt;Client Behavior&amp;lt;/code&amp;gt;: Just plays the Sound Event.&lt;br /&gt;
#* &amp;lt;code&amp;gt;Server Behavior&amp;lt;/code&amp;gt;: Method is client-only.&lt;br /&gt;
#* &amp;lt;code&amp;gt;Usage&amp;lt;/code&amp;gt;: Just like the ones in &amp;lt;code&amp;gt;Level&amp;lt;/code&amp;gt;, these two overrides in the player classes seem to be for code that runs together on both sides. The client handles playing the sound to the user, while the server handles everyone else hearing it without re-playing to the original user.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Game Effects]]&lt;/div&gt;</summary>
		<author><name>Curle</name></author>
	</entry>
	<entry>
		<id>https://forge.gemwire.uk/index.php?title=Dynamic_Loot_Modification&amp;diff=2829</id>
		<title>Dynamic Loot Modification</title>
		<link rel="alternate" type="text/html" href="https://forge.gemwire.uk/index.php?title=Dynamic_Loot_Modification&amp;diff=2829"/>
		<updated>2021-07-30T13:57:30Z</updated>

		<summary type="html">&lt;p&gt;Curle: Formatting adjust?&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Global Loot Modifiers are a data-driven method of handling modification of harvested drops without the need to overwrite dozens to hundreds of vanilla loot tables or to handle effects that would require interactions with another mod's loot tables without knowing what mods may be loaded. Global Loot Modifiers are also stacking, rather than last-load-wins as modifications to loot tables would be.&lt;br /&gt;
&lt;br /&gt;
== Registering a Global Loot Modifier ==&lt;br /&gt;
&lt;br /&gt;
You will need 3 things:&lt;br /&gt;
# Create a &amp;lt;code&amp;gt;global_loot_modifiers.json&amp;lt;/code&amp;gt; file at &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;/data/forge/loot_modifiers/&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
#* This will tell Forge about your modifiers and works similar to [[Tags|tags]].&lt;br /&gt;
# A serialized json representing your modifier at &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;/data/&amp;lt;modID&amp;gt;/loot_modifiers/&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
#* This will contain all of the data about your modification and allows data packs to tweak your effect.&lt;br /&gt;
# A class that extends &amp;lt;code&amp;gt;LootModifier&amp;lt;/code&amp;gt;&lt;br /&gt;
#* The operational code that makes your modifier work and associated serializer.&lt;br /&gt;
&lt;br /&gt;
Finally, the serializer for your operational class is [[Registration|registered]] as any other &amp;lt;code&amp;gt;ForgeRegistryEntry&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==The global_loot_modifiers.json==&lt;br /&gt;
All you need to add here are the file names of your loot modifiers.&lt;br /&gt;
These are the names of the json files you have made in the loot_modifiers folder, in ResourceLocation 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;replace&amp;quot;: false,&lt;br /&gt;
  &amp;quot;entries&amp;quot;: [&lt;br /&gt;
    &amp;quot;global_loot_test:silk_touch_bamboo&amp;quot;,&lt;br /&gt;
    &amp;quot;global_loot_test:smelting&amp;quot;,&lt;br /&gt;
    &amp;quot;global_loot_test:wheat_harvest&amp;quot;&lt;br /&gt;
  ]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;replace&amp;lt;/code&amp;gt; causes the cache of modifiers to be cleared fully when this asset loads (mods are loaded in an order that may be specified by a data pack). For modders you will want to use &amp;lt;code&amp;gt;false&amp;lt;/code&amp;gt; while data pack makers may want to specify their overrides with &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;entries&amp;lt;/code&amp;gt; is an ''ordered list'' of the modifiers that will be loaded. Any modifier that is not listed will not be loaded and the ones listed are called in the order listed. This is primarily relevant to data pack makers for resolving conflicts between modifiers from separate mods.&lt;br /&gt;
&lt;br /&gt;
== The serialized json ==&lt;br /&gt;
&lt;br /&gt;
This file contains all of the potential variables related to your modifier, including the conditions that must be met prior to modifying any loot as well as any other parameters your modifier might have. Avoid hard-coded values where ever possible so that data pack makers can adjust balance if they wish to.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;json&amp;quot;&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;conditions&amp;quot;: [&lt;br /&gt;
    {&lt;br /&gt;
      &amp;quot;condition&amp;quot;: &amp;quot;minecraft:match_tool&amp;quot;,&lt;br /&gt;
      &amp;quot;predicate&amp;quot;: {&lt;br /&gt;
        &amp;quot;item&amp;quot;: &amp;quot;minecraft:shears&amp;quot;&lt;br /&gt;
      }&lt;br /&gt;
    },&lt;br /&gt;
    {&lt;br /&gt;
      &amp;quot;condition&amp;quot;: &amp;quot;block_state_property&amp;quot;,&lt;br /&gt;
      &amp;quot;block&amp;quot;:&amp;quot;minecraft:wheat&amp;quot;&lt;br /&gt;
    }&lt;br /&gt;
  ],&lt;br /&gt;
  &amp;quot;seedItem&amp;quot;: &amp;quot;minecraft:wheat_seeds&amp;quot;,&lt;br /&gt;
  &amp;quot;numSeeds&amp;quot;: 3,&lt;br /&gt;
  &amp;quot;replacement&amp;quot;: &amp;quot;minecraft:wheat&amp;quot;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the above example, the modification only happens if the player harvests wheat when using shears (specified by the two &amp;lt;code&amp;gt;conditions&amp;lt;/code&amp;gt; which are automatically &amp;lt;code&amp;gt;AND&amp;lt;/code&amp;gt;ed together). The &amp;lt;code&amp;gt;seedsItem&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;numSeeds&amp;lt;/code&amp;gt; values are then used to count how many seeds were generated by the vanilla loot table, and if matched, are substituted for an additional &amp;lt;code&amp;gt;replacement&amp;lt;/code&amp;gt; item instead. The operation code will be shown below.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{{Tip|&amp;lt;code&amp;gt;conditions&amp;lt;/code&amp;gt; is the only object needed by the system specification, everything else is the mod maker's data. &lt;br /&gt;
 &lt;br /&gt;
&amp;lt;code&amp;gt;seedItem&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;numSeeds&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;replacement&amp;lt;/code&amp;gt; are NOT standard elements of Global Loot Modifiers.  &lt;br /&gt;
&lt;br /&gt;
They are deserialized manually in the next section.}}&lt;br /&gt;
&lt;br /&gt;
== The LootModifier Subclass ==&lt;br /&gt;
&lt;br /&gt;
You will also need a static child class that extends &amp;lt;code&amp;gt;GlobalLootModifierSerializer&amp;lt;T&amp;gt;&amp;lt;/code&amp;gt; where &amp;lt;code&amp;gt;T&amp;lt;/code&amp;gt; is your LootModifier subclass in order to deserialize your json data file into operational code.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
private static class WheatSeedsConverterModifier extends LootModifier {&lt;br /&gt;
	private final int numSeedsToConvert;&lt;br /&gt;
	private final Item itemToCheck;&lt;br /&gt;
	private final Item itemReward;&lt;br /&gt;
	public WheatSeedsConverterModifier(ILootCondition[] conditionsIn, int numSeeds, Item itemCheck, Item reward) {&lt;br /&gt;
		super(conditionsIn);&lt;br /&gt;
		numSeedsToConvert = numSeeds;&lt;br /&gt;
		itemToCheck = itemCheck;&lt;br /&gt;
		itemReward = reward;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	@Nonnull&lt;br /&gt;
	@Override&lt;br /&gt;
	public List&amp;lt;ItemStack&amp;gt; doApply(List&amp;lt;ItemStack&amp;gt; generatedLoot, LootContext context) {&lt;br /&gt;
		/*&lt;br /&gt;
		* Additional conditions can be checked, though as much as possible should be parameterized via JSON data.&lt;br /&gt;
		* It is better to write a new ILootCondition implementation than to do things here.&lt;br /&gt;
		*/&lt;br /&gt;
		int numSeeds = 0;&lt;br /&gt;
		for(ItemStack stack : generatedLoot) {&lt;br /&gt;
			if(stack.getItem() == itemToCheck)&lt;br /&gt;
				numSeeds+=stack.getCount();&lt;br /&gt;
		}&lt;br /&gt;
		if(numSeeds &amp;gt;= numSeedsToConvert) {&lt;br /&gt;
			generatedLoot.removeIf(x -&amp;gt; x.getItem() == itemToCheck);&lt;br /&gt;
			generatedLoot.add(new ItemStack(itemReward, (numSeeds/numSeedsToConvert)));&lt;br /&gt;
			numSeeds = numSeeds%numSeedsToConvert;&lt;br /&gt;
			if(numSeeds &amp;gt; 0)&lt;br /&gt;
				generatedLoot.add(new ItemStack(itemToCheck, numSeeds));&lt;br /&gt;
		}&lt;br /&gt;
		return generatedLoot;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	private static class Serializer extends GlobalLootModifierSerializer&amp;lt;WheatSeedsConverterModifier&amp;gt; {&lt;br /&gt;
&lt;br /&gt;
		@Override&lt;br /&gt;
		public WheatSeedsConverterModifier read(ResourceLocation name, JsonObject object, ILootCondition[] conditionsIn) {&lt;br /&gt;
			int numSeeds = JSONUtils.getInt(object, &amp;quot;numSeeds&amp;quot;);&lt;br /&gt;
			Item seed = ForgeRegistries.ITEMS.getValue(new ResourceLocation((JSONUtils.getString(object, &amp;quot;seedItem&amp;quot;))));&lt;br /&gt;
			Item wheat = ForgeRegistries.ITEMS.getValue(new ResourceLocation(JSONUtils.getString(object, &amp;quot;replacement&amp;quot;)));&lt;br /&gt;
			return new WheatSeedsConverterModifier(conditionsIn, numSeeds, seed, wheat);&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The critical portion is the &amp;lt;code&amp;gt;doApply&amp;lt;/code&amp;gt; method.&lt;br /&gt;
&lt;br /&gt;
This method is only called if the &amp;lt;code&amp;gt;conditions&amp;lt;/code&amp;gt; specified return &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt; and the modder is now able to make the modifications they desire. In this case we can see that the number of &amp;lt;code&amp;gt;itemToCheck&amp;lt;/code&amp;gt; meets or exceeds the &amp;lt;code&amp;gt;numSeedsToConvert&amp;lt;/code&amp;gt; before modifying the list by adding an &amp;lt;code&amp;gt;itemReward&amp;lt;/code&amp;gt; and removing any excess &amp;lt;code&amp;gt;itemToCheck&amp;lt;/code&amp;gt; stacks, matching the previously mentioned effects: When a wheat block is harvested with shears, if enough seeds are generated as loot, they are converted to additional wheat instead.&lt;br /&gt;
&lt;br /&gt;
Also take note of the &amp;lt;code&amp;gt;read&amp;lt;/code&amp;gt; method in the serializer. The conditions are already deserialized for you and if you have no other data, simply &amp;lt;code&amp;gt;return new MyModifier(conditionsIn)&amp;lt;/code&amp;gt;. However, the full &amp;lt;code&amp;gt;JsonObject&amp;lt;/code&amp;gt; is available if needed.&lt;br /&gt;
&lt;br /&gt;
Additional [https://github.com/MinecraftForge/MinecraftForge/blob/1.15.x/src/test/java/net/minecraftforge/debug/gameplay/loot/GlobalLootModifiersTest.java examples] can be found on the Forge Git repository, including silk touch and smelting effects.&lt;/div&gt;</summary>
		<author><name>Curle</name></author>
	</entry>
	<entry>
		<id>https://forge.gemwire.uk/index.php?title=Dynamic_Loot_Modification&amp;diff=2828</id>
		<title>Dynamic Loot Modification</title>
		<link rel="alternate" type="text/html" href="https://forge.gemwire.uk/index.php?title=Dynamic_Loot_Modification&amp;diff=2828"/>
		<updated>2021-07-30T13:57:09Z</updated>

		<summary type="html">&lt;p&gt;Curle: Formatting adjust?&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Global Loot Modifiers are a data-driven method of handling modification of harvested drops without the need to overwrite dozens to hundreds of vanilla loot tables or to handle effects that would require interactions with another mod's loot tables without knowing what mods may be loaded. Global Loot Modifiers are also stacking, rather than last-load-wins as modifications to loot tables would be.&lt;br /&gt;
&lt;br /&gt;
== Registering a Global Loot Modifier ==&lt;br /&gt;
&lt;br /&gt;
You will need 3 things:&lt;br /&gt;
# Create a &amp;lt;code&amp;gt;global_loot_modifiers.json&amp;lt;/code&amp;gt; file at &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;/data/forge/loot_modifiers/&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
#* This will tell Forge about your modifiers and works similar to [[Tags|tags]].&lt;br /&gt;
# A serialized json representing your modifier at &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;/data/&amp;lt;modID&amp;gt;/loot_modifiers/&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
#* This will contain all of the data about your modification and allows data packs to tweak your effect.&lt;br /&gt;
# A class that extends &amp;lt;code&amp;gt;LootModifier&amp;lt;/code&amp;gt;&lt;br /&gt;
#* The operational code that makes your modifier work and associated serializer.&lt;br /&gt;
&lt;br /&gt;
Finally, the serializer for your operational class is [[Registration|registered]] as any other &amp;lt;code&amp;gt;ForgeRegistryEntry&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==The global_loot_modifiers.json==&lt;br /&gt;
All you need to add here are the file names of your loot modifiers.&lt;br /&gt;
These are the names of the json files you have made in the loot_modifiers folder, in ResourceLocation 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;replace&amp;quot;: false,&lt;br /&gt;
  &amp;quot;entries&amp;quot;: [&lt;br /&gt;
    &amp;quot;global_loot_test:silk_touch_bamboo&amp;quot;,&lt;br /&gt;
    &amp;quot;global_loot_test:smelting&amp;quot;,&lt;br /&gt;
    &amp;quot;global_loot_test:wheat_harvest&amp;quot;&lt;br /&gt;
  ]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;replace&amp;lt;/code&amp;gt; causes the cache of modifiers to be cleared fully when this asset loads (mods are loaded in an order that may be specified by a data pack). For modders you will want to use &amp;lt;code&amp;gt;false&amp;lt;/code&amp;gt; while data pack makers may want to specify their overrides with &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;entries&amp;lt;/code&amp;gt; is an ''ordered list'' of the modifiers that will be loaded. Any modifier that is not listed will not be loaded and the ones listed are called in the order listed. This is primarily relevant to data pack makers for resolving conflicts between modifiers from separate mods.&lt;br /&gt;
&lt;br /&gt;
== The serialized json ==&lt;br /&gt;
&lt;br /&gt;
This file contains all of the potential variables related to your modifier, including the conditions that must be met prior to modifying any loot as well as any other parameters your modifier might have. Avoid hard-coded values where ever possible so that data pack makers can adjust balance if they wish to.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;json&amp;quot;&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;conditions&amp;quot;: [&lt;br /&gt;
    {&lt;br /&gt;
      &amp;quot;condition&amp;quot;: &amp;quot;minecraft:match_tool&amp;quot;,&lt;br /&gt;
      &amp;quot;predicate&amp;quot;: {&lt;br /&gt;
        &amp;quot;item&amp;quot;: &amp;quot;minecraft:shears&amp;quot;&lt;br /&gt;
      }&lt;br /&gt;
    },&lt;br /&gt;
    {&lt;br /&gt;
      &amp;quot;condition&amp;quot;: &amp;quot;block_state_property&amp;quot;,&lt;br /&gt;
      &amp;quot;block&amp;quot;:&amp;quot;minecraft:wheat&amp;quot;&lt;br /&gt;
    }&lt;br /&gt;
  ],&lt;br /&gt;
  &amp;quot;seedItem&amp;quot;: &amp;quot;minecraft:wheat_seeds&amp;quot;,&lt;br /&gt;
  &amp;quot;numSeeds&amp;quot;: 3,&lt;br /&gt;
  &amp;quot;replacement&amp;quot;: &amp;quot;minecraft:wheat&amp;quot;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the above example, the modification only happens if the player harvests wheat when using shears (specified by the two &amp;lt;code&amp;gt;conditions&amp;lt;/code&amp;gt; which are automatically &amp;lt;code&amp;gt;AND&amp;lt;/code&amp;gt;ed together). The &amp;lt;code&amp;gt;seedsItem&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;numSeeds&amp;lt;/code&amp;gt; values are then used to count how many seeds were generated by the vanilla loot table, and if matched, are substituted for an additional &amp;lt;code&amp;gt;replacement&amp;lt;/code&amp;gt; item instead. The operation code will be shown below.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{{Tip|&amp;lt;code&amp;gt;conditions&amp;lt;/code&amp;gt; is the only object needed by the system specification, everything else is the mod maker's data.  &lt;br /&gt;
&amp;lt;code&amp;gt;seedItem&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;numSeeds&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;replacement&amp;lt;/code&amp;gt; are NOT standard elements of Global Loot Modifiers.  &lt;br /&gt;
They are deserialized manually in the next section.}}&lt;br /&gt;
&lt;br /&gt;
== The LootModifier Subclass ==&lt;br /&gt;
&lt;br /&gt;
You will also need a static child class that extends &amp;lt;code&amp;gt;GlobalLootModifierSerializer&amp;lt;T&amp;gt;&amp;lt;/code&amp;gt; where &amp;lt;code&amp;gt;T&amp;lt;/code&amp;gt; is your LootModifier subclass in order to deserialize your json data file into operational code.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
private static class WheatSeedsConverterModifier extends LootModifier {&lt;br /&gt;
	private final int numSeedsToConvert;&lt;br /&gt;
	private final Item itemToCheck;&lt;br /&gt;
	private final Item itemReward;&lt;br /&gt;
	public WheatSeedsConverterModifier(ILootCondition[] conditionsIn, int numSeeds, Item itemCheck, Item reward) {&lt;br /&gt;
		super(conditionsIn);&lt;br /&gt;
		numSeedsToConvert = numSeeds;&lt;br /&gt;
		itemToCheck = itemCheck;&lt;br /&gt;
		itemReward = reward;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	@Nonnull&lt;br /&gt;
	@Override&lt;br /&gt;
	public List&amp;lt;ItemStack&amp;gt; doApply(List&amp;lt;ItemStack&amp;gt; generatedLoot, LootContext context) {&lt;br /&gt;
		/*&lt;br /&gt;
		* Additional conditions can be checked, though as much as possible should be parameterized via JSON data.&lt;br /&gt;
		* It is better to write a new ILootCondition implementation than to do things here.&lt;br /&gt;
		*/&lt;br /&gt;
		int numSeeds = 0;&lt;br /&gt;
		for(ItemStack stack : generatedLoot) {&lt;br /&gt;
			if(stack.getItem() == itemToCheck)&lt;br /&gt;
				numSeeds+=stack.getCount();&lt;br /&gt;
		}&lt;br /&gt;
		if(numSeeds &amp;gt;= numSeedsToConvert) {&lt;br /&gt;
			generatedLoot.removeIf(x -&amp;gt; x.getItem() == itemToCheck);&lt;br /&gt;
			generatedLoot.add(new ItemStack(itemReward, (numSeeds/numSeedsToConvert)));&lt;br /&gt;
			numSeeds = numSeeds%numSeedsToConvert;&lt;br /&gt;
			if(numSeeds &amp;gt; 0)&lt;br /&gt;
				generatedLoot.add(new ItemStack(itemToCheck, numSeeds));&lt;br /&gt;
		}&lt;br /&gt;
		return generatedLoot;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	private static class Serializer extends GlobalLootModifierSerializer&amp;lt;WheatSeedsConverterModifier&amp;gt; {&lt;br /&gt;
&lt;br /&gt;
		@Override&lt;br /&gt;
		public WheatSeedsConverterModifier read(ResourceLocation name, JsonObject object, ILootCondition[] conditionsIn) {&lt;br /&gt;
			int numSeeds = JSONUtils.getInt(object, &amp;quot;numSeeds&amp;quot;);&lt;br /&gt;
			Item seed = ForgeRegistries.ITEMS.getValue(new ResourceLocation((JSONUtils.getString(object, &amp;quot;seedItem&amp;quot;))));&lt;br /&gt;
			Item wheat = ForgeRegistries.ITEMS.getValue(new ResourceLocation(JSONUtils.getString(object, &amp;quot;replacement&amp;quot;)));&lt;br /&gt;
			return new WheatSeedsConverterModifier(conditionsIn, numSeeds, seed, wheat);&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The critical portion is the &amp;lt;code&amp;gt;doApply&amp;lt;/code&amp;gt; method.&lt;br /&gt;
&lt;br /&gt;
This method is only called if the &amp;lt;code&amp;gt;conditions&amp;lt;/code&amp;gt; specified return &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt; and the modder is now able to make the modifications they desire. In this case we can see that the number of &amp;lt;code&amp;gt;itemToCheck&amp;lt;/code&amp;gt; meets or exceeds the &amp;lt;code&amp;gt;numSeedsToConvert&amp;lt;/code&amp;gt; before modifying the list by adding an &amp;lt;code&amp;gt;itemReward&amp;lt;/code&amp;gt; and removing any excess &amp;lt;code&amp;gt;itemToCheck&amp;lt;/code&amp;gt; stacks, matching the previously mentioned effects: When a wheat block is harvested with shears, if enough seeds are generated as loot, they are converted to additional wheat instead.&lt;br /&gt;
&lt;br /&gt;
Also take note of the &amp;lt;code&amp;gt;read&amp;lt;/code&amp;gt; method in the serializer. The conditions are already deserialized for you and if you have no other data, simply &amp;lt;code&amp;gt;return new MyModifier(conditionsIn)&amp;lt;/code&amp;gt;. However, the full &amp;lt;code&amp;gt;JsonObject&amp;lt;/code&amp;gt; is available if needed.&lt;br /&gt;
&lt;br /&gt;
Additional [https://github.com/MinecraftForge/MinecraftForge/blob/1.15.x/src/test/java/net/minecraftforge/debug/gameplay/loot/GlobalLootModifiersTest.java examples] can be found on the Forge Git repository, including silk touch and smelting effects.&lt;/div&gt;</summary>
		<author><name>Curle</name></author>
	</entry>
	<entry>
		<id>https://forge.gemwire.uk/index.php?title=Dynamic_Loot_Modification&amp;diff=2827</id>
		<title>Dynamic Loot Modification</title>
		<link rel="alternate" type="text/html" href="https://forge.gemwire.uk/index.php?title=Dynamic_Loot_Modification&amp;diff=2827"/>
		<updated>2021-07-30T13:55:58Z</updated>

		<summary type="html">&lt;p&gt;Curle: Move qualification into a tip box.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Global Loot Modifiers are a data-driven method of handling modification of harvested drops without the need to overwrite dozens to hundreds of vanilla loot tables or to handle effects that would require interactions with another mod's loot tables without knowing what mods may be loaded. Global Loot Modifiers are also stacking, rather than last-load-wins as modifications to loot tables would be.&lt;br /&gt;
&lt;br /&gt;
== Registering a Global Loot Modifier ==&lt;br /&gt;
&lt;br /&gt;
You will need 3 things:&lt;br /&gt;
# Create a &amp;lt;code&amp;gt;global_loot_modifiers.json&amp;lt;/code&amp;gt; file at &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;/data/forge/loot_modifiers/&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
#* This will tell Forge about your modifiers and works similar to [[Tags|tags]].&lt;br /&gt;
# A serialized json representing your modifier at &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;/data/&amp;lt;modID&amp;gt;/loot_modifiers/&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
#* This will contain all of the data about your modification and allows data packs to tweak your effect.&lt;br /&gt;
# A class that extends &amp;lt;code&amp;gt;LootModifier&amp;lt;/code&amp;gt;&lt;br /&gt;
#* The operational code that makes your modifier work and associated serializer.&lt;br /&gt;
&lt;br /&gt;
Finally, the serializer for your operational class is [[Registration|registered]] as any other &amp;lt;code&amp;gt;ForgeRegistryEntry&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==The global_loot_modifiers.json==&lt;br /&gt;
All you need to add here are the file names of your loot modifiers.&lt;br /&gt;
These are the names of the json files you have made in the loot_modifiers folder, in ResourceLocation 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;replace&amp;quot;: false,&lt;br /&gt;
  &amp;quot;entries&amp;quot;: [&lt;br /&gt;
    &amp;quot;global_loot_test:silk_touch_bamboo&amp;quot;,&lt;br /&gt;
    &amp;quot;global_loot_test:smelting&amp;quot;,&lt;br /&gt;
    &amp;quot;global_loot_test:wheat_harvest&amp;quot;&lt;br /&gt;
  ]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;replace&amp;lt;/code&amp;gt; causes the cache of modifiers to be cleared fully when this asset loads (mods are loaded in an order that may be specified by a data pack). For modders you will want to use &amp;lt;code&amp;gt;false&amp;lt;/code&amp;gt; while data pack makers may want to specify their overrides with &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;entries&amp;lt;/code&amp;gt; is an ''ordered list'' of the modifiers that will be loaded. Any modifier that is not listed will not be loaded and the ones listed are called in the order listed. This is primarily relevant to data pack makers for resolving conflicts between modifiers from separate mods.&lt;br /&gt;
&lt;br /&gt;
== The serialized json ==&lt;br /&gt;
&lt;br /&gt;
This file contains all of the potential variables related to your modifier, including the conditions that must be met prior to modifying any loot as well as any other parameters your modifier might have. Avoid hard-coded values where ever possible so that data pack makers can adjust balance if they wish to.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;json&amp;quot;&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;conditions&amp;quot;: [&lt;br /&gt;
    {&lt;br /&gt;
      &amp;quot;condition&amp;quot;: &amp;quot;minecraft:match_tool&amp;quot;,&lt;br /&gt;
      &amp;quot;predicate&amp;quot;: {&lt;br /&gt;
        &amp;quot;item&amp;quot;: &amp;quot;minecraft:shears&amp;quot;&lt;br /&gt;
      }&lt;br /&gt;
    },&lt;br /&gt;
    {&lt;br /&gt;
      &amp;quot;condition&amp;quot;: &amp;quot;block_state_property&amp;quot;,&lt;br /&gt;
      &amp;quot;block&amp;quot;:&amp;quot;minecraft:wheat&amp;quot;&lt;br /&gt;
    }&lt;br /&gt;
  ],&lt;br /&gt;
  &amp;quot;seedItem&amp;quot;: &amp;quot;minecraft:wheat_seeds&amp;quot;,&lt;br /&gt;
  &amp;quot;numSeeds&amp;quot;: 3,&lt;br /&gt;
  &amp;quot;replacement&amp;quot;: &amp;quot;minecraft:wheat&amp;quot;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the above example, the modification only happens if the player harvests wheat when using shears (specified by the two &amp;lt;code&amp;gt;conditions&amp;lt;/code&amp;gt; which are automatically &amp;lt;code&amp;gt;AND&amp;lt;/code&amp;gt;ed together). The &amp;lt;code&amp;gt;seedsItem&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;numSeeds&amp;lt;/code&amp;gt; values are then used to count how many seeds were generated by the vanilla loot table, and if matched, are substituted for an additional &amp;lt;code&amp;gt;replacement&amp;lt;/code&amp;gt; item instead. The operation code will be shown below.&lt;br /&gt;
&lt;br /&gt;
{{Tip|&amp;lt;code&amp;gt;conditions&amp;lt;/code&amp;gt; is the only object needed by the system specification, everything else is the mod maker's data. &amp;lt;code&amp;gt;seedItem&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;numSeeds&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;replacement&amp;lt;/code&amp;gt; are NOT standard elements of Global Loot Modifiers.}}&lt;br /&gt;
&lt;br /&gt;
== The LootModifier Subclass ==&lt;br /&gt;
&lt;br /&gt;
You will also need a static child class that extends &amp;lt;code&amp;gt;GlobalLootModifierSerializer&amp;lt;T&amp;gt;&amp;lt;/code&amp;gt; where &amp;lt;code&amp;gt;T&amp;lt;/code&amp;gt; is your LootModifier subclass in order to deserialize your json data file into operational code.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
private static class WheatSeedsConverterModifier extends LootModifier {&lt;br /&gt;
	private final int numSeedsToConvert;&lt;br /&gt;
	private final Item itemToCheck;&lt;br /&gt;
	private final Item itemReward;&lt;br /&gt;
	public WheatSeedsConverterModifier(ILootCondition[] conditionsIn, int numSeeds, Item itemCheck, Item reward) {&lt;br /&gt;
		super(conditionsIn);&lt;br /&gt;
		numSeedsToConvert = numSeeds;&lt;br /&gt;
		itemToCheck = itemCheck;&lt;br /&gt;
		itemReward = reward;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	@Nonnull&lt;br /&gt;
	@Override&lt;br /&gt;
	public List&amp;lt;ItemStack&amp;gt; doApply(List&amp;lt;ItemStack&amp;gt; generatedLoot, LootContext context) {&lt;br /&gt;
		/*&lt;br /&gt;
		* Additional conditions can be checked, though as much as possible should be parameterized via JSON data.&lt;br /&gt;
		* It is better to write a new ILootCondition implementation than to do things here.&lt;br /&gt;
		*/&lt;br /&gt;
		int numSeeds = 0;&lt;br /&gt;
		for(ItemStack stack : generatedLoot) {&lt;br /&gt;
			if(stack.getItem() == itemToCheck)&lt;br /&gt;
				numSeeds+=stack.getCount();&lt;br /&gt;
		}&lt;br /&gt;
		if(numSeeds &amp;gt;= numSeedsToConvert) {&lt;br /&gt;
			generatedLoot.removeIf(x -&amp;gt; x.getItem() == itemToCheck);&lt;br /&gt;
			generatedLoot.add(new ItemStack(itemReward, (numSeeds/numSeedsToConvert)));&lt;br /&gt;
			numSeeds = numSeeds%numSeedsToConvert;&lt;br /&gt;
			if(numSeeds &amp;gt; 0)&lt;br /&gt;
				generatedLoot.add(new ItemStack(itemToCheck, numSeeds));&lt;br /&gt;
		}&lt;br /&gt;
		return generatedLoot;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	private static class Serializer extends GlobalLootModifierSerializer&amp;lt;WheatSeedsConverterModifier&amp;gt; {&lt;br /&gt;
&lt;br /&gt;
		@Override&lt;br /&gt;
		public WheatSeedsConverterModifier read(ResourceLocation name, JsonObject object, ILootCondition[] conditionsIn) {&lt;br /&gt;
			int numSeeds = JSONUtils.getInt(object, &amp;quot;numSeeds&amp;quot;);&lt;br /&gt;
			Item seed = ForgeRegistries.ITEMS.getValue(new ResourceLocation((JSONUtils.getString(object, &amp;quot;seedItem&amp;quot;))));&lt;br /&gt;
			Item wheat = ForgeRegistries.ITEMS.getValue(new ResourceLocation(JSONUtils.getString(object, &amp;quot;replacement&amp;quot;)));&lt;br /&gt;
			return new WheatSeedsConverterModifier(conditionsIn, numSeeds, seed, wheat);&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The critical portion is the &amp;lt;code&amp;gt;doApply&amp;lt;/code&amp;gt; method.&lt;br /&gt;
&lt;br /&gt;
This method is only called if the &amp;lt;code&amp;gt;conditions&amp;lt;/code&amp;gt; specified return &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt; and the modder is now able to make the modifications they desire. In this case we can see that the number of &amp;lt;code&amp;gt;itemToCheck&amp;lt;/code&amp;gt; meets or exceeds the &amp;lt;code&amp;gt;numSeedsToConvert&amp;lt;/code&amp;gt; before modifying the list by adding an &amp;lt;code&amp;gt;itemReward&amp;lt;/code&amp;gt; and removing any excess &amp;lt;code&amp;gt;itemToCheck&amp;lt;/code&amp;gt; stacks, matching the previously mentioned effects: When a wheat block is harvested with shears, if enough seeds are generated as loot, they are converted to additional wheat instead.&lt;br /&gt;
&lt;br /&gt;
Also take note of the &amp;lt;code&amp;gt;read&amp;lt;/code&amp;gt; method in the serializer. The conditions are already deserialized for you and if you have no other data, simply &amp;lt;code&amp;gt;return new MyModifier(conditionsIn)&amp;lt;/code&amp;gt;. However, the full &amp;lt;code&amp;gt;JsonObject&amp;lt;/code&amp;gt; is available if needed.&lt;br /&gt;
&lt;br /&gt;
Additional [https://github.com/MinecraftForge/MinecraftForge/blob/1.15.x/src/test/java/net/minecraftforge/debug/gameplay/loot/GlobalLootModifiersTest.java examples] can be found on the Forge Git repository, including silk touch and smelting effects.&lt;/div&gt;</summary>
		<author><name>Curle</name></author>
	</entry>
	<entry>
		<id>https://forge.gemwire.uk/index.php?title=Dynamic_Loot_Modification&amp;diff=2826</id>
		<title>Dynamic Loot Modification</title>
		<link rel="alternate" type="text/html" href="https://forge.gemwire.uk/index.php?title=Dynamic_Loot_Modification&amp;diff=2826"/>
		<updated>2021-07-30T13:53:15Z</updated>

		<summary type="html">&lt;p&gt;Curle: Qualify where seedItem, numSeeds and replacement come from.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Global Loot Modifiers are a data-driven method of handling modification of harvested drops without the need to overwrite dozens to hundreds of vanilla loot tables or to handle effects that would require interactions with another mod's loot tables without knowing what mods may be loaded. Global Loot Modifiers are also stacking, rather than last-load-wins as modifications to loot tables would be.&lt;br /&gt;
&lt;br /&gt;
== Registering a Global Loot Modifier ==&lt;br /&gt;
&lt;br /&gt;
You will need 3 things:&lt;br /&gt;
# Create a &amp;lt;code&amp;gt;global_loot_modifiers.json&amp;lt;/code&amp;gt; file at &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;/data/forge/loot_modifiers/&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
#* This will tell Forge about your modifiers and works similar to [[Tags|tags]].&lt;br /&gt;
# A serialized json representing your modifier at &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;/data/&amp;lt;modID&amp;gt;/loot_modifiers/&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
#* This will contain all of the data about your modification and allows data packs to tweak your effect.&lt;br /&gt;
# A class that extends &amp;lt;code&amp;gt;LootModifier&amp;lt;/code&amp;gt;&lt;br /&gt;
#* The operational code that makes your modifier work and associated serializer.&lt;br /&gt;
&lt;br /&gt;
Finally, the serializer for your operational class is [[Registration|registered]] as any other &amp;lt;code&amp;gt;ForgeRegistryEntry&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==The global_loot_modifiers.json==&lt;br /&gt;
All you need to add here are the file names of your loot modifiers.&lt;br /&gt;
These are the names of the json files you have made in the loot_modifiers folder, in ResourceLocation 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;replace&amp;quot;: false,&lt;br /&gt;
  &amp;quot;entries&amp;quot;: [&lt;br /&gt;
    &amp;quot;global_loot_test:silk_touch_bamboo&amp;quot;,&lt;br /&gt;
    &amp;quot;global_loot_test:smelting&amp;quot;,&lt;br /&gt;
    &amp;quot;global_loot_test:wheat_harvest&amp;quot;&lt;br /&gt;
  ]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;replace&amp;lt;/code&amp;gt; causes the cache of modifiers to be cleared fully when this asset loads (mods are loaded in an order that may be specified by a data pack). For modders you will want to use &amp;lt;code&amp;gt;false&amp;lt;/code&amp;gt; while data pack makers may want to specify their overrides with &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;entries&amp;lt;/code&amp;gt; is an ''ordered list'' of the modifiers that will be loaded. Any modifier that is not listed will not be loaded and the ones listed are called in the order listed. This is primarily relevant to data pack makers for resolving conflicts between modifiers from separate mods.&lt;br /&gt;
&lt;br /&gt;
== The serialized json ==&lt;br /&gt;
&lt;br /&gt;
This file contains all of the potential variables related to your modifier, including the conditions that must be met prior to modifying any loot as well as any other parameters your modifier might have. Avoid hard-coded values where ever possible so that data pack makers can adjust balance if they wish to.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;json&amp;quot;&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;conditions&amp;quot;: [&lt;br /&gt;
    {&lt;br /&gt;
      &amp;quot;condition&amp;quot;: &amp;quot;minecraft:match_tool&amp;quot;,&lt;br /&gt;
      &amp;quot;predicate&amp;quot;: {&lt;br /&gt;
        &amp;quot;item&amp;quot;: &amp;quot;minecraft:shears&amp;quot;&lt;br /&gt;
      }&lt;br /&gt;
    },&lt;br /&gt;
    {&lt;br /&gt;
      &amp;quot;condition&amp;quot;: &amp;quot;block_state_property&amp;quot;,&lt;br /&gt;
      &amp;quot;block&amp;quot;:&amp;quot;minecraft:wheat&amp;quot;&lt;br /&gt;
    }&lt;br /&gt;
  ],&lt;br /&gt;
  &amp;quot;seedItem&amp;quot;: &amp;quot;minecraft:wheat_seeds&amp;quot;,&lt;br /&gt;
  &amp;quot;numSeeds&amp;quot;: 3,&lt;br /&gt;
  &amp;quot;replacement&amp;quot;: &amp;quot;minecraft:wheat&amp;quot;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the above example, the modification only happens if the player harvests wheat when using shears (specified by the two &amp;lt;code&amp;gt;conditions&amp;lt;/code&amp;gt; which are automatically &amp;lt;code&amp;gt;AND&amp;lt;/code&amp;gt;ed together). The &amp;lt;code&amp;gt;seedsItem&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;numSeeds&amp;lt;/code&amp;gt; values are then used to count how many seeds were generated by the vanilla loot table, and if matched, are substituted for an additional &amp;lt;code&amp;gt;replacement&amp;lt;/code&amp;gt; item instead. The operation code will be shown below.&lt;br /&gt;
&amp;lt;code&amp;gt;conditions&amp;lt;/code&amp;gt; is the only object needed by the system specification, everything else is the mod maker's data.&lt;br /&gt;
&lt;br /&gt;
Note that seedItem, numSeeds and replacement are NOT standard elements of Global Loot Modifiers. They are added by the creator of this json, and are parsed manually using the Serializer of the next section:&lt;br /&gt;
&lt;br /&gt;
== The LootModifier Subclass ==&lt;br /&gt;
&lt;br /&gt;
You will also need a static child class that extends &amp;lt;code&amp;gt;GlobalLootModifierSerializer&amp;lt;T&amp;gt;&amp;lt;/code&amp;gt; where &amp;lt;code&amp;gt;T&amp;lt;/code&amp;gt; is your LootModifier subclass in order to deserialize your json data file into operational code.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
private static class WheatSeedsConverterModifier extends LootModifier {&lt;br /&gt;
	private final int numSeedsToConvert;&lt;br /&gt;
	private final Item itemToCheck;&lt;br /&gt;
	private final Item itemReward;&lt;br /&gt;
	public WheatSeedsConverterModifier(ILootCondition[] conditionsIn, int numSeeds, Item itemCheck, Item reward) {&lt;br /&gt;
		super(conditionsIn);&lt;br /&gt;
		numSeedsToConvert = numSeeds;&lt;br /&gt;
		itemToCheck = itemCheck;&lt;br /&gt;
		itemReward = reward;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	@Nonnull&lt;br /&gt;
	@Override&lt;br /&gt;
	public List&amp;lt;ItemStack&amp;gt; doApply(List&amp;lt;ItemStack&amp;gt; generatedLoot, LootContext context) {&lt;br /&gt;
		/*&lt;br /&gt;
		* Additional conditions can be checked, though as much as possible should be parameterized via JSON data.&lt;br /&gt;
		* It is better to write a new ILootCondition implementation than to do things here.&lt;br /&gt;
		*/&lt;br /&gt;
		int numSeeds = 0;&lt;br /&gt;
		for(ItemStack stack : generatedLoot) {&lt;br /&gt;
			if(stack.getItem() == itemToCheck)&lt;br /&gt;
				numSeeds+=stack.getCount();&lt;br /&gt;
		}&lt;br /&gt;
		if(numSeeds &amp;gt;= numSeedsToConvert) {&lt;br /&gt;
			generatedLoot.removeIf(x -&amp;gt; x.getItem() == itemToCheck);&lt;br /&gt;
			generatedLoot.add(new ItemStack(itemReward, (numSeeds/numSeedsToConvert)));&lt;br /&gt;
			numSeeds = numSeeds%numSeedsToConvert;&lt;br /&gt;
			if(numSeeds &amp;gt; 0)&lt;br /&gt;
				generatedLoot.add(new ItemStack(itemToCheck, numSeeds));&lt;br /&gt;
		}&lt;br /&gt;
		return generatedLoot;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	private static class Serializer extends GlobalLootModifierSerializer&amp;lt;WheatSeedsConverterModifier&amp;gt; {&lt;br /&gt;
&lt;br /&gt;
		@Override&lt;br /&gt;
		public WheatSeedsConverterModifier read(ResourceLocation name, JsonObject object, ILootCondition[] conditionsIn) {&lt;br /&gt;
			int numSeeds = JSONUtils.getInt(object, &amp;quot;numSeeds&amp;quot;);&lt;br /&gt;
			Item seed = ForgeRegistries.ITEMS.getValue(new ResourceLocation((JSONUtils.getString(object, &amp;quot;seedItem&amp;quot;))));&lt;br /&gt;
			Item wheat = ForgeRegistries.ITEMS.getValue(new ResourceLocation(JSONUtils.getString(object, &amp;quot;replacement&amp;quot;)));&lt;br /&gt;
			return new WheatSeedsConverterModifier(conditionsIn, numSeeds, seed, wheat);&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The critical portion is the &amp;lt;code&amp;gt;doApply&amp;lt;/code&amp;gt; method.&lt;br /&gt;
&lt;br /&gt;
This method is only called if the &amp;lt;code&amp;gt;conditions&amp;lt;/code&amp;gt; specified return &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt; and the modder is now able to make the modifications they desire. In this case we can see that the number of &amp;lt;code&amp;gt;itemToCheck&amp;lt;/code&amp;gt; meets or exceeds the &amp;lt;code&amp;gt;numSeedsToConvert&amp;lt;/code&amp;gt; before modifying the list by adding an &amp;lt;code&amp;gt;itemReward&amp;lt;/code&amp;gt; and removing any excess &amp;lt;code&amp;gt;itemToCheck&amp;lt;/code&amp;gt; stacks, matching the previously mentioned effects: When a wheat block is harvested with shears, if enough seeds are generated as loot, they are converted to additional wheat instead.&lt;br /&gt;
&lt;br /&gt;
Also take note of the &amp;lt;code&amp;gt;read&amp;lt;/code&amp;gt; method in the serializer. The conditions are already deserialized for you and if you have no other data, simply &amp;lt;code&amp;gt;return new MyModifier(conditionsIn)&amp;lt;/code&amp;gt;. However, the full &amp;lt;code&amp;gt;JsonObject&amp;lt;/code&amp;gt; is available if needed.&lt;br /&gt;
&lt;br /&gt;
Additional [https://github.com/MinecraftForge/MinecraftForge/blob/1.15.x/src/test/java/net/minecraftforge/debug/gameplay/loot/GlobalLootModifiersTest.java examples] can be found on the Forge Git repository, including silk touch and smelting effects.&lt;/div&gt;</summary>
		<author><name>Curle</name></author>
	</entry>
	<entry>
		<id>https://forge.gemwire.uk/index.php?title=Structures&amp;diff=2679</id>
		<title>Structures</title>
		<link rel="alternate" type="text/html" href="https://forge.gemwire.uk/index.php?title=Structures&amp;diff=2679"/>
		<updated>2021-07-24T02:11:52Z</updated>

		<summary type="html">&lt;p&gt;Curle: new page&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;https://github.com/TelepathicGrunt/StructureTutorialMod&lt;/div&gt;</summary>
		<author><name>Curle</name></author>
	</entry>
	<entry>
		<id>https://forge.gemwire.uk/index.php?title=File:Hammer150.png&amp;diff=2596</id>
		<title>File:Hammer150.png</title>
		<link rel="alternate" type="text/html" href="https://forge.gemwire.uk/index.php?title=File:Hammer150.png&amp;diff=2596"/>
		<updated>2021-05-15T16:13:57Z</updated>

		<summary type="html">&lt;p&gt;Curle: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Curle</name></author>
	</entry>
	<entry>
		<id>https://forge.gemwire.uk/index.php?title=MediaWiki:Common.css&amp;diff=2452</id>
		<title>MediaWiki:Common.css</title>
		<link rel="alternate" type="text/html" href="https://forge.gemwire.uk/index.php?title=MediaWiki:Common.css&amp;diff=2452"/>
		<updated>2021-02-20T05:07:27Z</updated>

		<summary type="html">&lt;p&gt;Curle: Make question text stand out on create account screen&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;/* CSS placed here will be applied to all skins */&lt;br /&gt;
&lt;br /&gt;
/* Hides the Main Page's first header */&lt;br /&gt;
body.page-Main_Page h1.firstHeading,&lt;br /&gt;
body.page-Main_Page #siteSub {&lt;br /&gt;
  display: none; &lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.htmlform-tip + .mw-htmlform-field-HTMLInfoField { color:red; }&lt;/div&gt;</summary>
		<author><name>Curle</name></author>
	</entry>
	<entry>
		<id>https://forge.gemwire.uk/index.php?title=Events/FMLCommonSetupEvent&amp;diff=2416</id>
		<title>Events/FMLCommonSetupEvent</title>
		<link rel="alternate" type="text/html" href="https://forge.gemwire.uk/index.php?title=Events/FMLCommonSetupEvent&amp;diff=2416"/>
		<updated>2021-02-14T01:46:01Z</updated>

		<summary type="html">&lt;p&gt;Curle: Create page.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This event is a parallel dispatch event - you must use &amp;lt;code&amp;gt;event.enqueueWork&amp;lt;/code&amp;gt; to interact with the game state in any way.&lt;br /&gt;
&lt;br /&gt;
CommonSetup is fired after all the [[Events/RegistryEvent]]s, but before the [[Events/FMLClientSetupEvent]] and [[Events/FMLDedicatedServerSetupEvent]]. This makes it useful for non-specific mod setup.&lt;br /&gt;
&lt;br /&gt;
Register it any way you would normally register an event.&lt;/div&gt;</summary>
		<author><name>Curle</name></author>
	</entry>
	<entry>
		<id>https://forge.gemwire.uk/index.php?title=Events&amp;diff=2415</id>
		<title>Events</title>
		<link rel="alternate" type="text/html" href="https://forge.gemwire.uk/index.php?title=Events&amp;diff=2415"/>
		<updated>2021-02-14T01:31:01Z</updated>

		<summary type="html">&lt;p&gt;Curle: fix code tag&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Under construction}}&lt;br /&gt;
&lt;br /&gt;
An '''event''' is a signal that is fired on an '''event bus''' to inform registered listeners about some type of action or state. This is the primary way by which Forge allows mods to hook into vanilla and game behavior; Forge has an array of different events which are fired when different actions happen within the game, and mods may act upon receiving these events.  &lt;br /&gt;
&lt;br /&gt;
Additionally, mods may create their own events and fire them for other mods to listen for, allowing for higher compatibility.&lt;br /&gt;
&lt;br /&gt;
= Cancellable Events =&lt;br /&gt;
An event may be marked as '''cancellable''', which allows event listeners to cancel the event.&lt;br /&gt;
&lt;br /&gt;
A cancellable event may be cancelled by using &amp;lt;code&amp;gt;Event#setCanceled(true)&amp;lt;/code&amp;gt;. Attempting to call this method on a non-cancellable event will result in a &amp;lt;code&amp;gt;UnsupportedOperationException&amp;lt;/code&amp;gt;. A cancelled event behaves similarly to a regular noncancelled event, with one main difference: an event listener will not receive cancelled events unless they are explicitly registered to listen for cancelled events.&lt;br /&gt;
&lt;br /&gt;
To mark an event as cancellable, the event class should be annotated with &amp;lt;code&amp;gt;@Cancelable&amp;lt;/code&amp;gt;. This will automatically make &amp;lt;code&amp;gt;Event#isCancelable()&amp;lt;/code&amp;gt; return &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt;. Modders may check if an event has a result through the presence of the annotation or by calling the given method.&lt;br /&gt;
&lt;br /&gt;
= Events with Results =&lt;br /&gt;
An event may have a ```result''', which is an enum of &amp;lt;code&amp;gt;Event.Result&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;Event.Result&amp;lt;/code&amp;gt; enum has three values: &amp;lt;code&amp;gt;ALLOW&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;DEFAULT&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;DENY&amp;lt;/code&amp;gt;. The meaning of these result values is entirely dependent on the event itself.&lt;br /&gt;
 &lt;br /&gt;
An event's current result can be retrieved through &amp;lt;code&amp;gt;Event#getResult()&amp;lt;/code&amp;gt;. The result on an event can be set through &amp;lt;code&amp;gt;Event#setResult(Event.Result)&amp;lt;/code&amp;gt;. You can set the result for an event which is not marked as having a result, however this will cause nothing to happen if the event does not use the result value.&lt;br /&gt;
&lt;br /&gt;
To mark an event as having a result, the event class should be annotated with &amp;lt;code&amp;gt;@Event.HasResult&amp;lt;/code&amp;gt;. This will automatically make &amp;lt;code&amp;gt;Event#hasResult&amp;lt;/code&amp;gt; return &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt;. Modders may check if an event has a result through the presence of the annotation or by calling the given method.&lt;br /&gt;
&lt;br /&gt;
= Event Bus =&lt;br /&gt;
An '''event bus''' is an object which holds a list of event listeners, and the logic for firing the events. Events may be posted on these event buses, which then invokes the handlers.&lt;br /&gt;
&lt;br /&gt;
== Forge and Mod Buses ==&lt;br /&gt;
There are two event buses of note to a mod: the '''main Forge event bus''', and the '''mod-specific event bus'''.&lt;br /&gt;
&lt;br /&gt;
The Forge event bus, which can be referenced through &amp;lt;code&amp;gt;MinecraftForge.EVENT_BUS&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;EventBusSubscriber.Bus.FORGE&amp;lt;/code&amp;gt; (the latter being an enum that provides handy references to both busses), fires events that depend solely on the game state. This means that:&lt;br /&gt;
* Entity Events&lt;br /&gt;
* Ticking Events&lt;br /&gt;
* Server Events&lt;br /&gt;
and more, are fired on the Forge bus.&lt;br /&gt;
&lt;br /&gt;
The Mod bus, referenced through &amp;lt;code&amp;gt;FMLJavaModLoadingContext.get().getModEventBus()&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;EventBusSubscriber.Bus.MOD&amp;lt;/code&amp;gt;, fires events that depend solely on mod state, or which are used to initialise such.&lt;br /&gt;
This means that:&lt;br /&gt;
* Registration Events&lt;br /&gt;
* Mod Lifecycle Events&lt;br /&gt;
* Model Events (bake and register)&lt;br /&gt;
* Config Events&lt;br /&gt;
* Data Provider Events&lt;br /&gt;
and more, are fired on the Mod bus. See [[Stages of Modloading|mod loading events]]. Note that some of these are fired in parallel.&lt;br /&gt;
&lt;br /&gt;
== Sub Events ==&lt;br /&gt;
&lt;br /&gt;
Many events have different variations of themselves, these can be different but all based around one common factor (e.g. &amp;lt;code&amp;gt;PlayerEvent&amp;lt;/code&amp;gt;) or can be an event that has multiple phases (e.g. &amp;lt;code&amp;gt;PotionBrewEvent&amp;lt;/code&amp;gt;). Take note that if you listen to the parent event class, you will receive calls to your method for ''all'' subclasses.&lt;br /&gt;
&lt;br /&gt;
== Event Handlers ==&lt;br /&gt;
Event handlers are methods, which have four main properties. They are communicated to the event bus you want them to listen on, and when the event is posted on that bus, the hander is invoked.&lt;br /&gt;
&lt;br /&gt;
Event handlers' properties are as such:&lt;br /&gt;
- Registered to an event bus&lt;br /&gt;
- May be static or instance&lt;br /&gt;
- Have a single argument, which is used to determine the event that is being listened for&lt;br /&gt;
- The argument given is the instance of the Event being posted.&lt;br /&gt;
&lt;br /&gt;
Note that handlers may take the form of anonymous functions - lambdas.&lt;br /&gt;
&lt;br /&gt;
== Registering Event Handlers ==&lt;br /&gt;
Event handlers are registered typically one of four ways:&lt;br /&gt;
* &amp;lt;code&amp;gt;EventBusSubscriber&amp;lt;/code&amp;gt; (which requires a static, annotated handler method)&lt;br /&gt;
* &amp;lt;code&amp;gt;EventBus#register(T.class)&amp;lt;/code&amp;gt; (which requires a static, annotated handler method)&lt;br /&gt;
* &amp;lt;code&amp;gt;EventBus#register(new X())&amp;lt;/code&amp;gt; (which requires an instance, annotated handler method)&lt;br /&gt;
* &amp;lt;code&amp;gt;EventBus#addListener(Class::function)&amp;lt;/code&amp;gt; (which requires an instance, non-annotated handler method)&lt;br /&gt;
* as an extension of the above: &amp;lt;code&amp;gt;EventBus#&amp;lt;LivingHurtEvent&amp;gt;addListener(event -&amp;gt; { code })&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Each of these will be explained in detail as follows.&lt;br /&gt;
&lt;br /&gt;
=== Annotated Event Handlers ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
public class MyForgeEventHandler {&lt;br /&gt;
    @SubscribeEvent&lt;br /&gt;
    public void pickupItem(EntityItemPickupEvent event) {&lt;br /&gt;
        System.out.println(&amp;quot;Item picked up!&amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This event handler listens for the &amp;lt;code&amp;gt;EntityItemPickupEvent&amp;lt;/code&amp;gt;, which is, as the name states, posted to the event bus whenever an &amp;lt;code&amp;gt;Entity&amp;lt;/code&amp;gt; picks up an item.&lt;br /&gt;
&lt;br /&gt;
This function would be registered with &amp;lt;code&amp;gt;EventBus#register(new X())&amp;lt;/code&amp;gt; in the above examples.&lt;br /&gt;
&lt;br /&gt;
=== Static Event Handlers ===&lt;br /&gt;
&lt;br /&gt;
An event handler may also be static. The handling method is still annotated with &amp;lt;code&amp;gt;@SubscribeEvent&amp;lt;/code&amp;gt; with the only difference from an instance handler is that it is also marked static. In order to register a static event handler, an instance of the class won’t do, the Class itself has to be passed in. An example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
public class MyStaticForgeEventHandler {&lt;br /&gt;
    @SubscribeEvent&lt;br /&gt;
    public static void arrowNocked(ArrowNockEvent event) {&lt;br /&gt;
        System.out.println(&amp;quot;Arrow nocked!&amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
which must be registered &amp;lt;code&amp;gt;EventBus#register(MyStaticForgeEventHandler.class)&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;h3 id=&amp;quot;eventbussubscriber&amp;quot;&amp;gt;Using &amp;lt;tt style=&amp;quot;font-size: 100%&amp;quot;&amp;gt;@Mod.EventBusSubscriber&amp;lt;/tt&amp;gt;&amp;lt;/h3&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A class may be annotated with the &amp;lt;code&amp;gt;@Mod.EventBusSubscriber&amp;lt;/code&amp;gt; annotation. Such a class is automatically registered to the configured bus when the &amp;lt;code&amp;gt;@Mod&amp;lt;/code&amp;gt; class itself is constructed. This is essentially equivalent to adding &amp;lt;code&amp;gt;EventBus#register(AnnotatedClass.class);&amp;lt;/code&amp;gt; at the end of the &amp;lt;code&amp;gt;@Mod&amp;lt;/code&amp;gt; class's constructor.&lt;br /&gt;
&lt;br /&gt;
The mod ID must be specified unless your class is already annotated with an &amp;lt;code&amp;gt;@Mod&amp;lt;/code&amp;gt; annotation. You can pass the bus you want to listen to inside the &amp;lt;code&amp;gt;@Mod.EventBusSubscriber&amp;lt;/code&amp;gt; annotation.&lt;br /&gt;
&lt;br /&gt;
The bus registered with &amp;lt;code&amp;gt;EventBusSubscriber&amp;lt;/code&amp;gt; defaults to the Forge event bus.&lt;br /&gt;
&lt;br /&gt;
You can also specify the &amp;lt;code&amp;gt;Dist&amp;lt;/code&amp;gt;s to load this event subscriber on. This can be used to not load client specific event subscribers on the dedicated server.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
An example for a static event listener listening to &amp;lt;code&amp;gt;RenderWorldLastEvent&amp;lt;/code&amp;gt; which will only be called on the physical client: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
@Mod.EventBusSubscriber(modid = &amp;quot;examplemod&amp;quot;, dist = Dist.CLIENT)&lt;br /&gt;
public class MyStaticClientOnlyEventHandler {&lt;br /&gt;
    @SubscribeEvent&lt;br /&gt;
    public static void drawLast(RenderWorldLastEvent event) {&lt;br /&gt;
        System.out.println(&amp;quot;Drawing!&amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Tip/Important|This does not register an instance of the class; it registers the class itself (i.e. the event handling methods must be static).}}&lt;br /&gt;
&lt;br /&gt;
=== Non-Annotated Event Handlers ===&lt;br /&gt;
&lt;br /&gt;
Event handlers do not need to be annotated if they are directly referred to using &amp;lt;code&amp;gt;EventBus#addListener&amp;lt;/code&amp;gt; (or &amp;lt;code&amp;gt;EventBus#addGenericListener&amp;lt;/code&amp;gt; for generic events).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
@Mod(&amp;quot;examplemod&amp;quot;)&lt;br /&gt;
public class MyMainModClass {&lt;br /&gt;
&lt;br /&gt;
  public MyMainModClass() {&lt;br /&gt;
    FMLJavaModLoadingContext.get().getModEventBus().addGenericListener(Entity.class, this::entityCap);&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  private void entityCap(AttachCapabilitiesEvent&amp;lt;Entity&amp;gt; event) {&lt;br /&gt;
    System.out.println(&amp;quot;Capability attached!&amp;quot;);&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Tip/Important|The generic passed into the event must be referenced directly within the code itself. Otherwise, the event will not be called whatsoever. For example, if you use &amp;lt;code&amp;gt;AttachCapabilitiesEvent&amp;lt;LivingEntity&amp;gt;&amp;lt;/code&amp;gt;, the event will never be called as no call of this event uses &amp;lt;code&amp;gt;LivingEntity&amp;lt;/code&amp;gt;, only &amp;lt;code&amp;gt;Entity&amp;lt;/code&amp;gt;.}}&lt;br /&gt;
&lt;br /&gt;
== Cancelling ==&lt;br /&gt;
&lt;br /&gt;
If an event can be cancelled, it will be marked with the &amp;lt;code&amp;gt;@Cancelable&amp;lt;/code&amp;gt; annotation, and the method &amp;lt;code&amp;gt;Event#isCancelable()&amp;lt;/code&amp;gt; will return &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt;. The cancel state of a cancellable event may be modified by calling &amp;lt;code&amp;gt;Event#setCanceled(boolean canceled)&amp;lt;/code&amp;gt;, wherein passing the boolean value &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt; is interpreted as cancelling the event, and passing the boolean value &amp;lt;code&amp;gt;false&amp;lt;/code&amp;gt; is interpreted as “un-cancelling” the event.&lt;br /&gt;
&lt;br /&gt;
{{Tip/Important|Not all events can be cancelled! Attempting to cancel an event that is not cancellable will result in an unchecked &amp;lt;code&amp;gt;UnsupportedOperationException&amp;lt;/code&amp;gt; being thrown, which is expected to result in the game crashing. Always check that an event can be cancelled using &amp;lt;code&amp;gt;Event#isCancelable()&amp;lt;/code&amp;gt; before attempting to cancel it.}}&lt;br /&gt;
&lt;br /&gt;
== Results ==&lt;br /&gt;
&lt;br /&gt;
Some events have an &amp;lt;code&amp;gt;Event.Result&amp;lt;/code&amp;gt; as denoted by &amp;lt;code&amp;gt;@HasResult&amp;lt;/code&amp;gt;. A result can be one of three things: &amp;lt;code&amp;gt;DENY&amp;lt;/code&amp;gt; which stops the event, &amp;lt;code&amp;gt;DEFAULT&amp;lt;/code&amp;gt; which uses the Vanilla behavior, and &amp;lt;code&amp;gt;ALLOW&amp;lt;/code&amp;gt; which forces the action to take place, regardless of if it would have originally. The result of an event can be set by calling &amp;lt;code&amp;gt;setResult&amp;lt;/code&amp;gt; with an Event.Result on the event.&lt;br /&gt;
&lt;br /&gt;
{{Colored box|title=Information|content=Different events may use results in different ways, refer to the event's JavaDoc before using the result.}}&lt;br /&gt;
&lt;br /&gt;
== Priority ==&lt;br /&gt;
&lt;br /&gt;
Event handler methods have a priority. You can set the &amp;lt;code&amp;gt;priority&amp;lt;/code&amp;gt; of an event handler method by setting the priority value of the annotation or the listener. The priority can be any value of the &amp;lt;code&amp;gt;EventPriority&amp;lt;/code&amp;gt; enum (&amp;lt;code&amp;gt;HIGHEST&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;HIGH&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;NORMAL&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;LOW&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;LOWEST&amp;lt;/code&amp;gt;). Event handlers with priority &amp;lt;code&amp;gt;HIGHEST&amp;lt;/code&amp;gt; are executed first and from there in descending order until &amp;lt;code&amp;gt;LOWEST&amp;lt;/code&amp;gt; events which are executed last.&lt;br /&gt;
&lt;br /&gt;
== Mod Event Bus ==&lt;br /&gt;
The mod event bus is primarily used for listening to lifecycle events in which mods should initialize. Many of these events are also ran in parallel so mods can be initialized at the same time. This does mean you cannot directly execute code from other mods in these events. Use the &amp;lt;code&amp;gt;InterModComms&amp;lt;/code&amp;gt; system for that.&lt;br /&gt;
&lt;br /&gt;
It is impossible for an event to be posted on the Mod bus that does not inherit the IModBusEvent interface.&lt;br /&gt;
Thus, this provides a good, easy way to tell which events are fired on this bus.&lt;br /&gt;
&lt;br /&gt;
These are the four most commonly used lifecycle events that are called during mod initialization on the mod event bus: &lt;br /&gt;
* &amp;lt;code&amp;gt;FMLCommonSetupEvent&amp;lt;/code&amp;gt; &lt;br /&gt;
* &amp;lt;code&amp;gt;FMLClientSetupEvent&amp;lt;/code&amp;gt; &amp;amp; &amp;lt;code&amp;gt;FMLDedicatedServerSetupEvent&amp;lt;/code&amp;gt; (''These events are only called on their respective [[Sides#Different_Kinds_of_Sides|physical side]].'')&lt;br /&gt;
* &amp;lt;code&amp;gt;InterModEnqueueEvent&amp;lt;/code&amp;gt; &lt;br /&gt;
* &amp;lt;code&amp;gt;InterModProcessEvent&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
These four lifecycle events are all ran in parallel. If you want to run code on the main thread during these events you can use the &amp;lt;code&amp;gt;enqueueWork&amp;lt;/code&amp;gt; methods within the events to do so.&lt;br /&gt;
&lt;br /&gt;
Next to the lifecycle events there are a few miscellaneous events that are fired on the mod event bus where you can register, set up, or initialize various things. Most of these events are not ran in parallel in contrast to the lifecycle events:&lt;br /&gt;
* &amp;lt;code&amp;gt;ColorHandlerEvent&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;ModelBakeEvent&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;TextureStitchEvent&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;RegistryEvent&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;GatherDataEvent&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;SoundLoadEvent&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;ParticleFactoryRegisterEvent&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;ModConfigEvent&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A good rule of thumb: events are fired on the mod event bus when they should be handled during initialization of a mod. or where they are used to set state (eg. the config event.)&lt;br /&gt;
&lt;br /&gt;
Detailed information about these events will be found in their respective pages, once they are ready.&lt;br /&gt;
&lt;br /&gt;
== Forge Event Bus ==&lt;br /&gt;
The Forge event bus is where game state events are fired. If anything changes to do with the game, or anything happens that you would need to know about, there's a good chance it's sent here.&lt;br /&gt;
&lt;br /&gt;
A full list of the events fired here is as follows, split into discrete categories:&lt;br /&gt;
&lt;br /&gt;
=== Render Events ===&lt;br /&gt;
* &amp;lt;code&amp;gt;RenderWorldLastEvent&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;RenderHandEvent&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;RenderLivingEvent&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;RenderItemInFrameEvent&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;RenderBlockOverlayEvent&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;DrawHighlightEvent&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;RenderTooltipEvent&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;EntityViewRenderEvent&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;RenderGameOverlayEvent&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;FOVUpdateEvent&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== GUI Events ===&lt;br /&gt;
* &amp;lt;code&amp;gt;GuiScreenEvent&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;GuiContainerEvent&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;GuiOpenEvent&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Super Events ===&lt;br /&gt;
(Events that exist to contain other events)&lt;br /&gt;
* &amp;lt;code&amp;gt;BlockEvent&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;WorldEvent&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;InputEvent&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;NetworkEvent&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;GenericEvent&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;ExplosionEvent&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;SoundEvent&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;EntityEvent&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;TickEvent&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Chat Events ===&lt;br /&gt;
* &amp;lt;code&amp;gt;ServerChatEvent&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;ClientChatEvent&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;ClientChatReceivedEvent&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Data Loading Events ===&lt;br /&gt;
* &amp;lt;code&amp;gt;RecipesUpdatedEvent&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;BiomeLoadingEvent&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;LootTableLoadEvent&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;StructureSpawnListGatherEvent&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Startup Events ===&lt;br /&gt;
* &amp;lt;code&amp;gt;AddReloadListenerEvent&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;RegisterCommandsEvent&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;ServerLifecycleEvent&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Gamemode Events ===&lt;br /&gt;
* &amp;lt;code&amp;gt;DifficultyChangeEvent&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;ClientPlayerChangeGamemodeEvent&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Trade Events ===&lt;br /&gt;
* &amp;lt;code&amp;gt;WandererTradesEvent&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;VillagerTradesEvent&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Other Events ===&lt;br /&gt;
* &amp;lt;code&amp;gt;FurnaceFuelBurnTimeEvent&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;BabyEntitySpawnEvent&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;VillageSiegeEvent&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;TagsUpdatedEvent&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;PotionBrewEvent&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;ScreenshotEvent&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;EnchantmentLevelSetEvent&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;CommandEvent&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;AnvilUpdateEvent&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;ItemAttributeModifierEvent&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;ClientPlayerNetworkEvent&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;ChunkWatchEvent&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Like before, each of these events (especially the Super Events, which contain most of the useful events in the game) will have their own article explaining their purpose and usefulness.&lt;/div&gt;</summary>
		<author><name>Curle</name></author>
	</entry>
	<entry>
		<id>https://forge.gemwire.uk/index.php?title=Events&amp;diff=2414</id>
		<title>Events</title>
		<link rel="alternate" type="text/html" href="https://forge.gemwire.uk/index.php?title=Events&amp;diff=2414"/>
		<updated>2021-02-14T01:29:45Z</updated>

		<summary type="html">&lt;p&gt;Curle: Rewrite article.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Under construction}}&lt;br /&gt;
&lt;br /&gt;
An '''event''' is a signal that is fired on an '''event bus''' to inform registered listeners about some type of action or state. This is the primary way by which Forge allows mods to hook into vanilla and game behavior; Forge has an array of different events which are fired when different actions happen within the game, and mods may act upon receiving these events.  &lt;br /&gt;
&lt;br /&gt;
Additionally, mods may create their own events and fire them for other mods to listen for, allowing for higher compatibility.&lt;br /&gt;
&lt;br /&gt;
= Cancellable Events =&lt;br /&gt;
An event may be marked as '''cancellable''', which allows event listeners to cancel the event.&lt;br /&gt;
&lt;br /&gt;
A cancellable event may be cancelled by using &amp;lt;code&amp;gt;Event#setCanceled(true)&amp;lt;/code&amp;gt;. Attempting to call this method on a non-cancellable event will result in a &amp;lt;code&amp;gt;UnsupportedOperationException&amp;lt;/code&amp;gt;. A cancelled event behaves similarly to a regular noncancelled event, with one main difference: an event listener will not receive cancelled events unless they are explicitly registered to listen for cancelled events.&lt;br /&gt;
&lt;br /&gt;
To mark an event as cancellable, the event class should be annotated with &amp;lt;code&amp;gt;@Cancelable&amp;lt;/code&amp;gt;. This will automatically make &amp;lt;code&amp;gt;Event#isCancelable()&amp;lt;/code&amp;gt; return &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt;. Modders may check if an event has a result through the presence of the annotation or by calling the given method.&lt;br /&gt;
&lt;br /&gt;
= Events with Results =&lt;br /&gt;
An event may have a ```result''', which is an enum of &amp;lt;code&amp;gt;Event.Result&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;Event.Result&amp;lt;/code&amp;gt; enum has three values: &amp;lt;code&amp;gt;ALLOW&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;DEFAULT&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;DENY&amp;lt;/code&amp;gt;. The meaning of these result values is entirely dependent on the event itself.&lt;br /&gt;
 &lt;br /&gt;
An event's current result can be retrieved through &amp;lt;code&amp;gt;Event#getResult()&amp;lt;/code&amp;gt;. The result on an event can be set through &amp;lt;code&amp;gt;Event#setResult(Event.Result)&amp;lt;/code&amp;gt;. You can set the result for an event which is not marked as having a result, however this will cause nothing to happen if the event does not use the result value.&lt;br /&gt;
&lt;br /&gt;
To mark an event as having a result, the event class should be annotated with &amp;lt;code&amp;gt;@Event.HasResult&amp;lt;/code&amp;gt;. This will automatically make &amp;lt;code&amp;gt;Event#hasResult&amp;lt;/code&amp;gt; return &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt;. Modders may check if an event has a result through the presence of the annotation or by calling the given method.&lt;br /&gt;
&lt;br /&gt;
= Event Bus =&lt;br /&gt;
An '''event bus''' is an object which holds a list of event listeners, and the logic for firing the events. Events may be posted on these event buses, which then invokes the handlers.&lt;br /&gt;
&lt;br /&gt;
== Forge and Mod Buses ==&lt;br /&gt;
There are two event buses of note to a mod: the '''main Forge event bus''', and the '''mod-specific event bus'''.&lt;br /&gt;
&lt;br /&gt;
The Forge event bus, which can be referenced through &amp;lt;code&amp;gt;MinecraftForge.EVENT_BUS&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;EventBusSubscriber.Bus.FORGE&amp;lt;/code&amp;gt; (the latter being an enum that provides handy references to both busses), fires events that depend solely on the game state. This means that:&lt;br /&gt;
* Entity Events&lt;br /&gt;
* Ticking Events&lt;br /&gt;
* Server Events&lt;br /&gt;
and more, are fired on the Forge bus.&lt;br /&gt;
&lt;br /&gt;
The Mod bus, referenced through &amp;lt;code&amp;gt;FMLJavaModLoadingContext.get().getModEventBus()&amp;lt;/code&amp;gt; or &amp;lt;EventBusSubscriber.Bus.MOD&amp;lt;/code&amp;gt;, fires events that depend solely on mod state, or which are used to initialise such.&lt;br /&gt;
This means that:&lt;br /&gt;
* Registration Events&lt;br /&gt;
* Mod Lifecycle Events&lt;br /&gt;
* Model Events (bake and register)&lt;br /&gt;
* Config Events&lt;br /&gt;
* Data Provider Events&lt;br /&gt;
and more, are fired on the Mod bus. See [[Stages of Modloading|mod loading events]]. Note that some of these are fired in parallel.&lt;br /&gt;
&lt;br /&gt;
== Sub Events ==&lt;br /&gt;
&lt;br /&gt;
Many events have different variations of themselves, these can be different but all based around one common factor (e.g. &amp;lt;code&amp;gt;PlayerEvent&amp;lt;/code&amp;gt;) or can be an event that has multiple phases (e.g. &amp;lt;code&amp;gt;PotionBrewEvent&amp;lt;/code&amp;gt;). Take note that if you listen to the parent event class, you will receive calls to your method for ''all'' subclasses.&lt;br /&gt;
&lt;br /&gt;
== Event Handlers ==&lt;br /&gt;
Event handlers are methods, which have four main properties. They are communicated to the event bus you want them to listen on, and when the event is posted on that bus, the hander is invoked.&lt;br /&gt;
&lt;br /&gt;
Event handlers' properties are as such:&lt;br /&gt;
- Registered to an event bus&lt;br /&gt;
- May be static or instance&lt;br /&gt;
- Have a single argument, which is used to determine the event that is being listened for&lt;br /&gt;
- The argument given is the instance of the Event being posted.&lt;br /&gt;
&lt;br /&gt;
Note that handlers may take the form of anonymous functions - lambdas.&lt;br /&gt;
&lt;br /&gt;
== Registering Event Handlers ==&lt;br /&gt;
Event handlers are registered typically one of four ways:&lt;br /&gt;
* &amp;lt;code&amp;gt;EventBusSubscriber&amp;lt;/code&amp;gt; (which requires a static, annotated handler method)&lt;br /&gt;
* &amp;lt;code&amp;gt;EventBus#register(T.class)&amp;lt;/code&amp;gt; (which requires a static, annotated handler method)&lt;br /&gt;
* &amp;lt;code&amp;gt;EventBus#register(new X())&amp;lt;/code&amp;gt; (which requires an instance, annotated handler method)&lt;br /&gt;
* &amp;lt;code&amp;gt;EventBus#addListener(Class::function)&amp;lt;/code&amp;gt; (which requires an instance, non-annotated handler method)&lt;br /&gt;
* as an extension of the above: &amp;lt;code&amp;gt;EventBus#&amp;lt;LivingHurtEvent&amp;gt;addListener(event -&amp;gt; { code })&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Each of these will be explained in detail as follows.&lt;br /&gt;
&lt;br /&gt;
=== Annotated Event Handlers ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
public class MyForgeEventHandler {&lt;br /&gt;
    @SubscribeEvent&lt;br /&gt;
    public void pickupItem(EntityItemPickupEvent event) {&lt;br /&gt;
        System.out.println(&amp;quot;Item picked up!&amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This event handler listens for the &amp;lt;code&amp;gt;EntityItemPickupEvent&amp;lt;/code&amp;gt;, which is, as the name states, posted to the event bus whenever an &amp;lt;code&amp;gt;Entity&amp;lt;/code&amp;gt; picks up an item.&lt;br /&gt;
&lt;br /&gt;
This function would be registered with &amp;lt;code&amp;gt;EventBus#register(new X())&amp;lt;/code&amp;gt; in the above examples.&lt;br /&gt;
&lt;br /&gt;
=== Static Event Handlers ===&lt;br /&gt;
&lt;br /&gt;
An event handler may also be static. The handling method is still annotated with &amp;lt;code&amp;gt;@SubscribeEvent&amp;lt;/code&amp;gt; with the only difference from an instance handler is that it is also marked static. In order to register a static event handler, an instance of the class won’t do, the Class itself has to be passed in. An example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
public class MyStaticForgeEventHandler {&lt;br /&gt;
    @SubscribeEvent&lt;br /&gt;
    public static void arrowNocked(ArrowNockEvent event) {&lt;br /&gt;
        System.out.println(&amp;quot;Arrow nocked!&amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
which must be registered &amp;lt;code&amp;gt;EventBus#register(MyStaticForgeEventHandler.class)&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;h3 id=&amp;quot;eventbussubscriber&amp;quot;&amp;gt;Using &amp;lt;tt style=&amp;quot;font-size: 100%&amp;quot;&amp;gt;@Mod.EventBusSubscriber&amp;lt;/tt&amp;gt;&amp;lt;/h3&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A class may be annotated with the &amp;lt;code&amp;gt;@Mod.EventBusSubscriber&amp;lt;/code&amp;gt; annotation. Such a class is automatically registered to the configured bus when the &amp;lt;code&amp;gt;@Mod&amp;lt;/code&amp;gt; class itself is constructed. This is essentially equivalent to adding &amp;lt;code&amp;gt;EventBus#register(AnnotatedClass.class);&amp;lt;/code&amp;gt; at the end of the &amp;lt;code&amp;gt;@Mod&amp;lt;/code&amp;gt; class's constructor.&lt;br /&gt;
&lt;br /&gt;
The mod ID must be specified unless your class is already annotated with an &amp;lt;code&amp;gt;@Mod&amp;lt;/code&amp;gt; annotation. You can pass the bus you want to listen to inside the &amp;lt;code&amp;gt;@Mod.EventBusSubscriber&amp;lt;/code&amp;gt; annotation.&lt;br /&gt;
&lt;br /&gt;
The bus registered with &amp;lt;code&amp;gt;EventBusSubscriber&amp;lt;/code&amp;gt; defaults to the Forge event bus.&lt;br /&gt;
&lt;br /&gt;
You can also specify the &amp;lt;code&amp;gt;Dist&amp;lt;/code&amp;gt;s to load this event subscriber on. This can be used to not load client specific event subscribers on the dedicated server.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
An example for a static event listener listening to &amp;lt;code&amp;gt;RenderWorldLastEvent&amp;lt;/code&amp;gt; which will only be called on the physical client: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
@Mod.EventBusSubscriber(modid = &amp;quot;examplemod&amp;quot;, dist = Dist.CLIENT)&lt;br /&gt;
public class MyStaticClientOnlyEventHandler {&lt;br /&gt;
    @SubscribeEvent&lt;br /&gt;
    public static void drawLast(RenderWorldLastEvent event) {&lt;br /&gt;
        System.out.println(&amp;quot;Drawing!&amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Tip/Important|This does not register an instance of the class; it registers the class itself (i.e. the event handling methods must be static).}}&lt;br /&gt;
&lt;br /&gt;
=== Non-Annotated Event Handlers ===&lt;br /&gt;
&lt;br /&gt;
Event handlers do not need to be annotated if they are directly referred to using &amp;lt;code&amp;gt;EventBus#addListener&amp;lt;/code&amp;gt; (or &amp;lt;code&amp;gt;EventBus#addGenericListener&amp;lt;/code&amp;gt; for generic events).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
@Mod(&amp;quot;examplemod&amp;quot;)&lt;br /&gt;
public class MyMainModClass {&lt;br /&gt;
&lt;br /&gt;
  public MyMainModClass() {&lt;br /&gt;
    FMLJavaModLoadingContext.get().getModEventBus().addGenericListener(Entity.class, this::entityCap);&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  private void entityCap(AttachCapabilitiesEvent&amp;lt;Entity&amp;gt; event) {&lt;br /&gt;
    System.out.println(&amp;quot;Capability attached!&amp;quot;);&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Tip/Important|The generic passed into the event must be referenced directly within the code itself. Otherwise, the event will not be called whatsoever. For example, if you use &amp;lt;code&amp;gt;AttachCapabilitiesEvent&amp;lt;LivingEntity&amp;gt;&amp;lt;/code&amp;gt;, the event will never be called as no call of this event uses &amp;lt;code&amp;gt;LivingEntity&amp;lt;/code&amp;gt;, only &amp;lt;code&amp;gt;Entity&amp;lt;/code&amp;gt;.}}&lt;br /&gt;
&lt;br /&gt;
== Cancelling ==&lt;br /&gt;
&lt;br /&gt;
If an event can be cancelled, it will be marked with the &amp;lt;code&amp;gt;@Cancelable&amp;lt;/code&amp;gt; annotation, and the method &amp;lt;code&amp;gt;Event#isCancelable()&amp;lt;/code&amp;gt; will return &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt;. The cancel state of a cancellable event may be modified by calling &amp;lt;code&amp;gt;Event#setCanceled(boolean canceled)&amp;lt;/code&amp;gt;, wherein passing the boolean value &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt; is interpreted as cancelling the event, and passing the boolean value &amp;lt;code&amp;gt;false&amp;lt;/code&amp;gt; is interpreted as “un-cancelling” the event.&lt;br /&gt;
&lt;br /&gt;
{{Tip/Important|Not all events can be cancelled! Attempting to cancel an event that is not cancellable will result in an unchecked &amp;lt;code&amp;gt;UnsupportedOperationException&amp;lt;/code&amp;gt; being thrown, which is expected to result in the game crashing. Always check that an event can be cancelled using &amp;lt;code&amp;gt;Event#isCancelable()&amp;lt;/code&amp;gt; before attempting to cancel it.}}&lt;br /&gt;
&lt;br /&gt;
== Results ==&lt;br /&gt;
&lt;br /&gt;
Some events have an &amp;lt;code&amp;gt;Event.Result&amp;lt;/code&amp;gt; as denoted by &amp;lt;code&amp;gt;@HasResult&amp;lt;/code&amp;gt;. A result can be one of three things: &amp;lt;code&amp;gt;DENY&amp;lt;/code&amp;gt; which stops the event, &amp;lt;code&amp;gt;DEFAULT&amp;lt;/code&amp;gt; which uses the Vanilla behavior, and &amp;lt;code&amp;gt;ALLOW&amp;lt;/code&amp;gt; which forces the action to take place, regardless of if it would have originally. The result of an event can be set by calling &amp;lt;code&amp;gt;setResult&amp;lt;/code&amp;gt; with an Event.Result on the event.&lt;br /&gt;
&lt;br /&gt;
{{Colored box|title=Information|content=Different events may use results in different ways, refer to the event's JavaDoc before using the result.}}&lt;br /&gt;
&lt;br /&gt;
== Priority ==&lt;br /&gt;
&lt;br /&gt;
Event handler methods have a priority. You can set the &amp;lt;code&amp;gt;priority&amp;lt;/code&amp;gt; of an event handler method by setting the priority value of the annotation or the listener. The priority can be any value of the &amp;lt;code&amp;gt;EventPriority&amp;lt;/code&amp;gt; enum (&amp;lt;code&amp;gt;HIGHEST&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;HIGH&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;NORMAL&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;LOW&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;LOWEST&amp;lt;/code&amp;gt;). Event handlers with priority &amp;lt;code&amp;gt;HIGHEST&amp;lt;/code&amp;gt; are executed first and from there in descending order until &amp;lt;code&amp;gt;LOWEST&amp;lt;/code&amp;gt; events which are executed last.&lt;br /&gt;
&lt;br /&gt;
== Mod Event Bus ==&lt;br /&gt;
The mod event bus is primarily used for listening to lifecycle events in which mods should initialize. Many of these events are also ran in parallel so mods can be initialized at the same time. This does mean you cannot directly execute code from other mods in these events. Use the &amp;lt;code&amp;gt;InterModComms&amp;lt;/code&amp;gt; system for that.&lt;br /&gt;
&lt;br /&gt;
It is impossible for an event to be posted on the Mod bus that does not inherit the IModBusEvent interface.&lt;br /&gt;
Thus, this provides a good, easy way to tell which events are fired on this bus.&lt;br /&gt;
&lt;br /&gt;
These are the four most commonly used lifecycle events that are called during mod initialization on the mod event bus: &lt;br /&gt;
* &amp;lt;code&amp;gt;FMLCommonSetupEvent&amp;lt;/code&amp;gt; &lt;br /&gt;
* &amp;lt;code&amp;gt;FMLClientSetupEvent&amp;lt;/code&amp;gt; &amp;amp; &amp;lt;code&amp;gt;FMLDedicatedServerSetupEvent&amp;lt;/code&amp;gt; (''These events are only called on their respective [[Sides#Different_Kinds_of_Sides|physical side]].'')&lt;br /&gt;
* &amp;lt;code&amp;gt;InterModEnqueueEvent&amp;lt;/code&amp;gt; &lt;br /&gt;
* &amp;lt;code&amp;gt;InterModProcessEvent&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
These four lifecycle events are all ran in parallel. If you want to run code on the main thread during these events you can use the &amp;lt;code&amp;gt;enqueueWork&amp;lt;/code&amp;gt; methods within the events to do so.&lt;br /&gt;
&lt;br /&gt;
Next to the lifecycle events there are a few miscellaneous events that are fired on the mod event bus where you can register, set up, or initialize various things. Most of these events are not ran in parallel in contrast to the lifecycle events:&lt;br /&gt;
* &amp;lt;code&amp;gt;ColorHandlerEvent&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;ModelBakeEvent&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;TextureStitchEvent&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;RegistryEvent&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;GatherDataEvent&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;SoundLoadEvent&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;ParticleFactoryRegisterEvent&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;ModConfigEvent&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A good rule of thumb: events are fired on the mod event bus when they should be handled during initialization of a mod. or where they are used to set state (eg. the config event.)&lt;br /&gt;
&lt;br /&gt;
Detailed information about these events will be found in their respective pages, once they are ready.&lt;br /&gt;
&lt;br /&gt;
== Forge Event Bus ==&lt;br /&gt;
The Forge event bus is where game state events are fired. If anything changes to do with the game, or anything happens that you would need to know about, there's a good chance it's sent here.&lt;br /&gt;
&lt;br /&gt;
A full list of the events fired here is as follows, split into discrete categories:&lt;br /&gt;
&lt;br /&gt;
=== Render Events ===&lt;br /&gt;
* &amp;lt;code&amp;gt;RenderWorldLastEvent&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;RenderHandEvent&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;RenderLivingEvent&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;RenderItemInFrameEvent&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;RenderBlockOverlayEvent&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;DrawHighlightEvent&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;RenderTooltipEvent&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;EntityViewRenderEvent&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;RenderGameOverlayEvent&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;FOVUpdateEvent&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== GUI Events ===&lt;br /&gt;
* &amp;lt;code&amp;gt;GuiScreenEvent&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;GuiContainerEvent&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;GuiOpenEvent&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Super Events ===&lt;br /&gt;
(Events that exist to contain other events)&lt;br /&gt;
* &amp;lt;code&amp;gt;BlockEvent&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;WorldEvent&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;InputEvent&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;NetworkEvent&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;GenericEvent&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;ExplosionEvent&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;SoundEvent&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;EntityEvent&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;TickEvent&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Chat Events ===&lt;br /&gt;
* &amp;lt;code&amp;gt;ServerChatEvent&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;ClientChatEvent&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;ClientChatReceivedEvent&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Data Loading Events ===&lt;br /&gt;
* &amp;lt;code&amp;gt;RecipesUpdatedEvent&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;BiomeLoadingEvent&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;LootTableLoadEvent&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;StructureSpawnListGatherEvent&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Startup Events ===&lt;br /&gt;
* &amp;lt;code&amp;gt;AddReloadListenerEvent&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;RegisterCommandsEvent&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;ServerLifecycleEvent&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Gamemode Events ===&lt;br /&gt;
* &amp;lt;code&amp;gt;DifficultyChangeEvent&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;ClientPlayerChangeGamemodeEvent&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Trade Events ===&lt;br /&gt;
* &amp;lt;code&amp;gt;WandererTradesEvent&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;VillagerTradesEvent&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Other Events ===&lt;br /&gt;
* &amp;lt;code&amp;gt;FurnaceFuelBurnTimeEvent&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;BabyEntitySpawnEvent&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;VillageSiegeEvent&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;TagsUpdatedEvent&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;PotionBrewEvent&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;ScreenshotEvent&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;EnchantmentLevelSetEvent&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;CommandEvent&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;AnvilUpdateEvent&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;ItemAttributeModifierEvent&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;ClientPlayerNetworkEvent&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;ChunkWatchEvent&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Like before, each of these events (especially the Super Events, which contain most of the useful events in the game) will have their own article explaining their purpose and usefulness.&lt;/div&gt;</summary>
		<author><name>Curle</name></author>
	</entry>
	<entry>
		<id>https://forge.gemwire.uk/index.php?title=Getting_Started&amp;diff=2394</id>
		<title>Getting Started</title>
		<link rel="alternate" type="text/html" href="https://forge.gemwire.uk/index.php?title=Getting_Started&amp;diff=2394"/>
		<updated>2021-02-07T20:16:29Z</updated>

		<summary type="html">&lt;p&gt;Curle: Test Edit&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Minecraft Forge''' is a modding framework, designed to allow different mods to load and work together to be compatible. Through the years, there has been many changes in the Forge tooling to make working with mods as seamless as possible. It is now easier than ever to start making your own mod.&lt;br /&gt;
&lt;br /&gt;
== The Mod Development Kit ==&lt;br /&gt;
The '''Mod Development Kit''' or '''MDK''' is a downloadable archive that contains the basic skeleton for starting a new mod. It contains the following files and folders:&lt;br /&gt;
&lt;br /&gt;
{{Tree list}}&lt;br /&gt;
* '''The Mod Development Kit'''&lt;br /&gt;
** &amp;lt;code&amp;gt;gradle/wrapper/&amp;lt;/code&amp;gt; - The folder containing the [https://docs.gradle.org/current/userguide/gradle_wrapper.html Gradle wrapper]'', Forge uses Gradle '''4.10.3'''''&lt;br /&gt;
** &amp;lt;code&amp;gt;src&amp;lt;/code&amp;gt; - The sources folder&lt;br /&gt;
*** &amp;lt;code&amp;gt;main&amp;lt;/code&amp;gt; - The &amp;lt;code&amp;gt;main&amp;lt;/code&amp;gt; source set&lt;br /&gt;
**** &amp;lt;code&amp;gt;java&amp;lt;/code&amp;gt; - The java sources for the &amp;lt;code&amp;gt;main&amp;lt;/code&amp;gt; source set&lt;br /&gt;
***** ...&lt;br /&gt;
**** &amp;lt;code&amp;gt;resources&amp;lt;/code&amp;gt; - The resources for the &amp;lt;code&amp;gt;main&amp;lt;/code&amp;gt; source set&lt;br /&gt;
***** &amp;lt;code&amp;gt;META-INF&amp;lt;/code&amp;gt; - The folder for '''metadata inf'''ormation files&amp;lt;ref&amp;gt;[https://stackoverflow.com/a/6075320/14416954 StackOverflow answer]: ''... Basically, if it was stored in META-INF, it was Meta-data Information...''&amp;lt;/ref&amp;gt;&lt;br /&gt;
****** &amp;lt;code&amp;gt;mods.toml&amp;lt;/code&amp;gt; - The [[Proper Mod Structuring#The mods.toml file|&amp;lt;tt&amp;gt;mods.toml&amp;lt;/tt&amp;gt; file]], where mods are declared&lt;br /&gt;
***** &amp;lt;code&amp;gt;pack.mcmeta&amp;lt;/code&amp;gt; - File used by Minecraft to [[mc:Data Pack#pack.mcmeta|identify data and resource packs]]&lt;br /&gt;
** &amp;lt;code&amp;gt;.gitattributes&amp;lt;/code&amp;gt; - Used by [[wikipedia:Git|Git]] for specifying attributes for files&amp;lt;ref&amp;gt;[https://git-scm.com/docs/gitattributes Official git documentation on &amp;lt;tt&amp;gt;.gitattributes&amp;lt;/tt&amp;gt;]&amp;lt;/ref&amp;gt;&lt;br /&gt;
** &amp;lt;code&amp;gt;.gitignore&amp;lt;/code&amp;gt; - Used by Git for specifying intentionally untracked/ignored files&amp;lt;ref&amp;gt;[https://git-scm.com/docs/gitignore Official git documentation on &amp;lt;tt&amp;gt;.gitignore&amp;lt;/tt&amp;gt;]&amp;lt;/ref&amp;gt;&lt;br /&gt;
** &amp;lt;code&amp;gt;build.gradle&amp;lt;/code&amp;gt; - The Gradle buildscript, which defines the project and tasks&amp;lt;ref&amp;gt;[https://docs.gradle.org/4.10.3/userguide/tutorial_using_tasks.html Gradle User Guide for 4.10.3: ''Build Script Basics'']&amp;lt;/ref&amp;gt;&lt;br /&gt;
** &amp;lt;code&amp;gt;changelog.txt&amp;lt;/code&amp;gt; - The Forge version changelog&lt;br /&gt;
** &amp;lt;code&amp;gt;CREDITS.txt&amp;lt;/code&amp;gt; - Forge's credits/''thank you'' file&lt;br /&gt;
** &amp;lt;code&amp;gt;gradle.properties&amp;lt;/code&amp;gt; - The Gradle properties file, for defining additional variables and options&amp;lt;ref&amp;gt;[https://docs.gradle.org/4.10.3/userguide/build_environment.html#sec:gradle_configuration_properties Gradle User Guide for 4.10.3: ''Build Environment § Gradle properties'']&amp;lt;/ref&amp;gt;&lt;br /&gt;
** &amp;lt;code&amp;gt;gradlew&amp;lt;/code&amp;gt; - The *nix shell file for executing the Gradle wrapper&lt;br /&gt;
** &amp;lt;code&amp;gt;gradlew.bat&amp;lt;/code&amp;gt; - The Windows batch file for executing the Gradle wrapper&lt;br /&gt;
** &amp;lt;code&amp;gt;LICENSE.txt&amp;lt;/code&amp;gt; - File containing the licensing information for Forge and libraries&lt;br /&gt;
** &amp;lt;code&amp;gt;README.txt&amp;lt;/code&amp;gt; - Readme file with basic setup instructions&lt;br /&gt;
{{Tree list/end}}&lt;br /&gt;
&lt;br /&gt;
== Basic MDK Setup ==&lt;br /&gt;
# Download the MDK from the [https://files.minecraftforge.net/ official Minecraft Forge download site] and extract the MDK into an empty folder.&lt;br /&gt;
# Open your IDE of choice, and import the project as a Gradle project.&lt;br /&gt;
#* For '''Eclipse''': &amp;lt;tt&amp;gt;File &amp;gt; Import &amp;gt; Gradle &amp;gt; Existing Gradle Project&amp;lt;/tt&amp;gt;, select the folder for the &amp;lt;tt&amp;gt;Project root directory&amp;lt;/tt&amp;gt;, click &amp;lt;tt&amp;gt;Finish&amp;lt;/tt&amp;gt;&lt;br /&gt;
#* For '''IntelliJ IDEA''': &amp;lt;tt&amp;gt;File &amp;gt; Open&amp;lt;/tt&amp;gt;, select and open the folder, select the &amp;lt;tt&amp;gt;build.gradle&amp;lt;/tt&amp;gt; file, click &amp;lt;tt&amp;gt;OK&amp;lt;/tt&amp;gt;, click &amp;lt;tt&amp;gt;Open as Project&amp;lt;/tt&amp;gt;&lt;br /&gt;
# Wait for the setup process to complete and the Minecraft sources are decompiled.&lt;br /&gt;
# Generate the run configurations for your IDE using the appropriate Gradle task. &amp;lt;br&amp;gt;These tasks can be run on the command line using ''(Windows)'' &amp;lt;code&amp;gt;gradlew gen***Runs&amp;lt;/code&amp;gt; or ''(*nix)'' &amp;lt;code&amp;gt;./gradlew gen***Runs&amp;lt;/code&amp;gt;.&lt;br /&gt;
#* For ''Eclipse'': the task is &amp;lt;code&amp;gt;genEclipseRuns&amp;lt;/code&amp;gt;; to run in the IDE directly, open the &amp;lt;tt&amp;gt;Gradle Tasks&amp;lt;/tt&amp;gt; tab on the bottom panel, ''wait until the tasks have loaded'' then expand the folder, expand the &amp;lt;tt&amp;gt;fg_runs&amp;lt;/tt&amp;gt; folder, then double-click &amp;lt;tt&amp;gt;genEclipseRuns&amp;lt;/tt&amp;gt;.&lt;br /&gt;
#* For ''IntelliJ IDEA'': the task is &amp;lt;code&amp;gt;genIntellijRuns&amp;lt;/code&amp;gt;; to run in the IDE directly, open the &amp;lt;tt&amp;gt;Gradle&amp;lt;/tt&amp;gt; on the right, expand the project folder, double-click &amp;lt;tt&amp;gt;Tasks &amp;gt; fg_runs &amp;gt; genIntellijRuns&amp;lt;/tt&amp;gt;.&lt;br /&gt;
#* For ''Visual Studio Code'': the task is &amp;lt;code&amp;gt;genVSCodeRuns&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Tip/Warning|Although there is a run generation task for Visual Studio Code, it is ''not'' officially supported by Forge. Using Visual Studio Code as an IDE for Forge mod development is not supported, and any broken functionality due to this must be solved by the user on their own.}}&lt;br /&gt;
&lt;br /&gt;
== Customizing the MDK ==&lt;br /&gt;
The MDK provides default values for the buildscript and &amp;lt;tt&amp;gt;mods.toml&amp;lt;/tt&amp;gt; file. These values should be replaced with your own mod's information.&lt;br /&gt;
&lt;br /&gt;
All edits should be done below the &amp;lt;code&amp;gt;apply plugin: 'net.minecraftforge.gradle'&amp;lt;/code&amp;gt; line. The lines above it are required for the Forge MDK to work correctly, and should not be modified without proper knowledge.&lt;br /&gt;
* All references to &amp;lt;code&amp;gt;examplemod&amp;lt;/code&amp;gt; in the buildscript should be replaced with your modid.&lt;br /&gt;
** Use your IDE's find-and-replace function to quickly replace these values.&lt;br /&gt;
** Pick a unique and memorable modid. The modid must be between 2 and 64 characters, and must consist of lowercase letters, numbers, underscores (&amp;lt;code&amp;gt;_&amp;lt;/code&amp;gt;) and hyphens (&amp;lt;code&amp;gt;-&amp;lt;/code&amp;gt;). The recommendation is to avoid using acronyms and abbreviations.&lt;br /&gt;
* Change the &amp;lt;code&amp;gt;archivesBaseName&amp;lt;/code&amp;gt; variable to your modid. This is used as the base name for the JAR file when you build your mod, and as the &amp;lt;tt&amp;gt;artifactId&amp;lt;/tt&amp;gt; of your mod's [https://maven.apache.org/pom.html#Maven_Coordinates maven coordinates].&lt;br /&gt;
* Change the &amp;lt;code&amp;gt;group&amp;lt;/code&amp;gt; to your [[Proper Mod Structuring#Packaging|unique root java package]]. This is used as the &amp;lt;tt&amp;gt;groupId&amp;lt;/tt&amp;gt; of your mod's maven coordinates.&lt;br /&gt;
* In the &amp;lt;code&amp;gt;jar&amp;lt;/code&amp;gt; task, change the values of the &amp;lt;code&amp;gt;Specification-Vendor&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;Implementation-Vendor&amp;lt;/code&amp;gt; keys to your username/brand name or other form of identification.&lt;br /&gt;
* ''Optional suggestion: '' Change the &amp;lt;code&amp;gt;version&amp;lt;/code&amp;gt; variable to have a 0 as the major version (ex. &amp;lt;code&amp;gt;'0.1'&amp;lt;/code&amp;gt;. This is to follow [[Semantic Versioning#During Development|semantic versioning guidelines]] for versions in active development.&lt;br /&gt;
&lt;br /&gt;
== Building and Testing ==&lt;br /&gt;
You can test your mod in the development environment using either your IDE's run configurations and built-in debugging utilities, or by running the &amp;lt;code&amp;gt;run*&amp;lt;/code&amp;gt; task as defined by the buildscript's run configurations.&lt;br /&gt;
&lt;br /&gt;
There are three default run configurations with the MDK:&lt;br /&gt;
* &amp;lt;code&amp;gt;runClient&amp;lt;/code&amp;gt;, for starting the client.&lt;br /&gt;
* &amp;lt;code&amp;gt;runServer&amp;lt;/code&amp;gt;, for starting the dedicated server. ''You will need to accept the EULA through the &amp;lt;tt&amp;gt;eula.txt&amp;lt;/tt&amp;gt; after running the server for the first time.''&lt;br /&gt;
* &amp;lt;code&amp;gt;runData&amp;lt;/code&amp;gt;, for starting the client in [[Datageneration|data generation]] mode.&lt;br /&gt;
&lt;br /&gt;
{{Tip|Always test your mod in both the client and the dedicated server, even if you are making a one-sided mod. Mods should not crash when running on both sides, and one-sided mods should not crash if they run on the wrong side.}}&lt;br /&gt;
&lt;br /&gt;
You can build your mod's final JAR using the &amp;lt;code&amp;gt;build&amp;lt;/code&amp;gt; task. The resulting JAR will be located in the &amp;lt;code&amp;gt;build/libs&amp;lt;/code&amp;gt; folder under your project directory.&lt;br /&gt;
&lt;br /&gt;
[[Category:Getting Started]]&lt;/div&gt;</summary>
		<author><name>Curle</name></author>
	</entry>
	<entry>
		<id>https://forge.gemwire.uk/index.php?title=Toolchain&amp;diff=2392</id>
		<title>Toolchain</title>
		<link rel="alternate" type="text/html" href="https://forge.gemwire.uk/index.php?title=Toolchain&amp;diff=2392"/>
		<updated>2021-01-19T02:09:09Z</updated>

		<summary type="html">&lt;p&gt;Curle: SRG-&amp;gt;Searge's Retro Guard&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{DISPLAYTITLE:Deobfuscation Process}}&lt;br /&gt;
{{Under construction}}&lt;br /&gt;
&lt;br /&gt;
The Forge toolchain is designed to clean up, merge, deobfuscate, rename, patch and provide the Minecraft source code for the usage of modders, researchers, or just those curious about how the game works.&lt;br /&gt;
&lt;br /&gt;
This serves as an explanation as to how the development environment sets up your code, and aims to help you troubleshoot in case something goes wrong.&lt;br /&gt;
&lt;br /&gt;
== Overall process ==&lt;br /&gt;
When setting up the environment for the first time, a gradle refresh triggers three things:&lt;br /&gt;
# ForgeGradle downloads the MCPConfig zip for the file you're using, and triggers the SetupMCP task.&lt;br /&gt;
# After that, it processes the jar - applies access transformers, MCPCleanup and others&lt;br /&gt;
# Finally, it patches and finalises the code, ready for modder consumption.&lt;br /&gt;
&lt;br /&gt;
== Needed knowledge ==&lt;br /&gt;
=== Obfuscation ===&lt;br /&gt;
'''Obfuscation''' is the process of renaming all of the fields, methods, and classes of the compiled code into unreadable, machine-generated names (such as &amp;lt;code&amp;gt;aaa&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;bC&amp;lt;/code&amp;gt;), and removing package structures (this makes everything package-local and makes the obfuscated code smaller somewhat. This is commonly used by companies to prevent external entities from easily decompiling their released binaries/executables and retrieving their source code/intellectual property, though it does have size advantages.&lt;br /&gt;
&lt;br /&gt;
Additionally, due to the way the Local Variable Table (LVT) of Java bytecode is stored, every function-local variable name is turned to ☃ (that's right, a snowman) in the compiled files. This makes immediate recompilation of the game literally and physically impossible, as every Java compiler currently available requires that local variables have unique names.&lt;br /&gt;
&lt;br /&gt;
Minecraft is a commercial game, which means the source code is unavailable to all except the developers of Mojang. To prevent piracy and the copying of their intellectual property, Mojang applies this obfuscation process to the game before they release it. They use a tool called [https://www.guardsquare.com/en/products/proguard ProGuard], which is both an optimizer&amp;lt;ref&amp;gt;An optimizer is a program that removes redundant/unused instructions and compacts the code to be faster and smaller.&amp;lt;/ref&amp;gt; and an obfuscator.&lt;br /&gt;
&lt;br /&gt;
=== Problematic Naming ===&lt;br /&gt;
There are a few big problems with using these obfuscated names directly for modding.&lt;br /&gt;
&lt;br /&gt;
# It is incredibly difficult to create mods using these obfuscated names. It requires immense patience to reverse-engineer the meanings behind each and every name, and to keep relating those names to what was already reverse-engineered. Although, tools do exist to make this process easier, such as IntelliJ IDEA plugins that provide naming hints automatically.&lt;br /&gt;
# Because the obfuscation process takes place after compilation (the obfuscator operates on the compiled classes), the obfuscated names are not handled by the compiler. Thus, obfuscated classes may contain member&amp;lt;ref&amp;gt;'''member''' refers to class fields and methods.&amp;lt;/ref&amp;gt; names that are invalid in the Java source language, but valid in compiled bytecode (like ☃ discussed earlier); this means that the decompiled source of the game is not immediately recompilable.&lt;br /&gt;
# These obfuscated names are automatically generated by the obfuscator for each independent release. This means that the obfuscated names may change signficantly between any two versions, making it harder for mod developers to update mods between releases.&lt;br /&gt;
&lt;br /&gt;
=== SRGification ===&lt;br /&gt;
Some background on what SRG is and how it works:&lt;br /&gt;
&lt;br /&gt;
'''SRG''' stands for '''S'''earge's ''R'''etro ''G''uard; RetroGuard being an early attempt to reverse the ProGuard obfuscation, and Searge being co-author of the Mod Creator Pack, who created this process.&lt;br /&gt;
Each obfuscated class, method, and field is assigned a unique number by the [[Toolchain:MCPConfig|backend]], via a sequential counter. This unique number is called the '''SRG ID''' of that class/method/field (henceforth called member).&lt;br /&gt;
&lt;br /&gt;
The SRG name of the member is then derived from its SRG ID, its type (function {given the prefix func_}, field {given the prefix field_}, parameter {given the prefix p_, or p_i if this is the parameter of a constructor}), and (optionally) the obfuscated name of the object at the time it was given its SRG name&amp;lt;ref&amp;gt;The SRG name for a given member is only created once, when it first appears in the code. Therefore, the SRG postfix may be different from the current obf name.&amp;lt;/ref&amp;gt;. This inclusion of the SRG ID into the name guarantees that the SRG name for all members are unique, and is the reason the ID is generated.&lt;br /&gt;
&lt;br /&gt;
The actual conversion of obf names to SRG names is done by a tool called [[Toolchain:SpecialSource|SpecialSource]]. More information on how it works can be found on that page.&lt;br /&gt;
&lt;br /&gt;
== The Setup ==&lt;br /&gt;
The process can be broken up into 3 steps; MCPConfig, patch and provide.&lt;br /&gt;
The MCPConfig step is, understandably, the biggest and most prone to failure.&lt;br /&gt;
An explanation of MCPConfig itself, how it works, what it's for (but NOT how to use it) can be found [[Toolchain:MCPConfig|here]]. For the purpose of this guide, you need only know that its' goal is to get the game decompiled, and into a state where it can immediately be recompiled. Due to certain flaws in the rest of the toolchain, this means it needs to fix and patch the source code before passing it onto Forge.&lt;br /&gt;
&lt;br /&gt;
In this way, MCPConfig can be thought of the vanilla side of the setup. It does not modify the game.&lt;br /&gt;
&lt;br /&gt;
The following steps are all executed in order of appearance.&lt;br /&gt;
&lt;br /&gt;
=== Download and parsing MCPConfig ===&lt;br /&gt;
The first thing that ForgeGradle does upon initialising a first-time setup, is starting the [https://github.com/MinecraftForge/ForgeGradle/blob/e2ed49546abced95650635f81be071441ec60995/src/mcp/java/net/minecraftforge/gradle/mcp/task/SetupMCPTask.java#L91 SetupMCP] task. &lt;br /&gt;
&lt;br /&gt;
This task then seeks to [https://github.com/MinecraftForge/ForgeGradle/blob/e2ed49546abced95650635f81be071441ec60995/src/mcp/java/net/minecraftforge/gradle/mcp/task/DownloadMCPConfigTask.java#L78 download the MCPConfig.zip jar] for the version you're setting up.&lt;br /&gt;
Once it is acquired, it &lt;br /&gt;
[https://github.com/MinecraftForge/ForgeGradle/blob/e2ed49546abced95650635f81be071441ec60995/src/mcp/java/net/minecraftforge/gradle/mcp/util/MCPRuntime.java#L74 parses the steps contained within the config.json]. It does this by interpreting the file with the following rules:&lt;br /&gt;
* Every key, except for libraries, is interpreted as the name of a step.&lt;br /&gt;
* Steps are executed in order.&lt;br /&gt;
* The version value is interpreted as a maven coordinate of a file to download.&lt;br /&gt;
* If there is a repo value, it is used instead of the maven repositories defined in the buildscript, to retrieve the version.&lt;br /&gt;
* The args array is parsed, and {values} like this are interpreted as inputs, which can be substituted accordingly.&lt;br /&gt;
* Once the step is all parsed in, it is executed:&lt;br /&gt;
** java -jar &amp;amp;lt;version&amp;amp;gt; &amp;amp;lt;args&amp;amp;gt; &amp;amp;lt;jvmArgs&amp;amp;gt;&lt;br /&gt;
&lt;br /&gt;
An example config.json can be found [https://github.com/MinecraftForge/MCPConfig/blob/master/versions/release/1.16.4/config.json here].&lt;br /&gt;
&lt;br /&gt;
It defines the steps:&lt;br /&gt;
* [[Toolchain:MCinjector|mcinjector]]&lt;br /&gt;
** version: de.oceanlabs.mcp:mcinjector:3.8.0:fatjar&lt;br /&gt;
** args: --in {input} --out {output} --log {log} --level=INFO --lvt=LVT --exc {exceptions} --acc {access} --ctr {constructors}&lt;br /&gt;
* [[Toolchain:ForgeFlower|fernflower]]&lt;br /&gt;
** version: net.minecraftforge:forgeflower:1.5.478.16&lt;br /&gt;
** args: -din=1 -rbr=1 -dgs=1 -asc=1 -rsy=1 -iec=1 -jvn=1 -isl=0 -iib=1 -log=TRACE -cfg {libraries} {input} {output}&lt;br /&gt;
** jvmargs: -Xmx4G&lt;br /&gt;
* [[Toolchain:Mergetool|merge]]&lt;br /&gt;
** version: net.minecraftforge:mergetool:1.1.1:fatjar&lt;br /&gt;
** args: --client {client} --server {server} --ann {version} --output {output} --inject false&amp;quot;&lt;br /&gt;
* [[Toolchain:MCInjector|rename]]&lt;br /&gt;
** version: net.md-5:SpecialSource:1.8.3:shaded&lt;br /&gt;
** args: --in-jar {input} --out-jar {output} --srg-in {mappings}&lt;br /&gt;
** repo: https://repo1.maven.org/maven2/&lt;br /&gt;
&lt;br /&gt;
More information about each of these tools can be found at the link provided, as well as what each of these arguments do. A brief description is provided.&lt;br /&gt;
&lt;br /&gt;
=== MCInjector ===&lt;br /&gt;
[https://github.com/ModCoderPack/MCInjector MCInjector] is the tool we use to apply various fixes to the code, while it is still in bytecode form. That meaning, it works on compiled code, not sourcecode. It does this because it's easier to rename LVT entries (from the snowman) to readable names while you can search for every other code path that references that specific entry; ergo renaming all accesses at once. This is impossible in sourcecode, where every name is identical and string matching is impossible.&lt;br /&gt;
&lt;br /&gt;
It:&lt;br /&gt;
* Removes synthetic parameters from constructors&lt;br /&gt;
** In bytecode, inner classes have the outer class as their first constructor parameter, but Java source code does not.&lt;br /&gt;
* Handles adding annotations for parameters that have synthetic data&lt;br /&gt;
** In bytecode, these Nonnull (or whatever) annotations are attached to the parameters, not to the function that contains them.&lt;br /&gt;
* Adds constructors for inner classes&lt;br /&gt;
** These are removed by Proguard sometimes, as they are not required in the bytecode if the parent has a default constructor.&lt;br /&gt;
* Adds synthetic (invisible) constructors for classes without them&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
It also applies fixes for things like EXC;&lt;br /&gt;
* Renaming parameters inside constructors, such that subclasses retain the ID of their parent.&lt;br /&gt;
* Fixing access for select functions, where it is required for the proper recompilation.&lt;br /&gt;
* Applying proper typing to constructor parameters&lt;br /&gt;
* Applying proper external (LWJGL) exception data to functions and classes.&lt;br /&gt;
&lt;br /&gt;
Note that it does NOT rename to SRG. LVT (Local Variables) are renamed to lvt_&amp;amp;lt;index&amp;amp;gt;_&amp;amp;lt;version&amp;amp;gt;&amp;lt;ref&amp;gt;Index means: the place where this item was found. If it is the 4th entry in the table, it is index 3.&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== ForgeFlower === &lt;br /&gt;
After the code has been cleaned up by MCInjector, to a state where it no longer conflicts with itself, it can be passed to the decompiler. &lt;br /&gt;
&lt;br /&gt;
The decompiler used by ForgeGradle is a custom fork of [https://github.com/JetBrains/intellij-community/tree/master/plugins/java-decompiler/engine Jetbrains' FernFlower], called [https://github.com/MinecraftForge/ForgeFlower ForgeFlower].&lt;br /&gt;
&lt;br /&gt;
It simply searches the jar for files, converts the bytecode into a reasonable best-guess interpretation.&lt;br /&gt;
&lt;br /&gt;
As you can see by the repository, a lot of work has gone into tuning it for Minecraft's needs, but it is still a far way from perfect. This is why the patches are needed.&lt;br /&gt;
&lt;br /&gt;
If you [https://github.com/MinecraftForge/MCPConfig/blob/master/versions/release/1.16.4/patches/ look at the patches] for 1.16.4, they are mostly incredibly simple changes. Adding generics, making types more strict. &lt;br /&gt;
&lt;br /&gt;
This is all stuff that should be done by the decompiler, and PRs are always welcome at the ForgeFlower repository for changes and fixes that would reduce the amount of MCPConfig patches required to get the game to compile.&lt;br /&gt;
&lt;br /&gt;
For now, it is a necessity.&lt;br /&gt;
&lt;br /&gt;
=== Mergetool ===&lt;br /&gt;
The game is split into two distributions; server and client.&lt;br /&gt;
&lt;br /&gt;
Because the server contains no rendering code, and the client contains none of the server-specific code (like the UI), this means there are differences between what can run on one side or the other.&lt;br /&gt;
&lt;br /&gt;
To get around this, we have a tool called Mergetool, which can search for the differences between two files (down to the function level) and merge them into one large (referred to as joined) jar file.&lt;br /&gt;
&lt;br /&gt;
It is a simple program, but it works.&lt;br /&gt;
&lt;br /&gt;
=== SpecialSource ===&lt;br /&gt;
SpecialSource is where SRG starts to come into play. It serves the role of our deobfuscator, performing deobfuscation.&lt;br /&gt;
&lt;br /&gt;
This process is done with the help of a '''deobfusation map''', a file generated by the original obfuscator (in this case, ProGuard) that contains a map of the obfuscated names to original, non-obfuscated names. This is commonly used on debofuscating stack traces outputted by an obfuscated program, for debugging purposes.&amp;lt;ref name=&amp;quot;retrace&amp;quot;/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We have three sets of deobfuscation maps available to us; the obf-&amp;gt;SRG mappings distributed with the MCPConfig system, the Yarn intermediary system, or the offical mappings.&amp;lt;ref name=&amp;quot;mojmappings&amp;quot;/&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
To rectify this problem, Forge has it's own process to create deobfuscation mappings for the game, using community-sourced human-readable names. This process is split into two separate parts: the '''SRG renaming''', and the '''MCP mapping'''. During the SetupMCP task, only the SRG renaming is performed.&lt;br /&gt;
&lt;br /&gt;
SpecialSource itself operates on the source jar, as can be gathered by the name, and takes in a .tsrg file, like that [https://github.com/MinecraftForge/MCPConfig/blob/master/versions/release/1.16.4/joined.tsrg contained in the MCPConfig zip].&lt;br /&gt;
&lt;br /&gt;
It first renames classes, straight into MCP names.&lt;br /&gt;
Then, iterating the members of the class, it renames fields, methods, parameters and inner classes.&lt;br /&gt;
&lt;br /&gt;
A recap from earlier:&lt;br /&gt;
* For classes -&amp;gt; &amp;lt;code&amp;gt;c_###_&amp;lt;/code&amp;gt; (but it is immediately changed without the c_ being written to disk)&lt;br /&gt;
* For functions/methods -&amp;gt; &amp;lt;code&amp;gt;func_&amp;amp;lt;ID&amp;amp;gt;_&amp;amp;lt;obf-name&amp;amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
* For fields -&amp;gt; &amp;lt;code&amp;gt;field_&amp;amp;lt;ID&amp;amp;gt;_&amp;amp;lt;obf-name&amp;amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
* For function/method parameters -&amp;gt; &amp;lt;code&amp;gt;p_###_#_&amp;lt;/code&amp;gt; for normal methods, &amp;lt;code&amp;gt;p_i###_#&amp;lt;/code&amp;gt; for constructors; the second number is the index&amp;lt;ref&amp;gt;The index is the position of the argument. 0 on the left, 1 after that, 2 after that. Note that double and long arguments increase their index by two, rather than one.&amp;lt;/ref&amp;gt; of the parameter.&lt;br /&gt;
&lt;br /&gt;
For example, &amp;lt;code&amp;gt;func_71410_x&amp;lt;/code&amp;gt; refers to a function with SRG ID 71410 and original obfuscated name of &amp;lt;code&amp;gt;x&amp;lt;/code&amp;gt;.&amp;lt;ref&amp;gt;For version 1.16.2, &amp;lt;code&amp;gt;func_71410_x&amp;lt;/code&amp;gt; refers to &amp;lt;code&amp;gt;Minecraft.getInstance()&amp;lt;/code&amp;gt;, with real obfuscated name of &amp;lt;code&amp;gt;B&amp;lt;/code&amp;gt;, but when the getInstance() function was first discovered in code, it was called x.&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
At this point, combined with the MCInjector step from earlier, we have a completely SRGed-up source jar.&lt;br /&gt;
&lt;br /&gt;
=== Patches ===&lt;br /&gt;
Once we have the source code ready to go, the final step in the setup is to apply patches.&lt;br /&gt;
These are done trivially, using diffs and [https://github.com/CadixDev/gitpatcher gitpatcher].&lt;br /&gt;
&lt;br /&gt;
=== Clean-up ===&lt;br /&gt;
Because of the way Proguard (or whatever obfuscator) and ForgeFlower mangle the source code, we need to take some steps to clean it up before we can proceed.&lt;br /&gt;
&lt;br /&gt;
Assorted cleanup fixes are performed by the [https://github.com/MinecraftForge/MCPCleanup/ MCPCleanup] utility. These include:&lt;br /&gt;
* removing trailing whitespace at the end of lines&lt;br /&gt;
* removing extra newlines at the start and end of files&lt;br /&gt;
* removing extra newlines between every line of code (every set of concurrent newlines is replaced with a single)&lt;br /&gt;
* removing comments (// hello, /* hello */)&lt;br /&gt;
** the purpose of this step is unclear - it seems to be a preventative measure to ensure that Java changes do not interfere with the patch alignment in the future. Comments from the decompiler are still sometimes present in the source code.&lt;br /&gt;
* removing imports from the package a class is in&lt;br /&gt;
* removing comments that include the phrase &amp;lt;code&amp;gt;GL_[^*]+&amp;lt;/code&amp;gt;&lt;br /&gt;
* replacing [[Toolchain:Magic Constants|magic constants]] with their code substitutions&lt;br /&gt;
* replacing &amp;lt;code&amp;gt;Character.valueOf(&amp;amp;lt;character&amp;amp;gt;)&amp;lt;/code&amp;gt; with &amp;lt;code&amp;gt;&amp;amp;lt;character&amp;amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
* replacing OpenGL integer constants with their code representation&lt;br /&gt;
* converting unicode character constants back into integer representation&lt;br /&gt;
* formatting the code with JAStyle&lt;br /&gt;
&lt;br /&gt;
It also adjusts abstract functions in some way - after running the program on a jar, the parameters of a default abstract function get renamed, but it is unclear exactly what part of the source code does this.&lt;br /&gt;
&lt;br /&gt;
== The Forge Side ==&lt;br /&gt;
&lt;br /&gt;
After the MCPConfig/SetupMCP tasks are finished, ForgeGradle will print '''MCP Environment Setup is complete''' and wait for the user input.&lt;br /&gt;
&lt;br /&gt;
The next step is to run the &amp;lt;code&amp;gt;gradlew setup&amp;lt;/code&amp;gt; task, which does what it implies: Applying the Forge system to the processed vanilla code.&lt;br /&gt;
&lt;br /&gt;
First, it applies ATs. After that, patches. Finally, MCP/Crowdsourced mappings are applied.&lt;br /&gt;
&lt;br /&gt;
All in all, compared to the MCPConfig setup, this is a string of extremely basic tasks - mostly just one-line commands.&lt;br /&gt;
&lt;br /&gt;
=== Applying Access Transformers ===&lt;br /&gt;
&lt;br /&gt;
[[Access Transformers]] are a way of changing the visibility and finality of classes and class members. A full explanation of how it works, what the specification is, and what exactly they're used for, can be found at that page.&lt;br /&gt;
&lt;br /&gt;
They are applied by passing the AT Config (nowadays called accesstransformer.cfg) into SpecialSource:&lt;br /&gt;
* &amp;lt;code&amp;gt;SpecialSource.jar --in-jar {input} --out-jar {output} --access-transformer {at.cfg}&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[https://github.com/MinecraftForge/MinecraftForge/blob/c3e84646db70f518dd0b37a8fcfc42cb814d7ba8/src/main/resources/META-INF/accesstransformer.cfg The current AT cfg can be found here.]&lt;br /&gt;
&lt;br /&gt;
=== Applying Patches ===&lt;br /&gt;
&lt;br /&gt;
The patches used for Forge itself are different from those used by MCPConfig, which means there are two separate patching stages performed.&lt;br /&gt;
&lt;br /&gt;
As opposed to the minimal MCPConfig patching, with the goal to make the code recompileable, the Forge patching is done to apply the API and modloader to the code.&lt;br /&gt;
&lt;br /&gt;
It does this in a very similar way, with the [https://github.com/CadixDev/gitpatcher gitpatcher] utility.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Applying Mappings ===&lt;br /&gt;
This step isn't strictly necessary, and it can be ommitted. However, working with exclusively SRG names is confusing for most people, so we have an extra step to apply human names to the SRG.&lt;br /&gt;
&lt;br /&gt;
These renames can come from any source; as mentioned earlier, the MCP/Crowdsourced naming, the Yarn naming, or the Mojang Obf-map naming. ForgeGradle does not care, as long as there is a valid SRG-&amp;gt;names map.&lt;br /&gt;
&lt;br /&gt;
How ForgeGradle retrieves these mappings is covered in the [[ForgeGradle/mappings|appropriate article]].&lt;br /&gt;
&lt;br /&gt;
The process of renaming itself is a simple regex substitution, performed by [https://github.com/MinecraftForge/ForgeGradle/blob/e2ed49546abced95650635f81be071441ec60995/src/common/java/net/minecraftforge/gradle/common/util/McpNames.java#L104 ForgeGradle itself]. This is made possible by the assured uniqueness of SRG names.&lt;br /&gt;
&lt;br /&gt;
=== Post-processing ===&lt;br /&gt;
&lt;br /&gt;
At this point, the files are ready to go. We have processed the Minecraft jar such that it can be recompiled, we have applied appropriate access transformers and the Forge patches, and optionally renamed every applicable SRG name to whatever chosen distribution of mappings.&lt;br /&gt;
&lt;br /&gt;
There is not much left to do but package the code into a jar file, and place it into the gradle cache (so that this process does not occur every single time the project is opened). It calculates this name based on many factors, and this is covered in the [[ForgeGradle#naming|naming]] article.&lt;br /&gt;
&lt;br /&gt;
== Some additional Infos ==&lt;br /&gt;
# You will never see c_XXX_ for classes, because the class names are picked beforehand&lt;br /&gt;
#* this is still crowdsourced, but before a new version is ready for Forge, all classes are given an &amp;lt;code&amp;gt;MCP&amp;lt;/code&amp;gt; name&lt;br /&gt;
#* this &amp;lt;code&amp;gt;MCP&amp;lt;/code&amp;gt; name stays constant throughout the game version it was picked for; it can change between versions, but it usually wont for already-named classes (except for misspells, typos, and misnames)&lt;br /&gt;
# If you look into the JAR, you won't see any packages for the obfuscated classes, but the deobfuscated classes do have the packages, this is because the same process that names the classes, also decides what package they belong to&lt;br /&gt;
# parameters have special names&lt;br /&gt;
#* there are two types of parameter names: &amp;lt;code&amp;gt;p_XXX_X_&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;p_iXXX_X_&amp;lt;/code&amp;gt;&lt;br /&gt;
#* the one with the i means that it's a parameter for a constructor&lt;br /&gt;
#* the first set of numbers are the SRG ID of their parent method, and the second number denotes the index of the parameter&lt;br /&gt;
#* the index of the parameter is a bit more involved, but this will not be explained here&lt;br /&gt;
# If you look into the source, you'll see that parameters for lambdas don't have mapped names&lt;br /&gt;
#* This is because of a complication in how the lambdas are compiled/decompiled; it's a more advanced topic which involves how the compiler compiles lambdas which we will not explain here.&lt;br /&gt;
&lt;br /&gt;
== See also ==&lt;br /&gt;
* [https://en.wikipedia.org/wiki/Obfuscation_(software) Obfuscation]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;references&amp;gt;&lt;br /&gt;
&amp;lt;ref name=&amp;quot;retrace&amp;quot;&amp;gt;For ProGuard users (such as Mojang), this is done using [https://www.guardsquare.com/en/products/proguard/manual/retrace ReTrace].&amp;lt;/ref&amp;gt;&lt;br /&gt;
&amp;lt;ref name=&amp;quot;mojmappings&amp;quot;&amp;gt;Mojang recently released their deobfuscation mappings for Minecraft (colloquially named &amp;lt;code&amp;gt;mojmappings&amp;lt;/code&amp;gt;), but the licensing for its uses is a bit ambiguous. [https://cpw.github.io/MinecraftMappingData See this post by cpw] for more information.&amp;lt;/ref&amp;gt;&lt;br /&gt;
&amp;lt;/references&amp;gt;&lt;/div&gt;</summary>
		<author><name>Curle</name></author>
	</entry>
	<entry>
		<id>https://forge.gemwire.uk/index.php?title=Main_Page&amp;diff=2390</id>
		<title>Main Page</title>
		<link rel="alternate" type="text/html" href="https://forge.gemwire.uk/index.php?title=Main_Page&amp;diff=2390"/>
		<updated>2021-01-11T17:04:00Z</updated>

		<summary type="html">&lt;p&gt;Curle: Rename toolchain article&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.4'''. 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|Getting Started]]&lt;br /&gt;
* [[Proper_Mod_Structuring|Proper Mod Structuring]]&lt;br /&gt;
* [[Debug_Profiler|The Debug Profiler]]&lt;br /&gt;
* [[Update_Checker|Update 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|Registration]]&lt;br /&gt;
* [[Internationalization|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|Semantic Versioning]]&lt;br /&gt;
* [[Stages_of_Modloading|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|Recipes]]&lt;br /&gt;
* [[Tags|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|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|Making Items]]&lt;br /&gt;
* [[Making_Tools|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|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|Model JSONs]]&lt;br /&gt;
* [[BlockState_JSONs|BlockState JSONs]]&lt;br /&gt;
* [[Coloring_textures_dynamically|Dynamically Colored Textures]]&lt;br /&gt;
* [[Item_Overrides|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|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|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|Effects]]&lt;br /&gt;
* [[Potions|Potions]]&lt;br /&gt;
* [[Particles|Particles]]&lt;br /&gt;
* [[Sounds|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;Others&amp;lt;/h3&amp;gt;&lt;br /&gt;
* [[Dynamic_Loot_Modification|Dynamic Loot Modification]]&lt;br /&gt;
* [[Key_Bindings|Key Bindings]]&lt;br /&gt;
* [[Access_Transformers|Access Transformers]]&lt;br /&gt;
* [[Toolchain|ForgeGradle Setup]]&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>Curle</name></author>
	</entry>
	<entry>
		<id>https://forge.gemwire.uk/index.php?title=Toolchain&amp;diff=2389</id>
		<title>Toolchain</title>
		<link rel="alternate" type="text/html" href="https://forge.gemwire.uk/index.php?title=Toolchain&amp;diff=2389"/>
		<updated>2021-01-11T17:00:18Z</updated>

		<summary type="html">&lt;p&gt;Curle: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{DISPLAYTITLE:Deobfuscation Process}}&lt;br /&gt;
{{Under construction}}&lt;br /&gt;
&lt;br /&gt;
The Forge toolchain is designed to clean up, merge, deobfuscate, rename, patch and provide the Minecraft source code for the usage of modders, researchers, or just those curious about how the game works.&lt;br /&gt;
&lt;br /&gt;
This serves as an explanation as to how the development environment sets up your code, and aims to help you troubleshoot in case something goes wrong.&lt;br /&gt;
&lt;br /&gt;
== Overall process ==&lt;br /&gt;
When setting up the environment for the first time, a gradle refresh triggers three things:&lt;br /&gt;
# ForgeGradle downloads the MCPConfig zip for the file you're using, and triggers the SetupMCP task.&lt;br /&gt;
# After that, it processes the jar - applies access transformers, MCPCleanup and others&lt;br /&gt;
# Finally, it patches and finalises the code, ready for modder consumption.&lt;br /&gt;
&lt;br /&gt;
== Needed knowledge ==&lt;br /&gt;
=== Obfuscation ===&lt;br /&gt;
'''Obfuscation''' is the process of renaming all of the fields, methods, and classes of the compiled code into unreadable, machine-generated names (such as &amp;lt;code&amp;gt;aaa&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;bC&amp;lt;/code&amp;gt;), and removing package structures (this makes everything package-local and makes the obfuscated code smaller somewhat. This is commonly used by companies to prevent external entities from easily decompiling their released binaries/executables and retrieving their source code/intellectual property, though it does have size advantages.&lt;br /&gt;
&lt;br /&gt;
Additionally, due to the way the Local Variable Table (LVT) of Java bytecode is stored, every function-local variable name is turned to ☃ (that's right, a snowman) in the compiled files. This makes immediate recompilation of the game literally and physically impossible, as every Java compiler currently available requires that local variables have unique names.&lt;br /&gt;
&lt;br /&gt;
Minecraft is a commercial game, which means the source code is unavailable to all except the developers of Mojang. To prevent piracy and the copying of their intellectual property, Mojang applies this obfuscation process to the game before they release it. They use a tool called [https://www.guardsquare.com/en/products/proguard ProGuard], which is both an optimizer&amp;lt;ref&amp;gt;An optimizer is a program that removes redundant/unused instructions and compacts the code to be faster and smaller.&amp;lt;/ref&amp;gt; and an obfuscator.&lt;br /&gt;
&lt;br /&gt;
=== Problematic Naming ===&lt;br /&gt;
There are a few big problems with using these obfuscated names directly for modding.&lt;br /&gt;
&lt;br /&gt;
# It is incredibly difficult to create mods using these obfuscated names. It requires immense patience to reverse-engineer the meanings behind each and every name, and to keep relating those names to what was already reverse-engineered. Although, tools do exist to make this process easier, such as IntelliJ IDEA plugins that provide naming hints automatically.&lt;br /&gt;
# Because the obfuscation process takes place after compilation (the obfuscator operates on the compiled classes), the obfuscated names are not handled by the compiler. Thus, obfuscated classes may contain member&amp;lt;ref&amp;gt;'''member''' refers to class fields and methods.&amp;lt;/ref&amp;gt; names that are invalid in the Java source language, but valid in compiled bytecode (like ☃ discussed earlier); this means that the decompiled source of the game is not immediately recompilable.&lt;br /&gt;
# These obfuscated names are automatically generated by the obfuscator for each independent release. This means that the obfuscated names may change signficantly between any two versions, making it harder for mod developers to update mods between releases.&lt;br /&gt;
&lt;br /&gt;
=== SRGification ===&lt;br /&gt;
Some background on what SRG is and how it works:&lt;br /&gt;
&lt;br /&gt;
'''SRG''' stands for '''S'''ea'''RG'''e, co-author of the Mod Creator Pack, who created this process.&lt;br /&gt;
Each obfuscated class, method, and field is assigned a unique number by the [[Toolchain:MCPConfig|backend]], via a sequential counter. This unique number is called the '''SRG ID''' of that class/method/field (henceforth called member).&lt;br /&gt;
&lt;br /&gt;
The SRG name of the member is then derived from its SRG ID, its type (function {given the prefix func_}, field {given the prefix field_}, parameter {given the prefix p_, or p_i if this is the parameter of a constructor}), and (optionally) the obfuscated name of the object at the time it was given its SRG name&amp;lt;ref&amp;gt;The SRG name for a given member is only created once, when it first appears in the code. Therefore, the SRG postfix may be different from the current obf name.&amp;lt;/ref&amp;gt;. This inclusion of the SRG ID into the name guarantees that the SRG name for all members are unique, and is the reason the ID is generated.&lt;br /&gt;
&lt;br /&gt;
The actual conversion of obf names to SRG names is done by a tool called [[Toolchain:SpecialSource|SpecialSource]]. More information on how it works can be found on that page.&lt;br /&gt;
&lt;br /&gt;
== The Setup ==&lt;br /&gt;
The process can be broken up into 3 steps; MCPConfig, patch and provide.&lt;br /&gt;
The MCPConfig step is, understandably, the biggest and most prone to failure.&lt;br /&gt;
An explanation of MCPConfig itself, how it works, what it's for (but NOT how to use it) can be found [[Toolchain:MCPConfig|here]]. For the purpose of this guide, you need only know that its' goal is to get the game decompiled, and into a state where it can immediately be recompiled. Due to certain flaws in the rest of the toolchain, this means it needs to fix and patch the source code before passing it onto Forge.&lt;br /&gt;
&lt;br /&gt;
In this way, MCPConfig can be thought of the vanilla side of the setup. It does not modify the game.&lt;br /&gt;
&lt;br /&gt;
The following steps are all executed in order of appearance.&lt;br /&gt;
&lt;br /&gt;
=== Download and parsing MCPConfig ===&lt;br /&gt;
The first thing that ForgeGradle does upon initialising a first-time setup, is starting the [https://github.com/MinecraftForge/ForgeGradle/blob/e2ed49546abced95650635f81be071441ec60995/src/mcp/java/net/minecraftforge/gradle/mcp/task/SetupMCPTask.java#L91 SetupMCP] task. &lt;br /&gt;
&lt;br /&gt;
This task then seeks to [https://github.com/MinecraftForge/ForgeGradle/blob/e2ed49546abced95650635f81be071441ec60995/src/mcp/java/net/minecraftforge/gradle/mcp/task/DownloadMCPConfigTask.java#L78 download the MCPConfig.zip jar] for the version you're setting up.&lt;br /&gt;
Once it is acquired, it &lt;br /&gt;
[https://github.com/MinecraftForge/ForgeGradle/blob/e2ed49546abced95650635f81be071441ec60995/src/mcp/java/net/minecraftforge/gradle/mcp/util/MCPRuntime.java#L74 parses the steps contained within the config.json]. It does this by interpreting the file with the following rules:&lt;br /&gt;
* Every key, except for libraries, is interpreted as the name of a step.&lt;br /&gt;
* Steps are executed in order.&lt;br /&gt;
* The version value is interpreted as a maven coordinate of a file to download.&lt;br /&gt;
* If there is a repo value, it is used instead of the maven repositories defined in the buildscript, to retrieve the version.&lt;br /&gt;
* The args array is parsed, and {values} like this are interpreted as inputs, which can be substituted accordingly.&lt;br /&gt;
* Once the step is all parsed in, it is executed:&lt;br /&gt;
** java -jar &amp;amp;lt;version&amp;amp;gt; &amp;amp;lt;args&amp;amp;gt; &amp;amp;lt;jvmArgs&amp;amp;gt;&lt;br /&gt;
&lt;br /&gt;
An example config.json can be found [https://github.com/MinecraftForge/MCPConfig/blob/master/versions/release/1.16.4/config.json here].&lt;br /&gt;
&lt;br /&gt;
It defines the steps:&lt;br /&gt;
* [[Toolchain:MCinjector|mcinjector]]&lt;br /&gt;
** version: de.oceanlabs.mcp:mcinjector:3.8.0:fatjar&lt;br /&gt;
** args: --in {input} --out {output} --log {log} --level=INFO --lvt=LVT --exc {exceptions} --acc {access} --ctr {constructors}&lt;br /&gt;
* [[Toolchain:ForgeFlower|fernflower]]&lt;br /&gt;
** version: net.minecraftforge:forgeflower:1.5.478.16&lt;br /&gt;
** args: -din=1 -rbr=1 -dgs=1 -asc=1 -rsy=1 -iec=1 -jvn=1 -isl=0 -iib=1 -log=TRACE -cfg {libraries} {input} {output}&lt;br /&gt;
** jvmargs: -Xmx4G&lt;br /&gt;
* [[Toolchain:Mergetool|merge]]&lt;br /&gt;
** version: net.minecraftforge:mergetool:1.1.1:fatjar&lt;br /&gt;
** args: --client {client} --server {server} --ann {version} --output {output} --inject false&amp;quot;&lt;br /&gt;
* [[Toolchain:MCInjector|rename]]&lt;br /&gt;
** version: net.md-5:SpecialSource:1.8.3:shaded&lt;br /&gt;
** args: --in-jar {input} --out-jar {output} --srg-in {mappings}&lt;br /&gt;
** repo: https://repo1.maven.org/maven2/&lt;br /&gt;
&lt;br /&gt;
More information about each of these tools can be found at the link provided, as well as what each of these arguments do. A brief description is provided.&lt;br /&gt;
&lt;br /&gt;
=== MCInjector ===&lt;br /&gt;
[https://github.com/ModCoderPack/MCInjector MCInjector] is the tool we use to apply various fixes to the code, while it is still in bytecode form. That meaning, it works on compiled code, not sourcecode. It does this because it's easier to rename LVT entries (from the snowman) to readable names while you can search for every other code path that references that specific entry; ergo renaming all accesses at once. This is impossible in sourcecode, where every name is identical and string matching is impossible.&lt;br /&gt;
&lt;br /&gt;
It:&lt;br /&gt;
* Removes synthetic parameters from constructors&lt;br /&gt;
** In bytecode, inner classes have the outer class as their first constructor parameter, but Java source code does not.&lt;br /&gt;
* Handles adding annotations for parameters that have synthetic data&lt;br /&gt;
** In bytecode, these Nonnull (or whatever) annotations are attached to the parameters, not to the function that contains them.&lt;br /&gt;
* Adds constructors for inner classes&lt;br /&gt;
** These are removed by Proguard sometimes, as they are not required in the bytecode if the parent has a default constructor.&lt;br /&gt;
* Adds synthetic (invisible) constructors for classes without them&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
It also applies fixes for things like EXC;&lt;br /&gt;
* Renaming parameters inside constructors, such that subclasses retain the ID of their parent.&lt;br /&gt;
* Fixing access for select functions, where it is required for the proper recompilation.&lt;br /&gt;
* Applying proper typing to constructor parameters&lt;br /&gt;
* Applying proper external (LWJGL) exception data to functions and classes.&lt;br /&gt;
&lt;br /&gt;
Note that it does NOT rename to SRG. LVT (Local Variables) are renamed to lvt_&amp;amp;lt;index&amp;amp;gt;_&amp;amp;lt;version&amp;amp;gt;&amp;lt;ref&amp;gt;Index means: the place where this item was found. If it is the 4th entry in the table, it is index 3.&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== ForgeFlower === &lt;br /&gt;
After the code has been cleaned up by MCInjector, to a state where it no longer conflicts with itself, it can be passed to the decompiler. &lt;br /&gt;
&lt;br /&gt;
The decompiler used by ForgeGradle is a custom fork of [https://github.com/JetBrains/intellij-community/tree/master/plugins/java-decompiler/engine Jetbrains' FernFlower], called [https://github.com/MinecraftForge/ForgeFlower ForgeFlower].&lt;br /&gt;
&lt;br /&gt;
It simply searches the jar for files, converts the bytecode into a reasonable best-guess interpretation.&lt;br /&gt;
&lt;br /&gt;
As you can see by the repository, a lot of work has gone into tuning it for Minecraft's needs, but it is still a far way from perfect. This is why the patches are needed.&lt;br /&gt;
&lt;br /&gt;
If you [https://github.com/MinecraftForge/MCPConfig/blob/master/versions/release/1.16.4/patches/ look at the patches] for 1.16.4, they are mostly incredibly simple changes. Adding generics, making types more strict. &lt;br /&gt;
&lt;br /&gt;
This is all stuff that should be done by the decompiler, and PRs are always welcome at the ForgeFlower repository for changes and fixes that would reduce the amount of MCPConfig patches required to get the game to compile.&lt;br /&gt;
&lt;br /&gt;
For now, it is a necessity.&lt;br /&gt;
&lt;br /&gt;
=== Mergetool ===&lt;br /&gt;
The game is split into two distributions; server and client.&lt;br /&gt;
&lt;br /&gt;
Because the server contains no rendering code, and the client contains none of the server-specific code (like the UI), this means there are differences between what can run on one side or the other.&lt;br /&gt;
&lt;br /&gt;
To get around this, we have a tool called Mergetool, which can search for the differences between two files (down to the function level) and merge them into one large (referred to as joined) jar file.&lt;br /&gt;
&lt;br /&gt;
It is a simple program, but it works.&lt;br /&gt;
&lt;br /&gt;
=== SpecialSource ===&lt;br /&gt;
SpecialSource is where SRG starts to come into play. It serves the role of our deobfuscator, performing deobfuscation.&lt;br /&gt;
&lt;br /&gt;
This process is done with the help of a '''deobfusation map''', a file generated by the original obfuscator (in this case, ProGuard) that contains a map of the obfuscated names to original, non-obfuscated names. This is commonly used on debofuscating stack traces outputted by an obfuscated program, for debugging purposes.&amp;lt;ref name=&amp;quot;retrace&amp;quot;/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We have three sets of deobfuscation maps available to us; the obf-&amp;gt;SRG mappings distributed with the MCPConfig system, the Yarn intermediary system, or the offical mappings.&amp;lt;ref name=&amp;quot;mojmappings&amp;quot;/&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
To rectify this problem, Forge has it's own process to create deobfuscation mappings for the game, using community-sourced human-readable names. This process is split into two separate parts: the '''SRG renaming''', and the '''MCP mapping'''. During the SetupMCP task, only the SRG renaming is performed.&lt;br /&gt;
&lt;br /&gt;
SpecialSource itself operates on the source jar, as can be gathered by the name, and takes in a .tsrg file, like that [https://github.com/MinecraftForge/MCPConfig/blob/master/versions/release/1.16.4/joined.tsrg contained in the MCPConfig zip].&lt;br /&gt;
&lt;br /&gt;
It first renames classes, straight into MCP names.&lt;br /&gt;
Then, iterating the members of the class, it renames fields, methods, parameters and inner classes.&lt;br /&gt;
&lt;br /&gt;
A recap from earlier:&lt;br /&gt;
* For classes -&amp;gt; &amp;lt;code&amp;gt;c_###_&amp;lt;/code&amp;gt; (but it is immediately changed without the c_ being written to disk)&lt;br /&gt;
* For functions/methods -&amp;gt; &amp;lt;code&amp;gt;func_&amp;amp;lt;ID&amp;amp;gt;_&amp;amp;lt;obf-name&amp;amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
* For fields -&amp;gt; &amp;lt;code&amp;gt;field_&amp;amp;lt;ID&amp;amp;gt;_&amp;amp;lt;obf-name&amp;amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
* For function/method parameters -&amp;gt; &amp;lt;code&amp;gt;p_###_#_&amp;lt;/code&amp;gt; for normal methods, &amp;lt;code&amp;gt;p_i###_#&amp;lt;/code&amp;gt; for constructors; the second number is the index&amp;lt;ref&amp;gt;The index is the position of the argument. 0 on the left, 1 after that, 2 after that. Note that double and long arguments increase their index by two, rather than one.&amp;lt;/ref&amp;gt; of the parameter.&lt;br /&gt;
&lt;br /&gt;
For example, &amp;lt;code&amp;gt;func_71410_x&amp;lt;/code&amp;gt; refers to a function with SRG ID 71410 and original obfuscated name of &amp;lt;code&amp;gt;x&amp;lt;/code&amp;gt;.&amp;lt;ref&amp;gt;For version 1.16.2, &amp;lt;code&amp;gt;func_71410_x&amp;lt;/code&amp;gt; refers to &amp;lt;code&amp;gt;Minecraft.getInstance()&amp;lt;/code&amp;gt;, with real obfuscated name of &amp;lt;code&amp;gt;B&amp;lt;/code&amp;gt;, but when the getInstance() function was first discovered in code, it was called x.&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
At this point, combined with the MCInjector step from earlier, we have a completely SRGed-up source jar.&lt;br /&gt;
&lt;br /&gt;
=== Patches ===&lt;br /&gt;
Once we have the source code ready to go, the final step in the setup is to apply patches.&lt;br /&gt;
These are done trivially, using diffs and [https://github.com/CadixDev/gitpatcher gitpatcher].&lt;br /&gt;
&lt;br /&gt;
=== Clean-up ===&lt;br /&gt;
Because of the way Proguard (or whatever obfuscator) and ForgeFlower mangle the source code, we need to take some steps to clean it up before we can proceed.&lt;br /&gt;
&lt;br /&gt;
Assorted cleanup fixes are performed by the [https://github.com/MinecraftForge/MCPCleanup/ MCPCleanup] utility. These include:&lt;br /&gt;
* removing trailing whitespace at the end of lines&lt;br /&gt;
* removing extra newlines at the start and end of files&lt;br /&gt;
* removing extra newlines between every line of code (every set of concurrent newlines is replaced with a single)&lt;br /&gt;
* removing comments (// hello, /* hello */)&lt;br /&gt;
** the purpose of this step is unclear - it seems to be a preventative measure to ensure that Java changes do not interfere with the patch alignment in the future. Comments from the decompiler are still sometimes present in the source code.&lt;br /&gt;
* removing imports from the package a class is in&lt;br /&gt;
* removing comments that include the phrase &amp;lt;code&amp;gt;GL_[^*]+&amp;lt;/code&amp;gt;&lt;br /&gt;
* replacing [[Toolchain:Magic Constants|magic constants]] with their code substitutions&lt;br /&gt;
* replacing &amp;lt;code&amp;gt;Character.valueOf(&amp;amp;lt;character&amp;amp;gt;)&amp;lt;/code&amp;gt; with &amp;lt;code&amp;gt;&amp;amp;lt;character&amp;amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
* replacing OpenGL integer constants with their code representation&lt;br /&gt;
* converting unicode character constants back into integer representation&lt;br /&gt;
* formatting the code with JAStyle&lt;br /&gt;
&lt;br /&gt;
It also adjusts abstract functions in some way - after running the program on a jar, the parameters of a default abstract function get renamed, but it is unclear exactly what part of the source code does this.&lt;br /&gt;
&lt;br /&gt;
== The Forge Side ==&lt;br /&gt;
&lt;br /&gt;
After the MCPConfig/SetupMCP tasks are finished, ForgeGradle will print '''MCP Environment Setup is complete''' and wait for the user input.&lt;br /&gt;
&lt;br /&gt;
The next step is to run the &amp;lt;code&amp;gt;gradlew setup&amp;lt;/code&amp;gt; task, which does what it implies: Applying the Forge system to the processed vanilla code.&lt;br /&gt;
&lt;br /&gt;
First, it applies ATs. After that, patches. Finally, MCP/Crowdsourced mappings are applied.&lt;br /&gt;
&lt;br /&gt;
All in all, compared to the MCPConfig setup, this is a string of extremely basic tasks - mostly just one-line commands.&lt;br /&gt;
&lt;br /&gt;
=== Applying Access Transformers ===&lt;br /&gt;
&lt;br /&gt;
[[Access Transformers]] are a way of changing the visibility and finality of classes and class members. A full explanation of how it works, what the specification is, and what exactly they're used for, can be found at that page.&lt;br /&gt;
&lt;br /&gt;
They are applied by passing the AT Config (nowadays called accesstransformer.cfg) into SpecialSource:&lt;br /&gt;
* &amp;lt;code&amp;gt;SpecialSource.jar --in-jar {input} --out-jar {output} --access-transformer {at.cfg}&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[https://github.com/MinecraftForge/MinecraftForge/blob/c3e84646db70f518dd0b37a8fcfc42cb814d7ba8/src/main/resources/META-INF/accesstransformer.cfg The current AT cfg can be found here.]&lt;br /&gt;
&lt;br /&gt;
=== Applying Patches ===&lt;br /&gt;
&lt;br /&gt;
The patches used for Forge itself are different from those used by MCPConfig, which means there are two separate patching stages performed.&lt;br /&gt;
&lt;br /&gt;
As opposed to the minimal MCPConfig patching, with the goal to make the code recompileable, the Forge patching is done to apply the API and modloader to the code.&lt;br /&gt;
&lt;br /&gt;
It does this in a very similar way, with the [https://github.com/CadixDev/gitpatcher gitpatcher] utility.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Applying Mappings ===&lt;br /&gt;
This step isn't strictly necessary, and it can be ommitted. However, working with exclusively SRG names is confusing for most people, so we have an extra step to apply human names to the SRG.&lt;br /&gt;
&lt;br /&gt;
These renames can come from any source; as mentioned earlier, the MCP/Crowdsourced naming, the Yarn naming, or the Mojang Obf-map naming. ForgeGradle does not care, as long as there is a valid SRG-&amp;gt;names map.&lt;br /&gt;
&lt;br /&gt;
How ForgeGradle retrieves these mappings is covered in the [[ForgeGradle/mappings|appropriate article]].&lt;br /&gt;
&lt;br /&gt;
The process of renaming itself is a simple regex substitution, performed by [https://github.com/MinecraftForge/ForgeGradle/blob/e2ed49546abced95650635f81be071441ec60995/src/common/java/net/minecraftforge/gradle/common/util/McpNames.java#L104 ForgeGradle itself]. This is made possible by the assured uniqueness of SRG names.&lt;br /&gt;
&lt;br /&gt;
=== Post-processing ===&lt;br /&gt;
&lt;br /&gt;
At this point, the files are ready to go. We have processed the Minecraft jar such that it can be recompiled, we have applied appropriate access transformers and the Forge patches, and optionally renamed every applicable SRG name to whatever chosen distribution of mappings.&lt;br /&gt;
&lt;br /&gt;
There is not much left to do but package the code into a jar file, and place it into the gradle cache (so that this process does not occur every single time the project is opened). It calculates this name based on many factors, and this is covered in the [[ForgeGradle#naming|naming]] article.&lt;br /&gt;
&lt;br /&gt;
== Some additional Infos ==&lt;br /&gt;
# You will never see c_XXX_ for classes, because the class names are picked beforehand&lt;br /&gt;
#* this is still crowdsourced, but before a new version is ready for Forge, all classes are given an &amp;lt;code&amp;gt;MCP&amp;lt;/code&amp;gt; name&lt;br /&gt;
#* this &amp;lt;code&amp;gt;MCP&amp;lt;/code&amp;gt; name stays constant throughout the game version it was picked for; it can change between versions, but it usually wont for already-named classes (except for misspells, typos, and misnames)&lt;br /&gt;
# If you look into the JAR, you won't see any packages for the obfuscated classes, but the deobfuscated classes do have the packages, this is because the same process that names the classes, also decides what package they belong to&lt;br /&gt;
# parameters have special names&lt;br /&gt;
#* there are two types of parameter names: &amp;lt;code&amp;gt;p_XXX_X_&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;p_iXXX_X_&amp;lt;/code&amp;gt;&lt;br /&gt;
#* the one with the i means that it's a parameter for a constructor&lt;br /&gt;
#* the first set of numbers are the SRG ID of their parent method, and the second number denotes the index of the parameter&lt;br /&gt;
#* the index of the parameter is a bit more involved, but this will not be explained here&lt;br /&gt;
# If you look into the source, you'll see that parameters for lambdas don't have mapped names&lt;br /&gt;
#* This is because of a complication in how the lambdas are compiled/decompiled; it's a more advanced topic which involves how the compiler compiles lambdas which we will not explain here.&lt;br /&gt;
&lt;br /&gt;
== See also ==&lt;br /&gt;
* [https://en.wikipedia.org/wiki/Obfuscation_(software) Obfuscation]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;references&amp;gt;&lt;br /&gt;
&amp;lt;ref name=&amp;quot;retrace&amp;quot;&amp;gt;For ProGuard users (such as Mojang), this is done using [https://www.guardsquare.com/en/products/proguard/manual/retrace ReTrace].&amp;lt;/ref&amp;gt;&lt;br /&gt;
&amp;lt;ref name=&amp;quot;mojmappings&amp;quot;&amp;gt;Mojang recently released their deobfuscation mappings for Minecraft (colloquially named &amp;lt;code&amp;gt;mojmappings&amp;lt;/code&amp;gt;), but the licensing for its uses is a bit ambiguous. [https://cpw.github.io/MinecraftMappingData See this post by cpw] for more information.&amp;lt;/ref&amp;gt;&lt;br /&gt;
&amp;lt;/references&amp;gt;&lt;/div&gt;</summary>
		<author><name>Curle</name></author>
	</entry>
	<entry>
		<id>https://forge.gemwire.uk/index.php?title=Toolchain&amp;diff=2388</id>
		<title>Toolchain</title>
		<link rel="alternate" type="text/html" href="https://forge.gemwire.uk/index.php?title=Toolchain&amp;diff=2388"/>
		<updated>2021-01-11T16:59:09Z</updated>

		<summary type="html">&lt;p&gt;Curle: Forge side&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{DISPLAYTITLE:Deobfuscation Process}}&lt;br /&gt;
{{Under construction}}&lt;br /&gt;
&lt;br /&gt;
The Forge toolchain is designed to clean up, merge, deobfuscate, rename, patch and provide the Minecraft source code for the usage of modders, researchers, or just those curious about how the game works.&lt;br /&gt;
&lt;br /&gt;
This serves as an explanation as to how the development environment sets up your code, and aims to help you troubleshoot in case something goes wrong.&lt;br /&gt;
&lt;br /&gt;
== Overall process ==&lt;br /&gt;
When setting up the environment for the first time, a gradle refresh triggers three things:&lt;br /&gt;
# ForgeGradle downloads the MCPConfig zip for the file you're using, and triggers the SetupMCP task.&lt;br /&gt;
# After that, it processes the jar - applies access transformers, MCPCleanup and others&lt;br /&gt;
# Finally, it patches and finalises the code, ready for modder consumption.&lt;br /&gt;
&lt;br /&gt;
== Needed knowledge ==&lt;br /&gt;
=== Obfuscation ===&lt;br /&gt;
'''Obfuscation''' is the process of renaming all of the fields, methods, and classes of the compiled code into unreadable, machine-generated names (such as &amp;lt;code&amp;gt;aaa&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;bC&amp;lt;/code&amp;gt;), and removing package structures (this makes everything package-local and makes the obfuscated code smaller somewhat. This is commonly used by companies to prevent external entities from easily decompiling their released binaries/executables and retrieving their source code/intellectual property, though it does have size advantages.&lt;br /&gt;
&lt;br /&gt;
Additionally, due to the way the Local Variable Table (LVT) of Java bytecode is stored, every function-local variable name is turned to ☃ (that's right, a snowman) in the compiled files. This makes immediate recompilation of the game literally and physically impossible, as every Java compiler currently available requires that local variables have unique names.&lt;br /&gt;
&lt;br /&gt;
Minecraft is a commercial game, which means the source code is unavailable to all except the developers of Mojang. To prevent piracy and the copying of their intellectual property, Mojang applies this obfuscation process to the game before they release it. They use a tool called [https://www.guardsquare.com/en/products/proguard ProGuard], which is both an optimizer&amp;lt;ref&amp;gt;An optimizer is a program that removes redundant/unused instructions and compacts the code to be faster and smaller.&amp;lt;/ref&amp;gt; and an obfuscator.&lt;br /&gt;
&lt;br /&gt;
=== Problematic Naming ===&lt;br /&gt;
There are a few big problems with using these obfuscated names directly for modding.&lt;br /&gt;
&lt;br /&gt;
# It is incredibly difficult to create mods using these obfuscated names. It requires immense patience to reverse-engineer the meanings behind each and every name, and to keep relating those names to what was already reverse-engineered. Although, tools do exist to make this process easier, such as IntelliJ IDEA plugins that provide naming hints automatically.&lt;br /&gt;
# Because the obfuscation process takes place after compilation (the obfuscator operates on the compiled classes), the obfuscated names are not handled by the compiler. Thus, obfuscated classes may contain member&amp;lt;ref&amp;gt;'''member''' refers to class fields and methods.&amp;lt;/ref&amp;gt; names that are invalid in the Java source language, but valid in compiled bytecode (like ☃ discussed earlier); this means that the decompiled source of the game is not immediately recompilable.&lt;br /&gt;
# These obfuscated names are automatically generated by the obfuscator for each independent release. This means that the obfuscated names may change signficantly between any two versions, making it harder for mod developers to update mods between releases.&lt;br /&gt;
&lt;br /&gt;
=== SRGification ===&lt;br /&gt;
Some background on what SRG is and how it works:&lt;br /&gt;
&lt;br /&gt;
'''SRG''' stands for '''S'''ea'''RG'''e, co-author of the Mod Creator Pack, who created this process.&lt;br /&gt;
Each obfuscated class, method, and field is assigned a unique number by the [[Toolchain:MCPConfig|backend]], via a sequential counter. This unique number is called the '''SRG ID''' of that class/method/field (henceforth called member).&lt;br /&gt;
&lt;br /&gt;
The SRG name of the member is then derived from its SRG ID, its type (function {given the prefix func_}, field {given the prefix field_}, parameter {given the prefix p_, or p_i if this is the parameter of a constructor}), and (optionally) the obfuscated name of the object at the time it was given its SRG name&amp;lt;ref&amp;gt;The SRG name for a given member is only created once, when it first appears in the code. Therefore, the SRG postfix may be different from the current obf name.&amp;lt;/ref&amp;gt;. This inclusion of the SRG ID into the name guarantees that the SRG name for all members are unique, and is the reason the ID is generated.&lt;br /&gt;
&lt;br /&gt;
The actual conversion of obf names to SRG names is done by a tool called [[Toolchain:SpecialSource|SpecialSource]]. More information on how it works can be found on that page.&lt;br /&gt;
&lt;br /&gt;
== The Setup ==&lt;br /&gt;
The process can be broken up into 3 steps; MCPConfig, patch and provide.&lt;br /&gt;
The MCPConfig step is, understandably, the biggest and most prone to failure.&lt;br /&gt;
An explanation of MCPConfig itself, how it works, what it's for (but NOT how to use it) can be found [[Toolchain:MCPConfig|here]]. For the purpose of this guide, you need only know that its' goal is to get the game decompiled, and into a state where it can immediately be recompiled. Due to certain flaws in the rest of the toolchain, this means it needs to fix and patch the source code before passing it onto Forge.&lt;br /&gt;
&lt;br /&gt;
In this way, MCPConfig can be thought of the vanilla side of the setup. It does not modify the game.&lt;br /&gt;
&lt;br /&gt;
The following steps are all executed in order of appearance.&lt;br /&gt;
&lt;br /&gt;
=== Download and parsing MCPConfig ===&lt;br /&gt;
The first thing that ForgeGradle does upon initialising a first-time setup, is starting the [https://github.com/MinecraftForge/ForgeGradle/blob/e2ed49546abced95650635f81be071441ec60995/src/mcp/java/net/minecraftforge/gradle/mcp/task/SetupMCPTask.java#L91 SetupMCP] task. &lt;br /&gt;
&lt;br /&gt;
This task then seeks to [https://github.com/MinecraftForge/ForgeGradle/blob/e2ed49546abced95650635f81be071441ec60995/src/mcp/java/net/minecraftforge/gradle/mcp/task/DownloadMCPConfigTask.java#L78 download the MCPConfig.zip jar] for the version you're setting up.&lt;br /&gt;
Once it is acquired, it &lt;br /&gt;
[https://github.com/MinecraftForge/ForgeGradle/blob/e2ed49546abced95650635f81be071441ec60995/src/mcp/java/net/minecraftforge/gradle/mcp/util/MCPRuntime.java#L74 parses the steps contained within the config.json]. It does this by interpreting the file with the following rules:&lt;br /&gt;
* Every key, except for libraries, is interpreted as the name of a step.&lt;br /&gt;
* Steps are executed in order.&lt;br /&gt;
* The version value is interpreted as a maven coordinate of a file to download.&lt;br /&gt;
* If there is a repo value, it is used instead of the maven repositories defined in the buildscript, to retrieve the version.&lt;br /&gt;
* The args array is parsed, and {values} like this are interpreted as inputs, which can be substituted accordingly.&lt;br /&gt;
* Once the step is all parsed in, it is executed:&lt;br /&gt;
** java -jar &amp;amp;lt;version&amp;amp;gt; &amp;amp;lt;args&amp;amp;gt; &amp;amp;lt;jvmArgs&amp;amp;gt;&lt;br /&gt;
&lt;br /&gt;
An example config.json can be found [https://github.com/MinecraftForge/MCPConfig/blob/master/versions/release/1.16.4/config.json here].&lt;br /&gt;
&lt;br /&gt;
It defines the steps:&lt;br /&gt;
* [[Toolchain:MCinjector|mcinjector]]&lt;br /&gt;
** version: de.oceanlabs.mcp:mcinjector:3.8.0:fatjar&lt;br /&gt;
** args: --in {input} --out {output} --log {log} --level=INFO --lvt=LVT --exc {exceptions} --acc {access} --ctr {constructors}&lt;br /&gt;
* [[Toolchain:ForgeFlower|fernflower]]&lt;br /&gt;
** version: net.minecraftforge:forgeflower:1.5.478.16&lt;br /&gt;
** args: -din=1 -rbr=1 -dgs=1 -asc=1 -rsy=1 -iec=1 -jvn=1 -isl=0 -iib=1 -log=TRACE -cfg {libraries} {input} {output}&lt;br /&gt;
** jvmargs: -Xmx4G&lt;br /&gt;
* [[Toolchain:Mergetool|merge]]&lt;br /&gt;
** version: net.minecraftforge:mergetool:1.1.1:fatjar&lt;br /&gt;
** args: --client {client} --server {server} --ann {version} --output {output} --inject false&amp;quot;&lt;br /&gt;
* [[Toolchain:MCInjector|rename]]&lt;br /&gt;
** version: net.md-5:SpecialSource:1.8.3:shaded&lt;br /&gt;
** args: --in-jar {input} --out-jar {output} --srg-in {mappings}&lt;br /&gt;
** repo: https://repo1.maven.org/maven2/&lt;br /&gt;
&lt;br /&gt;
More information about each of these tools can be found at the link provided, as well as what each of these arguments do. A brief description is provided.&lt;br /&gt;
&lt;br /&gt;
=== MCInjector ===&lt;br /&gt;
[https://github.com/ModCoderPack/MCInjector MCInjector] is the tool we use to apply various fixes to the code, while it is still in bytecode form. That meaning, it works on compiled code, not sourcecode. It does this because it's easier to rename LVT entries (from the snowman) to readable names while you can search for every other code path that references that specific entry; ergo renaming all accesses at once. This is impossible in sourcecode, where every name is identical and string matching is impossible.&lt;br /&gt;
&lt;br /&gt;
It:&lt;br /&gt;
* Removes synthetic parameters from constructors&lt;br /&gt;
** In bytecode, inner classes have the outer class as their first constructor parameter, but Java source code does not.&lt;br /&gt;
* Handles adding annotations for parameters that have synthetic data&lt;br /&gt;
** In bytecode, these Nonnull (or whatever) annotations are attached to the parameters, not to the function that contains them.&lt;br /&gt;
* Adds constructors for inner classes&lt;br /&gt;
** These are removed by Proguard sometimes, as they are not required in the bytecode if the parent has a default constructor.&lt;br /&gt;
* Adds synthetic (invisible) constructors for classes without them&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
It also applies fixes for things like EXC;&lt;br /&gt;
* Renaming parameters inside constructors, such that subclasses retain the ID of their parent.&lt;br /&gt;
* Fixing access for select functions, where it is required for the proper recompilation.&lt;br /&gt;
* Applying proper typing to constructor parameters&lt;br /&gt;
* Applying proper external (LWJGL) exception data to functions and classes.&lt;br /&gt;
&lt;br /&gt;
Note that it does NOT rename to SRG. LVT (Local Variables) are renamed to lvt_&amp;amp;lt;index&amp;amp;gt;_&amp;amp;lt;version&amp;amp;gt;&amp;lt;ref&amp;gt;Index means: the place where this item was found. If it is the 4th entry in the table, it is index 3.&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== ForgeFlower === &lt;br /&gt;
After the code has been cleaned up by MCInjector, to a state where it no longer conflicts with itself, it can be passed to the decompiler. &lt;br /&gt;
&lt;br /&gt;
The decompiler used by ForgeGradle is a custom fork of [https://github.com/JetBrains/intellij-community/tree/master/plugins/java-decompiler/engine Jetbrains' FernFlower], called [https://github.com/MinecraftForge/ForgeFlower ForgeFlower].&lt;br /&gt;
&lt;br /&gt;
It simply searches the jar for files, converts the bytecode into a reasonable best-guess interpretation.&lt;br /&gt;
&lt;br /&gt;
As you can see by the repository, a lot of work has gone into tuning it for Minecraft's needs, but it is still a far way from perfect. This is why the patches are needed.&lt;br /&gt;
&lt;br /&gt;
If you [https://github.com/MinecraftForge/MCPConfig/blob/master/versions/release/1.16.4/patches/ look at the patches] for 1.16.4, they are mostly incredibly simple changes. Adding generics, making types more strict. &lt;br /&gt;
&lt;br /&gt;
This is all stuff that should be done by the decompiler, and PRs are always welcome at the ForgeFlower repository for changes and fixes that would reduce the amount of MCPConfig patches required to get the game to compile.&lt;br /&gt;
&lt;br /&gt;
For now, it is a necessity.&lt;br /&gt;
&lt;br /&gt;
=== Mergetool ===&lt;br /&gt;
The game is split into two distributions; server and client.&lt;br /&gt;
&lt;br /&gt;
Because the server contains no rendering code, and the client contains none of the server-specific code (like the UI), this means there are differences between what can run on one side or the other.&lt;br /&gt;
&lt;br /&gt;
To get around this, we have a tool called Mergetool, which can search for the differences between two files (down to the function level) and merge them into one large (referred to as joined) jar file.&lt;br /&gt;
&lt;br /&gt;
It is a simple program, but it works.&lt;br /&gt;
&lt;br /&gt;
=== SpecialSource ===&lt;br /&gt;
SpecialSource is where SRG starts to come into play. It serves the role of our deobfuscator, performing deobfuscation.&lt;br /&gt;
&lt;br /&gt;
This process is done with the help of a '''deobfusation map''', a file generated by the original obfuscator (in this case, ProGuard) that contains a map of the obfuscated names to original, non-obfuscated names. This is commonly used on debofuscating stack traces outputted by an obfuscated program, for debugging purposes.&amp;lt;ref name=&amp;quot;retrace&amp;quot;/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We have three sets of deobfuscation maps available to us; the obf-&amp;gt;SRG mappings distributed with the MCPConfig system, the Yarn intermediary system, or the offical mappings.&amp;lt;ref name=&amp;quot;mojmappings&amp;quot;/&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
To rectify this problem, Forge has it's own process to create deobfuscation mappings for the game, using community-sourced human-readable names. This process is split into two separate parts: the '''SRG renaming''', and the '''MCP mapping'''. During the SetupMCP task, only the SRG renaming is performed.&lt;br /&gt;
&lt;br /&gt;
SpecialSource itself operates on the source jar, as can be gathered by the name, and takes in a .tsrg file, like that [https://github.com/MinecraftForge/MCPConfig/blob/master/versions/release/1.16.4/joined.tsrg contained in the MCPConfig zip].&lt;br /&gt;
&lt;br /&gt;
It first renames classes, straight into MCP names.&lt;br /&gt;
Then, iterating the members of the class, it renames fields, methods, parameters and inner classes.&lt;br /&gt;
&lt;br /&gt;
A recap from earlier:&lt;br /&gt;
* For classes -&amp;gt; &amp;lt;code&amp;gt;c_###_&amp;lt;/code&amp;gt; (but it is immediately changed without the c_ being written to disk)&lt;br /&gt;
* For functions/methods -&amp;gt; &amp;lt;code&amp;gt;func_&amp;amp;lt;ID&amp;amp;gt;_&amp;amp;lt;obf-name&amp;amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
* For fields -&amp;gt; &amp;lt;code&amp;gt;field_&amp;amp;lt;ID&amp;amp;gt;_&amp;amp;lt;obf-name&amp;amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
* For function/method parameters -&amp;gt; &amp;lt;code&amp;gt;p_###_#_&amp;lt;/code&amp;gt; for normal methods, &amp;lt;code&amp;gt;p_i###_#&amp;lt;/code&amp;gt; for constructors; the second number is the index&amp;lt;ref&amp;gt;The index is the position of the argument. 0 on the left, 1 after that, 2 after that. Note that double and long arguments increase their index by two, rather than one.&amp;lt;/ref&amp;gt; of the parameter.&lt;br /&gt;
&lt;br /&gt;
For example, &amp;lt;code&amp;gt;func_71410_x&amp;lt;/code&amp;gt; refers to a function with SRG ID 71410 and original obfuscated name of &amp;lt;code&amp;gt;x&amp;lt;/code&amp;gt;.&amp;lt;ref&amp;gt;For version 1.16.2, &amp;lt;code&amp;gt;func_71410_x&amp;lt;/code&amp;gt; refers to &amp;lt;code&amp;gt;Minecraft.getInstance()&amp;lt;/code&amp;gt;, with real obfuscated name of &amp;lt;code&amp;gt;B&amp;lt;/code&amp;gt;, but when the getInstance() function was first discovered in code, it was called x.&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
At this point, combined with the MCInjector step from earlier, we have a completely SRGed-up source jar.&lt;br /&gt;
&lt;br /&gt;
=== Patches ===&lt;br /&gt;
Once we have the source code ready to go, the final step in the setup is to apply patches.&lt;br /&gt;
These are done trivially, using diffs and [https://github.com/CadixDev/gitpatcher gitpatcher].&lt;br /&gt;
&lt;br /&gt;
=== Clean-up ===&lt;br /&gt;
Because of the way Proguard (or whatever obfuscator) and ForgeFlower mangle the source code, we need to take some steps to clean it up before we can proceed.&lt;br /&gt;
&lt;br /&gt;
Assorted cleanup fixes are performed by the [https://github.com/MinecraftForge/MCPCleanup/ MCPCleanup] utility. These include:&lt;br /&gt;
* removing trailing whitespace at the end of lines&lt;br /&gt;
* removing extra newlines at the start and end of files&lt;br /&gt;
* removing extra newlines between every line of code (every set of concurrent newlines is replaced with a single)&lt;br /&gt;
* removing comments (// hello, /* hello */)&lt;br /&gt;
** the purpose of this step is unclear - it seems to be a preventative measure to ensure that Java changes do not interfere with the patch alignment in the future. Comments from the decompiler are still sometimes present in the source code.&lt;br /&gt;
* removing imports from the package a class is in&lt;br /&gt;
* removing comments that include the phrase &amp;lt;code&amp;gt;GL_[^*]+&amp;lt;/code&amp;gt;&lt;br /&gt;
* replacing [[Toolchain:Magic Constants|magic constants]] with their code substitutions&lt;br /&gt;
* replacing &amp;lt;code&amp;gt;Character.valueOf(&amp;amp;lt;character&amp;amp;gt;)&amp;lt;/code&amp;gt; with &amp;lt;code&amp;gt;&amp;amp;lt;character&amp;amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
* replacing OpenGL integer constants with their code representation&lt;br /&gt;
* converting unicode character constants back into integer representation&lt;br /&gt;
* formatting the code with JAStyle&lt;br /&gt;
&lt;br /&gt;
It also adjusts abstract functions in some way - after running the program on a jar, the parameters of a default abstract function get renamed, but it is unclear exactly what part of the source code does this.&lt;br /&gt;
&lt;br /&gt;
== The Forge Side ==&lt;br /&gt;
&lt;br /&gt;
After the MCPConfig/SetupMCP tasks are finished, ForgeGradle will print '''MCP Environment Setup is complete''' and wait for the user input.&lt;br /&gt;
&lt;br /&gt;
The next step is to run the &amp;lt;code&amp;gt;gradlew setup&amp;lt;/code&amp;gt; task, which does what it implies: Applying the Forge system to the processed vanilla code.&lt;br /&gt;
&lt;br /&gt;
First, it applies ATs. After that, patches. Finally, MCP/Crowdsourced mappings are applied.&lt;br /&gt;
&lt;br /&gt;
All in all, compared to the MCPConfig setup, this is a string of extremely basic tasks - mostly just one-line commands.&lt;br /&gt;
&lt;br /&gt;
=== Applying Access Transformers ===&lt;br /&gt;
&lt;br /&gt;
[[Access Transformers]] are a way of changing the visibility and finality of classes and class members. A full explanation of how it works, what the specification is, and what exactly they're used for, can be found at that page.&lt;br /&gt;
&lt;br /&gt;
They are applied by passing the AT Config (nowadays called accesstransformer.cfg) into SpecialSource:&lt;br /&gt;
* &amp;lt;code&amp;gt;SpecialSource.jar --in-jar {input} --out-jar {output} --access-transformer {at.cfg}&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[https://github.com/MinecraftForge/MinecraftForge/blob/c3e84646db70f518dd0b37a8fcfc42cb814d7ba8/src/main/resources/META-INF/accesstransformer.cfg The current AT cfg can be found here.]&lt;br /&gt;
&lt;br /&gt;
=== Applying Patches ===&lt;br /&gt;
&lt;br /&gt;
The patches used for Forge itself are different from those used by MCPConfig, which means there are two separate patching stages performed.&lt;br /&gt;
&lt;br /&gt;
As opposed to the minimal MCPConfig patching, with the goal to make the code recompileable, the Forge patching is done to apply the API and modloader to the code.&lt;br /&gt;
&lt;br /&gt;
It does this in a very similar way, with the [https://github.com/CadixDev/gitpatcher gitpatcher] utility.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Applying Mappings ===&lt;br /&gt;
This step isn't strictly necessary, and it can be ommitted. However, working with exclusively SRG names is confusing for most people, so we have an extra step to apply human names to the SRG.&lt;br /&gt;
&lt;br /&gt;
These renames can come from any source; as mentioned earlier, the MCP/Crowdsourced naming, the Yarn naming, or the Mojang Obf-map naming. ForgeGradle does not care, as long as there is a valid SRG-&amp;gt;names map.&lt;br /&gt;
&lt;br /&gt;
How ForgeGradle retrieves these mappings is covered in the [[ForgeGradle/mappings appropriate article]].&lt;br /&gt;
&lt;br /&gt;
The process of renaming itself is a simple regex substitution, performed by [https://github.com/MinecraftForge/ForgeGradle/blob/e2ed49546abced95650635f81be071441ec60995/src/common/java/net/minecraftforge/gradle/common/util/McpNames.java#L104 ForgeGradle itself]. This is made possible by the assured uniqueness of SRG names.&lt;br /&gt;
&lt;br /&gt;
=== Post-processing ===&lt;br /&gt;
&lt;br /&gt;
At this point, the files are ready to go. We have processed the Minecraft jar such that it can be recompiled, we have applied appropriate access transformers and the Forge patches, and optionally renamed every applicable SRG name to whatever chosen distribution of mappings.&lt;br /&gt;
&lt;br /&gt;
There is not much left to do but package the code into a jar file, and place it into the gradle cache (so that this process does not occur every single time the project is opened). It calculates this name based on many factors, and this is covered in the [[ForgeGradle#naming]] article.&lt;br /&gt;
&lt;br /&gt;
== Some additional Infos ==&lt;br /&gt;
# You will never see c_XXX_ for classes, because the class names are picked beforehand&lt;br /&gt;
#* this is still crowdsourced, but before a new version is ready for Forge, all classes are given an &amp;lt;code&amp;gt;MCP&amp;lt;/code&amp;gt; name&lt;br /&gt;
#* this &amp;lt;code&amp;gt;MCP&amp;lt;/code&amp;gt; name stays constant throughout the game version it was picked for; it can change between versions, but it usually wont for already-named classes (except for misspells, typos, and misnames)&lt;br /&gt;
# If you look into the JAR, you won't see any packages for the obfuscated classes, but the deobfuscated classes do have the packages, this is because the same process that names the classes, also decides what package they belong to&lt;br /&gt;
# parameters have special names&lt;br /&gt;
#* there are two types of parameter names: &amp;lt;code&amp;gt;p_XXX_X_&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;p_iXXX_X_&amp;lt;/code&amp;gt;&lt;br /&gt;
#* the one with the i means that it's a parameter for a constructor&lt;br /&gt;
#* the first set of numbers are the SRG ID of their parent method, and the second number denotes the index of the parameter&lt;br /&gt;
#* the index of the parameter is a bit more involved, but this will not be explained here&lt;br /&gt;
# If you look into the source, you'll see that parameters for lambdas don't have mapped names&lt;br /&gt;
#* This is because of a complication in how the lambdas are compiled/decompiled; it's a more advanced topic which involves how the compiler compiles lambdas which we will not explain here.&lt;br /&gt;
&lt;br /&gt;
== See also ==&lt;br /&gt;
* [https://en.wikipedia.org/wiki/Obfuscation_(software) Obfuscation]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;references&amp;gt;&lt;br /&gt;
&amp;lt;ref name=&amp;quot;retrace&amp;quot;&amp;gt;For ProGuard users (such as Mojang), this is done using [https://www.guardsquare.com/en/products/proguard/manual/retrace ReTrace].&amp;lt;/ref&amp;gt;&lt;br /&gt;
&amp;lt;ref name=&amp;quot;mojmappings&amp;quot;&amp;gt;Mojang recently released their deobfuscation mappings for Minecraft (colloquially named &amp;lt;code&amp;gt;mojmappings&amp;lt;/code&amp;gt;), but the licensing for its uses is a bit ambiguous. [https://cpw.github.io/MinecraftMappingData See this post by cpw] for more information.&amp;lt;/ref&amp;gt;&lt;br /&gt;
&amp;lt;/references&amp;gt;&lt;/div&gt;</summary>
		<author><name>Curle</name></author>
	</entry>
	<entry>
		<id>https://forge.gemwire.uk/index.php?title=Toolchain:Magic_Constants&amp;diff=2387</id>
		<title>Toolchain:Magic Constants</title>
		<link rel="alternate" type="text/html" href="https://forge.gemwire.uk/index.php?title=Toolchain:Magic_Constants&amp;diff=2387"/>
		<updated>2021-01-11T05:55:12Z</updated>

		<summary type="html">&lt;p&gt;Curle: Curle moved page Toolchain:Magic Constants to Toolchain/Magic Constants&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;#REDIRECT [[Toolchain/Magic Constants]]&lt;/div&gt;</summary>
		<author><name>Curle</name></author>
	</entry>
	<entry>
		<id>https://forge.gemwire.uk/index.php?title=Toolchain/Magic_Constants&amp;diff=2386</id>
		<title>Toolchain/Magic Constants</title>
		<link rel="alternate" type="text/html" href="https://forge.gemwire.uk/index.php?title=Toolchain/Magic_Constants&amp;diff=2386"/>
		<updated>2021-01-11T05:55:11Z</updated>

		<summary type="html">&lt;p&gt;Curle: Curle moved page Toolchain:Magic Constants to Toolchain/Magic Constants&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;The [[Toolchain:MCPCleanup]] utility has many functions, one among them is to convert known constants into code representation for easier visualisation.&lt;br /&gt;
&lt;br /&gt;
== Constants ==&lt;br /&gt;
&lt;br /&gt;
The known substitutions are:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;1.7976[0-9]*[Ee]+308[Dd]&amp;lt;/code&amp;gt; -&amp;gt; &amp;lt;code&amp;gt;Double.MAX_VALUE&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;3.1415[0-9]*[Dd]&amp;lt;/code&amp;gt; -&amp;gt; &amp;lt;code&amp;gt;Math.PI&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;3.1415[0-9]*[Ff]&amp;lt;/code&amp;gt; -&amp;gt; &amp;lt;code&amp;gt;(float)Math.PI&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;6.2831[0-9]*[Dd]&amp;lt;/code&amp;gt; -&amp;gt; &amp;lt;code&amp;gt;(Math.PI * 2D)&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;6.2831[0-9]*[Ff]&amp;lt;/code&amp;gt; -&amp;gt; &amp;lt;code&amp;gt;((float)Math.PI * 2F)&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;4.7123[0-9]*[Dd]&amp;lt;/code&amp;gt; -&amp;gt; &amp;lt;code&amp;gt;(Math.PI * 3D / 2D)&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;4.7123[0-9]*[Ff]&amp;lt;/code&amp;gt; -&amp;gt; &amp;lt;code&amp;gt;((float)Math.PI * 3F / 2F)&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;0.7853[0-9]*[Dd]&amp;lt;/code&amp;gt; -&amp;gt; &amp;lt;code&amp;gt;(Math.PI / 4D)&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;0.7853[0-9]*[Ff]&amp;lt;/code&amp;gt; -&amp;gt; &amp;lt;code&amp;gt;((float)Math.PI / 4F)&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;6.2831[0-9]*[Ff]&amp;lt;/code&amp;gt; -&amp;gt; &amp;lt;code&amp;gt;((float)Math.PI * 2F)&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;0.6283[0-9]*[Dd]&amp;lt;/code&amp;gt; -&amp;gt; &amp;lt;code&amp;gt;(Math.PI / 5D)&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;0.6283[0-9]*[Ff]&amp;lt;/code&amp;gt; -&amp;gt; &amp;lt;code&amp;gt;((float)Math.PI / 5F)&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;57.295[0-9]*[Dd]&amp;lt;/code&amp;gt; -&amp;gt; &amp;lt;code&amp;gt;(180D / Math.PI)&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;57.295[0-9]*[Ff]&amp;lt;/code&amp;gt; -&amp;gt; &amp;lt;code&amp;gt;(180F / (float)Math.PI)&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;0.6981[0-9]*[Dd]&amp;lt;/code&amp;gt; -&amp;gt; &amp;lt;code&amp;gt;(Math.PI * 2D / 9D)&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;0.6981[0-9]*[Ff]&amp;lt;/code&amp;gt; -&amp;gt; &amp;lt;code&amp;gt;((float)Math.PI * 2F / 9F)&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;0.3141[0-9]*[Dd]&amp;lt;/code&amp;gt; -&amp;gt; &amp;lt;code&amp;gt;(Math.PI / 10D)&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;0.3141[0-9]*[Ff]&amp;lt;/code&amp;gt; -&amp;gt; &amp;lt;code&amp;gt;((float)Math.PI / 10F)&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;1.2566[0-9]*[Dd]&amp;lt;/code&amp;gt; -&amp;gt; &amp;lt;code&amp;gt;(Math.PI * 2D / 5D)&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;1.2566[0-9]*[Ff]&amp;lt;/code&amp;gt; -&amp;gt; &amp;lt;code&amp;gt;((float)Math.PI 2F / 5F)&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;0.21991[0-9]*[Dd]&amp;lt;/code&amp;gt; -&amp;gt; &amp;lt;code&amp;gt;(Math.PI * 7D / 100D)&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;0.21991[0-9]*[Ff]&amp;lt;/code&amp;gt; -&amp;gt; &amp;lt;code&amp;gt;((float)Math.PI * 7F / 100F)&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;5.8119[0-9]*[Dd]&amp;lt;/code&amp;gt; -&amp;gt; &amp;lt;code&amp;gt;(Math.PI * 185D / 100D)&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;0.8119[0-9]*[Ff]&amp;lt;/code&amp;gt; -&amp;gt; &amp;lt;code&amp;gt;((float)Math.PI * 185F / 100F)&amp;lt;/code&amp;gt;&lt;/div&gt;</summary>
		<author><name>Curle</name></author>
	</entry>
	<entry>
		<id>https://forge.gemwire.uk/index.php?title=Toolchain/Magic_Constants&amp;diff=2385</id>
		<title>Toolchain/Magic Constants</title>
		<link rel="alternate" type="text/html" href="https://forge.gemwire.uk/index.php?title=Toolchain/Magic_Constants&amp;diff=2385"/>
		<updated>2021-01-11T05:52:08Z</updated>

		<summary type="html">&lt;p&gt;Curle: Create page&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;The [[Toolchain:MCPCleanup]] utility has many functions, one among them is to convert known constants into code representation for easier visualisation.&lt;br /&gt;
&lt;br /&gt;
== Constants ==&lt;br /&gt;
&lt;br /&gt;
The known substitutions are:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;1.7976[0-9]*[Ee]+308[Dd]&amp;lt;/code&amp;gt; -&amp;gt; &amp;lt;code&amp;gt;Double.MAX_VALUE&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;3.1415[0-9]*[Dd]&amp;lt;/code&amp;gt; -&amp;gt; &amp;lt;code&amp;gt;Math.PI&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;3.1415[0-9]*[Ff]&amp;lt;/code&amp;gt; -&amp;gt; &amp;lt;code&amp;gt;(float)Math.PI&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;6.2831[0-9]*[Dd]&amp;lt;/code&amp;gt; -&amp;gt; &amp;lt;code&amp;gt;(Math.PI * 2D)&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;6.2831[0-9]*[Ff]&amp;lt;/code&amp;gt; -&amp;gt; &amp;lt;code&amp;gt;((float)Math.PI * 2F)&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;4.7123[0-9]*[Dd]&amp;lt;/code&amp;gt; -&amp;gt; &amp;lt;code&amp;gt;(Math.PI * 3D / 2D)&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;4.7123[0-9]*[Ff]&amp;lt;/code&amp;gt; -&amp;gt; &amp;lt;code&amp;gt;((float)Math.PI * 3F / 2F)&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;0.7853[0-9]*[Dd]&amp;lt;/code&amp;gt; -&amp;gt; &amp;lt;code&amp;gt;(Math.PI / 4D)&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;0.7853[0-9]*[Ff]&amp;lt;/code&amp;gt; -&amp;gt; &amp;lt;code&amp;gt;((float)Math.PI / 4F)&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;6.2831[0-9]*[Ff]&amp;lt;/code&amp;gt; -&amp;gt; &amp;lt;code&amp;gt;((float)Math.PI * 2F)&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;0.6283[0-9]*[Dd]&amp;lt;/code&amp;gt; -&amp;gt; &amp;lt;code&amp;gt;(Math.PI / 5D)&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;0.6283[0-9]*[Ff]&amp;lt;/code&amp;gt; -&amp;gt; &amp;lt;code&amp;gt;((float)Math.PI / 5F)&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;57.295[0-9]*[Dd]&amp;lt;/code&amp;gt; -&amp;gt; &amp;lt;code&amp;gt;(180D / Math.PI)&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;57.295[0-9]*[Ff]&amp;lt;/code&amp;gt; -&amp;gt; &amp;lt;code&amp;gt;(180F / (float)Math.PI)&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;0.6981[0-9]*[Dd]&amp;lt;/code&amp;gt; -&amp;gt; &amp;lt;code&amp;gt;(Math.PI * 2D / 9D)&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;0.6981[0-9]*[Ff]&amp;lt;/code&amp;gt; -&amp;gt; &amp;lt;code&amp;gt;((float)Math.PI * 2F / 9F)&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;0.3141[0-9]*[Dd]&amp;lt;/code&amp;gt; -&amp;gt; &amp;lt;code&amp;gt;(Math.PI / 10D)&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;0.3141[0-9]*[Ff]&amp;lt;/code&amp;gt; -&amp;gt; &amp;lt;code&amp;gt;((float)Math.PI / 10F)&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;1.2566[0-9]*[Dd]&amp;lt;/code&amp;gt; -&amp;gt; &amp;lt;code&amp;gt;(Math.PI * 2D / 5D)&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;1.2566[0-9]*[Ff]&amp;lt;/code&amp;gt; -&amp;gt; &amp;lt;code&amp;gt;((float)Math.PI 2F / 5F)&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;0.21991[0-9]*[Dd]&amp;lt;/code&amp;gt; -&amp;gt; &amp;lt;code&amp;gt;(Math.PI * 7D / 100D)&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;0.21991[0-9]*[Ff]&amp;lt;/code&amp;gt; -&amp;gt; &amp;lt;code&amp;gt;((float)Math.PI * 7F / 100F)&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;5.8119[0-9]*[Dd]&amp;lt;/code&amp;gt; -&amp;gt; &amp;lt;code&amp;gt;(Math.PI * 185D / 100D)&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;0.8119[0-9]*[Ff]&amp;lt;/code&amp;gt; -&amp;gt; &amp;lt;code&amp;gt;((float)Math.PI * 185F / 100F)&amp;lt;/code&amp;gt;&lt;/div&gt;</summary>
		<author><name>Curle</name></author>
	</entry>
	<entry>
		<id>https://forge.gemwire.uk/index.php?title=Toolchain&amp;diff=2384</id>
		<title>Toolchain</title>
		<link rel="alternate" type="text/html" href="https://forge.gemwire.uk/index.php?title=Toolchain&amp;diff=2384"/>
		<updated>2021-01-11T05:34:50Z</updated>

		<summary type="html">&lt;p&gt;Curle: Undo weirdness from visual editor&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{DISPLAYTITLE:Deobfuscation Process}}&lt;br /&gt;
{{Under construction}}&lt;br /&gt;
&lt;br /&gt;
The Forge toolchain is designed to clean up, merge, deobfuscate, rename, patch and provide the Minecraft source code for the usage of modders, researchers, or just those curious about how the game works.&lt;br /&gt;
&lt;br /&gt;
This serves as an explanation as to how the development environment sets up your code, and aims to help you troubleshoot in case something goes wrong.&lt;br /&gt;
&lt;br /&gt;
== Overall process ==&lt;br /&gt;
When setting up the environment for the first time, a gradle refresh triggers three things:&lt;br /&gt;
# ForgeGradle downloads the MCPConfig zip for the file you're using, and triggers the SetupMCP task.&lt;br /&gt;
# After that, it processes the jar - applies access transformers, MCPCleanup and others&lt;br /&gt;
# Finally, it patches and finalises the code, ready for modder consumption.&lt;br /&gt;
&lt;br /&gt;
== Needed knowledge ==&lt;br /&gt;
=== Obfuscation ===&lt;br /&gt;
'''Obfuscation''' is the process of renaming all of the fields, methods, and classes of the compiled code into unreadable, machine-generated names (such as &amp;lt;code&amp;gt;aaa&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;bC&amp;lt;/code&amp;gt;), and removing package structures (this makes everything package-local and makes the obfuscated code smaller somewhat. This is commonly used by companies to prevent external entities from easily decompiling their released binaries/executables and retrieving their source code/intellectual property, though it does have size advantages.&lt;br /&gt;
&lt;br /&gt;
Additionally, due to the way the Local Variable Table (LVT) of Java bytecode is stored, every function-local variable name is turned to ☃ (that's right, a snowman) in the compiled files. This makes immediate recompilation of the game literally and physically impossible, as every Java compiler currently available requires that local variables have unique names.&lt;br /&gt;
&lt;br /&gt;
Minecraft is a commercial game, which means the source code is unavailable to all except the developers of Mojang. To prevent piracy and the copying of their intellectual property, Mojang applies this obfuscation process to the game before they release it. They use a tool called [https://www.guardsquare.com/en/products/proguard ProGuard], which is both an optimizer&amp;lt;ref&amp;gt;An optimizer is a program that removes redundant/unused instructions and compacts the code to be faster and smaller.&amp;lt;/ref&amp;gt; and an obfuscator.&lt;br /&gt;
&lt;br /&gt;
=== Problematic Naming ===&lt;br /&gt;
There are a few big problems with using these obfuscated names directly for modding.&lt;br /&gt;
&lt;br /&gt;
# It is incredibly difficult to create mods using these obfuscated names. It requires immense patience to reverse-engineer the meanings behind each and every name, and to keep relating those names to what was already reverse-engineered. Although, tools do exist to make this process easier, such as IntelliJ IDEA plugins that provide naming hints automatically.&lt;br /&gt;
# Because the obfuscation process takes place after compilation (the obfuscator operates on the compiled classes), the obfuscated names are not handled by the compiler. Thus, obfuscated classes may contain member&amp;lt;ref&amp;gt;'''member''' refers to class fields and methods.&amp;lt;/ref&amp;gt; names that are invalid in the Java source language, but valid in compiled bytecode (like ☃ discussed earlier); this means that the decompiled source of the game is not immediately recompilable.&lt;br /&gt;
# These obfuscated names are automatically generated by the obfuscator for each independent release. This means that the obfuscated names may change signficantly between any two versions, making it harder for mod developers to update mods between releases.&lt;br /&gt;
&lt;br /&gt;
=== SRGification ===&lt;br /&gt;
Some background on what SRG is and how it works:&lt;br /&gt;
&lt;br /&gt;
'''SRG''' stands for '''S'''ea'''RG'''e, co-author of the Mod Creator Pack, who created this process.&lt;br /&gt;
Each obfuscated class, method, and field is assigned a unique number by the [[Toolchain:MCPConfig|backend]], via a sequential counter. This unique number is called the '''SRG ID''' of that class/method/field (henceforth called member).&lt;br /&gt;
&lt;br /&gt;
The SRG name of the member is then derived from its SRG ID, its type (function {given the prefix func_}, field {given the prefix field_}, parameter {given the prefix p_, or p_i if this is the parameter of a constructor}), and (optionally) the obfuscated name of the object at the time it was given its SRG name&amp;lt;ref&amp;gt;The SRG name for a given member is only created once, when it first appears in the code. Therefore, the SRG postfix may be different from the current obf name.&amp;lt;/ref&amp;gt;. This inclusion of the SRG ID into the name guarantees that the SRG name for all members are unique, and is the reason the ID is generated.&lt;br /&gt;
&lt;br /&gt;
The actual conversion of obf names to SRG names is done by a tool called [[Toolchain:SpecialSource|SpecialSource]]. More information on how it works can be found on that page.&lt;br /&gt;
&lt;br /&gt;
== The Setup ==&lt;br /&gt;
The process can be broken up into 3 steps; MCPConfig, patch and provide.&lt;br /&gt;
The MCPConfig step is, understandably, the biggest and most prone to failure.&lt;br /&gt;
An explanation of MCPConfig itself, how it works, what it's for (but NOT how to use it) can be found [[Toolchain:MCPConfig|here]]. For the purpose of this guide, you need only know that its' goal is to get the game decompiled, and into a state where it can immediately be recompiled. Due to certain flaws in the rest of the toolchain, this means it needs to fix and patch the source code before passing it onto Forge.&lt;br /&gt;
&lt;br /&gt;
In this way, MCPConfig can be thought of the vanilla side of the setup. It does not modify the game.&lt;br /&gt;
&lt;br /&gt;
=== Download and parsing MCPConfig ===&lt;br /&gt;
The first thing that ForgeGradle does upon initialising a first-time setup, is starting the [https://github.com/MinecraftForge/ForgeGradle/blob/e2ed49546abced95650635f81be071441ec60995/src/mcp/java/net/minecraftforge/gradle/mcp/task/SetupMCPTask.java#L91 SetupMCP] task. &lt;br /&gt;
This task then seeks to [https://github.com/MinecraftForge/ForgeGradle/blob/e2ed49546abced95650635f81be071441ec60995/src/mcp/java/net/minecraftforge/gradle/mcp/task/DownloadMCPConfigTask.java#L78 download the MCPConfig.zip jar] for the version you're setting up.&lt;br /&gt;
Once it is acquired, it [https://github.com/MinecraftForge/ForgeGradle/blob/e2ed49546abced95650635f81be071441ec60995/src/mcp/java/net/minecraftforge/gradle/mcp/util/MCPRuntime.java#L74 parses the steps contained within the config.json]. It does this by interpreting the file with the following rules:&lt;br /&gt;
* Every key, except for libraries, is interpreted as the name of a step.&lt;br /&gt;
* Steps are executed in order.&lt;br /&gt;
* The version value is interpreted as a maven coordinate of a file to download.&lt;br /&gt;
* If there is a repo value, it is used instead of the maven repositories defined in the buildscript, to retrieve the version.&lt;br /&gt;
* The args array is parsed, and {values} like this are interpreted as inputs, which can be substituted accordingly.&lt;br /&gt;
* Once the step is all parsed in, it is executed:&lt;br /&gt;
** java -jar &amp;amp;lt;version&amp;amp;gt; &amp;amp;lt;args&amp;amp;gt; &amp;amp;lt;jvmArgs&amp;amp;gt;&lt;br /&gt;
&lt;br /&gt;
An example config.json can be found [https://github.com/MinecraftForge/MCPConfig/blob/master/versions/release/1.16.4/config.json here].&lt;br /&gt;
&lt;br /&gt;
It defines the steps:&lt;br /&gt;
* [[Toolchain:MCinjector|mcinjector]]&lt;br /&gt;
** version: de.oceanlabs.mcp:mcinjector:3.8.0:fatjar&lt;br /&gt;
** args: --in {input} --out {output} --log {log} --level=INFO --lvt=LVT --exc {exceptions} --acc {access} --ctr {constructors}&lt;br /&gt;
* [[Toolchain:ForgeFlower|fernflower]]&lt;br /&gt;
** version: net.minecraftforge:forgeflower:1.5.478.16&lt;br /&gt;
** args: -din=1 -rbr=1 -dgs=1 -asc=1 -rsy=1 -iec=1 -jvn=1 -isl=0 -iib=1 -log=TRACE -cfg {libraries} {input} {output}&lt;br /&gt;
** jvmargs: -Xmx4G&lt;br /&gt;
* [[Toolchain:Mergetool|merge]]&lt;br /&gt;
** version: net.minecraftforge:mergetool:1.1.1:fatjar&lt;br /&gt;
** args: --client {client} --server {server} --ann {version} --output {output} --inject false&amp;quot;&lt;br /&gt;
* [[Toolchain:MCInjector|rename]]&lt;br /&gt;
** version: net.md-5:SpecialSource:1.8.3:shaded&lt;br /&gt;
** args: --in-jar {input} --out-jar {output} --srg-in {mappings}&lt;br /&gt;
** repo: https://repo1.maven.org/maven2/&lt;br /&gt;
&lt;br /&gt;
More information about each of these tools can be found at the link provided, as well as what each of these arguments do. A brief description is provided.&lt;br /&gt;
&lt;br /&gt;
=== MCInjector ===&lt;br /&gt;
[https://github.com/ModCoderPack/MCInjector MCInjector] is the tool we use to apply various fixes to the code, while it is still in bytecode form. That meaning, it works on compiled code, not sourcecode. It does this because it's easier to rename LVT entries (from the snowman) to readable names while you can search for every other code path that references that specific entry; ergo renaming all accesses at once. This is impossible in sourcecode, where every name is identical and string matching is impossible.&lt;br /&gt;
&lt;br /&gt;
It:&lt;br /&gt;
* Removes synthetic parameters from constructors&lt;br /&gt;
** In bytecode, inner classes have the outer class as their first constructor parameter, but Java source code does not.&lt;br /&gt;
* Handles adding annotations for parameters that have synthetic data&lt;br /&gt;
** In bytecode, these Nonnull (or whatever) annotations are attached to the parameters, not to the function that contains them.&lt;br /&gt;
* Adds constructors for inner classes&lt;br /&gt;
** These are removed by Proguard sometimes, as they are not required in the bytecode if the parent has a default constructor.&lt;br /&gt;
* Adds synthetic (invisible) constructors for classes without them&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
It also applies fixes for things like EXC;&lt;br /&gt;
* Renaming parameters inside constructors, such that subclasses retain the ID of their parent.&lt;br /&gt;
* Fixing access for select functions, where it is required for the proper recompilation.&lt;br /&gt;
* Applying proper typing to constructor parameters&lt;br /&gt;
* Applying proper external (LWJGL) exception data to functions and classes.&lt;br /&gt;
&lt;br /&gt;
Note that it does NOT rename to SRG. LVT (Local Variables) are renamed to lvt_&amp;amp;lt;index&amp;amp;gt;_&amp;amp;lt;version&amp;amp;gt;&amp;lt;ref&amp;gt;Index means: the place where this item was found. If it is the 4th entry in the table, it is index 3.&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== ForgeFlower === &lt;br /&gt;
After the code has been cleaned up by MCInjector, to a state where it no longer conflicts with itself, it can be passed to the decompiler. &lt;br /&gt;
&lt;br /&gt;
The decompiler used by ForgeGradle is a custom fork of [https://github.com/JetBrains/intellij-community/tree/master/plugins/java-decompiler/engine Jetbrains' FernFlower], called [https://github.com/MinecraftForge/ForgeFlower ForgeFlower].&lt;br /&gt;
&lt;br /&gt;
It simply searches the jar for files, converts the bytecode into a reasonable best-guess interpretation.&lt;br /&gt;
As you can see by the repository, a lot of work has gone into tuning it for Minecraft's needs, but it is still a far way from perfect. This is why the patches are needed.&lt;br /&gt;
&lt;br /&gt;
If you [https://github.com/MinecraftForge/MCPConfig/blob/master/versions/release/1.16.4/patches/ look at the patches] for 1.16.4, they are mostly incredibly simple changes. Adding generics, making types more strict. &lt;br /&gt;
&lt;br /&gt;
This is all stuff that should be done by the decompiler, and PRs are always welcome at the ForgeFlower repository for changes and fixes that would reduce the amount of MCPConfig patches required to get the game to compile.&lt;br /&gt;
&lt;br /&gt;
For now, it is a necessity.&lt;br /&gt;
&lt;br /&gt;
=== Mergetool ===&lt;br /&gt;
The game is split into two distributions; server and client.&lt;br /&gt;
&lt;br /&gt;
Because the server contains no rendering code, and the client contains none of the server-specific code (like the UI), this means there are differences between what can run on one side or the other.&lt;br /&gt;
&lt;br /&gt;
To get around this, we have a tool called Mergetool, which can search for the differences between two files (down to the function level) and merge them into one large (referred to as joined) jar file.&lt;br /&gt;
&lt;br /&gt;
It is a simple program, but it works.&lt;br /&gt;
&lt;br /&gt;
=== SpecialSource ===&lt;br /&gt;
SpecialSource is where SRG starts to come into play. It serves the role of our deobfuscator, performing deobfuscation.&lt;br /&gt;
&lt;br /&gt;
This process is done with the help of a '''deobfusation map''', a file generated by the original obfuscator (in this case, ProGuard) that contains a map of the obfuscated names to original, non-obfuscated names. This is commonly used on debofuscating stack traces outputted by an obfuscated program, for debugging purposes.&amp;lt;ref name=&amp;quot;retrace&amp;quot;/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We have three sets of deobfuscation maps available to us; the obf-&amp;gt;SRG mappings distributed with the MCPConfig system, the Yarn intermediary system, or the offical mappings.&amp;lt;ref name=&amp;quot;mojmappings&amp;quot;/&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
To rectify this problem, Forge has it's own process to create deobfuscation mappings for the game, using community-sourced human-readable names. This process is split into two separate parts: the '''SRG renaming''', and the '''MCP mapping'''. During the SetupMCP task, only the SRG renaming is performed.&lt;br /&gt;
&lt;br /&gt;
SpecialSource itself operates on the source jar, as can be gathered by the name, and takes in a .tsrg file, like that [https://github.com/MinecraftForge/MCPConfig/blob/master/versions/release/1.16.4/joined.tsrg contained in the MCPConfig zip].&lt;br /&gt;
&lt;br /&gt;
It first renames classes, straight into MCP names.&lt;br /&gt;
Then, iterating the members of the class, it renames fields, methods, parameters and inner classes.&lt;br /&gt;
&lt;br /&gt;
A recap from earlier:&lt;br /&gt;
* For classes -&amp;gt; &amp;lt;code&amp;gt;c_###_&amp;lt;/code&amp;gt; (but it is immediately changed without the c_ being written to disk)&lt;br /&gt;
* For functions/methods -&amp;gt; &amp;lt;code&amp;gt;func_&amp;amp;lt;ID&amp;amp;gt;_&amp;amp;lt;obf-name&amp;amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
* For fields -&amp;gt; &amp;lt;code&amp;gt;field_&amp;amp;lt;ID&amp;amp;gt;_&amp;amp;lt;obf-name&amp;amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
* For function/method parameters -&amp;gt; &amp;lt;code&amp;gt;p_###_#_&amp;lt;/code&amp;gt; for normal methods, &amp;lt;code&amp;gt;p_i###_#&amp;lt;/code&amp;gt; for constructors; the second number is the index&amp;lt;ref&amp;gt;The index is the position of the argument. 0 on the left, 1 after that, 2 after that. Note that double and long arguments increase their index by two, rather than one.&amp;lt;/ref&amp;gt; of the parameter.&lt;br /&gt;
&lt;br /&gt;
For example, &amp;lt;code&amp;gt;func_71410_x&amp;lt;/code&amp;gt; refers to a function with SRG ID 71410 and original obfuscated name of &amp;lt;code&amp;gt;x&amp;lt;/code&amp;gt;.&amp;lt;ref&amp;gt;For version 1.16.2, &amp;lt;code&amp;gt;func_71410_x&amp;lt;/code&amp;gt; refers to &amp;lt;code&amp;gt;Minecraft.getInstance()&amp;lt;/code&amp;gt;, with real obfuscated name of &amp;lt;code&amp;gt;B&amp;lt;/code&amp;gt;, but when the getInstance() function was first discovered in code, it was called x.&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
At this point, combined with the MCInjector step from earlier, we have a completely SRGed-up source jar.&lt;br /&gt;
&lt;br /&gt;
=== Patches ===&lt;br /&gt;
Once we have the source code ready to go, the final step in the setup is to apply patches.&lt;br /&gt;
These are done trivially, using diffs and [https://github.com/CadixDev/gitpatcher gitpatcher].&lt;br /&gt;
&lt;br /&gt;
=== Clean-up ===&lt;br /&gt;
Because of the way Proguard (or whatever obfuscator) and ForgeFlower mangle the source code, we need to take some steps to clean it up before we can proceed.&lt;br /&gt;
&lt;br /&gt;
Assorted cleanup fixes are performed by the [https://github.com/MinecraftForge/MCPCleanup/ MCPCleanup] utility. These include:&lt;br /&gt;
* removing trailing whitespace at the end of lines&lt;br /&gt;
* removing extra newlines at the start and end of files&lt;br /&gt;
* removing extra newlines between every line of code (every set of concurrent newlines is replaced with a single)&lt;br /&gt;
* removing comments (// hello, /* hello */)&lt;br /&gt;
** the purpose of this step is unclear - it seems to be a preventative measure to ensure that Java changes do not interfere with the patch alignment in the future. Comments from the decompiler are still sometimes present in the source code.&lt;br /&gt;
* removing imports from the package a class is in&lt;br /&gt;
* removing comments that include the phrase &amp;lt;code&amp;gt;GL_[^*]+&amp;lt;/code&amp;gt;&lt;br /&gt;
* replacing [[Toolchain:Magic Constants|magic constants]] with their code substitutions&lt;br /&gt;
* replacing &amp;lt;code&amp;gt;Character.valueOf(&amp;amp;lt;character&amp;amp;gt;)&amp;lt;/code&amp;gt; with &amp;lt;code&amp;gt;&amp;amp;lt;character&amp;amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
* replacing OpenGL integer constants with their code representation&lt;br /&gt;
* converting unicode character constants back into integer representation&lt;br /&gt;
* formatting the code with JAStyle&lt;br /&gt;
&lt;br /&gt;
It also adjusts abstract functions in some way - after running the program on a jar, the parameters of a default abstract function get renamed, but it is unclear exactly what part of the source code does this.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Mappings ==&lt;br /&gt;
We don't need this step but coding with the &amp;lt;code&amp;gt;SRG&amp;lt;/code&amp;gt; names is hard and not really fun.&lt;br /&gt;
So we need to take the &amp;lt;code&amp;gt;SRG&amp;lt;/code&amp;gt; names and make them more user friendly, the user friendly names are community sourced names.&lt;br /&gt;
Since &amp;lt;code&amp;gt;SRG&amp;lt;/code&amp;gt; names are uniquely identifiable, due to the unique ID, it literally does a search-and-replace on all the source code text to do that &amp;lt;code&amp;gt;SRG&amp;lt;/code&amp;gt;-&amp;gt;&amp;lt;code&amp;gt;MCP&amp;lt;/code&amp;gt;(( &amp;lt;code&amp;gt;MCP&amp;lt;/code&amp;gt; stands for ModCoderPack (or previously, Minecraft Coder Pack) which was the toolchain that did all of this before the advent of ForgeGradle)) application.&lt;br /&gt;
&lt;br /&gt;
== Some additional Infos ==&lt;br /&gt;
# You will never see c_XXX_ for classes, because the class names are picked beforehand&lt;br /&gt;
#* this is still crowdsourced, but before a new version is ready for Forge, all classes are given an &amp;lt;code&amp;gt;MCP&amp;lt;/code&amp;gt; name&lt;br /&gt;
#* this &amp;lt;code&amp;gt;MCP&amp;lt;/code&amp;gt; name stays constant throughout the game version it was picked for; it can change between versions, but it usually wont for already-named classes (except for misspells, typos, and misnames)&lt;br /&gt;
# If you look into the JAR, you won't see any packages for the obfuscated classes, but the deobfuscated classes do have the packages, this is because the same process that names the classes, also decides what package they belong to&lt;br /&gt;
# parameters have special names&lt;br /&gt;
#* there are two types of parameter names: &amp;lt;code&amp;gt;p_XXX_X_&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;p_iXXX_X_&amp;lt;/code&amp;gt;&lt;br /&gt;
#* the one with the i means that it's a parameter for a constructor&lt;br /&gt;
#* the first set of numbers are the SRG ID of their parent method, and the second number denotes the index of the parameter&lt;br /&gt;
#* the index of the parameter is a bit more involved, but this will not be explained here&lt;br /&gt;
# If you look into the source, you'll see that parameters for lambdas don't have mapped names&lt;br /&gt;
#* This is because of a complication in how the lambdas are compiled/decompiled; it's a more advanced topic which involves how the compiler compiles lambdas which we will not explain here.&lt;br /&gt;
&lt;br /&gt;
== See also ==&lt;br /&gt;
* [https://en.wikipedia.org/wiki/Obfuscation_(software) Obfuscation]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;references&amp;gt;&lt;br /&gt;
&amp;lt;ref name=&amp;quot;retrace&amp;quot;&amp;gt;For ProGuard users (such as Mojang), this is done using [https://www.guardsquare.com/en/products/proguard/manual/retrace ReTrace].&amp;lt;/ref&amp;gt;&lt;br /&gt;
&amp;lt;ref name=&amp;quot;mojmappings&amp;quot;&amp;gt;Mojang recently released their deobfuscation mappings for Minecraft (colloquially named &amp;lt;code&amp;gt;mojmappings&amp;lt;/code&amp;gt;), but the licensing for its uses is a bit ambiguous. [https://cpw.github.io/MinecraftMappingData See this post by cpw] for more information.&amp;lt;/ref&amp;gt;&lt;br /&gt;
&amp;lt;/references&amp;gt;&lt;/div&gt;</summary>
		<author><name>Curle</name></author>
	</entry>
	<entry>
		<id>https://forge.gemwire.uk/index.php?title=Toolchain&amp;diff=2383</id>
		<title>Toolchain</title>
		<link rel="alternate" type="text/html" href="https://forge.gemwire.uk/index.php?title=Toolchain&amp;diff=2383"/>
		<updated>2021-01-11T05:33:15Z</updated>

		<summary type="html">&lt;p&gt;Curle: Fix link to &amp;quot;magic constants&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{DISPLAYTITLE:Deobfuscation Process}}&lt;br /&gt;
{{Under construction}}&lt;br /&gt;
&lt;br /&gt;
The Forge toolchain is designed to clean up, merge, deobfuscate, rename, patch and provide the Minecraft source code for the usage of modders, researchers, or just those curious about how the game works.&lt;br /&gt;
&lt;br /&gt;
This serves as an explanation as to how the development environment sets up your code, and aims to help you troubleshoot in case something goes wrong.&lt;br /&gt;
&lt;br /&gt;
== Overall process ==&lt;br /&gt;
When setting up the environment for the first time, a gradle refresh triggers three things:&lt;br /&gt;
# ForgeGradle downloads the MCPConfig zip for the file you're using, and triggers the SetupMCP task.&lt;br /&gt;
# After that, it processes the jar - applies access transformers, MCPCleanup and others&lt;br /&gt;
# Finally, it patches and finalises the code, ready for modder consumption.&lt;br /&gt;
&lt;br /&gt;
== Needed knowledge ==&lt;br /&gt;
=== Obfuscation ===&lt;br /&gt;
'''Obfuscation''' is the process of renaming all of the fields, methods, and classes of the compiled code into unreadable, machine-generated names (such as &amp;lt;code&amp;gt;aaa&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;bC&amp;lt;/code&amp;gt;), and removing package structures (this makes everything package-local and makes the obfuscated code smaller somewhat. This is commonly used by companies to prevent external entities from easily decompiling their released binaries/executables and retrieving their source code/intellectual property, though it does have size advantages.&lt;br /&gt;
&lt;br /&gt;
Additionally, due to the way the Local Variable Table (LVT) of Java bytecode is stored, every function-local variable name is turned to ☃ (that's right, a snowman) in the compiled files. This makes immediate recompilation of the game literally and physically impossible, as every Java compiler currently available requires that local variables have unique names.&lt;br /&gt;
&lt;br /&gt;
Minecraft is a commercial game, which means the source code is unavailable to all except the developers of Mojang. To prevent piracy and the copying of their intellectual property, Mojang applies this obfuscation process to the game before they release it. They use a tool called [https://www.guardsquare.com/en/products/proguard ProGuard], which is both an optimizer&amp;lt;ref&amp;gt;An optimizer is a program that removes redundant/unused instructions and compacts the code to be faster and smaller.&amp;lt;/ref&amp;gt; and an obfuscator.&lt;br /&gt;
&lt;br /&gt;
=== Problematic Naming ===&lt;br /&gt;
There are a few big problems with using these obfuscated names directly for modding.&lt;br /&gt;
&lt;br /&gt;
# It is incredibly difficult to create mods using these obfuscated names. It requires immense patience to reverse-engineer the meanings behind each and every name, and to keep relating those names to what was already reverse-engineered. Although, tools do exist to make this process easier, such as IntelliJ IDEA plugins that provide naming hints automatically.&lt;br /&gt;
# Because the obfuscation process takes place after compilation (the obfuscator operates on the compiled classes), the obfuscated names are not handled by the compiler. Thus, obfuscated classes may contain member&amp;lt;ref&amp;gt;'''member''' refers to class fields and methods.&amp;lt;/ref&amp;gt; names that are invalid in the Java source language, but valid in compiled bytecode (like ☃ discussed earlier); this means that the decompiled source of the game is not immediately recompilable.&lt;br /&gt;
# These obfuscated names are automatically generated by the obfuscator for each independent release. This means that the obfuscated names may change signficantly between any two versions, making it harder for mod developers to update mods between releases.&lt;br /&gt;
&lt;br /&gt;
=== SRGification ===&lt;br /&gt;
Some background on what SRG is and how it works:&lt;br /&gt;
&lt;br /&gt;
'''SRG''' stands for '''S'''ea'''RG'''e, co-author of the Mod Creator Pack, who created this process.&lt;br /&gt;
Each obfuscated class, method, and field is assigned a unique number by the [[Toolchain:MCPConfig|backend]], via a sequential counter. This unique number is called the '''SRG ID''' of that class/method/field (henceforth called member).&lt;br /&gt;
&lt;br /&gt;
The SRG name of the member is then derived from its SRG ID, its type (function {given the prefix func_}, field {given the prefix field_}, parameter {given the prefix p_, or p_i if this is the parameter of a constructor}), and (optionally) the obfuscated name of the object at the time it was given its SRG name&amp;lt;ref&amp;gt;The SRG name for a given member is only created once, when it first appears in the code. Therefore, the SRG postfix may be different from the current obf name.&amp;lt;/ref&amp;gt;. This inclusion of the SRG ID into the name guarantees that the SRG name for all members are unique, and is the reason the ID is generated.&lt;br /&gt;
&lt;br /&gt;
The actual conversion of obf names to SRG names is done by a tool called [[Toolchain:SpecialSource|SpecialSource]]. More information on how it works can be found on that page.&lt;br /&gt;
&lt;br /&gt;
== The Setup ==&lt;br /&gt;
The process can be broken up into 3 steps; MCPConfig, patch and provide.&lt;br /&gt;
The MCPConfig step is, understandably, the biggest and most prone to failure.&lt;br /&gt;
An explanation of MCPConfig itself, how it works, what it's for (but NOT how to use it) can be found [[Toolchain:MCPConfig|here]]. For the purpose of this guide, you need only know that its' goal is to get the game decompiled, and into a state where it can immediately be recompiled. Due to certain flaws in the rest of the toolchain, this means it needs to fix and patch the source code before passing it onto Forge.&lt;br /&gt;
&lt;br /&gt;
In this way, MCPConfig can be thought of the vanilla side of the setup. It does not modify the game.&lt;br /&gt;
&lt;br /&gt;
=== Download and parsing MCPConfig ===&lt;br /&gt;
The first thing that ForgeGradle does upon initialising a first-time setup, is starting the [https://github.com/MinecraftForge/ForgeGradle/blob/e2ed49546abced95650635f81be071441ec60995/src/mcp/java/net/minecraftforge/gradle/mcp/task/SetupMCPTask.java#L91 SetupMCP] task. &lt;br /&gt;
This task then seeks to [https://github.com/MinecraftForge/ForgeGradle/blob/e2ed49546abced95650635f81be071441ec60995/src/mcp/java/net/minecraftforge/gradle/mcp/task/DownloadMCPConfigTask.java#L78 download the MCPConfig.zip jar] for the version you're setting up.&lt;br /&gt;
Once it is acquired, it [https://github.com/MinecraftForge/ForgeGradle/blob/e2ed49546abced95650635f81be071441ec60995/src/mcp/java/net/minecraftforge/gradle/mcp/util/MCPRuntime.java#L74 parses the steps contained within the config.json]. It does this by interpreting the file with the following rules:&lt;br /&gt;
* Every key, except for libraries, is interpreted as the name of a step.&lt;br /&gt;
* Steps are executed in order.&lt;br /&gt;
* The version value is interpreted as a maven coordinate of a file to download.&lt;br /&gt;
* If there is a repo value, it is used instead of the maven repositories defined in the buildscript, to retrieve the version.&lt;br /&gt;
* The args array is parsed, and {values} like this are interpreted as inputs, which can be substituted accordingly.&lt;br /&gt;
* Once the step is all parsed in, it is executed:&lt;br /&gt;
** java -jar &amp;amp;lt;version&amp;amp;gt; &amp;amp;lt;args&amp;amp;gt; &amp;amp;lt;jvmArgs&amp;amp;gt;&lt;br /&gt;
&lt;br /&gt;
An example config.json can be found [https://github.com/MinecraftForge/MCPConfig/blob/master/versions/release/1.16.4/config.json here].&lt;br /&gt;
&lt;br /&gt;
It defines the steps:&lt;br /&gt;
* [[Toolchain:MCinjector|mcinjector]]&lt;br /&gt;
** version: de.oceanlabs.mcp:mcinjector:3.8.0:fatjar&lt;br /&gt;
** args: --in {input} --out {output} --log {log} --level=INFO --lvt=LVT --exc {exceptions} --acc {access} --ctr {constructors}&lt;br /&gt;
* [[Toolchain:ForgeFlower|fernflower]]&lt;br /&gt;
** version: net.minecraftforge:forgeflower:1.5.478.16&lt;br /&gt;
** args: -din=1 -rbr=1 -dgs=1 -asc=1 -rsy=1 -iec=1 -jvn=1 -isl=0 -iib=1 -log=TRACE -cfg {libraries} {input} {output}&lt;br /&gt;
** jvmargs: -Xmx4G&lt;br /&gt;
* [[Toolchain:Mergetool|merge]]&lt;br /&gt;
** version: net.minecraftforge:mergetool:1.1.1:fatjar&lt;br /&gt;
** args: --client {client} --server {server} --ann {version} --output {output} --inject false&amp;quot;&lt;br /&gt;
* [[Toolchain:MCInjector|rename]]&lt;br /&gt;
** version: net.md-5:SpecialSource:1.8.3:shaded&lt;br /&gt;
** args: --in-jar {input} --out-jar {output} --srg-in {mappings}&lt;br /&gt;
** repo: https://repo1.maven.org/maven2/&lt;br /&gt;
&lt;br /&gt;
More information about each of these tools can be found at the link provided, as well as what each of these arguments do. A brief description is provided.&lt;br /&gt;
&lt;br /&gt;
=== MCInjector ===&lt;br /&gt;
[https://github.com/ModCoderPack/MCInjector MCInjector] is the tool we use to apply various fixes to the code, while it is still in bytecode form. That meaning, it works on compiled code, not sourcecode. It does this because it's easier to rename LVT entries (from the snowman) to readable names while you can search for every other code path that references that specific entry; ergo renaming all accesses at once. This is impossible in sourcecode, where every name is identical and string matching is impossible.&lt;br /&gt;
&lt;br /&gt;
It:&lt;br /&gt;
* Removes synthetic parameters from constructors&lt;br /&gt;
** In bytecode, inner classes have the outer class as their first constructor parameter, but Java source code does not.&lt;br /&gt;
* Handles adding annotations for parameters that have synthetic data&lt;br /&gt;
** In bytecode, these Nonnull (or whatever) annotations are attached to the parameters, not to the function that contains them.&lt;br /&gt;
* Adds constructors for inner classes&lt;br /&gt;
** These are removed by Proguard sometimes, as they are not required in the bytecode if the parent has a default constructor.&lt;br /&gt;
* Adds synthetic (invisible) constructors for classes without them&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
It also applies fixes for things like EXC;&lt;br /&gt;
* Renaming parameters inside constructors, such that subclasses retain the ID of their parent.&lt;br /&gt;
* Fixing access for select functions, where it is required for the proper recompilation.&lt;br /&gt;
* Applying proper typing to constructor parameters&lt;br /&gt;
* Applying proper external (LWJGL) exception data to functions and classes.&lt;br /&gt;
&lt;br /&gt;
Note that it does NOT rename to SRG. LVT (Local Variables) are renamed to lvt_&amp;amp;lt;index&amp;amp;gt;_&amp;amp;lt;version&amp;amp;gt;&amp;lt;ref&amp;gt;Index means: the place where this item was found. If it is the 4th entry in the table, it is index 3.&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== ForgeFlower === &lt;br /&gt;
After the code has been cleaned up by MCInjector, to a state where it no longer conflicts with itself, it can be passed to the decompiler. &lt;br /&gt;
&lt;br /&gt;
The decompiler used by ForgeGradle is a custom fork of [https://github.com/JetBrains/intellij-community/tree/master/plugins/java-decompiler/engine Jetbrains' FernFlower], called [https://github.com/MinecraftForge/ForgeFlower ForgeFlower].&lt;br /&gt;
&lt;br /&gt;
It simply searches the jar for files, converts the bytecode into a reasonable best-guess interpretation.&lt;br /&gt;
As you can see by the repository, a lot of work has gone into tuning it for Minecraft's needs, but it is still a far way from perfect. This is why the patches are needed.&lt;br /&gt;
&lt;br /&gt;
If you [https://github.com/MinecraftForge/MCPConfig/blob/master/versions/release/1.16.4/patches/ look at the patches] for 1.16.4, they are mostly incredibly simple changes. Adding generics, making types more strict. &lt;br /&gt;
&lt;br /&gt;
This is all stuff that should be done by the decompiler, and PRs are always welcome at the ForgeFlower repository for changes and fixes that would reduce the amount of MCPConfig patches required to get the game to compile.&lt;br /&gt;
&lt;br /&gt;
For now, it is a necessity.&lt;br /&gt;
&lt;br /&gt;
=== Mergetool ===&lt;br /&gt;
The game is split into two distributions; server and client.&lt;br /&gt;
&lt;br /&gt;
Because the server contains no rendering code, and the client contains none of the server-specific code (like the UI), this means there are differences between what can run on one side or the other.&lt;br /&gt;
&lt;br /&gt;
To get around this, we have a tool called Mergetool, which can search for the differences between two files (down to the function level) and merge them into one large (referred to as joined) jar file.&lt;br /&gt;
&lt;br /&gt;
It is a simple program, but it works.&lt;br /&gt;
&lt;br /&gt;
=== SpecialSource ===&lt;br /&gt;
SpecialSource is where SRG starts to come into play. It serves the role of our deobfuscator, performing deobfuscation.&lt;br /&gt;
&lt;br /&gt;
This process is done with the help of a '''deobfusation map''', a file generated by the original obfuscator (in this case, ProGuard) that contains a map of the obfuscated names to original, non-obfuscated names. This is commonly used on debofuscating stack traces outputted by an obfuscated program, for debugging purposes.&amp;lt;ref name=&amp;quot;retrace&amp;quot;/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We have three sets of deobfuscation maps available to us; the obf-&amp;gt;SRG mappings distributed with the MCPConfig system, the Yarn intermediary system, or the offical mappings.&amp;lt;ref name=&amp;quot;mojmappings&amp;quot;/&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
To rectify this problem, Forge has it's own process to create deobfuscation mappings for the game, using community-sourced human-readable names. This process is split into two separate parts: the '''SRG renaming''', and the '''MCP mapping'''. During the SetupMCP task, only the SRG renaming is performed.&lt;br /&gt;
&lt;br /&gt;
SpecialSource itself operates on the source jar, as can be gathered by the name, and takes in a .tsrg file, like that [https://github.com/MinecraftForge/MCPConfig/blob/master/versions/release/1.16.4/joined.tsrg contained in the MCPConfig zip].&lt;br /&gt;
&lt;br /&gt;
It first renames classes, straight into MCP names.&lt;br /&gt;
Then, iterating the members of the class, it renames fields, methods, parameters and inner classes.&lt;br /&gt;
&lt;br /&gt;
A recap from earlier:&lt;br /&gt;
* For classes -&amp;gt; &amp;lt;code&amp;gt;c_###_&amp;lt;/code&amp;gt; (but it is immediately changed without the c_ being written to disk)&lt;br /&gt;
* For functions/methods -&amp;gt; &amp;lt;code&amp;gt;func_&amp;amp;lt;ID&amp;amp;gt;_&amp;amp;lt;obf-name&amp;amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
* For fields -&amp;gt; &amp;lt;code&amp;gt;field_&amp;amp;lt;ID&amp;amp;gt;_&amp;amp;lt;obf-name&amp;amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
* For function/method parameters -&amp;gt; &amp;lt;code&amp;gt;p_###_#_&amp;lt;/code&amp;gt; for normal methods, &amp;lt;code&amp;gt;p_i###_#&amp;lt;/code&amp;gt; for constructors; the second number is the index&amp;lt;ref&amp;gt;The index is the position of the argument. 0 on the left, 1 after that, 2 after that. Note that double and long arguments increase their index by two, rather than one.&amp;lt;/ref&amp;gt; of the parameter.&lt;br /&gt;
&lt;br /&gt;
For example, &amp;lt;code&amp;gt;func_71410_x&amp;lt;/code&amp;gt; refers to a function with SRG ID 71410 and original obfuscated name of &amp;lt;code&amp;gt;x&amp;lt;/code&amp;gt;.&amp;lt;ref&amp;gt;For version 1.16.2, &amp;lt;code&amp;gt;func_71410_x&amp;lt;/code&amp;gt; refers to &amp;lt;code&amp;gt;Minecraft.getInstance()&amp;lt;/code&amp;gt;, with real obfuscated name of &amp;lt;code&amp;gt;B&amp;lt;/code&amp;gt;, but when the getInstance() function was first discovered in code, it was called x.&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
At this point, combined with the MCInjector step from earlier, we have a completely SRGed-up source jar.&lt;br /&gt;
&lt;br /&gt;
=== Patches ===&lt;br /&gt;
Once we have the source code ready to go, the final step in the setup is to apply patches.&lt;br /&gt;
These are done trivially, using diffs and [https://github.com/CadixDev/gitpatcher gitpatcher].&lt;br /&gt;
&lt;br /&gt;
===Clean-up===&lt;br /&gt;
Because of the way Proguard (or whatever obfuscator) and ForgeFlower mangle the source code, we need to take some steps to clean it up before we can proceed.&lt;br /&gt;
&lt;br /&gt;
Assorted cleanup fixes are performed by the [https://github.com/MinecraftForge/MCPCleanup/ MCPCleanup] utility. These include:&lt;br /&gt;
* removing trailing whitespace at the end of lines&lt;br /&gt;
* removing extra newlines at the start and end of files&lt;br /&gt;
* removing extra newlines between every line of code (every set of concurrent newlines is replaced with a single)&lt;br /&gt;
* removing comments (// hello, /* hello */)&lt;br /&gt;
** the purpose of this step is unclear - it seems to be a preventative measure to ensure that Java changes do not interfere with the patch alignment in the future. Comments from the decompiler are still sometimes present in the source code.&lt;br /&gt;
* removing imports from the package a class is in&lt;br /&gt;
* removing comments that include the phrase &amp;lt;code&amp;gt;GL_[^*]+&amp;lt;/code&amp;gt;&lt;br /&gt;
* replacing [[Toolchain:Magic Constants|magic constants]] with their code substitutions&lt;br /&gt;
* replacing &amp;lt;code&amp;gt;Character.valueOf(&amp;lt;character&amp;gt;)&amp;lt;/code&amp;gt; with &amp;lt;code&amp;gt;&amp;lt;character&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
* replacing OpenGL integer constants with their code representation&lt;br /&gt;
* converting unicode character constants back into integer representation&lt;br /&gt;
* formatting the code with JAStyle&lt;br /&gt;
&lt;br /&gt;
It also adjusts abstract functions in some way - after running the program on a jar, the parameters of a default abstract function get renamed, but it is unclear exactly what part of the source code does this.&lt;br /&gt;
&lt;br /&gt;
== Mappings ==&lt;br /&gt;
We don't need this step but coding with the &amp;lt;code&amp;gt;SRG&amp;lt;/code&amp;gt; names is hard and not really fun.&lt;br /&gt;
So we need to take the &amp;lt;code&amp;gt;SRG&amp;lt;/code&amp;gt; names and make them more user friendly, the user friendly names are community sourced names.&lt;br /&gt;
Since &amp;lt;code&amp;gt;SRG&amp;lt;/code&amp;gt; names are uniquely identifiable, due to the unique ID, it literally does a search-and-replace on all the source code text to do that &amp;lt;code&amp;gt;SRG&amp;lt;/code&amp;gt;-&amp;gt;&amp;lt;code&amp;gt;MCP&amp;lt;/code&amp;gt;(( &amp;lt;code&amp;gt;MCP&amp;lt;/code&amp;gt; stands for ModCoderPack (or previously, Minecraft Coder Pack) which was the toolchain that did all of this before the advent of ForgeGradle)) application.&lt;br /&gt;
&lt;br /&gt;
== Some additional Infos ==&lt;br /&gt;
# You will never see c_XXX_ for classes, because the class names are picked beforehand&lt;br /&gt;
#* this is still crowdsourced, but before a new version is ready for Forge, all classes are given an &amp;lt;code&amp;gt;MCP&amp;lt;/code&amp;gt; name&lt;br /&gt;
#* this &amp;lt;code&amp;gt;MCP&amp;lt;/code&amp;gt; name stays constant throughout the game version it was picked for; it can change between versions, but it usually wont for already-named classes (except for misspells, typos, and misnames)&lt;br /&gt;
# If you look into the JAR, you won't see any packages for the obfuscated classes, but the deobfuscated classes do have the packages, this is because the same process that names the classes, also decides what package they belong to&lt;br /&gt;
# parameters have special names&lt;br /&gt;
#* there are two types of parameter names: &amp;lt;code&amp;gt;p_XXX_X_&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;p_iXXX_X_&amp;lt;/code&amp;gt;&lt;br /&gt;
#* the one with the i means that it's a parameter for a constructor&lt;br /&gt;
#* the first set of numbers are the SRG ID of their parent method, and the second number denotes the index of the parameter&lt;br /&gt;
#* the index of the parameter is a bit more involved, but this will not be explained here&lt;br /&gt;
# If you look into the source, you'll see that parameters for lambdas don't have mapped names&lt;br /&gt;
#* This is because of a complication in how the lambdas are compiled/decompiled; it's a more advanced topic which involves how the compiler compiles lambdas which we will not explain here.&lt;br /&gt;
&lt;br /&gt;
== See also ==&lt;br /&gt;
* [https://en.wikipedia.org/wiki/Obfuscation_(software) Obfuscation]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;references&amp;gt;&lt;br /&gt;
&amp;lt;ref name=&amp;quot;retrace&amp;quot;&amp;gt;For ProGuard users (such as Mojang), this is done using [https://www.guardsquare.com/en/products/proguard/manual/retrace ReTrace].&amp;lt;/ref&amp;gt;&lt;br /&gt;
&amp;lt;ref name=&amp;quot;mojmappings&amp;quot;&amp;gt;Mojang recently released their deobfuscation mappings for Minecraft (colloquially named &amp;lt;code&amp;gt;mojmappings&amp;lt;/code&amp;gt;), but the licensing for its uses is a bit ambiguous. [https://cpw.github.io/MinecraftMappingData See this post by cpw] for more information.&amp;lt;/ref&amp;gt;&lt;br /&gt;
&amp;lt;/references&amp;gt;&lt;/div&gt;</summary>
		<author><name>Curle</name></author>
	</entry>
	<entry>
		<id>https://forge.gemwire.uk/index.php?title=Toolchain&amp;diff=2382</id>
		<title>Toolchain</title>
		<link rel="alternate" type="text/html" href="https://forge.gemwire.uk/index.php?title=Toolchain&amp;diff=2382"/>
		<updated>2021-01-11T05:29:11Z</updated>

		<summary type="html">&lt;p&gt;Curle: Major overhaul. Still have yet to get into the Forge side of things.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{DISPLAYTITLE:Deobfuscation Process}}&lt;br /&gt;
{{Under construction}}&lt;br /&gt;
&lt;br /&gt;
The Forge toolchain is designed to clean up, merge, deobfuscate, rename, patch and provide the Minecraft source code for the usage of modders, researchers, or just those curious about how the game works.&lt;br /&gt;
&lt;br /&gt;
This serves as an explanation as to how the development environment sets up your code, and aims to help you troubleshoot in case something goes wrong.&lt;br /&gt;
&lt;br /&gt;
== Overall process ==&lt;br /&gt;
When setting up the environment for the first time, a gradle refresh triggers three things:&lt;br /&gt;
# ForgeGradle downloads the MCPConfig zip for the file you're using, and triggers the SetupMCP task.&lt;br /&gt;
# After that, it processes the jar - applies access transformers, MCPCleanup and others&lt;br /&gt;
# Finally, it patches and finalises the code, ready for modder consumption.&lt;br /&gt;
&lt;br /&gt;
== Needed knowledge ==&lt;br /&gt;
=== Obfuscation ===&lt;br /&gt;
'''Obfuscation''' is the process of renaming all of the fields, methods, and classes of the compiled code into unreadable, machine-generated names (such as &amp;lt;code&amp;gt;aaa&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;bC&amp;lt;/code&amp;gt;), and removing package structures (this makes everything package-local and makes the obfuscated code smaller somewhat. This is commonly used by companies to prevent external entities from easily decompiling their released binaries/executables and retrieving their source code/intellectual property, though it does have size advantages.&lt;br /&gt;
&lt;br /&gt;
Additionally, due to the way the Local Variable Table (LVT) of Java bytecode is stored, every function-local variable name is turned to ☃ (that's right, a snowman) in the compiled files. This makes immediate recompilation of the game literally and physically impossible, as every Java compiler currently available requires that local variables have unique names.&lt;br /&gt;
&lt;br /&gt;
Minecraft is a commercial game, which means the source code is unavailable to all except the developers of Mojang. To prevent piracy and the copying of their intellectual property, Mojang applies this obfuscation process to the game before they release it. They use a tool called [https://www.guardsquare.com/en/products/proguard ProGuard], which is both an optimizer&amp;lt;ref&amp;gt;An optimizer is a program that removes redundant/unused instructions and compacts the code to be faster and smaller.&amp;lt;/ref&amp;gt; and an obfuscator.&lt;br /&gt;
&lt;br /&gt;
=== Problematic Naming ===&lt;br /&gt;
There are a few big problems with using these obfuscated names directly for modding.&lt;br /&gt;
&lt;br /&gt;
# It is incredibly difficult to create mods using these obfuscated names. It requires immense patience to reverse-engineer the meanings behind each and every name, and to keep relating those names to what was already reverse-engineered. Although, tools do exist to make this process easier, such as IntelliJ IDEA plugins that provide naming hints automatically.&lt;br /&gt;
# Because the obfuscation process takes place after compilation (the obfuscator operates on the compiled classes), the obfuscated names are not handled by the compiler. Thus, obfuscated classes may contain member&amp;lt;ref&amp;gt;'''member''' refers to class fields and methods.&amp;lt;/ref&amp;gt; names that are invalid in the Java source language, but valid in compiled bytecode (like ☃ discussed earlier); this means that the decompiled source of the game is not immediately recompilable.&lt;br /&gt;
# These obfuscated names are automatically generated by the obfuscator for each independent release. This means that the obfuscated names may change signficantly between any two versions, making it harder for mod developers to update mods between releases.&lt;br /&gt;
&lt;br /&gt;
=== SRGification ===&lt;br /&gt;
Some background on what SRG is and how it works:&lt;br /&gt;
&lt;br /&gt;
'''SRG''' stands for '''S'''ea'''RG'''e, co-author of the Mod Creator Pack, who created this process.&lt;br /&gt;
Each obfuscated class, method, and field is assigned a unique number by the [[Toolchain:MCPConfig|backend]], via a sequential counter. This unique number is called the '''SRG ID''' of that class/method/field (henceforth called member).&lt;br /&gt;
&lt;br /&gt;
The SRG name of the member is then derived from its SRG ID, its type (function {given the prefix func_}, field {given the prefix field_}, parameter {given the prefix p_, or p_i if this is the parameter of a constructor}), and (optionally) the obfuscated name of the object at the time it was given its SRG name&amp;lt;ref&amp;gt;The SRG name for a given member is only created once, when it first appears in the code. Therefore, the SRG postfix may be different from the current obf name.&amp;lt;/ref&amp;gt;. This inclusion of the SRG ID into the name guarantees that the SRG name for all members are unique, and is the reason the ID is generated.&lt;br /&gt;
&lt;br /&gt;
The actual conversion of obf names to SRG names is done by a tool called [[Toolchain:SpecialSource|SpecialSource]]. More information on how it works can be found on that page.&lt;br /&gt;
&lt;br /&gt;
== The Setup ==&lt;br /&gt;
The process can be broken up into 3 steps; MCPConfig, patch and provide.&lt;br /&gt;
The MCPConfig step is, understandably, the biggest and most prone to failure.&lt;br /&gt;
An explanation of MCPConfig itself, how it works, what it's for (but NOT how to use it) can be found [[Toolchain:MCPConfig|here]]. For the purpose of this guide, you need only know that its' goal is to get the game decompiled, and into a state where it can immediately be recompiled. Due to certain flaws in the rest of the toolchain, this means it needs to fix and patch the source code before passing it onto Forge.&lt;br /&gt;
&lt;br /&gt;
In this way, MCPConfig can be thought of the vanilla side of the setup. It does not modify the game.&lt;br /&gt;
&lt;br /&gt;
=== Download and parsing MCPConfig ===&lt;br /&gt;
The first thing that ForgeGradle does upon initialising a first-time setup, is starting the [https://github.com/MinecraftForge/ForgeGradle/blob/e2ed49546abced95650635f81be071441ec60995/src/mcp/java/net/minecraftforge/gradle/mcp/task/SetupMCPTask.java#L91 SetupMCP] task. &lt;br /&gt;
This task then seeks to [https://github.com/MinecraftForge/ForgeGradle/blob/e2ed49546abced95650635f81be071441ec60995/src/mcp/java/net/minecraftforge/gradle/mcp/task/DownloadMCPConfigTask.java#L78 download the MCPConfig.zip jar] for the version you're setting up.&lt;br /&gt;
Once it is acquired, it [https://github.com/MinecraftForge/ForgeGradle/blob/e2ed49546abced95650635f81be071441ec60995/src/mcp/java/net/minecraftforge/gradle/mcp/util/MCPRuntime.java#L74 parses the steps contained within the config.json]. It does this by interpreting the file with the following rules:&lt;br /&gt;
* Every key, except for libraries, is interpreted as the name of a step.&lt;br /&gt;
* Steps are executed in order.&lt;br /&gt;
* The version value is interpreted as a maven coordinate of a file to download.&lt;br /&gt;
* If there is a repo value, it is used instead of the maven repositories defined in the buildscript, to retrieve the version.&lt;br /&gt;
* The args array is parsed, and {values} like this are interpreted as inputs, which can be substituted accordingly.&lt;br /&gt;
* Once the step is all parsed in, it is executed:&lt;br /&gt;
** java -jar &amp;amp;lt;version&amp;amp;gt; &amp;amp;lt;args&amp;amp;gt; &amp;amp;lt;jvmArgs&amp;amp;gt;&lt;br /&gt;
&lt;br /&gt;
An example config.json can be found [https://github.com/MinecraftForge/MCPConfig/blob/master/versions/release/1.16.4/config.json here].&lt;br /&gt;
&lt;br /&gt;
It defines the steps:&lt;br /&gt;
* [[Toolchain:MCinjector|mcinjector]]&lt;br /&gt;
** version: de.oceanlabs.mcp:mcinjector:3.8.0:fatjar&lt;br /&gt;
** args: --in {input} --out {output} --log {log} --level=INFO --lvt=LVT --exc {exceptions} --acc {access} --ctr {constructors}&lt;br /&gt;
* [[Toolchain:ForgeFlower|fernflower]]&lt;br /&gt;
** version: net.minecraftforge:forgeflower:1.5.478.16&lt;br /&gt;
** args: -din=1 -rbr=1 -dgs=1 -asc=1 -rsy=1 -iec=1 -jvn=1 -isl=0 -iib=1 -log=TRACE -cfg {libraries} {input} {output}&lt;br /&gt;
** jvmargs: -Xmx4G&lt;br /&gt;
* [[Toolchain:Mergetool|merge]]&lt;br /&gt;
** version: net.minecraftforge:mergetool:1.1.1:fatjar&lt;br /&gt;
** args: --client {client} --server {server} --ann {version} --output {output} --inject false&amp;quot;&lt;br /&gt;
* [[Toolchain:MCInjector|rename]]&lt;br /&gt;
** version: net.md-5:SpecialSource:1.8.3:shaded&lt;br /&gt;
** args: --in-jar {input} --out-jar {output} --srg-in {mappings}&lt;br /&gt;
** repo: https://repo1.maven.org/maven2/&lt;br /&gt;
&lt;br /&gt;
More information about each of these tools can be found at the link provided, as well as what each of these arguments do. A brief description is provided.&lt;br /&gt;
&lt;br /&gt;
=== MCInjector ===&lt;br /&gt;
[https://github.com/ModCoderPack/MCInjector MCInjector] is the tool we use to apply various fixes to the code, while it is still in bytecode form. That meaning, it works on compiled code, not sourcecode. It does this because it's easier to rename LVT entries (from the snowman) to readable names while you can search for every other code path that references that specific entry; ergo renaming all accesses at once. This is impossible in sourcecode, where every name is identical and string matching is impossible.&lt;br /&gt;
&lt;br /&gt;
It:&lt;br /&gt;
* Removes synthetic parameters from constructors&lt;br /&gt;
** In bytecode, inner classes have the outer class as their first constructor parameter, but Java source code does not.&lt;br /&gt;
* Handles adding annotations for parameters that have synthetic data&lt;br /&gt;
** In bytecode, these Nonnull (or whatever) annotations are attached to the parameters, not to the function that contains them.&lt;br /&gt;
* Adds constructors for inner classes&lt;br /&gt;
** These are removed by Proguard sometimes, as they are not required in the bytecode if the parent has a default constructor.&lt;br /&gt;
* Adds synthetic (invisible) constructors for classes without them&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
It also applies fixes for things like EXC;&lt;br /&gt;
* Renaming parameters inside constructors, such that subclasses retain the ID of their parent.&lt;br /&gt;
* Fixing access for select functions, where it is required for the proper recompilation.&lt;br /&gt;
* Applying proper typing to constructor parameters&lt;br /&gt;
* Applying proper external (LWJGL) exception data to functions and classes.&lt;br /&gt;
&lt;br /&gt;
Note that it does NOT rename to SRG. LVT (Local Variables) are renamed to lvt_&amp;amp;lt;index&amp;amp;gt;_&amp;amp;lt;version&amp;amp;gt;&amp;lt;ref&amp;gt;Index means: the place where this item was found. If it is the 4th entry in the table, it is index 3.&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== ForgeFlower === &lt;br /&gt;
After the code has been cleaned up by MCInjector, to a state where it no longer conflicts with itself, it can be passed to the decompiler. &lt;br /&gt;
&lt;br /&gt;
The decompiler used by ForgeGradle is a custom fork of [https://github.com/JetBrains/intellij-community/tree/master/plugins/java-decompiler/engine Jetbrains' FernFlower], called [https://github.com/MinecraftForge/ForgeFlower ForgeFlower].&lt;br /&gt;
&lt;br /&gt;
It simply searches the jar for files, converts the bytecode into a reasonable best-guess interpretation.&lt;br /&gt;
As you can see by the repository, a lot of work has gone into tuning it for Minecraft's needs, but it is still a far way from perfect. This is why the patches are needed.&lt;br /&gt;
&lt;br /&gt;
If you [https://github.com/MinecraftForge/MCPConfig/blob/master/versions/release/1.16.4/patches/ look at the patches] for 1.16.4, they are mostly incredibly simple changes. Adding generics, making types more strict. &lt;br /&gt;
&lt;br /&gt;
This is all stuff that should be done by the decompiler, and PRs are always welcome at the ForgeFlower repository for changes and fixes that would reduce the amount of MCPConfig patches required to get the game to compile.&lt;br /&gt;
&lt;br /&gt;
For now, it is a necessity.&lt;br /&gt;
&lt;br /&gt;
=== Mergetool ===&lt;br /&gt;
The game is split into two distributions; server and client.&lt;br /&gt;
&lt;br /&gt;
Because the server contains no rendering code, and the client contains none of the server-specific code (like the UI), this means there are differences between what can run on one side or the other.&lt;br /&gt;
&lt;br /&gt;
To get around this, we have a tool called Mergetool, which can search for the differences between two files (down to the function level) and merge them into one large (referred to as joined) jar file.&lt;br /&gt;
&lt;br /&gt;
It is a simple program, but it works.&lt;br /&gt;
&lt;br /&gt;
=== SpecialSource ===&lt;br /&gt;
SpecialSource is where SRG starts to come into play. It serves the role of our deobfuscator, performing deobfuscation.&lt;br /&gt;
&lt;br /&gt;
This process is done with the help of a '''deobfusation map''', a file generated by the original obfuscator (in this case, ProGuard) that contains a map of the obfuscated names to original, non-obfuscated names. This is commonly used on debofuscating stack traces outputted by an obfuscated program, for debugging purposes.&amp;lt;ref name=&amp;quot;retrace&amp;quot;/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We have three sets of deobfuscation maps available to us; the obf-&amp;gt;SRG mappings distributed with the MCPConfig system, the Yarn intermediary system, or the offical mappings.&amp;lt;ref name=&amp;quot;mojmappings&amp;quot;/&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
To rectify this problem, Forge has it's own process to create deobfuscation mappings for the game, using community-sourced human-readable names. This process is split into two separate parts: the '''SRG renaming''', and the '''MCP mapping'''. During the SetupMCP task, only the SRG renaming is performed.&lt;br /&gt;
&lt;br /&gt;
SpecialSource itself operates on the source jar, as can be gathered by the name, and takes in a .tsrg file, like that [https://github.com/MinecraftForge/MCPConfig/blob/master/versions/release/1.16.4/joined.tsrg contained in the MCPConfig zip].&lt;br /&gt;
&lt;br /&gt;
It first renames classes, straight into MCP names.&lt;br /&gt;
Then, iterating the members of the class, it renames fields, methods, parameters and inner classes.&lt;br /&gt;
&lt;br /&gt;
A recap from earlier:&lt;br /&gt;
* For classes -&amp;gt; &amp;lt;code&amp;gt;c_###_&amp;lt;/code&amp;gt; (but it is immediately changed without the c_ being written to disk)&lt;br /&gt;
* For functions/methods -&amp;gt; &amp;lt;code&amp;gt;func_&amp;amp;lt;ID&amp;amp;gt;_&amp;amp;lt;obf-name&amp;amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
* For fields -&amp;gt; &amp;lt;code&amp;gt;field_&amp;amp;lt;ID&amp;amp;gt;_&amp;amp;lt;obf-name&amp;amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
* For function/method parameters -&amp;gt; &amp;lt;code&amp;gt;p_###_#_&amp;lt;/code&amp;gt; for normal methods, &amp;lt;code&amp;gt;p_i###_#&amp;lt;/code&amp;gt; for constructors; the second number is the index&amp;lt;ref&amp;gt;The index is the position of the argument. 0 on the left, 1 after that, 2 after that. Note that double and long arguments increase their index by two, rather than one.&amp;lt;/ref&amp;gt; of the parameter.&lt;br /&gt;
&lt;br /&gt;
For example, &amp;lt;code&amp;gt;func_71410_x&amp;lt;/code&amp;gt; refers to a function with SRG ID 71410 and original obfuscated name of &amp;lt;code&amp;gt;x&amp;lt;/code&amp;gt;.&amp;lt;ref&amp;gt;For version 1.16.2, &amp;lt;code&amp;gt;func_71410_x&amp;lt;/code&amp;gt; refers to &amp;lt;code&amp;gt;Minecraft.getInstance()&amp;lt;/code&amp;gt;, with real obfuscated name of &amp;lt;code&amp;gt;B&amp;lt;/code&amp;gt;, but when the getInstance() function was first discovered in code, it was called x.&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
At this point, combined with the MCInjector step from earlier, we have a completely SRGed-up source jar.&lt;br /&gt;
&lt;br /&gt;
=== Patches ===&lt;br /&gt;
Once we have the source code ready to go, the final step in the setup is to apply patches.&lt;br /&gt;
These are done trivially, using diffs and [https://github.com/CadixDev/gitpatcher gitpatcher].&lt;br /&gt;
&lt;br /&gt;
=== Clean-up ===&lt;br /&gt;
Because of the way Proguard (or whatever obfuscator) and ForgeFlower mangle the source code, we need to take some steps to clean it up before we can proceed.&lt;br /&gt;
&lt;br /&gt;
Assorted cleanup fixes are performed by the [https://github.com/MinecraftForge/MCPCleanup/ MCPCleanup] utility. These include:&lt;br /&gt;
* removing trailing whitespace at the end of lines&lt;br /&gt;
* removing extra newlines at the start and end of files&lt;br /&gt;
* removing extra newlines between every line of code (every set of concurrent newlines is replaced with a single)&lt;br /&gt;
* removing comments (// hello, /* hello */)&lt;br /&gt;
** the purpose of this step is unclear - it seems to be a preventative measure to ensure that Java changes do not interfere with the patch alignment in the future. Comments from the decompiler are still sometimes present in the source code.&lt;br /&gt;
* removing imports from the package a class is in&lt;br /&gt;
* removing comments that include the phrase &amp;lt;code&amp;gt;GL_[^*]+&amp;lt;/code&amp;gt;&lt;br /&gt;
* replacing [Toolchain:Magic Constants|magic constants] with their code substitutions&lt;br /&gt;
* replacing &amp;lt;code&amp;gt;Character.valueOf(&amp;amp;lt;character&amp;amp;gt;)&amp;lt;/code&amp;gt; with &amp;lt;code&amp;gt;&amp;amp;lt;character&amp;amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
* replacing OpenGL integer constants with their code representation&lt;br /&gt;
* converting unicode character constants back into integer representation&lt;br /&gt;
* formatting the code with JAStyle&lt;br /&gt;
&lt;br /&gt;
It also adjusts abstract functions in some way - after running the program on a jar, the parameters of a default abstract function get renamed, but it is unclear exactly what part of the source code does this.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Mappings ==&lt;br /&gt;
We don't need this step but coding with the &amp;lt;code&amp;gt;SRG&amp;lt;/code&amp;gt; names is hard and not really fun.&lt;br /&gt;
So we need to take the &amp;lt;code&amp;gt;SRG&amp;lt;/code&amp;gt; names and make them more user friendly, the user friendly names are community sourced names.&lt;br /&gt;
Since &amp;lt;code&amp;gt;SRG&amp;lt;/code&amp;gt; names are uniquely identifiable, due to the unique ID, it literally does a search-and-replace on all the source code text to do that &amp;lt;code&amp;gt;SRG&amp;lt;/code&amp;gt;-&amp;gt;&amp;lt;code&amp;gt;MCP&amp;lt;/code&amp;gt;(( &amp;lt;code&amp;gt;MCP&amp;lt;/code&amp;gt; stands for ModCoderPack (or previously, Minecraft Coder Pack) which was the toolchain that did all of this before the advent of ForgeGradle)) application.&lt;br /&gt;
&lt;br /&gt;
== Some additional Infos ==&lt;br /&gt;
# You will never see c_XXX_ for classes, because the class names are picked beforehand&lt;br /&gt;
#* this is still crowdsourced, but before a new version is ready for Forge, all classes are given an &amp;lt;code&amp;gt;MCP&amp;lt;/code&amp;gt; name&lt;br /&gt;
#* this &amp;lt;code&amp;gt;MCP&amp;lt;/code&amp;gt; name stays constant throughout the game version it was picked for; it can change between versions, but it usually wont for already-named classes (except for misspells, typos, and misnames)&lt;br /&gt;
# If you look into the JAR, you won't see any packages for the obfuscated classes, but the deobfuscated classes do have the packages, this is because the same process that names the classes, also decides what package they belong to&lt;br /&gt;
# parameters have special names&lt;br /&gt;
#* there are two types of parameter names: &amp;lt;code&amp;gt;p_XXX_X_&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;p_iXXX_X_&amp;lt;/code&amp;gt;&lt;br /&gt;
#* the one with the i means that it's a parameter for a constructor&lt;br /&gt;
#* the first set of numbers are the SRG ID of their parent method, and the second number denotes the index of the parameter&lt;br /&gt;
#* the index of the parameter is a bit more involved, but this will not be explained here&lt;br /&gt;
# If you look into the source, you'll see that parameters for lambdas don't have mapped names&lt;br /&gt;
#* This is because of a complication in how the lambdas are compiled/decompiled; it's a more advanced topic which involves how the compiler compiles lambdas which we will not explain here.&lt;br /&gt;
&lt;br /&gt;
== See also ==&lt;br /&gt;
* [https://en.wikipedia.org/wiki/Obfuscation_(software) Obfuscation]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;references&amp;gt;&lt;br /&gt;
&amp;lt;ref name=&amp;quot;retrace&amp;quot;&amp;gt;For ProGuard users (such as Mojang), this is done using [https://www.guardsquare.com/en/products/proguard/manual/retrace ReTrace].&amp;lt;/ref&amp;gt;&lt;br /&gt;
&amp;lt;ref name=&amp;quot;mojmappings&amp;quot;&amp;gt;Mojang recently released their deobfuscation mappings for Minecraft (colloquially named &amp;lt;code&amp;gt;mojmappings&amp;lt;/code&amp;gt;), but the licensing for its uses is a bit ambiguous. [https://cpw.github.io/MinecraftMappingData See this post by cpw] for more information.&amp;lt;/ref&amp;gt;&lt;br /&gt;
&amp;lt;/references&amp;gt;&lt;/div&gt;</summary>
		<author><name>Curle</name></author>
	</entry>
	<entry>
		<id>https://forge.gemwire.uk/index.php?title=File:Exclamation.svg&amp;diff=2212</id>
		<title>File:Exclamation.svg</title>
		<link rel="alternate" type="text/html" href="https://forge.gemwire.uk/index.php?title=File:Exclamation.svg&amp;diff=2212"/>
		<updated>2020-11-08T16:49:02Z</updated>

		<summary type="html">&lt;p&gt;Curle: Exclamation mark for various templates&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Summary ==&lt;br /&gt;
Exclamation mark for various templates&lt;br /&gt;
== Licencing ==&lt;br /&gt;
{{subst:uwl}}&lt;/div&gt;</summary>
		<author><name>Curle</name></author>
	</entry>
	<entry>
		<id>https://forge.gemwire.uk/index.php?title=Template:Copy_Guard&amp;diff=2211</id>
		<title>Template:Copy Guard</title>
		<link rel="alternate" type="text/html" href="https://forge.gemwire.uk/index.php?title=Template:Copy_Guard&amp;diff=2211"/>
		<updated>2020-11-08T16:47:25Z</updated>

		<summary type="html">&lt;p&gt;Curle: Fix clr&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;templatestyles src=&amp;quot;Copy Guard/style.css&amp;quot;/&amp;gt;&lt;br /&gt;
&amp;lt;div class=&amp;quot;mw-tpl-nocopy&amp;quot;&amp;gt;&lt;br /&gt;
[[File:exclamation.svg|60px|class=mw-tpl-nocopy-exclamation|link=|alt=Important]]&lt;br /&gt;
&amp;lt;div&amp;gt;&lt;br /&gt;
&amp;lt;div class=&amp;quot;mw-tpl-nocopy-title&amp;quot;&amp;gt;This code will not compile.&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;div class=&amp;quot;mw-tpl-nocopy-content&amp;quot;&amp;gt;The content of this snippet is designed to show you how to use the relevant feature, but it will NOT compile if you copy-paste it. This is intentional.{{clr}}&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;/div&gt;</summary>
		<author><name>Curle</name></author>
	</entry>
	<entry>
		<id>https://forge.gemwire.uk/index.php?title=Template:Copy_Guard&amp;diff=2210</id>
		<title>Template:Copy Guard</title>
		<link rel="alternate" type="text/html" href="https://forge.gemwire.uk/index.php?title=Template:Copy_Guard&amp;diff=2210"/>
		<updated>2020-11-08T16:46:23Z</updated>

		<summary type="html">&lt;p&gt;Curle: Created page with &amp;quot;&amp;lt;templatestyles src=&amp;quot;Copy Guard/style.css&amp;quot;/&amp;gt; &amp;lt;div class=&amp;quot;mw-tpl-nocopy&amp;quot;&amp;gt; alt=Important &amp;lt;div&amp;gt; &amp;lt;div class=&amp;quot;mw...&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;templatestyles src=&amp;quot;Copy Guard/style.css&amp;quot;/&amp;gt;&lt;br /&gt;
&amp;lt;div class=&amp;quot;mw-tpl-nocopy&amp;quot;&amp;gt;&lt;br /&gt;
[[File:exclamation.svg|60px|class=mw-tpl-nocopy-exclamation|link=|alt=Important]]&lt;br /&gt;
&amp;lt;div&amp;gt;&lt;br /&gt;
&amp;lt;div class=&amp;quot;mw-tpl-nocopy-title&amp;quot;&amp;gt;This code will not compile.&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;div class=&amp;quot;mw-tpl-nocopy-content&amp;quot;&amp;gt;The content of this snippet is designed to show you how to use the relevant feature, but it will NOT compile if you copy-paste it. This is intentional.{clr}}&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;/div&gt;</summary>
		<author><name>Curle</name></author>
	</entry>
	<entry>
		<id>https://forge.gemwire.uk/index.php?title=Template:Copy_Guard/style.css&amp;diff=2209</id>
		<title>Template:Copy Guard/style.css</title>
		<link rel="alternate" type="text/html" href="https://forge.gemwire.uk/index.php?title=Template:Copy_Guard/style.css&amp;diff=2209"/>
		<updated>2020-11-08T16:46:21Z</updated>

		<summary type="html">&lt;p&gt;Curle: Created page with &amp;quot;.mw-tpl-nocopy {  display: flex;  align-items: center;  width: 75%;  margin: auto;  border-radius: 0.2em;  background: rgb(27, 32, 35);  box-shadow: 0 0 0.2em #999999;  overfl...&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;.mw-tpl-nocopy {&lt;br /&gt;
 display: flex;&lt;br /&gt;
 align-items: center;&lt;br /&gt;
 width: 75%;&lt;br /&gt;
 margin: auto;&lt;br /&gt;
 border-radius: 0.2em;&lt;br /&gt;
 background: rgb(27, 32, 35);&lt;br /&gt;
 box-shadow: 0 0 0.2em #999999;&lt;br /&gt;
 overflow: auto;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.mw-tpl-nocopy-title {&lt;br /&gt;
 color: #FFFFFF;&lt;br /&gt;
 font-size: 120%;&lt;br /&gt;
 font-weight: bold;&lt;br /&gt;
 padding: 0.25em 1em;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.mw-tpl-nocopy-exclamation {&lt;br /&gt;
 float: left;&lt;br /&gt;
 opacity: 0.8;&lt;br /&gt;
 margin: 1em;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.mw-tpl-nocopy-content {&lt;br /&gt;
 padding: 0.5em 1em 0.5em 1em;&lt;br /&gt;
 color: #FFFFFF;&lt;br /&gt;
}&lt;/div&gt;</summary>
		<author><name>Curle</name></author>
	</entry>
	<entry>
		<id>https://forge.gemwire.uk/index.php?title=Proper_Mod_Structuring&amp;diff=2191</id>
		<title>Proper Mod Structuring</title>
		<link rel="alternate" type="text/html" href="https://forge.gemwire.uk/index.php?title=Proper_Mod_Structuring&amp;diff=2191"/>
		<updated>2020-11-04T23:34:01Z</updated>

		<summary type="html">&lt;p&gt;Curle: revert attempted fix?&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
The structure of your mod is important in keeping your mod organized, for both your benefit and the benefit of anyone who wishses to make a feature for your mod. A disorganized mod structure may cause headaches when someone is trying to update it to a higher version, especially if they cannot modify the package structure, due to i.e. licensing.&lt;br /&gt;
&lt;br /&gt;
{{Colored box|title=Tip|background-title-color=#633193|content=Note that this page is only a recommendation for your mod structure; you may structure your mod in any way you see fit.}}&lt;br /&gt;
&lt;br /&gt;
== Packaging ==&lt;br /&gt;
&lt;br /&gt;
Pick a unique package name for your mod. If you own a URL associated with your project, you can use it as your top level package. For example if you own &amp;quot;example.com&amp;quot;, you may use &amp;lt;code&amp;gt;com.example&amp;lt;/code&amp;gt; as your top level package. &lt;br /&gt;
The next level package is usually your mod's ID: if your mod ID is &amp;lt;code&amp;gt;examplemod&amp;lt;/code&amp;gt;, your mod's package will be &amp;lt;code&amp;gt;com.example.examplemod&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
{{Colored box|title=Important|content=Do not use a domain for your top level package if you do not own that domain. It is perfectly acceptable to have your top level package be named with anything, such as your name/nickname, or the name of the mod (&amp;lt;code&amp;gt;me.exampledude.examplemod&amp;lt;/code&amp;gt;).}}&lt;br /&gt;
&lt;br /&gt;
=== Using Subpackages ===&lt;br /&gt;
&lt;br /&gt;
Rather than clutter up a single class and package with everything, it is recommended you break your mod into subpackages.&lt;br /&gt;
&lt;br /&gt;
A common strategy is to make a subpackage for grouping classes that have a common purpose. For example, your blocks classes can be under &amp;lt;code&amp;gt;blocks&amp;lt;/code&amp;gt;, your entities classes can be under &amp;lt;code&amp;gt;entities&amp;lt;/code&amp;gt;, your helper utilities can be under &amp;lt;code&amp;gt;helpers&amp;lt;/code&amp;gt;, etc.&lt;br /&gt;
&lt;br /&gt;
It is recommended to add a &amp;lt;code&amp;gt;client&amp;lt;/code&amp;gt; subpackage under your main package, to isolate your [[Sides|client-only code]] from the rest, such as your GUIs and renderers.&lt;br /&gt;
&lt;br /&gt;
By keeping your code in clean subpackages, you can grow your mod much more organically.&lt;br /&gt;
&lt;br /&gt;
== Class Naming Schemes ==&lt;br /&gt;
&lt;br /&gt;
A common class naming scheme allows easier deciphering of the purpose of the class, and makes it easier for someone developing for your mod to find specific classes.&lt;br /&gt;
&lt;br /&gt;
The usual style is to use suffixes for your classes, for example:&lt;br /&gt;
&lt;br /&gt;
* An &amp;lt;code&amp;gt;Item&amp;lt;/code&amp;gt; called &amp;lt;code&amp;gt;PowerRing&amp;lt;/code&amp;gt; would be in the &amp;lt;code&amp;gt;items&amp;lt;/code&amp;gt; package, with a class name of &amp;lt;code&amp;gt;PowerRingItem&amp;lt;/code&amp;gt;.&lt;br /&gt;
* A &amp;lt;code&amp;gt;Block&amp;lt;/code&amp;gt; called &amp;lt;code&amp;gt;NotDirt&amp;lt;/code&amp;gt; would be in a &amp;lt;code&amp;gt;blocks&amp;lt;/code&amp;gt;  package, with a class name of &amp;lt;code&amp;gt;NotDirtBlock&amp;lt;/code&amp;gt;.&lt;br /&gt;
* A &amp;lt;code&amp;gt;TileEntity&amp;lt;/code&amp;gt; for a block called &amp;lt;code&amp;gt;SuperChewer&amp;lt;/code&amp;gt; would be in a &amp;lt;code&amp;gt;tile&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;tileentity&amp;lt;/code&amp;gt; package, with a class name of &amp;lt;code&amp;gt;SuperChewerTile&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== The Mod File ==&lt;br /&gt;
&lt;br /&gt;
The main mod class - the class that is annotated with &amp;lt;code&amp;gt;@Mod&amp;lt;/code&amp;gt; - is usually put into the main package of your mod, and not placed into a subpackage. This allows an easier time to access this, as your main mod class is the entrypoint of your mod.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;@Mod&amp;lt;/code&amp;gt; annotation indicates to the mod loader that this class is the entry point of your mod. Each &amp;lt;code&amp;gt;@Mod&amp;lt;/code&amp;gt; annotation and their value should be paired with a mod id entry in your &amp;lt;code&amp;gt;mods.toml&amp;lt;/code&amp;gt; file.&lt;br /&gt;
&lt;br /&gt;
== The &amp;lt;code&amp;gt;mods.toml&amp;lt;/code&amp;gt; file ==&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;mods.toml&amp;lt;/code&amp;gt; file is read by the mod loader to determine what mods are packaged into your JAR file, and what information to display to the user in the Mods listing screen (accessible by pressing the &amp;quot;Mods&amp;quot; button on the main menu of the game). &lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;mods.toml&amp;lt;/code&amp;gt; file is formatted in [https://toml.io/en/ Tom's Obvious Minimal Language], or TOML for short. The example &amp;lt;code&amp;gt;mods.toml&amp;lt;/code&amp;gt; file in the MDK provides comments explaining the contents of the file. It should be stored under the &amp;lt;code&amp;gt;META-INF&amp;lt;/code&amp;gt; folder in your resources directory (&amp;lt;code&amp;gt;src/main/resources/META-INF/mods.toml&amp;lt;/code&amp;gt;).&lt;br /&gt;
&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 &amp;lt;code&amp;gt;mods.toml&amp;lt;/code&amp;gt; file&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;div class=&amp;quot;mw-collapsible-content&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;TOML&amp;quot;&amp;gt;&lt;br /&gt;
modLoader=&amp;quot;javafml&amp;quot;&lt;br /&gt;
# Forge for 1.16.3 is version 34&lt;br /&gt;
loaderVersion=&amp;quot;[34,)&amp;quot;&lt;br /&gt;
license=&amp;quot;All rights reserved&amp;quot;&lt;br /&gt;
issueTrackerURL=&amp;quot;github.com/MinecraftForge/MinecraftForge/issues&amp;quot;&lt;br /&gt;
showAsResourcePack=false&lt;br /&gt;
&lt;br /&gt;
[[mods]]&lt;br /&gt;
    modId=&amp;quot;examplemod&amp;quot;&lt;br /&gt;
    version=&amp;quot;1.0.0.0&amp;quot;&lt;br /&gt;
    displayName=&amp;quot;Example Mod&amp;quot;&lt;br /&gt;
    updateJSONURL=&amp;quot;minecraftforge.net/versions.json&amp;quot;&lt;br /&gt;
    displayURL=&amp;quot;minecraftforge.net&amp;quot;&lt;br /&gt;
    logoFile=&amp;quot;logo.png&amp;quot;&lt;br /&gt;
    credits=&amp;quot;I'd like to thank my mother and father.&amp;quot;&lt;br /&gt;
    authors=&amp;quot;Author&amp;quot;&lt;br /&gt;
    description='''&lt;br /&gt;
Lets you craft dirt into diamonds. This is a traditional mod that has existed for eons. It is ancient. The holy Notch created it. Jeb rainbowfied it. Dinnerbone made it upside down. Etc.&lt;br /&gt;
    '''&lt;br /&gt;
&lt;br /&gt;
[[dependencies.examplemod]]&lt;br /&gt;
    modId=&amp;quot;forge&amp;quot;&lt;br /&gt;
    mandatory=true&lt;br /&gt;
    versionRange=&amp;quot;[34,)&amp;quot;&lt;br /&gt;
    ordering=&amp;quot;NONE&amp;quot;&lt;br /&gt;
    side=&amp;quot;BOTH&amp;quot;&lt;br /&gt;
&lt;br /&gt;
[[dependencies.examplemod]]&lt;br /&gt;
    modId=&amp;quot;minecraft&amp;quot;&lt;br /&gt;
    mandatory=true&lt;br /&gt;
    versionRange=&amp;quot;[1.16.3]&amp;quot;&lt;br /&gt;
    ordering=&amp;quot;NONE&amp;quot;&lt;br /&gt;
    side=&amp;quot;BOTH&amp;quot;&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;
The default Gradle configuration replaces &amp;lt;code&amp;gt;${file.jarVersion}&amp;lt;/code&amp;gt; with the project version, but only within &amp;lt;code&amp;gt;mods.toml&amp;lt;/code&amp;gt;, so you should use those instead of directly writing them out. Here is a table of attributes that may be given to a mod, where &amp;lt;code&amp;gt;mandatory&amp;lt;/code&amp;gt; means there is no default and the absence of the property causes an error.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;mods.toml&amp;lt;/code&amp;gt; is split into three parts: the non-mod-specific properties, which are linked to the mod file; the mod properties, with a section for each mod; and dependency configurations, with a section for each mod's dependencies.&lt;br /&gt;
&lt;br /&gt;
=== Non-Mod-Specific Properties ===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Property !! Type !! Defaults&lt;br /&gt;
! Description&lt;br /&gt;
! Example&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;modLoader&amp;lt;/code&amp;gt; || string || '''mandatory'''&lt;br /&gt;
|  The language loader for the mod. Used to specify an alternative language for the mod, such as Kotlin, if one exists. The Forge-provided Java loader is &amp;lt;code&amp;gt;javafml&amp;lt;/code&amp;gt;.&lt;br /&gt;
| &amp;lt;code&amp;gt;&amp;quot;javafml&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;loaderVersion&amp;lt;/code&amp;gt; || string || '''mandatory'''&lt;br /&gt;
|  The acceptable version range of the language loader, expressed as a [https://maven.apache.org/enforcer/enforcer-rules/versionRanges.html Maven version spec]. For the Forge-provided Java loader, the version is the major version of the Forge version.&lt;br /&gt;
| &amp;lt;code&amp;gt;&amp;quot;[34,)&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;license&amp;lt;/code&amp;gt; || string || '''mandatory'''&lt;br /&gt;
| The license for the mod(s) in this JAR. This string may be any valid string, but it is suggested to set the value to be the name of your license, and/or a link to that license.&lt;br /&gt;
| &amp;lt;code&amp;gt;&amp;quot;GNU GPL v3, https://www.gnu.org/licenses/gpl-3.0.en.html&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;showAsResourcePack&amp;lt;/code&amp;gt; || boolean || &amp;lt;code&amp;gt;false&amp;lt;/code&amp;gt; &lt;br /&gt;
| Whether to display this mod's resources as a separate option in the resource pack menu. If disabled, the mod's resources will be rolled into the &amp;quot;Mod resources&amp;quot; pack. &lt;br /&gt;
| &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt; &lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;properties&amp;lt;/code&amp;gt; || table || &amp;lt;code&amp;gt;{}&amp;lt;/code&amp;gt; &lt;br /&gt;
| A table of custom substitution properties. This is used by &amp;lt;code&amp;gt;StringSubstitutor&amp;lt;/code&amp;gt; to replace values, using &amp;lt;code&amp;gt;${file.*}&amp;lt;/code&amp;gt;.&lt;br /&gt;
| &amp;lt;code&amp;gt;{ &amp;quot;thingy&amp;quot; = 1 }&amp;lt;/code&amp;gt;, used in &amp;lt;code&amp;gt;${file.thingy}&amp;lt;/code&amp;gt; &lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;issueTrackerURL&amp;lt;/code&amp;gt; || string || ''nothing''&lt;br /&gt;
| A URL for an issues tracker. &amp;lt;inline alert&amp;gt; This should never be a blank string, as that will cause an error. &amp;lt;/inline&amp;gt; &lt;br /&gt;
| &amp;lt;code&amp;gt;&amp;quot;http://my.issue.tracker/&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Mod Properties ===&lt;br /&gt;
&lt;br /&gt;
A mod entry is defined by a new section starting with a &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;[[mods]]&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt; header (In TOML, the &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;[[mods]]&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt; defines an [https://toml.io/en/v1.0.0-rc.2#array-of-tables array of tables]). All properties from that line until the next header will become the properties for that mod.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Property !! Type !! Defaults&lt;br /&gt;
! Description&lt;br /&gt;
! Example&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;modId&amp;lt;/code&amp;gt; || string || '''mandatory'''&lt;br /&gt;
| The mod's identifier (modid). This must match the following regex: &amp;lt;code&amp;gt;^[a-z][a-z0-9_-]{1,63}$&amp;lt;/code&amp;gt; (starts with a lowercase letter; other characters must be a lowercase letter, number, underscore or hyphen; must be 2-64 characters long). &lt;br /&gt;
| &amp;lt;code&amp;gt;&amp;quot;examplemod&amp;quot;&amp;lt;/code&amp;gt; &lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;namespace&amp;lt;/code&amp;gt; || string || value of &amp;lt;code&amp;gt;modId&amp;lt;/code&amp;gt; &lt;br /&gt;
| An override namespace. &amp;lt;inline info&amp;gt; Currently, there is no use for this property &amp;lt;/inline&amp;gt; &lt;br /&gt;
| &amp;lt;code&amp;gt;example&amp;lt;/code&amp;gt; &lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;version&amp;lt;/code&amp;gt; || string || &amp;lt;code&amp;gt;&amp;quot;1&amp;quot;&amp;lt;/code&amp;gt; &lt;br /&gt;
| The version of the mod jar, used when the mod is a dependency of another mod, expressed as numbers seperated by dots (&amp;lt;code&amp;gt;.&amp;lt;/code&amp;gt;), ideally conforming to [[Semantic_Versioning|Semantic Versioning]]. The default value in the MDK for this is &amp;lt;code&amp;gt;${file.jarVersion}&amp;lt;/code&amp;gt;, which is replaced at runtime with the &amp;lt;code&amp;gt;Implementation-Version&amp;lt;/code&amp;gt; found in the jar's manifest file. &lt;br /&gt;
| &amp;lt;code&amp;gt;&amp;quot;0.2.4-beta1&amp;quot;&amp;lt;/code&amp;gt; &lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;displayName&amp;lt;/code&amp;gt; || string || value of &amp;lt;code&amp;gt;modId&amp;lt;/code&amp;gt; &lt;br /&gt;
| The display name of the mod, for use in the Mods listing screen&lt;br /&gt;
| &amp;lt;code&amp;gt;&amp;quot;Example Mod&amp;quot;&amp;lt;/code&amp;gt; &lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;description&amp;lt;/code&amp;gt; || string || &amp;lt;code&amp;gt;&amp;quot;MISSING DESCRIPTION&amp;quot;&amp;lt;/code&amp;gt; &lt;br /&gt;
| The description of the mod, for use in the Mods listing screen. It's recommended to use a multiline string (surrounded by &amp;lt;code&amp;gt;'''&amp;lt;code&amp;gt;)&lt;br /&gt;
| &amp;lt;code&amp;gt;&amp;quot;Adds things and stuff. &amp;quot;&amp;lt;/code&amp;gt; &lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;logoFile&amp;lt;/code&amp;gt; || string || ''nothing''&lt;br /&gt;
| The path of the logo file image, for use in the Mods listing screen. The image must be in the root of the jar file, not in any subfolder thereof (e.g. the file is directly in &amp;lt;code&amp;gt;src/main/resources&amp;lt;/code&amp;gt;)&lt;br /&gt;
| &amp;lt;code&amp;gt;&amp;quot;myAwesomeLogo.png&amp;quot;&amp;lt;/code&amp;gt; &lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;logoBlur&amp;lt;/code&amp;gt; || boolean || &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt; &lt;br /&gt;
| Whether to do some blurring on the mod's logo in the Mods listing screen. Has no effect if &amp;lt;code&amp;gt;logoFile&amp;lt;/code&amp;gt; is not set. &lt;br /&gt;
| &amp;lt;code&amp;gt;false&amp;lt;/code&amp;gt; &lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;updateJSONURL&amp;lt;/code&amp;gt; || string || ''nothing''&lt;br /&gt;
| The update JSON URL, used by the [Update_Checker update checker]. &amp;lt;inline alert&amp;gt; This should never be a blank string, as that will cause an error. &amp;lt;/inline&amp;gt; &lt;br /&gt;
| &amp;lt;code&amp;gt;http://myurl.me/path/to/update.json&amp;lt;/code&amp;gt; &lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;modproperties&amp;lt;/code&amp;gt; || table || &amp;lt;code&amp;gt;{}&amp;lt;/code&amp;gt; &lt;br /&gt;
| A table of custom mod properties; this is not used for Forge, but is mainly for use by mods. &lt;br /&gt;
| &amp;lt;code&amp;gt;{ &amp;quot;useThing&amp;quot; = true }&amp;lt;/code&amp;gt; &lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;credits&amp;lt;/code&amp;gt; || string || ''nothing''&lt;br /&gt;
| Credits and acknowledgements for the mod, for use in the Mods listing screen. Can be any string. &lt;br /&gt;
| &amp;lt;code&amp;gt;&amp;quot;This person and that guy&amp;quot;&amp;lt;/code&amp;gt; &lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;authors&amp;lt;/code&amp;gt; || string || ''nothing''&lt;br /&gt;
| Authors for the mod, for use in the Mods listing screen. Can be any string. &lt;br /&gt;
| &amp;lt;code&amp;gt;&amp;quot;ExampleDude&amp;quot;&amp;lt;/code&amp;gt; &lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;displayURL&amp;lt;/code&amp;gt; || string || ''nothing''&lt;br /&gt;
| A URL, displayed on the Mods listing screen. Can be any string. &lt;br /&gt;
| &amp;lt;code&amp;gt;http://example.com/&amp;lt;/code&amp;gt; &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Dependency Configurations ===&lt;br /&gt;
&lt;br /&gt;
Mods can define dependencies for their mods, which are checked by Forge before loading mods. This is used for e.g. ensuring your mod loads after another, or hard-crashing if a mod with a specified version does not exist.&lt;br /&gt;
&lt;br /&gt;
These dependency configurations, like the mod properties, are defined by a new section starting with &amp;lt;code&amp;gt;[[dependencies.&amp;lt;modid&amp;gt;]]&amp;lt;/code&amp;gt;, with &amp;lt;code&amp;gt;&amp;lt;modid&amp;gt;&amp;lt;/code&amp;gt; being the mod id that has this dependency. All properties from that line until the next header will become the properties of that dependency configuration.&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
! Property !! Type !! Defaults &lt;br /&gt;
! Description &lt;br /&gt;
! Example&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;modId&amp;lt;/code&amp;gt; || string || '''mandatory'''&lt;br /&gt;
| The mod id of the dependency. &lt;br /&gt;
| &amp;lt;code&amp;gt;examplelibrary&amp;lt;/code&amp;gt; &lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;mandatory&amp;lt;/code&amp;gt; || boolean || '''mandatory'''&lt;br /&gt;
| Whether to crash if this dependency is not met. &lt;br /&gt;
| &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt; &lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;versionRange&amp;lt;/code&amp;gt; || string || &amp;lt;code&amp;gt;&amp;quot;&amp;quot;&amp;lt;/code&amp;gt; &lt;br /&gt;
| The acceptable version range of the dependency, expressed as a [https://maven.apache.org/enforcer/enforcer-rules/versionRanges.html Maven version spec]. An empty string is an unbounded version range, which matches any version. &lt;br /&gt;
| &amp;lt;code&amp;gt;&amp;quot;[1.0,2.0)&amp;quot;&amp;lt;/code&amp;gt; &lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ordering&amp;lt;/code&amp;gt; || string || &amp;lt;code&amp;gt;&amp;quot;NONE&amp;quot;&amp;lt;/code&amp;gt; &lt;br /&gt;
| Defines if the mod must load before or after this dependency. The valid values are &amp;lt;code&amp;gt;BEFORE&amp;lt;/code&amp;gt; (must load before), &amp;lt;code&amp;gt;AFTER&amp;lt;/code&amp;gt; (must load after), and &amp;lt;code&amp;gt;NONE&amp;lt;/code&amp;gt; (does not care about order). &lt;br /&gt;
| &amp;lt;code&amp;gt;&amp;quot;AFTER&amp;quot;&amp;lt;/code&amp;gt; &lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;side&amp;lt;/code&amp;gt; || string || &amp;lt;code&amp;gt;&amp;quot;BOTH&amp;quot;&amp;lt;/code&amp;gt; &lt;br /&gt;
| Defines if this dependency needs only to be met on a specfic [[Sides|physical side]]. The valid values are &amp;lt;code&amp;gt;CLIENT&amp;lt;/code&amp;gt; (present on the client), &amp;lt;code&amp;gt;SERVER&amp;lt;/code&amp;gt; (present on the dedicated server), and &amp;lt;code&amp;gt;BOTH&amp;lt;/code&amp;gt; (present on both sides). &lt;br /&gt;
| &amp;lt;code&amp;gt;&amp;quot;CLIENT&amp;quot;&amp;lt;/code&amp;gt; &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{{Colored box|title=Important|content=When specifying dependency ordering between two or more mods, beware of cyclic order!: ex. if mod A must load before mod B, and mod B must load before mod A, the game will crash because of the circular cycle.}}&lt;br /&gt;
&lt;br /&gt;
[[Category:Getting Started]]&lt;/div&gt;</summary>
		<author><name>Curle</name></author>
	</entry>
	<entry>
		<id>https://forge.gemwire.uk/index.php?title=Proper_Mod_Structuring&amp;diff=2190</id>
		<title>Proper Mod Structuring</title>
		<link rel="alternate" type="text/html" href="https://forge.gemwire.uk/index.php?title=Proper_Mod_Structuring&amp;diff=2190"/>
		<updated>2020-11-04T23:02:41Z</updated>

		<summary type="html">&lt;p&gt;Curle: attempt to fix highlight&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
The structure of your mod is important in keeping your mod organized, for both your benefit and the benefit of anyone who wishses to make a feature for your mod. A disorganized mod structure may cause headaches when someone is trying to update it to a higher version, especially if they cannot modify the package structure, due to i.e. licensing.&lt;br /&gt;
&lt;br /&gt;
{{Colored box|title=Tip|background-title-color=#633193|content=Note that this page is only a recommendation for your mod structure; you may structure your mod in any way you see fit.}}&lt;br /&gt;
&lt;br /&gt;
== Packaging ==&lt;br /&gt;
&lt;br /&gt;
Pick a unique package name for your mod. If you own a URL associated with your project, you can use it as your top level package. For example if you own &amp;quot;example.com&amp;quot;, you may use &amp;lt;code&amp;gt;com.example&amp;lt;/code&amp;gt; as your top level package. &lt;br /&gt;
The next level package is usually your mod's ID: if your mod ID is &amp;lt;code&amp;gt;examplemod&amp;lt;/code&amp;gt;, your mod's package will be &amp;lt;code&amp;gt;com.example.examplemod&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
{{Colored box|title=Important|content=Do not use a domain for your top level package if you do not own that domain. It is perfectly acceptable to have your top level package be named with anything, such as your name/nickname, or the name of the mod (&amp;lt;code&amp;gt;me.exampledude.examplemod&amp;lt;/code&amp;gt;).}}&lt;br /&gt;
&lt;br /&gt;
=== Using Subpackages ===&lt;br /&gt;
&lt;br /&gt;
Rather than clutter up a single class and package with everything, it is recommended you break your mod into subpackages.&lt;br /&gt;
&lt;br /&gt;
A common strategy is to make a subpackage for grouping classes that have a common purpose. For example, your blocks classes can be under &amp;lt;code&amp;gt;blocks&amp;lt;/code&amp;gt;, your entities classes can be under &amp;lt;code&amp;gt;entities&amp;lt;/code&amp;gt;, your helper utilities can be under &amp;lt;code&amp;gt;helpers&amp;lt;/code&amp;gt;, etc.&lt;br /&gt;
&lt;br /&gt;
It is recommended to add a &amp;lt;code&amp;gt;client&amp;lt;/code&amp;gt; subpackage under your main package, to isolate your [[Sides|client-only code]] from the rest, such as your GUIs and renderers.&lt;br /&gt;
&lt;br /&gt;
By keeping your code in clean subpackages, you can grow your mod much more organically.&lt;br /&gt;
&lt;br /&gt;
== Class Naming Schemes ==&lt;br /&gt;
&lt;br /&gt;
A common class naming scheme allows easier deciphering of the purpose of the class, and makes it easier for someone developing for your mod to find specific classes.&lt;br /&gt;
&lt;br /&gt;
The usual style is to use suffixes for your classes, for example:&lt;br /&gt;
&lt;br /&gt;
* An &amp;lt;code&amp;gt;Item&amp;lt;/code&amp;gt; called &amp;lt;code&amp;gt;PowerRing&amp;lt;/code&amp;gt; would be in the &amp;lt;code&amp;gt;items&amp;lt;/code&amp;gt; package, with a class name of &amp;lt;code&amp;gt;PowerRingItem&amp;lt;/code&amp;gt;.&lt;br /&gt;
* A &amp;lt;code&amp;gt;Block&amp;lt;/code&amp;gt; called &amp;lt;code&amp;gt;NotDirt&amp;lt;/code&amp;gt; would be in a &amp;lt;code&amp;gt;blocks&amp;lt;/code&amp;gt;  package, with a class name of &amp;lt;code&amp;gt;NotDirtBlock&amp;lt;/code&amp;gt;.&lt;br /&gt;
* A &amp;lt;code&amp;gt;TileEntity&amp;lt;/code&amp;gt; for a block called &amp;lt;code&amp;gt;SuperChewer&amp;lt;/code&amp;gt; would be in a &amp;lt;code&amp;gt;tile&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;tileentity&amp;lt;/code&amp;gt; package, with a class name of &amp;lt;code&amp;gt;SuperChewerTile&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== The Mod File ==&lt;br /&gt;
&lt;br /&gt;
The main mod class - the class that is annotated with &amp;lt;code&amp;gt;@Mod&amp;lt;/code&amp;gt; - is usually put into the main package of your mod, and not placed into a subpackage. This allows an easier time to access this, as your main mod class is the entrypoint of your mod.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;@Mod&amp;lt;/code&amp;gt; annotation indicates to the mod loader that this class is the entry point of your mod. Each &amp;lt;code&amp;gt;@Mod&amp;lt;/code&amp;gt; annotation and their value should be paired with a mod id entry in your &amp;lt;code&amp;gt;mods.toml&amp;lt;/code&amp;gt; file.&lt;br /&gt;
&lt;br /&gt;
== The &amp;lt;code&amp;gt;mods.toml&amp;lt;/code&amp;gt; file ==&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;mods.toml&amp;lt;/code&amp;gt; file is read by the mod loader to determine what mods are packaged into your JAR file, and what information to display to the user in the Mods listing screen (accessible by pressing the &amp;quot;Mods&amp;quot; button on the main menu of the game). &lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;mods.toml&amp;lt;/code&amp;gt; file is formatted in [https://toml.io/en/ Tom's Obvious Minimal Language], or TOML for short. The example &amp;lt;code&amp;gt;mods.toml&amp;lt;/code&amp;gt; file in the MDK provides comments explaining the contents of the file. It should be stored under the &amp;lt;code&amp;gt;META-INF&amp;lt;/code&amp;gt; folder in your resources directory (&amp;lt;code&amp;gt;src/main/resources/META-INF/mods.toml&amp;lt;/code&amp;gt;).&lt;br /&gt;
&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 &amp;lt;code&amp;gt;mods.toml&amp;lt;/code&amp;gt; file&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;div class=&amp;quot;mw-collapsible-content&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;toml&amp;quot;&amp;gt;&lt;br /&gt;
modLoader=&amp;quot;javafml&amp;quot;&lt;br /&gt;
# Forge for 1.16.3 is version 34&lt;br /&gt;
loaderVersion=&amp;quot;[34,)&amp;quot;&lt;br /&gt;
license=&amp;quot;All rights reserved&amp;quot;&lt;br /&gt;
issueTrackerURL=&amp;quot;github.com/MinecraftForge/MinecraftForge/issues&amp;quot;&lt;br /&gt;
showAsResourcePack=false&lt;br /&gt;
&lt;br /&gt;
[[mods]]&lt;br /&gt;
    modId=&amp;quot;examplemod&amp;quot;&lt;br /&gt;
    version=&amp;quot;1.0.0.0&amp;quot;&lt;br /&gt;
    displayName=&amp;quot;Example Mod&amp;quot;&lt;br /&gt;
    updateJSONURL=&amp;quot;minecraftforge.net/versions.json&amp;quot;&lt;br /&gt;
    displayURL=&amp;quot;minecraftforge.net&amp;quot;&lt;br /&gt;
    logoFile=&amp;quot;logo.png&amp;quot;&lt;br /&gt;
    credits=&amp;quot;I'd like to thank my mother and father.&amp;quot;&lt;br /&gt;
    authors=&amp;quot;Author&amp;quot;&lt;br /&gt;
    description='''&lt;br /&gt;
Lets you craft dirt into diamonds. This is a traditional mod that has existed for eons. It is ancient. The holy Notch created it. Jeb rainbowfied it. Dinnerbone made it upside down. Etc.&lt;br /&gt;
    '''&lt;br /&gt;
&lt;br /&gt;
[[dependencies.examplemod]]&lt;br /&gt;
    modId=&amp;quot;forge&amp;quot;&lt;br /&gt;
    mandatory=true&lt;br /&gt;
    versionRange=&amp;quot;[34,)&amp;quot;&lt;br /&gt;
    ordering=&amp;quot;NONE&amp;quot;&lt;br /&gt;
    side=&amp;quot;BOTH&amp;quot;&lt;br /&gt;
&lt;br /&gt;
[[dependencies.examplemod]]&lt;br /&gt;
    modId=&amp;quot;minecraft&amp;quot;&lt;br /&gt;
    mandatory=true&lt;br /&gt;
    versionRange=&amp;quot;[1.16.3]&amp;quot;&lt;br /&gt;
    ordering=&amp;quot;NONE&amp;quot;&lt;br /&gt;
    side=&amp;quot;BOTH&amp;quot;&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;
The default Gradle configuration replaces &amp;lt;code&amp;gt;${file.jarVersion}&amp;lt;/code&amp;gt; with the project version, but only within &amp;lt;code&amp;gt;mods.toml&amp;lt;/code&amp;gt;, so you should use those instead of directly writing them out. Here is a table of attributes that may be given to a mod, where &amp;lt;code&amp;gt;mandatory&amp;lt;/code&amp;gt; means there is no default and the absence of the property causes an error.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;mods.toml&amp;lt;/code&amp;gt; is split into three parts: the non-mod-specific properties, which are linked to the mod file; the mod properties, with a section for each mod; and dependency configurations, with a section for each mod's dependencies.&lt;br /&gt;
&lt;br /&gt;
=== Non-Mod-Specific Properties ===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Property !! Type !! Defaults&lt;br /&gt;
! Description&lt;br /&gt;
! Example&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;modLoader&amp;lt;/code&amp;gt; || string || '''mandatory'''&lt;br /&gt;
|  The language loader for the mod. Used to specify an alternative language for the mod, such as Kotlin, if one exists. The Forge-provided Java loader is &amp;lt;code&amp;gt;javafml&amp;lt;/code&amp;gt;.&lt;br /&gt;
| &amp;lt;code&amp;gt;&amp;quot;javafml&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;loaderVersion&amp;lt;/code&amp;gt; || string || '''mandatory'''&lt;br /&gt;
|  The acceptable version range of the language loader, expressed as a [https://maven.apache.org/enforcer/enforcer-rules/versionRanges.html Maven version spec]. For the Forge-provided Java loader, the version is the major version of the Forge version.&lt;br /&gt;
| &amp;lt;code&amp;gt;&amp;quot;[34,)&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;license&amp;lt;/code&amp;gt; || string || '''mandatory'''&lt;br /&gt;
| The license for the mod(s) in this JAR. This string may be any valid string, but it is suggested to set the value to be the name of your license, and/or a link to that license.&lt;br /&gt;
| &amp;lt;code&amp;gt;&amp;quot;GNU GPL v3, https://www.gnu.org/licenses/gpl-3.0.en.html&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;showAsResourcePack&amp;lt;/code&amp;gt; || boolean || &amp;lt;code&amp;gt;false&amp;lt;/code&amp;gt; &lt;br /&gt;
| Whether to display this mod's resources as a separate option in the resource pack menu. If disabled, the mod's resources will be rolled into the &amp;quot;Mod resources&amp;quot; pack. &lt;br /&gt;
| &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt; &lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;properties&amp;lt;/code&amp;gt; || table || &amp;lt;code&amp;gt;{}&amp;lt;/code&amp;gt; &lt;br /&gt;
| A table of custom substitution properties. This is used by &amp;lt;code&amp;gt;StringSubstitutor&amp;lt;/code&amp;gt; to replace values, using &amp;lt;code&amp;gt;${file.*}&amp;lt;/code&amp;gt;.&lt;br /&gt;
| &amp;lt;code&amp;gt;{ &amp;quot;thingy&amp;quot; = 1 }&amp;lt;/code&amp;gt;, used in &amp;lt;code&amp;gt;${file.thingy}&amp;lt;/code&amp;gt; &lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;issueTrackerURL&amp;lt;/code&amp;gt; || string || ''nothing''&lt;br /&gt;
| A URL for an issues tracker. &amp;lt;inline alert&amp;gt; This should never be a blank string, as that will cause an error. &amp;lt;/inline&amp;gt; &lt;br /&gt;
| &amp;lt;code&amp;gt;&amp;quot;http://my.issue.tracker/&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Mod Properties ===&lt;br /&gt;
&lt;br /&gt;
A mod entry is defined by a new section starting with a &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;[[mods]]&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt; header (In TOML, the &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;[[mods]]&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt; defines an [https://toml.io/en/v1.0.0-rc.2#array-of-tables array of tables]). All properties from that line until the next header will become the properties for that mod.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Property !! Type !! Defaults&lt;br /&gt;
! Description&lt;br /&gt;
! Example&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;modId&amp;lt;/code&amp;gt; || string || '''mandatory'''&lt;br /&gt;
| The mod's identifier (modid). This must match the following regex: &amp;lt;code&amp;gt;^[a-z][a-z0-9_-]{1,63}$&amp;lt;/code&amp;gt; (starts with a lowercase letter; other characters must be a lowercase letter, number, underscore or hyphen; must be 2-64 characters long). &lt;br /&gt;
| &amp;lt;code&amp;gt;&amp;quot;examplemod&amp;quot;&amp;lt;/code&amp;gt; &lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;namespace&amp;lt;/code&amp;gt; || string || value of &amp;lt;code&amp;gt;modId&amp;lt;/code&amp;gt; &lt;br /&gt;
| An override namespace. &amp;lt;inline info&amp;gt; Currently, there is no use for this property &amp;lt;/inline&amp;gt; &lt;br /&gt;
| &amp;lt;code&amp;gt;example&amp;lt;/code&amp;gt; &lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;version&amp;lt;/code&amp;gt; || string || &amp;lt;code&amp;gt;&amp;quot;1&amp;quot;&amp;lt;/code&amp;gt; &lt;br /&gt;
| The version of the mod jar, used when the mod is a dependency of another mod, expressed as numbers seperated by dots (&amp;lt;code&amp;gt;.&amp;lt;/code&amp;gt;), ideally conforming to [[Semantic_Versioning|Semantic Versioning]]. The default value in the MDK for this is &amp;lt;code&amp;gt;${file.jarVersion}&amp;lt;/code&amp;gt;, which is replaced at runtime with the &amp;lt;code&amp;gt;Implementation-Version&amp;lt;/code&amp;gt; found in the jar's manifest file. &lt;br /&gt;
| &amp;lt;code&amp;gt;&amp;quot;0.2.4-beta1&amp;quot;&amp;lt;/code&amp;gt; &lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;displayName&amp;lt;/code&amp;gt; || string || value of &amp;lt;code&amp;gt;modId&amp;lt;/code&amp;gt; &lt;br /&gt;
| The display name of the mod, for use in the Mods listing screen&lt;br /&gt;
| &amp;lt;code&amp;gt;&amp;quot;Example Mod&amp;quot;&amp;lt;/code&amp;gt; &lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;description&amp;lt;/code&amp;gt; || string || &amp;lt;code&amp;gt;&amp;quot;MISSING DESCRIPTION&amp;quot;&amp;lt;/code&amp;gt; &lt;br /&gt;
| The description of the mod, for use in the Mods listing screen. It's recommended to use a multiline string (surrounded by &amp;lt;code&amp;gt;'''&amp;lt;code&amp;gt;)&lt;br /&gt;
| &amp;lt;code&amp;gt;&amp;quot;Adds things and stuff. &amp;quot;&amp;lt;/code&amp;gt; &lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;logoFile&amp;lt;/code&amp;gt; || string || ''nothing''&lt;br /&gt;
| The path of the logo file image, for use in the Mods listing screen. The image must be in the root of the jar file, not in any subfolder thereof (e.g. the file is directly in &amp;lt;code&amp;gt;src/main/resources&amp;lt;/code&amp;gt;)&lt;br /&gt;
| &amp;lt;code&amp;gt;&amp;quot;myAwesomeLogo.png&amp;quot;&amp;lt;/code&amp;gt; &lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;logoBlur&amp;lt;/code&amp;gt; || boolean || &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt; &lt;br /&gt;
| Whether to do some blurring on the mod's logo in the Mods listing screen. Has no effect if &amp;lt;code&amp;gt;logoFile&amp;lt;/code&amp;gt; is not set. &lt;br /&gt;
| &amp;lt;code&amp;gt;false&amp;lt;/code&amp;gt; &lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;updateJSONURL&amp;lt;/code&amp;gt; || string || ''nothing''&lt;br /&gt;
| The update JSON URL, used by the [Update_Checker update checker]. &amp;lt;inline alert&amp;gt; This should never be a blank string, as that will cause an error. &amp;lt;/inline&amp;gt; &lt;br /&gt;
| &amp;lt;code&amp;gt;http://myurl.me/path/to/update.json&amp;lt;/code&amp;gt; &lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;modproperties&amp;lt;/code&amp;gt; || table || &amp;lt;code&amp;gt;{}&amp;lt;/code&amp;gt; &lt;br /&gt;
| A table of custom mod properties; this is not used for Forge, but is mainly for use by mods. &lt;br /&gt;
| &amp;lt;code&amp;gt;{ &amp;quot;useThing&amp;quot; = true }&amp;lt;/code&amp;gt; &lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;credits&amp;lt;/code&amp;gt; || string || ''nothing''&lt;br /&gt;
| Credits and acknowledgements for the mod, for use in the Mods listing screen. Can be any string. &lt;br /&gt;
| &amp;lt;code&amp;gt;&amp;quot;This person and that guy&amp;quot;&amp;lt;/code&amp;gt; &lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;authors&amp;lt;/code&amp;gt; || string || ''nothing''&lt;br /&gt;
| Authors for the mod, for use in the Mods listing screen. Can be any string. &lt;br /&gt;
| &amp;lt;code&amp;gt;&amp;quot;ExampleDude&amp;quot;&amp;lt;/code&amp;gt; &lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;displayURL&amp;lt;/code&amp;gt; || string || ''nothing''&lt;br /&gt;
| A URL, displayed on the Mods listing screen. Can be any string. &lt;br /&gt;
| &amp;lt;code&amp;gt;http://example.com/&amp;lt;/code&amp;gt; &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Dependency Configurations ===&lt;br /&gt;
&lt;br /&gt;
Mods can define dependencies for their mods, which are checked by Forge before loading mods. This is used for e.g. ensuring your mod loads after another, or hard-crashing if a mod with a specified version does not exist.&lt;br /&gt;
&lt;br /&gt;
These dependency configurations, like the mod properties, are defined by a new section starting with &amp;lt;code&amp;gt;[[dependencies.&amp;lt;modid&amp;gt;]]&amp;lt;/code&amp;gt;, with &amp;lt;code&amp;gt;&amp;lt;modid&amp;gt;&amp;lt;/code&amp;gt; being the mod id that has this dependency. All properties from that line until the next header will become the properties of that dependency configuration.&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
! Property !! Type !! Defaults &lt;br /&gt;
! Description &lt;br /&gt;
! Example&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;modId&amp;lt;/code&amp;gt; || string || '''mandatory'''&lt;br /&gt;
| The mod id of the dependency. &lt;br /&gt;
| &amp;lt;code&amp;gt;examplelibrary&amp;lt;/code&amp;gt; &lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;mandatory&amp;lt;/code&amp;gt; || boolean || '''mandatory'''&lt;br /&gt;
| Whether to crash if this dependency is not met. &lt;br /&gt;
| &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt; &lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;versionRange&amp;lt;/code&amp;gt; || string || &amp;lt;code&amp;gt;&amp;quot;&amp;quot;&amp;lt;/code&amp;gt; &lt;br /&gt;
| The acceptable version range of the dependency, expressed as a [https://maven.apache.org/enforcer/enforcer-rules/versionRanges.html Maven version spec]. An empty string is an unbounded version range, which matches any version. &lt;br /&gt;
| &amp;lt;code&amp;gt;&amp;quot;[1.0,2.0)&amp;quot;&amp;lt;/code&amp;gt; &lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ordering&amp;lt;/code&amp;gt; || string || &amp;lt;code&amp;gt;&amp;quot;NONE&amp;quot;&amp;lt;/code&amp;gt; &lt;br /&gt;
| Defines if the mod must load before or after this dependency. The valid values are &amp;lt;code&amp;gt;BEFORE&amp;lt;/code&amp;gt; (must load before), &amp;lt;code&amp;gt;AFTER&amp;lt;/code&amp;gt; (must load after), and &amp;lt;code&amp;gt;NONE&amp;lt;/code&amp;gt; (does not care about order). &lt;br /&gt;
| &amp;lt;code&amp;gt;&amp;quot;AFTER&amp;quot;&amp;lt;/code&amp;gt; &lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;side&amp;lt;/code&amp;gt; || string || &amp;lt;code&amp;gt;&amp;quot;BOTH&amp;quot;&amp;lt;/code&amp;gt; &lt;br /&gt;
| Defines if this dependency needs only to be met on a specfic [[Sides|physical side]]. The valid values are &amp;lt;code&amp;gt;CLIENT&amp;lt;/code&amp;gt; (present on the client), &amp;lt;code&amp;gt;SERVER&amp;lt;/code&amp;gt; (present on the dedicated server), and &amp;lt;code&amp;gt;BOTH&amp;lt;/code&amp;gt; (present on both sides). &lt;br /&gt;
| &amp;lt;code&amp;gt;&amp;quot;CLIENT&amp;quot;&amp;lt;/code&amp;gt; &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{{Colored box|title=Important|content=When specifying dependency ordering between two or more mods, beware of cyclic order!: ex. if mod A must load before mod B, and mod B must load before mod A, the game will crash because of the circular cycle.}}&lt;br /&gt;
&lt;br /&gt;
[[Category:Getting Started]]&lt;/div&gt;</summary>
		<author><name>Curle</name></author>
	</entry>
	<entry>
		<id>https://forge.gemwire.uk/index.php?title=Proper_Mod_Structuring&amp;diff=2070</id>
		<title>Proper Mod Structuring</title>
		<link rel="alternate" type="text/html" href="https://forge.gemwire.uk/index.php?title=Proper_Mod_Structuring&amp;diff=2070"/>
		<updated>2020-09-19T04:14:44Z</updated>

		<summary type="html">&lt;p&gt;Curle: /* The mods.toml file */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
== Structuring Your Mod ==&lt;br /&gt;
&lt;br /&gt;
We’ll look at how to organize your mod into different files and what those files should do.&lt;br /&gt;
=== Packaging ===&lt;br /&gt;
&lt;br /&gt;
Pick a unique package name. If you own a URL associated with your project, you can use it as your top level package. For example if you own “example.com”, you may use &amp;lt;code&amp;gt;com.example&amp;lt;/code&amp;gt; as your top level package.&lt;br /&gt;
&lt;br /&gt;
{{Colored box|title=Important|content=If you do not own a domain, do not use it for your top level package. It is perfectly acceptable to start your package with anything, such as your name/nickname, or the name of the mod.}}&lt;br /&gt;
&lt;br /&gt;
After the top level package (if you have one) you append a unique name for your mod, such as &amp;lt;code&amp;gt;examplemod&amp;lt;/code&amp;gt;. In our case it will end up as &amp;lt;code&amp;gt;com.example.examplemod&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== The &amp;lt;code&amp;gt;mods.toml&amp;lt;/code&amp;gt; file ===&lt;br /&gt;
&lt;br /&gt;
This file defines the metadata of your mod. Its information may be viewed by users from the main screen of the game through the Mods button. A single info file can describe several mods.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;mods.toml&amp;lt;/code&amp;gt; file is formatted as [https://github.com/toml-lang/toml TOML], the example mods.toml file in the MDK provides comments explaining the contents of the file. It should be stored as &amp;lt;code&amp;gt;src/main/resources/META-INF/mods.toml&amp;lt;/code&amp;gt;. A basic &amp;lt;code&amp;gt;mods.toml&amp;lt;/code&amp;gt;, describing one mod, may look like this:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;toml&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
    # The name of the mod loader type to load - for regular FML @Mod mods it should be javafml&lt;br /&gt;
    modLoader=&amp;quot;javafml&amp;quot;&lt;br /&gt;
    # A version range to match for said mod loader - for regular FML @Mod it will be the forge version&lt;br /&gt;
    # Forge for 1.15.2 is version 31&lt;br /&gt;
    loaderVersion=&amp;quot;[31,)&amp;quot;&lt;br /&gt;
    # A URL to refer people to when problems occur with this mod&lt;br /&gt;
    issueTrackerURL=&amp;quot;github.com/MinecraftForge/MinecraftForge/issues&amp;quot;&lt;br /&gt;
    # If the mods defined in this file should show as seperate resource packs&lt;br /&gt;
    showAsResourcePack=false&lt;br /&gt;
    [[mods]]&lt;br /&gt;
      modId=&amp;quot;examplemod&amp;quot;&lt;br /&gt;
      version=&amp;quot;1.0.0.0&amp;quot;&lt;br /&gt;
      displayName=&amp;quot;Example Mod&amp;quot;&lt;br /&gt;
      updateJSONURL=&amp;quot;minecraftforge.net/versions.json&amp;quot;&lt;br /&gt;
      displayURL=&amp;quot;minecraftforge.net&amp;quot;&lt;br /&gt;
      logoFile=&amp;quot;assets/examplemod/textures/logo.png&amp;quot;&lt;br /&gt;
      credits=&amp;quot;I'd like to thank my mother and father.&amp;quot;&lt;br /&gt;
      authors=&amp;quot;Author&amp;quot;&lt;br /&gt;
      description='''&lt;br /&gt;
      Lets you craft dirt into diamonds. This is a traditional mod that has existed for eons. It is ancient. The holy Notch created it. Jeb rainbowfied it. Dinnerbone made it upside down. Etc.&lt;br /&gt;
      '''&lt;br /&gt;
&lt;br /&gt;
      [[dependencies.examplemod]]&lt;br /&gt;
        modId=&amp;quot;forge&amp;quot;&lt;br /&gt;
        mandatory=true&lt;br /&gt;
        versionRange=&amp;quot;[31,)&amp;quot;&lt;br /&gt;
        ordering=&amp;quot;NONE&amp;quot;&lt;br /&gt;
        side=&amp;quot;BOTH&amp;quot;&lt;br /&gt;
&lt;br /&gt;
      [[dependencies.examplemod]]&lt;br /&gt;
        modId=&amp;quot;minecraft&amp;quot;&lt;br /&gt;
        mandatory=true&lt;br /&gt;
        versionRange=&amp;quot;[1.15.2]&amp;quot;&lt;br /&gt;
        ordering=&amp;quot;NONE&amp;quot;&lt;br /&gt;
        side=&amp;quot;BOTH&amp;quot;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The default Gradle configuration replaces &amp;lt;code&amp;gt;${file.jarVersion}&amp;lt;/code&amp;gt; with the project version, but ''only'' within &amp;lt;code&amp;gt;mods.toml&amp;lt;/code&amp;gt;, so you should use those instead of directly writing them out. Here is a table of attributes that may be given to a mod, where &amp;lt;code&amp;gt;mandatory&amp;lt;/code&amp;gt; means there is no default and the absence of the property causes an error.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Property      !! Type    !! Default      !! Description&lt;br /&gt;
|-&lt;br /&gt;
| modid         || string  || mandatory    || The modid this file is linked to.&lt;br /&gt;
|-&lt;br /&gt;
| version       || string  || mandatory    || The version of the mod. It should be just numbers seperated by dots, ideally conforming to Semantic Versioning.&lt;br /&gt;
|-&lt;br /&gt;
| license       || string  || mandatory    || The license that the mod is held under&lt;br /&gt;
|-&lt;br /&gt;
| displayName   || string  || mandatory    || The user-friendly name of this mod.&lt;br /&gt;
|-&lt;br /&gt;
| updateJSONURL || string  || &amp;quot;&amp;quot;           || The URL to a version JSON.&lt;br /&gt;
|-&lt;br /&gt;
| displayURL    || string  || &amp;quot;&amp;quot; 	   || A link to the mod’s homepage.&lt;br /&gt;
|-&lt;br /&gt;
| logoFile 	|| string  || &amp;quot;&amp;quot; 	   || The filename of the mod’s logo. It must be placed in the root resource folder, not in a subfolder.&lt;br /&gt;
|-&lt;br /&gt;
| credits 	|| string  || &amp;quot;&amp;quot; 	   || A string that contains any acknowledgements you want to mention.&lt;br /&gt;
|-&lt;br /&gt;
| authors 	|| string  || &amp;quot;&amp;quot; 	   || The authors to this mod.&lt;br /&gt;
|-&lt;br /&gt;
| description 	|| string  || mandatory    || A description of this mod.&lt;br /&gt;
|-&lt;br /&gt;
| dependencies 	|| [list]  || [] 	   || A list of dependencies of this mod.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
NOTE:  All version ranges use the [https://maven.apache.org/enforcer/enforcer-rules/versionRanges.html Maven Version Range Specification].&lt;br /&gt;
&lt;br /&gt;
=== The Mod File ===&lt;br /&gt;
&lt;br /&gt;
Generally, we’ll start with a file named after your mod, and put into your package. This is the ''entry point'' to your mod and will contain some special indicators marking it as such.&lt;br /&gt;
&lt;br /&gt;
==== What is &amp;lt;code&amp;gt;@Mod&amp;lt;/code&amp;gt;? ====&lt;br /&gt;
&lt;br /&gt;
This is an annotation indicating to the Forge Mod Loader that the class is a Mod entry point. The &amp;lt;code&amp;gt;@Mod&amp;lt;/code&amp;gt; annotation’s value should match a mod id in the &amp;lt;code&amp;gt;src/main/resources/META-INF/mods.toml&amp;lt;/code&amp;gt; file.&lt;br /&gt;
&lt;br /&gt;
==== Keeping Your Code Clean Using Sub-packages ====&lt;br /&gt;
&lt;br /&gt;
Rather than clutter up a single class and package with everything, it is recommended you break your mod into subpackages.&lt;br /&gt;
&lt;br /&gt;
A common subpackage strategy has packages for &amp;lt;code&amp;gt;common&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;client&amp;lt;/code&amp;gt; code, which is code that can be run on server/client and client, respectively. Inside the &amp;lt;code&amp;gt;common&amp;lt;/code&amp;gt; package would go things like Items, Blocks, and Tile Entities (which can each in turn be another subpackage). Things like GUIs and Renderers would go inside the &amp;lt;code&amp;gt;client&amp;lt;/code&amp;gt; package.&lt;br /&gt;
&lt;br /&gt;
{{Colored box|title=Note|content=This package style is only a suggestion, though it is a commonly used style. Feel free to use your own packaging system.}}&lt;br /&gt;
&lt;br /&gt;
By keeping your code in clean subpackages, you can grow your mod much more organically.&lt;br /&gt;
&lt;br /&gt;
==== Class Naming Schemes ====&lt;br /&gt;
&lt;br /&gt;
A common class naming scheme allows easier deciphering of what a class is, and also makes it easier for someone developing with your mod to find things.&lt;br /&gt;
&lt;br /&gt;
For Example:&lt;br /&gt;
&lt;br /&gt;
* An &amp;lt;code&amp;gt;Item&amp;lt;/code&amp;gt; called &amp;lt;code&amp;gt;PowerRing&amp;lt;/code&amp;gt; would be in an &amp;lt;code&amp;gt;item&amp;lt;/code&amp;gt; package, with a class name of &amp;lt;code&amp;gt;PowerRingItem&amp;lt;/code&amp;gt;.&lt;br /&gt;
* A &amp;lt;code&amp;gt;Block&amp;lt;/code&amp;gt; called &amp;lt;code&amp;gt;NotDirt&amp;lt;/code&amp;gt; would be in a &amp;lt;code&amp;gt;block&amp;lt;/code&amp;gt; package, with a class name of &amp;lt;code&amp;gt;NotDirtBlock&amp;lt;/code&amp;gt;.&lt;br /&gt;
* Finally, a &amp;lt;code&amp;gt;TileEntity&amp;lt;/code&amp;gt; for a block called &amp;lt;code&amp;gt;SuperChewer&amp;lt;/code&amp;gt; would be in a &amp;lt;code&amp;gt;tile&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;tileentity&amp;lt;/code&amp;gt; package, with a class name of &amp;lt;code&amp;gt;SuperChewerTile&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Appending your class names with what ''kind'' of object they are makes it easier to figure out what a class is, or guess the class for an object.&lt;br /&gt;
&lt;br /&gt;
[[Category:Getting Started]]&lt;/div&gt;</summary>
		<author><name>Curle</name></author>
	</entry>
	<entry>
		<id>https://forge.gemwire.uk/index.php?title=Proper_Mod_Structuring&amp;diff=2069</id>
		<title>Proper Mod Structuring</title>
		<link rel="alternate" type="text/html" href="https://forge.gemwire.uk/index.php?title=Proper_Mod_Structuring&amp;diff=2069"/>
		<updated>2020-09-19T04:01:16Z</updated>

		<summary type="html">&lt;p&gt;Curle: Add Mod Structuring article&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
== Structuring Your Mod ==&lt;br /&gt;
&lt;br /&gt;
We’ll look at how to organize your mod into different files and what those files should do.&lt;br /&gt;
=== Packaging ===&lt;br /&gt;
&lt;br /&gt;
Pick a unique package name. If you own a URL associated with your project, you can use it as your top level package. For example if you own “example.com”, you may use &amp;lt;code&amp;gt;com.example&amp;lt;/code&amp;gt; as your top level package.&lt;br /&gt;
&lt;br /&gt;
{{Colored box|title=Important|content=If you do not own a domain, do not use it for your top level package. It is perfectly acceptable to start your package with anything, such as your name/nickname, or the name of the mod.}}&lt;br /&gt;
&lt;br /&gt;
After the top level package (if you have one) you append a unique name for your mod, such as &amp;lt;code&amp;gt;examplemod&amp;lt;/code&amp;gt;. In our case it will end up as &amp;lt;code&amp;gt;com.example.examplemod&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== The &amp;lt;code&amp;gt;mods.toml&amp;lt;/code&amp;gt; file ===&lt;br /&gt;
&lt;br /&gt;
This file defines the metadata of your mod. Its information may be viewed by users from the main screen of the game through the Mods button. A single info file can describe several mods.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;mods.toml&amp;lt;/code&amp;gt; file is formatted as [https://github.com/toml-lang/toml TOML], the example mods.toml file in the MDK provides comments explaining the contents of the file. It should be stored as &amp;lt;code&amp;gt;src/main/resources/META-INF/mods.toml&amp;lt;/code&amp;gt;. A basic &amp;lt;code&amp;gt;mods.toml&amp;lt;/code&amp;gt;, describing one mod, may look like this:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;toml&amp;quot;&amp;gt;&lt;br /&gt;
    # The name of the mod loader type to load - for regular FML @Mod mods it should be javafml&lt;br /&gt;
    modLoader=&amp;quot;javafml&amp;quot;&lt;br /&gt;
    # A version range to match for said mod loader - for regular FML @Mod it will be the forge version&lt;br /&gt;
    # Forge for 1.15.2 is version 31&lt;br /&gt;
    loaderVersion=&amp;quot;[31,)&amp;quot;&lt;br /&gt;
    # A URL to refer people to when problems occur with this mod&lt;br /&gt;
    issueTrackerURL=&amp;quot;github.com/MinecraftForge/MinecraftForge/issues&amp;quot;&lt;br /&gt;
    # If the mods defined in this file should show as seperate resource packs&lt;br /&gt;
    showAsResourcePack=false&lt;br /&gt;
    [[mods]]&lt;br /&gt;
      modId=&amp;quot;examplemod&amp;quot;&lt;br /&gt;
      version=&amp;quot;1.0.0.0&amp;quot;&lt;br /&gt;
      displayName=&amp;quot;Example Mod&amp;quot;&lt;br /&gt;
      updateJSONURL=&amp;quot;minecraftforge.net/versions.json&amp;quot;&lt;br /&gt;
      displayURL=&amp;quot;minecraftforge.net&amp;quot;&lt;br /&gt;
      logoFile=&amp;quot;assets/examplemod/textures/logo.png&amp;quot;&lt;br /&gt;
      credits=&amp;quot;I'd like to thank my mother and father.&amp;quot;&lt;br /&gt;
      authors=&amp;quot;Author&amp;quot;&lt;br /&gt;
      description='''&lt;br /&gt;
      Lets you craft dirt into diamonds. This is a traditional mod that has existed for eons. It is ancient. The holy Notch created it. Jeb rainbowfied it. Dinnerbone made it upside down. Etc.&lt;br /&gt;
      '''&lt;br /&gt;
&lt;br /&gt;
      [[dependencies.examplemod]]&lt;br /&gt;
        modId=&amp;quot;forge&amp;quot;&lt;br /&gt;
        mandatory=true&lt;br /&gt;
        versionRange=&amp;quot;[31,)&amp;quot;&lt;br /&gt;
        ordering=&amp;quot;NONE&amp;quot;&lt;br /&gt;
        side=&amp;quot;BOTH&amp;quot;&lt;br /&gt;
&lt;br /&gt;
      [[dependencies.examplemod]]&lt;br /&gt;
        modId=&amp;quot;minecraft&amp;quot;&lt;br /&gt;
        mandatory=true&lt;br /&gt;
        versionRange=&amp;quot;[1.15.2]&amp;quot;&lt;br /&gt;
        ordering=&amp;quot;NONE&amp;quot;&lt;br /&gt;
        side=&amp;quot;BOTH&amp;quot;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
The default Gradle configuration replaces &amp;lt;code&amp;gt;${file.jarVersion}&amp;lt;/code&amp;gt; with the project version, but ''only'' within &amp;lt;code&amp;gt;mods.toml&amp;lt;/code&amp;gt;, so you should use those instead of directly writing them out. Here is a table of attributes that may be given to a mod, where &amp;lt;code&amp;gt;mandatory&amp;lt;/code&amp;gt; means there is no default and the absence of the property causes an error.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Property      !! Type    !! Default      !! Description&lt;br /&gt;
|-&lt;br /&gt;
| modid         || string  || mandatory    || The modid this file is linked to.&lt;br /&gt;
|-&lt;br /&gt;
| version       || string  || mandatory    || The version of the mod. It should be just numbers seperated by dots, ideally conforming to Semantic Versioning.&lt;br /&gt;
|-&lt;br /&gt;
| license       || string  || mandatory    || The license that the mod is held under&lt;br /&gt;
|-&lt;br /&gt;
| displayName   || string  || mandatory    || The user-friendly name of this mod.&lt;br /&gt;
|-&lt;br /&gt;
| updateJSONURL || string  || &amp;quot;&amp;quot;           || The URL to a version JSON.&lt;br /&gt;
|-&lt;br /&gt;
| displayURL    || string  || &amp;quot;&amp;quot; 	   || A link to the mod’s homepage.&lt;br /&gt;
|-&lt;br /&gt;
| logoFile 	|| string  || &amp;quot;&amp;quot; 	   || The filename of the mod’s logo. It must be placed in the root resource folder, not in a subfolder.&lt;br /&gt;
|-&lt;br /&gt;
| credits 	|| string  || &amp;quot;&amp;quot; 	   || A string that contains any acknowledgements you want to mention.&lt;br /&gt;
|-&lt;br /&gt;
| authors 	|| string  || &amp;quot;&amp;quot; 	   || The authors to this mod.&lt;br /&gt;
|-&lt;br /&gt;
| description 	|| string  || mandatory    || A description of this mod.&lt;br /&gt;
|-&lt;br /&gt;
| dependencies 	|| [list]  || [] 	   || A list of dependencies of this mod.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
NOTE:  All version ranges use the [https://maven.apache.org/enforcer/enforcer-rules/versionRanges.html Maven Version Range Specification].&lt;br /&gt;
&lt;br /&gt;
=== The Mod File ===&lt;br /&gt;
&lt;br /&gt;
Generally, we’ll start with a file named after your mod, and put into your package. This is the ''entry point'' to your mod and will contain some special indicators marking it as such.&lt;br /&gt;
&lt;br /&gt;
==== What is &amp;lt;code&amp;gt;@Mod&amp;lt;/code&amp;gt;? ====&lt;br /&gt;
&lt;br /&gt;
This is an annotation indicating to the Forge Mod Loader that the class is a Mod entry point. The &amp;lt;code&amp;gt;@Mod&amp;lt;/code&amp;gt; annotation’s value should match a mod id in the &amp;lt;code&amp;gt;src/main/resources/META-INF/mods.toml&amp;lt;/code&amp;gt; file.&lt;br /&gt;
&lt;br /&gt;
==== Keeping Your Code Clean Using Sub-packages ====&lt;br /&gt;
&lt;br /&gt;
Rather than clutter up a single class and package with everything, it is recommended you break your mod into subpackages.&lt;br /&gt;
&lt;br /&gt;
A common subpackage strategy has packages for &amp;lt;code&amp;gt;common&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;client&amp;lt;/code&amp;gt; code, which is code that can be run on server/client and client, respectively. Inside the &amp;lt;code&amp;gt;common&amp;lt;/code&amp;gt; package would go things like Items, Blocks, and Tile Entities (which can each in turn be another subpackage). Things like GUIs and Renderers would go inside the &amp;lt;code&amp;gt;client&amp;lt;/code&amp;gt; package.&lt;br /&gt;
&lt;br /&gt;
{{Colored box|title=Note|content=This package style is only a suggestion, though it is a commonly used style. Feel free to use your own packaging system.}}&lt;br /&gt;
&lt;br /&gt;
By keeping your code in clean subpackages, you can grow your mod much more organically.&lt;br /&gt;
&lt;br /&gt;
==== Class Naming Schemes ====&lt;br /&gt;
&lt;br /&gt;
A common class naming scheme allows easier deciphering of what a class is, and also makes it easier for someone developing with your mod to find things.&lt;br /&gt;
&lt;br /&gt;
For Example:&lt;br /&gt;
&lt;br /&gt;
* An &amp;lt;code&amp;gt;Item&amp;lt;/code&amp;gt; called &amp;lt;code&amp;gt;PowerRing&amp;lt;/code&amp;gt; would be in an &amp;lt;code&amp;gt;item&amp;lt;/code&amp;gt; package, with a class name of &amp;lt;code&amp;gt;PowerRingItem&amp;lt;/code&amp;gt;.&lt;br /&gt;
* A &amp;lt;code&amp;gt;Block&amp;lt;/code&amp;gt; called &amp;lt;code&amp;gt;NotDirt&amp;lt;/code&amp;gt; would be in a &amp;lt;code&amp;gt;block&amp;lt;/code&amp;gt; package, with a class name of &amp;lt;code&amp;gt;NotDirtBlock&amp;lt;/code&amp;gt;.&lt;br /&gt;
* Finally, a &amp;lt;code&amp;gt;TileEntity&amp;lt;/code&amp;gt; for a block called &amp;lt;code&amp;gt;SuperChewer&amp;lt;/code&amp;gt; would be in a &amp;lt;code&amp;gt;tile&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;tileentity&amp;lt;/code&amp;gt; package, with a class name of &amp;lt;code&amp;gt;SuperChewerTile&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Appending your class names with what ''kind'' of object they are makes it easier to figure out what a class is, or guess the class for an object.&lt;br /&gt;
&lt;br /&gt;
[[Category:Getting Started]]&lt;/div&gt;</summary>
		<author><name>Curle</name></author>
	</entry>
	<entry>
		<id>https://forge.gemwire.uk/index.php?title=Template:Colored_box/style.css&amp;diff=2068</id>
		<title>Template:Colored box/style.css</title>
		<link rel="alternate" type="text/html" href="https://forge.gemwire.uk/index.php?title=Template:Colored_box/style.css&amp;diff=2068"/>
		<updated>2020-09-19T03:04:08Z</updated>

		<summary type="html">&lt;p&gt;Curle: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;.mw-tpl-colorbox {&lt;br /&gt;
 box-sizing: border-box;&lt;br /&gt;
 margin: 0.5em 0.5em 1em 0.5em;&lt;br /&gt;
 border-radius: 0.2em;&lt;br /&gt;
 background: rgb(27, 32, 35);&lt;br /&gt;
 box-shadow: 0 0 0.2em #999999;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.mw-tpl-colorbox-title {&lt;br /&gt;
 background: rgb(0, 71, 127);&lt;br /&gt;
 color: #FFFFFF;&lt;br /&gt;
 border-radius: 0.2em 0.2em 0 0;&lt;br /&gt;
 padding: 0.5em 1em 0.5em 1em;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.mw-tpl-colorbox-title-icon {&lt;br /&gt;
 opacity: 0.8;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.mw-tpl-colorbox-title-corner {&lt;br /&gt;
 float: right;&lt;br /&gt;
 font-size: 0.7em;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.mw-tpl-colorbox-content {&lt;br /&gt;
 padding: 0.5em 1em 0.5em 1em;&lt;br /&gt;
 color: #FFFFFF;&lt;br /&gt;
}&lt;/div&gt;</summary>
		<author><name>Curle</name></author>
	</entry>
	<entry>
		<id>https://forge.gemwire.uk/index.php?title=Template:Colored_box&amp;diff=2067</id>
		<title>Template:Colored box</title>
		<link rel="alternate" type="text/html" href="https://forge.gemwire.uk/index.php?title=Template:Colored_box&amp;diff=2067"/>
		<updated>2020-09-19T03:03:49Z</updated>

		<summary type="html">&lt;p&gt;Curle: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;templatestyles src=&amp;quot;Colored box/style.css&amp;quot;/&amp;gt;&amp;lt;div class=&amp;quot;mw-tpl-colorbox&amp;quot; style=&amp;quot;{{#if:{{{background-content-color|}}}| background-color: {{{background-content-color|rgb(27, 32, 35)}}}; }} {{{style|}}};&amp;quot;&amp;gt;&amp;lt;!--&lt;br /&gt;
--&amp;gt;&amp;lt;div class=&amp;quot;mw-tpl-colorbox-title&amp;quot; style=&amp;quot;{{#if:{{{background-title-color|}}}|background-color:{{{background-title-color|rgb(0, 71, 127)}}};}}&amp;quot;&amp;gt;{{#if:{{{icon|}}}|[[File:{{{icon}}}|20px|class=colorbox-title-icon|link=|alt=]]&amp;amp;#32;}}&amp;lt;strong style=&amp;quot;{{#if:{{{title-color|}}}| color: {{{title-color|#FFFFFF}}}; }}&amp;quot;&amp;gt;{{{title}}}&amp;lt;/strong&amp;gt;&amp;lt;!--&lt;br /&gt;
--&amp;gt;{{#if:{{{link|}}}|&amp;lt;div class=&amp;quot;mw-tpl-colorbox-title-corner&amp;quot;&amp;gt;[[{{{link}}}|&amp;lt;span style=&amp;quot;{{#if:{{{link-color|{{{title-color|}}}}}}| color: {{{link-color|{{{title-color|}}}}}}; }}&amp;quot;&amp;gt;{{{view-text|view}}}&amp;lt;/span&amp;gt;]]&amp;lt;/div&amp;gt;}}&lt;br /&gt;
&amp;lt;/div&amp;gt;&amp;lt;!--&lt;br /&gt;
--&amp;gt;&amp;lt;div class=&amp;quot;mw-tpl-colorbox-content&amp;quot;&amp;gt;&lt;br /&gt;
{{{content}}}{{clr}}&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;/div&gt;</summary>
		<author><name>Curle</name></author>
	</entry>
	<entry>
		<id>https://forge.gemwire.uk/index.php?title=Template:Colored_box&amp;diff=2066</id>
		<title>Template:Colored box</title>
		<link rel="alternate" type="text/html" href="https://forge.gemwire.uk/index.php?title=Template:Colored_box&amp;diff=2066"/>
		<updated>2020-09-19T03:03:22Z</updated>

		<summary type="html">&lt;p&gt;Curle: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;templatestyles src=&amp;quot;Colored box/style.css&amp;quot;/&amp;gt;&amp;lt;div class=&amp;quot;mw-tpl-colorbox&amp;quot; style=&amp;quot;{{#if:{{{background-content-color|}}}| background-color: {{{background-content-color|rgb(27, 32, 35)}}}; }} {{{style|}}};&amp;quot;&amp;gt;&amp;lt;!--&lt;br /&gt;
--&amp;gt;&amp;lt;div class=&amp;quot;mw-tpl-colorbox-title&amp;quot; style=&amp;quot;{{#if:{{{background-title-color|}}}|background-color:{{{background-title-color|rgb(0, 71, 127)}}};}}&amp;quot;&amp;gt;{{#if:{{{icon|}}}|[[File:{{{icon}}}|20px|class=colorbox-title-icon|link=|alt=]]&amp;amp;#32;}}&amp;lt;strong style=&amp;quot;{{#if:{{{title-color|}}}| color: {{{title-color|#000000}}}; }}&amp;quot;&amp;gt;{{{title}}}&amp;lt;/strong&amp;gt;&amp;lt;!--&lt;br /&gt;
--&amp;gt;{{#if:{{{link|}}}|&amp;lt;div class=&amp;quot;mw-tpl-colorbox-title-corner&amp;quot;&amp;gt;[[{{{link}}}|&amp;lt;span style=&amp;quot;{{#if:{{{link-color|{{{title-color|}}}}}}| color: {{{link-color|{{{title-color|}}}}}}; }}&amp;quot;&amp;gt;{{{view-text|view}}}&amp;lt;/span&amp;gt;]]&amp;lt;/div&amp;gt;}}&lt;br /&gt;
&amp;lt;/div&amp;gt;&amp;lt;!--&lt;br /&gt;
--&amp;gt;&amp;lt;div class=&amp;quot;mw-tpl-colorbox-content&amp;quot;&amp;gt;&lt;br /&gt;
{{{content}}}{{clr}}&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;/div&gt;</summary>
		<author><name>Curle</name></author>
	</entry>
	<entry>
		<id>https://forge.gemwire.uk/index.php?title=Template:Colored_box/style.css&amp;diff=2065</id>
		<title>Template:Colored box/style.css</title>
		<link rel="alternate" type="text/html" href="https://forge.gemwire.uk/index.php?title=Template:Colored_box/style.css&amp;diff=2065"/>
		<updated>2020-09-19T03:02:25Z</updated>

		<summary type="html">&lt;p&gt;Curle: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;.mw-tpl-colorbox {&lt;br /&gt;
 box-sizing: border-box;&lt;br /&gt;
 margin: 0.5em 0.5em 1em 0.5em;&lt;br /&gt;
 border-radius: 0.2em;&lt;br /&gt;
 background: rgb(27, 32, 35);&lt;br /&gt;
 box-shadow: 0 0 0.2em #999999;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.mw-tpl-colorbox-title {&lt;br /&gt;
 background: rgb(0, 71, 127);&lt;br /&gt;
 color: #000000;&lt;br /&gt;
 border-radius: 0.2em 0.2em 0 0;&lt;br /&gt;
 padding: 0.5em 1em 0.5em 1em;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.mw-tpl-colorbox-title-icon {&lt;br /&gt;
 opacity: 0.8;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.mw-tpl-colorbox-title-corner {&lt;br /&gt;
 float: right;&lt;br /&gt;
 font-size: 0.7em;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.mw-tpl-colorbox-content {&lt;br /&gt;
 padding: 0.5em 1em 0.5em 1em;&lt;br /&gt;
 color: #11151d;&lt;br /&gt;
}&lt;/div&gt;</summary>
		<author><name>Curle</name></author>
	</entry>
	<entry>
		<id>https://forge.gemwire.uk/index.php?title=Template:Colored_box/style.css&amp;diff=2064</id>
		<title>Template:Colored box/style.css</title>
		<link rel="alternate" type="text/html" href="https://forge.gemwire.uk/index.php?title=Template:Colored_box/style.css&amp;diff=2064"/>
		<updated>2020-09-19T03:01:00Z</updated>

		<summary type="html">&lt;p&gt;Curle: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;.mw-tpl-colorbox {&lt;br /&gt;
 box-sizing: border-box;&lt;br /&gt;
 margin: 0.5em 0.5em 1em 0.5em;&lt;br /&gt;
 border-radius: 0.2em;&lt;br /&gt;
 background: rgb(27, 32, 35);&lt;br /&gt;
 box-shadow: 0 0 0.2em #999999;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.mw-tpl-colorbox-title {&lt;br /&gt;
 background: #7dbae8;&lt;br /&gt;
 color: #000000;&lt;br /&gt;
 border-radius: 0.2em 0.2em 0 0;&lt;br /&gt;
 padding: 0.5em 1em 0.5em 1em;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.mw-tpl-colorbox-title-icon {&lt;br /&gt;
 opacity: 0.8;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.mw-tpl-colorbox-title-corner {&lt;br /&gt;
 float: right;&lt;br /&gt;
 font-size: 0.7em;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.mw-tpl-colorbox-content {&lt;br /&gt;
 padding: 0.5em 1em 0.5em 1em;&lt;br /&gt;
 color: #11151d;&lt;br /&gt;
}&lt;/div&gt;</summary>
		<author><name>Curle</name></author>
	</entry>
	<entry>
		<id>https://forge.gemwire.uk/index.php?title=Category:Getting_Started&amp;diff=2063</id>
		<title>Category:Getting Started</title>
		<link rel="alternate" type="text/html" href="https://forge.gemwire.uk/index.php?title=Category:Getting_Started&amp;diff=2063"/>
		<updated>2020-09-19T02:56:53Z</updated>

		<summary type="html">&lt;p&gt;Curle: Created page with &amp;quot;For absolute beginners who need an introduction to the whole system. Important information is split up across the subcategories for those who need help with the less commonly...&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;For absolute beginners who need an introduction to the whole system.&lt;br /&gt;
Important information is split up across the subcategories for those who need help with the less commonly explained things.&lt;/div&gt;</summary>
		<author><name>Curle</name></author>
	</entry>
	<entry>
		<id>https://forge.gemwire.uk/index.php?title=Getting_Started&amp;diff=2062</id>
		<title>Getting Started</title>
		<link rel="alternate" type="text/html" href="https://forge.gemwire.uk/index.php?title=Getting_Started&amp;diff=2062"/>
		<updated>2020-09-19T02:55:31Z</updated>

		<summary type="html">&lt;p&gt;Curle: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;!-- need to format code Tags --&amp;gt;&lt;br /&gt;
= Home = &lt;br /&gt;
== Getting Started with Forge ==&lt;br /&gt;
This is a simple guide to get you from nothing to a basic mod. The rest of this documentation is about where to go from here.&lt;br /&gt;
=== From Zero to Modding ===&lt;br /&gt;
# Obtain a source distribution from forge’s [https://files.minecraftforge.net/ files] site. (Look for the MDK file type)&lt;br /&gt;
# Extract the downloaded source distribution to an empty directory. You should see a bunch of files, and an example mod is placed in &amp;lt;code&amp;gt;src/main/java&amp;lt;/code&amp;gt; for you to look at. Only a few of these files are strictly necessary for mod development, and you may reuse these files for all your projects These files are:&lt;br /&gt;
#* &amp;lt;code&amp;gt;build.gradle&amp;lt;/code&amp;gt;&lt;br /&gt;
#* &amp;lt;code&amp;gt;gradlew.bat&amp;lt;/code&amp;gt;&lt;br /&gt;
#* &amp;lt;code&amp;gt;gradlew&amp;lt;/code&amp;gt;&lt;br /&gt;
#* the &amp;lt;code&amp;gt;gradle&amp;lt;/code&amp;gt; folder&lt;br /&gt;
# Move the files listed above to a new folder, this will be your mod project folder.&lt;br /&gt;
# Choose your IDE:&lt;br /&gt;
#* Forge explicitly supports developing with Eclipse or IntelliJ environments, but any environment, from Netbeans to vi/emacs, can be made to work.&lt;br /&gt;
#* For both Intellij IDEA and Eclipse their Gradle integration will handle the rest of the initial workspace setup, this includes downloading packages from Mojang, MinecraftForge, and a few other software sharing sites.&lt;br /&gt;
#* For most, if not all, changes to the build.gradle file to take effect Gradle will need to be invoked to re-evaluate the project, this can be done through Refresh buttons in the Gradle panels of both the previously mentioned IDEs.&lt;br /&gt;
# Generating IDE Launch/Run Configurations:&lt;br /&gt;
#*For Eclipse, run the &amp;lt;code&amp;gt;genEclipseRuns&amp;lt;/code&amp;gt; gradle task (&amp;lt;code&amp;gt;gradlew genEclipseRuns&amp;lt;/code&amp;gt;). This will generate the Launch Configurations and download any required assets for the game to run. After this has finished refresh your project.&lt;br /&gt;
#*or IntelliJ, run the &amp;lt;code&amp;gt;genIntellijRuns&amp;lt;/code&amp;gt; gradle task (&amp;lt;code&amp;gt;gradlew genIntellijRuns&amp;lt;/code&amp;gt;). This will generate the Run Configurations and download any required assets for the game to run. After this has finished edit your Configurations to fix the “module not specified” error by changing selecting your “main” module.&lt;br /&gt;
&lt;br /&gt;
=== Customizing Your Mod Information ===&lt;br /&gt;
Edit the &amp;lt;code&amp;gt;build.gradle&amp;lt;/code&amp;gt; file to customize how your mod is built (the file names, versions, and other things).&lt;br /&gt;
&lt;br /&gt;
{{Colored box|title=Important|content='''Do not''' edit the &amp;lt;code&amp;gt;buildscript {}&amp;lt;/code&amp;gt; section of the build.gradle file, its default text is necessary for ForgeGradle to function.}}&lt;br /&gt;
&lt;br /&gt;
Almost anything underneath the &amp;lt;code&amp;gt;// Only edit below this line, the above code adds and enables the necessary things for Forge to be setup.&amp;lt;/code&amp;gt; marker can be changed, many things can be removed and customized there as well.&lt;br /&gt;
&lt;br /&gt;
There is a whole site dedicated to customizing the forge &amp;lt;code&amp;gt;build.gradle&amp;lt;/code&amp;gt; files - the [https://forgegradle.readthedocs.org/en/latest/cookbook/ ForgeGradle cookbook]. Once you’re comfortable with your mod setup, you’ll find many useful recipes there.&lt;br /&gt;
&lt;br /&gt;
==== Simple build.gradle Customizations ====&lt;br /&gt;
These customizations are highly recommended for all projects.&lt;br /&gt;
* To change the name of the file you build - edit the value of &amp;lt;code&amp;gt;archivesBaseName&amp;lt;/code&amp;gt; to suit.&lt;br /&gt;
* To change your “maven coordinates” - edit the value of &amp;lt;code&amp;gt;group&amp;lt;/code&amp;gt; as well.&lt;br /&gt;
* To change the version number - edit the value of &amp;lt;code&amp;gt;version&amp;lt;/code&amp;gt;.&lt;br /&gt;
* To update the run configurations - replace all occurrences of &amp;lt;code&amp;gt;examplemod&amp;lt;/code&amp;gt; to the mod id of your mod.&lt;br /&gt;
&lt;br /&gt;
=== Building and Testing Your Mod ===&lt;br /&gt;
# To build your mod, run &amp;lt;code&amp;gt;gradlew build&amp;lt;/code&amp;gt;. This will output a file in &amp;lt;code&amp;gt;build/libs&amp;lt;/code&amp;gt; with the name &amp;lt;code&amp;gt;[archivesBaseName]-[version].jar&amp;lt;/code&amp;gt;. This file can be placed in the &amp;lt;code&amp;gt;mods&amp;lt;/code&amp;gt; folder of a forge enabled Minecraft setup, and distributed.&lt;br /&gt;
# To test run with your mod, the easiest way is to use the run configs that were generated when you set up your project. Otherwise, you can run &amp;lt;code&amp;gt;gradlew runClient&amp;lt;/code&amp;gt;. This will launch Minecraft from the &amp;lt;code&amp;gt;&amp;lt;runDir&amp;gt;&amp;lt;/code&amp;gt; location, including your mod code. There are various customizations to this command. Consult the [https://forgegradle.readthedocs.org/en/latest/cookbook/ ForgeGradle cookbook] for more information.&lt;br /&gt;
# You can also run a dedicated server using the server run config, or &amp;lt;code&amp;gt;gradlew runServer&amp;lt;/code&amp;gt;. This will launch the Minecraft server with its GUI.&lt;br /&gt;
&lt;br /&gt;
{{Colored box|title=Note|content=It is always advisable to test your mod in a dedicated server environment if it is intended to run there.}}&lt;br /&gt;
&lt;br /&gt;
[[Category:Getting Started]]&lt;/div&gt;</summary>
		<author><name>Curle</name></author>
	</entry>
	<entry>
		<id>https://forge.gemwire.uk/index.php?title=Template:Colored_box/style.css&amp;diff=2061</id>
		<title>Template:Colored box/style.css</title>
		<link rel="alternate" type="text/html" href="https://forge.gemwire.uk/index.php?title=Template:Colored_box/style.css&amp;diff=2061"/>
		<updated>2020-09-19T02:54:13Z</updated>

		<summary type="html">&lt;p&gt;Curle: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;.mw-tpl-colorbox {&lt;br /&gt;
 box-sizing: border-box;&lt;br /&gt;
 margin: 0.5em 0.5em 1em 0.5em;&lt;br /&gt;
 border-radius: 0.2em;&lt;br /&gt;
 background: #fff;&lt;br /&gt;
 box-shadow: 0 0 0.2em #999999;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.mw-tpl-colorbox-title {&lt;br /&gt;
 background: #eaecf0;&lt;br /&gt;
 color: #000000;&lt;br /&gt;
 border-radius: 0.2em 0.2em 0 0;&lt;br /&gt;
 padding: 0.5em 1em 0.5em 1em;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.mw-tpl-colorbox-title-icon {&lt;br /&gt;
 opacity: 0.8;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.mw-tpl-colorbox-title-corner {&lt;br /&gt;
 float: right;&lt;br /&gt;
 font-size: 0.7em;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.mw-tpl-colorbox-content {&lt;br /&gt;
 padding: 0.5em 1em 0.5em 1em;&lt;br /&gt;
 color: #11151d;&lt;br /&gt;
}&lt;/div&gt;</summary>
		<author><name>Curle</name></author>
	</entry>
	<entry>
		<id>https://forge.gemwire.uk/index.php?title=Template:Colored_box&amp;diff=2060</id>
		<title>Template:Colored box</title>
		<link rel="alternate" type="text/html" href="https://forge.gemwire.uk/index.php?title=Template:Colored_box&amp;diff=2060"/>
		<updated>2020-09-19T02:34:02Z</updated>

		<summary type="html">&lt;p&gt;Curle: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;templatestyles src=&amp;quot;Colored box/style.css&amp;quot;/&amp;gt;&amp;lt;div class=&amp;quot;mw-tpl-colorbox&amp;quot; style=&amp;quot;{{#if:{{{background-content-color|}}}| background-color: {{{background-content-color|#fff}}}; }} {{{style|}}};&amp;quot;&amp;gt;&amp;lt;!--&lt;br /&gt;
--&amp;gt;&amp;lt;div class=&amp;quot;mw-tpl-colorbox-title&amp;quot; style=&amp;quot;{{#if:{{{background-title-color|}}}|background-color:{{{background-title-color|#eaecf0}}};}}&amp;quot;&amp;gt;{{#if:{{{icon|}}}|[[File:{{{icon}}}|20px|class=colorbox-title-icon|link=|alt=]]&amp;amp;#32;}}&amp;lt;strong style=&amp;quot;{{#if:{{{title-color|}}}| color: {{{title-color|#000000}}}; }}&amp;quot;&amp;gt;{{{title}}}&amp;lt;/strong&amp;gt;&amp;lt;!--&lt;br /&gt;
--&amp;gt;{{#if:{{{link|}}}|&amp;lt;div class=&amp;quot;mw-tpl-colorbox-title-corner&amp;quot;&amp;gt;[[{{{link}}}|&amp;lt;span style=&amp;quot;{{#if:{{{link-color|{{{title-color|}}}}}}| color: {{{link-color|{{{title-color|}}}}}}; }}&amp;quot;&amp;gt;{{{view-text|view}}}&amp;lt;/span&amp;gt;]]&amp;lt;/div&amp;gt;}}&lt;br /&gt;
&amp;lt;/div&amp;gt;&amp;lt;!--&lt;br /&gt;
--&amp;gt;&amp;lt;div class=&amp;quot;mw-tpl-colorbox-content&amp;quot;&amp;gt;&lt;br /&gt;
{{{content}}}{{clr}}&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;/div&gt;</summary>
		<author><name>Curle</name></author>
	</entry>
</feed>