<?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=SciWhiz12</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=SciWhiz12"/>
	<link rel="alternate" type="text/html" href="https://forge.gemwire.uk/wiki/Special:Contributions/SciWhiz12"/>
	<updated>2026-06-02T01:39:43Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.35.0</generator>
	<entry>
		<id>https://forge.gemwire.uk/index.php?title=Custom_recipes&amp;diff=3398</id>
		<title>Custom recipes</title>
		<link rel="alternate" type="text/html" href="https://forge.gemwire.uk/index.php?title=Custom_recipes&amp;diff=3398"/>
		<updated>2023-04-15T23:01:54Z</updated>

		<summary type="html">&lt;p&gt;SciWhiz12: Redirected page to Custom Recipes&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;#REDIRECT [[Custom Recipes]]&lt;/div&gt;</summary>
		<author><name>SciWhiz12</name></author>
	</entry>
	<entry>
		<id>https://forge.gemwire.uk/index.php?title=Main_Page&amp;diff=3310</id>
		<title>Main Page</title>
		<link rel="alternate" type="text/html" href="https://forge.gemwire.uk/index.php?title=Main_Page&amp;diff=3310"/>
		<updated>2022-08-13T20:38:46Z</updated>

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

		<summary type="html">&lt;p&gt;SciWhiz12: SciWhiz12 moved page Datageneration/Datapack Registries to Datapack Registries: by request of User:SizableShrimp&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;#REDIRECT [[Datapack Registries]]&lt;/div&gt;</summary>
		<author><name>SciWhiz12</name></author>
	</entry>
	<entry>
		<id>https://forge.gemwire.uk/index.php?title=Datapack_Registries&amp;diff=3308</id>
		<title>Datapack Registries</title>
		<link rel="alternate" type="text/html" href="https://forge.gemwire.uk/index.php?title=Datapack_Registries&amp;diff=3308"/>
		<updated>2022-08-13T20:37:09Z</updated>

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

		<summary type="html">&lt;p&gt;SciWhiz12: SciWhiz12 moved page Jar-in-jar to Jar-in-Jar: capitalization pls&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;#REDIRECT [[Jar-in-Jar]]&lt;/div&gt;</summary>
		<author><name>SciWhiz12</name></author>
	</entry>
	<entry>
		<id>https://forge.gemwire.uk/index.php?title=Jar-in-Jar&amp;diff=3295</id>
		<title>Jar-in-Jar</title>
		<link rel="alternate" type="text/html" href="https://forge.gemwire.uk/index.php?title=Jar-in-Jar&amp;diff=3295"/>
		<updated>2022-07-06T21:53:19Z</updated>

		<summary type="html">&lt;p&gt;SciWhiz12: SciWhiz12 moved page Jar-in-jar to Jar-in-Jar: capitalization pls&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Jar-in-Jar is a way to handle the dependencies of your mod.&lt;br /&gt;
Sometimes these are libraries pulled from a central maven repository, sometimes these are libraries specially designed for Minecraft and sometimes these are completely other mods.&lt;br /&gt;
Whatever the reason for using a library during the development of your mods, you will need to ensure that the end user has them available when he runs your mod in his environment.&lt;br /&gt;
&lt;br /&gt;
Although there are several options available to achieve this, including for example the Shading plugin, this does not work all the time and can even cause problems along the way when for example two mods need the same dependency.&lt;br /&gt;
Introducing the all-new, all-shiny: Jar-In-Jar.&lt;br /&gt;
====Central function====&lt;br /&gt;
Jar-In-Jar is first and foremost a way to load dependencies for mods, from the jars of the mods.&lt;br /&gt;
To achieve this it looks for a file called: ''META-INF/jarjar/metadata.json''. If you are interested in the format of this file, see the following section of the JarJar library which we expose: [https://github.com/MinecraftForge/JarJar/tree/main/src/main/java/net/minecraftforge/jarjar/metadata JarJar Library - Metadata Source] &lt;br /&gt;
&lt;br /&gt;
In short, this metadata file lists a set of dependencies to include, what their maven coordinate is, the accepted version range that your mod supports, the version of the dependency that is included in your mods jar as well as a path to the jar in your mods jar file.&lt;br /&gt;
&lt;br /&gt;
During the startup of the game, FML will first collect all mods and then collect all their dependencies to load. Jar-In-Jar hooks into this second phase and reads all the dependency files (recursively) and then determines what versions of the dependencies to load. &lt;br /&gt;
====Dependency negotiation====&lt;br /&gt;
Because different mods might need different versions of the same dependency (and have those included) Jar-In-Jar is first and foremost a negotiation system (hence you having to supply a version range your mod supports). From all dependencies that need to be loaded their supported version range is narrowed down to the agreeable range that all mods support. Then there are in principle three outcomes that can occur:&lt;br /&gt;
# No agreeable version range is found: Loading can not continue and the user will see an error message that mods require different dependency versions which are not compatible.&lt;br /&gt;
# An agreeable version range is found, but no jar was included in any of the dependencies which have a version that fits in the agreed range: Loading can not continue and the user will see an error message that the mods have agreed upon a supported range, but no file was found with the required version.&lt;br /&gt;
# An agreeable version range is found, and a matching jar could be located: That dependency will be loaded.&lt;br /&gt;
&lt;br /&gt;
====Dependency loading====&lt;br /&gt;
Once negotiation ends, the selected jars are loaded into the game.&lt;br /&gt;
The class loading layer is determined in two ways:&lt;br /&gt;
# The default way: If a mod, plugin, or language loader is detected then it is loaded in the appropriate layer and processed as such.&lt;br /&gt;
# The override way: If a library is supposed to be loaded which is not aware of Minecraft (for example JGraphT) then it will be loaded as a game library only. Meaning that your mod has access to it, but not plugins or language loaders. Those as such can only use libraries that are Minecraft aware or Shaded instead of Jar-In-Jarred into their respective jar.&lt;br /&gt;
&lt;br /&gt;
=== Using ForgeGradle to generate a Jar-In-Jar ===&lt;br /&gt;
Jar-In-Jar is a completely optional system.&lt;br /&gt;
To enable it, you need to call `jarJar.enable()` anywhere in your buildscript.&lt;br /&gt;
By default, this will include all the dependencies in the `jarjar` configuration into the task output of the `jarJar` task.&lt;br /&gt;
''Note: The task jarJar is not accessible via the `jarJar` statement, since this references the project extension to manage Jar-In-Jar. If you need to modify the task use: `tasks.jarJar.configure { ... } `''&lt;br /&gt;
&lt;br /&gt;
==== Using the runtime dependencies ====&lt;br /&gt;
To include the runtime dependencies as well, you can invoke `jarJar.fromRuntimeConfiguration()` which will include the dependencies which are found at the runtime. If you use this, it is highly suggested to include a dependency filter, since else every single dependency, including Minecraft, forge, and their dependencies are included as well.&lt;br /&gt;
&lt;br /&gt;
==== Using dependency filters ====&lt;br /&gt;
While you can filter the dependencies by including them in the `jarJar` configuration or not, this is not always as flexible as you need it to be. To achieve fine grain filtering the dependency configuration endpoint has been added to the `jarJar` extension as well as to the `jarJar` task. &lt;br /&gt;
Using this endpoint you can configure dependency patterns (including using regular expressions) which you can include and exclude from the configuration:&lt;br /&gt;
&lt;br /&gt;
===== Exclude gson example =====&lt;br /&gt;
 dependencies {&lt;br /&gt;
     exclude(dependency('com.google.gson.*')) &lt;br /&gt;
 }&lt;br /&gt;
This example excludes any dependency which has `com.google.gson.` as a prefix of the group name of that artifact.&lt;br /&gt;
&lt;br /&gt;
===== Include filters with runtime configuration usage =====&lt;br /&gt;
It is generally recommended to set at least one `include` filter when using the `fromRuntimeConfiguration` option.&lt;br /&gt;
&lt;br /&gt;
==== Dependency version pinning ====&lt;br /&gt;
Since Jar-In-Jar is first and foremost a negotiation system it is required that you provide a way to supply it with a supported range, by default this is done via the version property of your dependency:&lt;br /&gt;
 dependencies {&lt;br /&gt;
    jarJar(group: 'com.google.code.gson', name: 'gson', version: '[2.0,3.0)')&lt;br /&gt;
 }&lt;br /&gt;
However, this might not produce the required result or even the required artifact you wish to include (by default the highest supported version is included based on Gradle dependency resolution rules).&lt;br /&gt;
Using dependency version pinning you can specify which version of the dependency Jar-In-Jar should include when the jar is made. To achieve this configure the dependency and invoke: `jarJar.pin(&amp;lt;dependency instance&amp;gt;, &amp;quot;version_string&amp;quot;)` as follows:&lt;br /&gt;
 dependencies {&lt;br /&gt;
    implementation(group: 'com.google.code.gson', name: 'gson', version: '[2.0,3.0)') {&lt;br /&gt;
        jarJar.pin(it, &amp;quot;2.8.0&amp;quot;)&lt;br /&gt;
    }&lt;br /&gt;
 }&lt;br /&gt;
The example above will include version 2.8.0 of the GSON library into the Jar-In-Jar jar built by the `jarJar` task.&lt;br /&gt;
&lt;br /&gt;
==== Dependency range pinning ====&lt;br /&gt;
Next to dependency version pinning Jar-In-Jar also supports pinning the version range which your mod supports, outside of the compile dependency range that you specify in the dependency statement:&lt;br /&gt;
 dependencies {&lt;br /&gt;
    implementation(group: 'com.google.code.gson', name: 'gson', version: '2.8.0') {&lt;br /&gt;
        jarJar.ranged(it, &amp;quot;[2.0,3.0)&amp;quot;)&lt;br /&gt;
    }&lt;br /&gt;
 }&lt;br /&gt;
As you can see this function is very useful when you combine it with runtime configuration-based dependency selection since it allows you to use a single statement to add the dependency to your project, as well as include it with a properly supported version range within your Jar-In-Jar jar.&lt;br /&gt;
&lt;br /&gt;
==== Publishing a Jar-in-Jar jar to maven ====&lt;br /&gt;
Although in practice this is not really useful to do, for archival reasons FG supports publishing Jar-In-Jar artifacts to a maven of choice. The setup is similar to how the Shadow plugin handles this:&lt;br /&gt;
 publications {&lt;br /&gt;
     mavenJava(MavenPublication) {&lt;br /&gt;
         from components.java&lt;br /&gt;
         jarJar.component(it)&lt;br /&gt;
  &lt;br /&gt;
         //Other statements related to configuring the POM go here&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
Using this technique will add all Jar-In-Jar you build in the project to the publication at once and publish them with the other artifacts.&lt;br /&gt;
If you want to only publish a specific Jar-In-Jar artifact to this publication use the following statement, which accepts a task instance to achieve this:&lt;br /&gt;
 publications {&lt;br /&gt;
     mavenJava(MavenPublication) {&lt;br /&gt;
         from components.java&lt;br /&gt;
         jarJar.component(it, tasks.jarJarOther)&lt;br /&gt;
  &lt;br /&gt;
         //Other statements related to configuring the POM go here&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;/div&gt;</summary>
		<author><name>SciWhiz12</name></author>
	</entry>
	<entry>
		<id>https://forge.gemwire.uk/index.php?title=Events&amp;diff=3118</id>
		<title>Events</title>
		<link rel="alternate" type="text/html" href="https://forge.gemwire.uk/index.php?title=Events&amp;diff=3118"/>
		<updated>2022-01-15T12:12:38Z</updated>

		<summary type="html">&lt;p&gt;SciWhiz12: /* Generic Events */ note wildcard only applies to EventBus#register&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. If an event listener is registered using &amp;lt;code&amp;gt;EventBus#register(Object)&amp;lt;/code&amp;gt;, it 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;RenderLevelLastEvent&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(RenderLevelLastEvent 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;RenderLevelLastEvent&amp;lt;/code&amp;gt; - Fired after level 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;FOVModifierEvent&amp;lt;/code&amp;gt; - Fired when the FOV of the player is requested (?)&lt;br /&gt;
** '''Screen events''' ('''client-only''')&lt;br /&gt;
*** &amp;lt;code&amp;gt;ScreenEvent&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;ScreenContainerEvent&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;ScreenOpenEvent&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 level&lt;br /&gt;
*** &amp;lt;code&amp;gt;LevelEvent&amp;lt;/code&amp;gt; - Superclass for events relating to the level&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 level&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;ClientPlayerChangeGameTypeEvent&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>SciWhiz12</name></author>
	</entry>
	<entry>
		<id>https://forge.gemwire.uk/index.php?title=Access_Transformers&amp;diff=3104</id>
		<title>Access Transformers</title>
		<link rel="alternate" type="text/html" href="https://forge.gemwire.uk/index.php?title=Access_Transformers&amp;diff=3104"/>
		<updated>2021-12-31T23:55:37Z</updated>

		<summary type="html">&lt;p&gt;SciWhiz12: /* Background */ fix link to Encapsulation&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Access transformers''' (abbreviated as ''ATs'') are declarations for modifying or transforming the access visibility or finality of a class member (classes, fields, methods). These declarations are parsed by a transformer and applied to classes using the ASM library, either modifying the class files on-disk or modifying the class bytes during runtime.&lt;br /&gt;
&lt;br /&gt;
The [https://github.com/MinecraftForge/AccessTransformers AccessTransformers] library provides a pluggable ModLauncher transformation service and a command-line application for applying access transformers on class bytes during runtime and on class files on-disk.&lt;br /&gt;
&lt;br /&gt;
== Background ==&lt;br /&gt;
Java provides the mechanism of '''access level modifiers''' (or ''access modifiers''), to modify the ''visibility'' of a member with the modifier to other classes. This is commonly used to hide fields and methods from other classes, such as instance fields for [[:wikipedia:Encapsulation (computer programming)|encapsulation]] or private methods which are part of the implementation of the class and not normally exposed to callers.&lt;br /&gt;
&lt;br /&gt;
A member can be declared with any of the modifier keywords &amp;lt;code&amp;gt;public&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;private&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;protected&amp;lt;/code&amp;gt; to set the access level of the member, or none of the keywords, which defaults to a ''package-private'' access level.&lt;br /&gt;
&lt;br /&gt;
The following table shows the different access levels and their modifiers, and what classes may access members with that access level:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;text-align:center;&amp;quot;&lt;br /&gt;
|+ Access levels&lt;br /&gt;
! Access modifier&lt;br /&gt;
! Within the same class&lt;br /&gt;
! Classes in the same package&lt;br /&gt;
! Subclasses&lt;br /&gt;
! All other classes&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;public&amp;lt;/code&amp;gt;&lt;br /&gt;
| style=&amp;quot;color:limegreen&amp;quot; | '''Yes'''&lt;br /&gt;
| style=&amp;quot;color:limegreen&amp;quot; | '''Yes'''&lt;br /&gt;
| style=&amp;quot;color:limegreen&amp;quot; | '''Yes'''&lt;br /&gt;
| style=&amp;quot;color:limegreen&amp;quot; | '''Yes'''&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;protected&amp;lt;/code&amp;gt;&lt;br /&gt;
| style=&amp;quot;color:limegreen&amp;quot; | '''Yes'''&lt;br /&gt;
| style=&amp;quot;color:limegreen&amp;quot; | '''Yes'''&lt;br /&gt;
| style=&amp;quot;color:limegreen&amp;quot; | '''Yes'''&lt;br /&gt;
| style=&amp;quot;color:indianred&amp;quot; | '''No'''&lt;br /&gt;
|-&lt;br /&gt;
| ''no modifier''&lt;br /&gt;
| style=&amp;quot;color:limegreen&amp;quot; | '''Yes'''&lt;br /&gt;
| style=&amp;quot;color:limegreen&amp;quot; | '''Yes'''&lt;br /&gt;
| style=&amp;quot;color:indianred&amp;quot; | '''No'''&lt;br /&gt;
| style=&amp;quot;color:indianred&amp;quot; | '''No'''&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;private&amp;lt;/code&amp;gt;&lt;br /&gt;
| style=&amp;quot;color:limegreen&amp;quot; | '''Yes'''&lt;br /&gt;
| style=&amp;quot;color:indianred&amp;quot; | '''No'''&lt;br /&gt;
| style=&amp;quot;color:indianred&amp;quot; | '''No'''&lt;br /&gt;
| style=&amp;quot;color:indianred&amp;quot; | '''No'''&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
For example, a field marked &amp;lt;code&amp;gt;protected&amp;lt;/code&amp;gt; cannot be accessed by a class in another package, but can be accessed by: any class within the same package, any subclass of the class (even if the subclass belongs to another package), and within the same class where the field is declared.&lt;br /&gt;
&lt;br /&gt;
Additionally to the access modifiers, there exists the &amp;lt;code&amp;gt;final&amp;lt;/code&amp;gt; keyword, which:&lt;br /&gt;
* on classes, prevents any subclassing of the class;&lt;br /&gt;
* on fields, marks it as being assignable only once during construction; and&lt;br /&gt;
* on methods, prevents any subclasses from overriding the method with their own implementation.&lt;br /&gt;
&lt;br /&gt;
Normally, Java programmers restrict access levels to be as restrictive as they need to be, controlling what is the effective publicly-available surface for the application. For example, a field may be declared as &amp;lt;code&amp;gt;private&amp;lt;/code&amp;gt; while providing setter and getter methods to access the field (a technique known as encapsulation).&lt;br /&gt;
&lt;br /&gt;
However, this convention of restricting access levels and marking members as &amp;lt;code&amp;gt;final&amp;lt;/code&amp;gt; where approriate presents a problem with modding Minecraft, because they restrict what parts of the game that modders can access or modify, usually without other means to access or modify them (such as setters and getters for fields).&lt;br /&gt;
&lt;br /&gt;
One solution is to use Java [[:wikipedia:reflection|reflection]] to reflectively access these fields and methods during runtime, but they suffer from some problems:&lt;br /&gt;
* Reflection is slower than regular method calls or field accesses, as certain optimizations done by the JVM cannot be applied.&amp;lt;ref&amp;gt;[https://docs.oracle.com/javase/tutorial/reflect/index.html The Java™ Tutorials: The Reflection API]: ''&amp;quot;Consequently, reflective operations have slower performance than their non-reflective counterparts, and should be avoided in sections of code which are called frequently in performance-sensitive applications.&amp;quot;''&amp;lt;/ref&amp;gt; This makes reflection unsuitable for performance-critical code, such as during rendering.&lt;br /&gt;
* Reflection cannot allow the modification of &amp;lt;code&amp;gt;final&amp;lt;/code&amp;gt; fields which are either marked &amp;lt;code&amp;gt;static&amp;lt;/code&amp;gt; or belong to a record class.&amp;lt;ref&amp;gt;[https://docs.oracle.com/en/java/javase/16/docs/api/java.base/java/lang/reflect/AccessibleObject.html#setAccessible(boolean) Java 16 javadocs] for &amp;lt;code&amp;gt;java.lang.reflect.AccessibleObject.setAccessible(boolean)&amp;lt;/code&amp;gt;&amp;lt;/ref&amp;gt;&lt;br /&gt;
* Runtime reflection loses the benefit of compile-time type checks, which allows dangerous operations such as trying to set a field's value to an incompatible type.&lt;br /&gt;
* The use of reflection does not allow a class to extend a non-visible class.&lt;br /&gt;
&lt;br /&gt;
These problems are solved with the use of access transformers, which allow modification of the access modifiers of members such that they can be applied on class files on-disk to allow compiling against them, and applying the same transformer declarations on class bytes during runtime to allow classes which compiled against those transformed classes to work correctly.&lt;br /&gt;
&lt;br /&gt;
== Usage ==&lt;br /&gt;
&lt;br /&gt;
To use access transformers in the development environment, ForgeGradle must be configured with the location of the access transformer configuration file (or files). Because FML is hardwired to look for the configuration file at &amp;lt;code&amp;gt;META-INF/accesstransformer.cfg&amp;lt;/code&amp;gt; within JAR files, it is recommended that the AT configuration file for the project be placed at the same location: within the resources folder of the main source set, or &amp;lt;code&amp;gt;src/main/resources/META-INF/accesstransformer.cfg&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
To configure the location of the access transformer configuration file with ForgeGradle:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;gradle&amp;quot;&amp;gt;&lt;br /&gt;
minecraft { // Within the minecraft block&lt;br /&gt;
    // Configures FG to look at the given file path for the AT configuration file&lt;br /&gt;
    accessTransformer = file(&amp;quot;src/main/resources/META-INF/accesstransformer.cfg&amp;quot;)&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Access-transformers-uncomment-this-line-in-build-gradle.png|thumb|300px]]&lt;br /&gt;
&lt;br /&gt;
The Forge-provided mod development environment's buildscript contains the above line but commented out, as the MDK does not ship with an access transformer file. Users of the MDK can therefore uncomment out the above line and create the AT configuration file at the same location. &lt;br /&gt;
&lt;br /&gt;
Once the configuration file(s) has been added and everytime the contents or location of the file(s) changes, the developer should then refresh the Gradle nature/project in their IDE of choice for ForgeGradle to apply the access transformers to the compiled source. Each change to the access transformer configuration will trigger a full decompilation of the game.&lt;br /&gt;
&lt;br /&gt;
== Declarations ==&lt;br /&gt;
&lt;br /&gt;
Access transformers are declared line-by-line in configuration files, which are then parsed by ForgeGradle in the development environment and by FML in the production or end-user environment.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;#&amp;lt;/code&amp;gt; character and any content after that up to the end of the line is considered a comment, and will be ignored by the parser. Any lines which are either empty or consist of only whitespace or comments are ignored.&lt;br /&gt;
&lt;br /&gt;
An access transformer declaration has three different variations, depending on the target to be transformed:&lt;br /&gt;
&lt;br /&gt;
* for '''classes''': &amp;lt;code&amp;gt;''&amp;lt;modifier&amp;gt;'' ''&amp;lt;class name&amp;gt;''&amp;lt;/code&amp;gt;&lt;br /&gt;
* for '''methods''': &amp;lt;code&amp;gt;''&amp;lt;modifier&amp;gt;'' ''&amp;lt;class name&amp;gt;'' ''&amp;lt;method name&amp;gt;'''''('''''[parameter descriptors]''''')'''''&amp;amp;lt;return descriptor&amp;gt;''&amp;lt;/code&amp;gt;&lt;br /&gt;
* for '''fields''': &amp;lt;code&amp;gt;''&amp;lt;modifier&amp;gt;'' ''&amp;lt;class name&amp;gt;'' ''&amp;lt;field name&amp;gt;''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The modifier consists of one of the following words:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;public&amp;lt;/code&amp;gt; for the ''public'' access level (denoted by the modifier keyword of the same name)&lt;br /&gt;
* &amp;lt;code&amp;gt;protected&amp;lt;/code&amp;gt; for the ''protected'' access level (denoted by the modifier keyword of the same name)&lt;br /&gt;
* &amp;lt;code&amp;gt;default&amp;lt;/code&amp;gt; for the ''package-private'' access level (denoted by the absence of an access modifier keyword)&lt;br /&gt;
* &amp;lt;code&amp;gt;private&amp;lt;/code&amp;gt; for the ''private'' access level (denoted by the modifier keyword of the same name)&lt;br /&gt;
* For any of the preceding words, the &amp;lt;code&amp;gt;-f&amp;lt;/code&amp;gt; suffix removes the &amp;lt;code&amp;gt;final&amp;lt;/code&amp;gt; modifier, while the &amp;lt;code&amp;gt;+f&amp;lt;/code&amp;gt; suffix adds the modifier.&lt;br /&gt;
&lt;br /&gt;
The class name is the fully qualified name of the class, using &amp;lt;code&amp;gt;.&amp;lt;/code&amp;gt; (dots) to separate between (sub)packages and classes (for example, &amp;lt;code&amp;gt;java.lang.Object&amp;lt;/code&amp;gt;). &lt;br /&gt;
&lt;br /&gt;
For methods, the method descriptor&amp;lt;ref&amp;gt;''[https://docs.oracle.com/javase/specs/jvms/se16/html/jvms-4.html#jvms-4.3.3 Java Virtual Machine Specification, Java SE 16 Edition]'', 4.3.3. Method Descriptors &amp;lt;/ref&amp;gt; of the method is included, which consists of the descriptors for each of the method's parameters and the method's return type. The method parameters descriptors can be absent if there are no parameters in the method, but the return type descriptor must be present.&lt;br /&gt;
&lt;br /&gt;
The following are the matching descriptors for each type as seen in the method declaration:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ Matching type descriptors&lt;br /&gt;
! Descriptor&lt;br /&gt;
! Source form&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;Z&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;boolean&amp;lt;/code&amp;gt; || a &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;false&amp;lt;/code&amp;gt; value&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;B&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;byte&amp;lt;/code&amp;gt; || a 8-bit signed number&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;S&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;short&amp;lt;/code&amp;gt; || a 16-bit signed number&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;C&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;char&amp;lt;/code&amp;gt; || a Unicode character code point in UTF-16&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;I&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;int&amp;lt;/code&amp;gt; || a 32-bit signed number&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;F&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;float&amp;lt;/code&amp;gt; || a single-precision floating-point value&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;J&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;long&amp;lt;/code&amp;gt; || a 64-bit signed number&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;D&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;double&amp;lt;/code&amp;gt; || a double-precision floating-point value&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;[''I''&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;''int''[]&amp;lt;/code&amp;gt; || one dimension of an array; this can be repeated, and must end with another descriptor other than an array&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;L''java/lang/Object'';&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;java.lang.Object&amp;lt;/code&amp;gt; || a reference type; the internal form of the class' binary name must be present (in the given example, the class referenced is &amp;lt;code&amp;gt;java.lang.Object&amp;lt;/code&amp;gt;). &lt;br /&gt;
Note that inner classes are separated using the &amp;lt;code&amp;gt;$&amp;lt;/code&amp;gt; (dollar sign) character, such as &amp;lt;code&amp;gt;java/lang/System$Logger&amp;lt;/code&amp;gt;.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;V&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;void&amp;lt;/code&amp;gt; || a void or no-value return type; only available for the return type of a method descriptor&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{{Tip/Danger&lt;br /&gt;
|title=Wildcard access transformers&lt;br /&gt;
|A special type of access transformers called '''wildcard ATs''' (oftentimes referred to as '''shotgun ATs''' allows transforming the access modifier and finality of ''all'' fields or methods within a class.&lt;br /&gt;
&lt;br /&gt;
To use wildcard access transformers:&lt;br /&gt;
* for all methods within a class: &amp;lt;code&amp;gt;''&amp;lt;modifier&amp;gt;'' ''&amp;lt;class name&amp;gt;'' '''*()'''&amp;lt;/code&amp;gt;&lt;br /&gt;
* for all fields within a class: &amp;lt;code&amp;gt;''&amp;lt;modifier&amp;gt;'' ''&amp;lt;class name&amp;gt;'' '''*'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Modders should avoid using this in live code.''' Access transformers should always have the fewest and narrowest targets possible, and wildcard ATs violate this convention. Use of wildcard ATs may cause problems with both the ForgeGradle setup process. Wildcard ATs may be removed in a future update of the access transformer specification.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
== Examples ==&lt;br /&gt;
&lt;br /&gt;
The following are some examples of access transformer declarations:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
# Makes public the ScreenConstructor class in MenuScreens&lt;br /&gt;
public net.minecraft.client.gui.screens.MenuScreens$ScreenConstructor&lt;br /&gt;
&lt;br /&gt;
# Makes protected the 'COLOR_WHITE' field in Gui&lt;br /&gt;
protected net.minecraft.client.gui.Gui f_168667_ # COLOR_WHITE&lt;br /&gt;
&lt;br /&gt;
# Makes protected and removes the final modifier from 'random' field in MinecraftServer&lt;br /&gt;
protected-f net.minecraft.server.MinecraftServer f_129758_ # random&lt;br /&gt;
&lt;br /&gt;
# Makes public the 'makeExecutor' method in Util,&lt;br /&gt;
# which accepts a String and returns an ExecutorService&lt;br /&gt;
public net.minecraft.Util m_137477_(Ljava/lang/String;)Ljava/util/concurrent/ExecutorService; # makeExecutor&lt;br /&gt;
&lt;br /&gt;
# Makes public the 'leastMostToIntArray' method in SerializableUUID,&lt;br /&gt;
# which accepts two longs and returns an int[]&lt;br /&gt;
public net.minecraft.core.SerializableUUID m_123274_(JJ)[I # leastMostToIntArray&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>SciWhiz12</name></author>
	</entry>
	<entry>
		<id>https://forge.gemwire.uk/index.php?title=Sides&amp;diff=3103</id>
		<title>Sides</title>
		<link rel="alternate" type="text/html" href="https://forge.gemwire.uk/index.php?title=Sides&amp;diff=3103"/>
		<updated>2021-12-23T01:50:09Z</updated>

		<summary type="html">&lt;p&gt;SciWhiz12: it's now NetworkConstants without the FML prefix&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Under construction}} &amp;lt;!-- modloading process is missing --&amp;gt; &lt;br /&gt;
A very important concept to understand when modding Minecraft are the two sides: '''client''' and '''server'''. There are many, many common misconceptions and mistakes regarding siding, which can lead to bugs that might not crash the game, but can rather have unintended and often unpredictable effects.&lt;br /&gt;
&lt;br /&gt;
== Different Kinds of Sides ==&lt;br /&gt;
&lt;br /&gt;
When we say &amp;quot;client&amp;quot; or &amp;quot;server&amp;quot;, it usually follows with a fairly intuitive understanding of what part of the game we’re talking about. After all, a client is what the user interacts with, and a server is where the user connects for a multiplayer game. Easy, right?&lt;br /&gt;
&lt;br /&gt;
But because of the structure of how Minecraft works, there can be some ambiguity even with two such terms. Here we disambiguate the four possible meanings of &amp;quot;client&amp;quot; and &amp;quot;server&amp;quot;:&lt;br /&gt;
&lt;br /&gt;
* '''Physical Client''' - The ''physical client'' is the entire program that runs whenever you launch Minecraft from the launcher. All threads, processes, and services that run during the game’s graphical, interactable lifetime are part of the physical client.&lt;br /&gt;
* '''Physical Server''' - Often known as the dedicated server, the ''physical server'' is the entire program that runs whenever you launch any dedicated server executable or JAR (&amp;lt;code&amp;gt;minecraft_server.jar&amp;lt;/code&amp;gt;) that does not bring up a playable GUI.&lt;br /&gt;
* '''Logical Server''' - The ''logical server'' is what runs game logic: mob spawning, weather, updating inventories, health, AI, and all other game mechanics. The logical server is present within the physical server, but is also can run inside a physical client together with a logical client, as a single player world. The logical server always runs in a thread named the &amp;lt;code&amp;gt;Server Thread&amp;lt;/code&amp;gt;.&lt;br /&gt;
* '''Logical Client''' - The ''logical client'' is what accepts input from the player and relays it to the logical server. In addition, it also receives information from the logical server and makes it available graphically to the player. The logical client runs in the &amp;lt;code&amp;gt;Render Thread&amp;lt;/code&amp;gt;, though often several other threads are spawned to handle things like audio and chunk render batching.&lt;br /&gt;
&lt;br /&gt;
In the Minecraft codebase, the physical sides are represented by an enum called &amp;lt;code&amp;gt;Dist&amp;lt;/code&amp;gt;, while the logical sides are represented by an enum called &amp;lt;code&amp;gt;LogicalSide&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
{{Tip|It is guaranteed that the logical cient always runs on the physical client; however, the same cannot be said of the logical server.}}&lt;br /&gt;
&lt;br /&gt;
== Performing Side-Specific Operations ==&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;Level#isClientSide&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
This &amp;lt;code&amp;gt;boolean&amp;lt;/code&amp;gt; check is the most common way (and the most recommended way) to check the currently running '''logical side'''. Querying this field on a &amp;lt;code&amp;gt;Level&amp;lt;/code&amp;gt; object establishes the logical side that the level belongs to. That is, if this field is &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt;, the level extends &amp;lt;code&amp;gt;ClientLevel&amp;lt;/code&amp;gt; and is currently running on the logical client, while if the field is &amp;lt;code&amp;gt;false&amp;lt;/code&amp;gt;, the level extends &amp;lt;code&amp;gt;ServerLevel&amp;lt;/code&amp;gt; and is running on the logical server. &lt;br /&gt;
&lt;br /&gt;
It follows that the physical/dedicated server will always contain &amp;lt;code&amp;gt;false&amp;lt;/code&amp;gt; in this field, but we cannot assume that &amp;lt;code&amp;gt;false&amp;lt;/code&amp;gt; implies a physical server, since this field can also be &amp;lt;code&amp;gt;false&amp;lt;/code&amp;gt; for the logical server inside a physical client (in other words, a single player world).&lt;br /&gt;
&lt;br /&gt;
Use this check whenever you need to determine if game logic and other mechanics should be run. For example, if you want to damage the player every time they click your block, or have your machine process dirt into diamonds, you should only do so after ensuring &amp;lt;code&amp;gt;level#isClientSide&amp;lt;/code&amp;gt; is &amp;lt;code&amp;gt;false&amp;lt;/code&amp;gt;. Applying game logic to the logical client can cause desynchronization (ghost entities, desynchronized stats, etc.) in the best case, and crashes in the worst case.&lt;br /&gt;
&lt;br /&gt;
This check should be used as your go-to default. Aside from the sided events and &amp;lt;code&amp;gt;DistExecutor&amp;lt;/code&amp;gt;, rarely will you need the other ways of determining sides and adjusting behavior.&lt;br /&gt;
&lt;br /&gt;
=== Sided Setup Events ===&lt;br /&gt;
&lt;br /&gt;
There are different events which are fired at different stages during the [[Stages_of_Modloading|modloading process]]. Most of these events are fired on both physical sides, except for the '''sided setup events''': &amp;lt;code&amp;gt;FMLClientSetupEvent&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;FMLDedicatedServerSetupEvent&amp;lt;/code&amp;gt;, which is fired on the physical client and the physical/dedicated server respectively.&lt;br /&gt;
&lt;br /&gt;
These events should be used for running side-specific initialization code. It is recommended to either put your sided event handler registration behind a &amp;lt;code&amp;gt;DistExecutor&amp;lt;/code&amp;gt; call, or use the &amp;lt;code&amp;gt;@Mod.EventBusSubscriber&amp;lt;/code&amp;gt; anntoation with '&amp;lt;code&amp;gt;value = Dist.CLIENT&amp;lt;/code&amp;gt; for clients (or &amp;lt;code&amp;gt;value = Dist.DEDICATED_SERVER&amp;lt;/code&amp;gt; for the dedicated server) to conditionally register your event handlers and prevent the classes referenced within from crashing upon being loaded.&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;DistExecutor&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
Considering the use of a single &amp;quot;universal&amp;quot; jar for client and server mods, and the separation of the physical sides into two jars, an important question comes to mind: How do we use code that is only present on one physical side? All code in &amp;lt;code&amp;gt;net.minecraft.client&amp;lt;/code&amp;gt; (such as anything rendering-related) is only present on the physical client, and all code in &amp;lt;code&amp;gt;net.minecraft.server.dedicated&amp;lt;/code&amp;gt; is only present on the physical server. &lt;br /&gt;
&lt;br /&gt;
If any class you write references those names in any way, they will crash the game when that respective class is loaded in an environment where those names do not exist. For example, a very common mistake in beginners is to call &amp;lt;code&amp;gt;Minecraft.getMinecraft().&amp;lt;doStuff&amp;gt;()&amp;lt;/code&amp;gt; in block or block entity classes, which will crash any physical/dedicated server as soon as the class is loaded.&lt;br /&gt;
&lt;br /&gt;
How do we resolve this? Forge provides the &amp;lt;code&amp;gt;DistExecutor&amp;lt;/code&amp;gt; utility class, which provides various methods to run and call different code depending on the physical side. There are two versions of each method: &amp;lt;code&amp;gt;safe*&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;unsafe&amp;lt;/code&amp;gt;. &amp;lt;code&amp;gt;safe*&amp;lt;/code&amp;gt; methods accept a supplied method reference from another class; otherwise, an error will be thrown. &amp;lt;code&amp;gt;unsafe*&amp;lt;/code&amp;gt; methods accept a doubly supplied instance instead. &amp;lt;code&amp;gt;unsafe*&amp;lt;/code&amp;gt; methods could cause &amp;lt;code&amp;gt;ClassNotFoundException&amp;lt;/code&amp;gt;s depending on how they are used, though in standard cases referencing an external class within the double supplier should be safe. In any case, make sure you understand how the [https://docs.oracle.com/javase/specs/jvms/se16/html/jvms-5.html#jvms-5.4.1 class verifier] works to load classes before using this.&lt;br /&gt;
&lt;br /&gt;
{{Tip/Important|&lt;br /&gt;
It is important to understand that &amp;lt;code&amp;gt;DistExecutor&amp;lt;/code&amp;gt; checks the '''physical''' side. A single player world (logical server + logical client within a physical client) will always use &amp;lt;code&amp;gt;Dist.CLIENT&amp;lt;/code&amp;gt;!}}&lt;br /&gt;
&lt;br /&gt;
=== Thread Groups ===&lt;br /&gt;
&lt;br /&gt;
If &amp;lt;code&amp;gt;Thread.currentThread().getThreadGroup() == SidedThreadGroups.SERVER&amp;lt;/code&amp;gt;, it is likely the current thread is on the logical server. Otherwise, it is likely on the logical client. This is useful to retrieve the '''logical''' side when you do not have access to a &amp;lt;code&amp;gt;Level&amp;lt;/code&amp;gt; object to check &amp;lt;code&amp;gt;isClientSide&amp;lt;/code&amp;gt;. It ''guesses'' which logical side you are on by looking at the thread group of the currently running thread. Because it is a guess, this method should only be used when other options have been exhausted. In all other cases, you should prefer checking &amp;lt;code&amp;gt;level#isClientSide&amp;lt;/code&amp;gt; to this check.&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;FMLEnvironment.dist&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;FMLEnvironment.dist&amp;lt;/code&amp;gt; holds the '''physical''' side your code is running on, as a value of &amp;lt;code&amp;gt;Dist.CLIENT&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;Dist.DEDICATED_SERVER&amp;lt;/code&amp;gt;. This is determined by the mod loading code, so it always hold the correct value. However, there is little reason to directly query this variable, as most use-cases can use &amp;lt;code&amp;gt;DistExecutor&amp;lt;/code&amp;gt; instead (which uses this value internally).&lt;br /&gt;
&lt;br /&gt;
== &amp;lt;tt&amp;gt;@OnlyIn&amp;lt;/tt&amp;gt; ==&lt;br /&gt;
&lt;br /&gt;
Annotating a method or field with the &amp;lt;code&amp;gt;@OnlyIn(Dist)&amp;lt;/code&amp;gt; annotation indicates to the loader that the respective member should be completely stripped out of the definition not on the specified '''physical''' side. Usually, these are only seen when browsing through the decompiled Minecraft code, indicating methods that the Mojang obfuscator stripped out. &lt;br /&gt;
&lt;br /&gt;
{{Tip/Important|There is '''NO''' reason for using this annotation directly. Use &amp;lt;code&amp;gt;DistExecutor&amp;lt;/code&amp;gt; or a check on &amp;lt;code&amp;gt;FMLEnvironment.dist&amp;lt;/code&amp;gt; instead.}}&lt;br /&gt;
&lt;br /&gt;
== Common Mistakes ==&lt;br /&gt;
&lt;br /&gt;
=== Reaching Across Logical Sides ===&lt;br /&gt;
&lt;br /&gt;
Whenever you want to send information from one logical side to another, you must '''always''' use [[SimpleChannel|network packets]]. It is incredibly tempting, when in a single player scenario, to directly transfer data from the logical server to the logical client.&lt;br /&gt;
&lt;br /&gt;
This is actually very commonly inadvertently done through static fields. Since the logical client and logical server share the same JVM instance in a single player scenario, both threads writing to and reading from static fields will cause all sorts of race conditions and classical issues associated with threading.&lt;br /&gt;
&lt;br /&gt;
This mistake can also be made explicitly by accessing physical client-only classes such as &amp;lt;code&amp;gt;Minecraft&amp;lt;/code&amp;gt; from common code that runs or can run on the logical server. This mistake is easy to miss for beginners, who debug in a physical client. The code will work there, but will immediately crash on a physical server. For this reason, it is always recommended to test your mod with the physical/dedicated server.&lt;br /&gt;
&lt;br /&gt;
===Writing One-Sided Mods===&lt;br /&gt;
Your mods are expected to always load, regardless of if they are loaded on the client or the server. For one-sided mods, this means that they must still run on the opposite physical side.&lt;br /&gt;
&lt;br /&gt;
So for one-sided mods, you would typically register your event handlers using [[#DistExecutor|&amp;lt;code&amp;gt;DistExecutor&amp;lt;/code&amp;gt;]] or &amp;lt;code&amp;gt;@EventBusSubscriber(value = Dist.*)&amp;lt;/code&amp;gt;, instead of directly calling the relevant registration methods in the constructor. The idea is that, if your mod is loaded on the wrong side, it should simply do nothing: listen to no events, do no special behaviors, and so on. A one-sided mod by nature should not register blocks, items, … since they would need to be available on the other side, too.&lt;br /&gt;
&lt;br /&gt;
Additionally, if your mod is one-sided, it typically does not forbid the user from joining a server that is lacking that mod, but the server menu will display the server as being incompatible (with a red &amp;lt;code&amp;gt;X&amp;lt;/code&amp;gt; at the side). Therefore, you should register an &amp;lt;code&amp;gt;IExtensionPoint$DisplayTest&amp;lt;/code&amp;gt; extension point to make sure that Forge does not think your mod is required on the server: (this is usually done in the mod constructor)&lt;br /&gt;
&lt;br /&gt;
{{Template:Tabs/Code_Snippets&lt;br /&gt;
|java=// Make sure the mod being absent on the other network side does not cause the client to display the server as incompatible&lt;br /&gt;
ModLoadingContext.get().registerExtensionPoint(IExtensionPoint.DisplayTest.class, () -&amp;gt; new IExtensionPoint.DisplayTest(() -&amp;gt; NetworkConstants.IGNORESERVERONLY, (a, b) -&amp;gt; true));&lt;br /&gt;
|kotlin=// Make sure the mod being absent on the other network side does not cause the client to display the server as incompatible&lt;br /&gt;
ModLoadingContext.get().registerExtensionPoint(IExtensionPoint.DisplayTest.class) { IExtensionPoint.DisplayTest(Supplier { NetworkConstants.IGNORESERVERONLY }, BiPredicate { _: String, _: Boolean -&amp;gt; true }) }&lt;br /&gt;
|scala=import scala.compat.java8.FunctionConverters._&lt;br /&gt;
// Make sure the mod being absent on the other network side does not cause the client to display the server as incompatible&lt;br /&gt;
ModLoadingContext.get.registerExtensionPoint(IExtensionPoint.DisplayTest.class, (() =&amp;gt; new IExtensionPoint.DisplayTest((() =&amp;gt; NetworkConstants.IGNORESERVERONLY).asJava, asJavaBiPredicate((_: String, _: java.lang.Boolean) =&amp;gt; true))).asJava)&lt;br /&gt;
|}}&lt;br /&gt;
&lt;br /&gt;
This tells the client that it should ignore the server version being absent, and tells the server that it should not tell the client this mod should be present.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Common Concepts]]&lt;/div&gt;</summary>
		<author><name>SciWhiz12</name></author>
	</entry>
	<entry>
		<id>https://forge.gemwire.uk/index.php?title=Tags&amp;diff=3102</id>
		<title>Tags</title>
		<link rel="alternate" type="text/html" href="https://forge.gemwire.uk/index.php?title=Tags&amp;diff=3102"/>
		<updated>2021-12-18T12:25:06Z</updated>

		<summary type="html">&lt;p&gt;SciWhiz12: /* Using Tags In Code */ use tip template instead of custom colored box template&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Tags are generalized sets of objects in the game, used for grouping related things together and providing fast membership checks.&lt;br /&gt;
&lt;br /&gt;
== Declaring Your Own Groupings ==&lt;br /&gt;
Tags are declared in your mod’s [https://mcforge.readthedocs.io/en/latest/utilities/tags/datapacks.md datapack]. For example, &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;/data/modid/tags/blocks/foo/tagname.json&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt; will declare a &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;Tag$Named&amp;lt;Block&amp;gt;&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt; with ID &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;modid:foo/tagname&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;. Similarly, you may append to or override tags declared in other domains, such as Vanilla, by declaring your own JSONs. For example, to add your own mod’s saplings to the Vanilla sapling tag, you would specify it in &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;/data/minecraft/tags/blocks/saplings.json&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;, and Vanilla will merge everything into one tag at reload, if the &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;replace&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt; option is false. If &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;replace&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt; is true, then all entries before the json specifying &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;replace&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt; will be removed. See the [https://minecraft.gamepedia.com/Tag#JSON_format Vanilla wiki] for a description of the base syntax.&lt;br /&gt;
&lt;br /&gt;
Forge provides two extensions on the Vanilla syntax: * You may declare an &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;optional&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt; array of the same format as the &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;values&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt; array, but any values listed here that are not present will not cause the tag loading to error. This is useful to provide integration for mods that may or may not be present at runtime. &lt;br /&gt;
* You may declare a &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;remove&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt; array of the same format as the &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;values&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt; array. Any values listed here will be removed from the tag. This acts as a finer grained version of the Vanilla &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;replace&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt; option.&lt;br /&gt;
&lt;br /&gt;
==Using Tags In Code==&lt;br /&gt;
Block, Item, and Fluid tags are automatically sent from the server to any remote clients on login and reload. Function tags are not synced.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;BlockTags#getAllTags&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;ItemTags#getAllTags()&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt; will retrieve the current &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;TagCollection&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;, from which you can retrieve a &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;Tag&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt; object by its ID. With a &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;Tag&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt; object in hand, membership can be tested with &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;tag.contains(thing)&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;, or all the objects in the tag queried with &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;tag.getAllElements()&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
As an example: &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
public static final Tag.Named&amp;lt;Item&amp;gt; myTag = ItemTags.bind(&amp;quot;mymod:myitemgroup&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
// In some method&lt;br /&gt;
Item unknownItem = stack.getItem();&lt;br /&gt;
boolean isInGroup = unknownItem.is(myTag);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Tip|The &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;TagCollection&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt; returned by &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;#getAllTags&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt; (and the &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;Tag&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;s within it) may expire if a reload happens, so you should always query the collection anew every time you need it. The static &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;Tag$Named&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt; fields in &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;BlockTags&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;ItemTags&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt; avoid this by introducing a wrapper that handles this expiring. Alternatively, a resource reload listener can be used to refresh any cached tags.}}&lt;br /&gt;
&lt;br /&gt;
== Conventions ==&lt;br /&gt;
&lt;br /&gt;
There are several conventions that will help facilitate compatibility in the ecosystem: &lt;br /&gt;
   * If there is a Vanilla tag that fits your block or item, add it to that tag. See the [https://minecraft.gamepedia.com/Tag#List_of_tags list of Vanilla tags]. &lt;br /&gt;
   * If there is a Forge tag that fits your block or item, add it to that tag. The list of tags declared by Forge can be seen on [https://github.com/MinecraftForge/MinecraftForge/tree/1.16.x/src/generated/resources/data/forge/tags GitHub]. &lt;br /&gt;
   * If there is a group of something you feel should be shared by the community, consider PR-ing it to Forge instead of making your own tag &lt;br /&gt;
   * Tag naming conventions should follow Vanilla conventions. In particular, item and block groupings are plural instead of singular. E.g. &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;minecraft:logs&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;minecraft:saplings&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;. &lt;br /&gt;
   * Item tags should be sorted into subdirectories according to the type of item, e.g. &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;forge:ingots/iron&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;forge:nuggets/brass&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;, etc.&lt;br /&gt;
&lt;br /&gt;
== Migration from OreDictionary ==&lt;br /&gt;
* For recipes, tags can be used directly in the vanilla recipe format (see below)&lt;br /&gt;
* For matching items in code, see the section above.&lt;br /&gt;
* If you are declaring a new type of item grouping, follow a couple naming conventions:&lt;br /&gt;
** Use &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;domain:type/material&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;. When the name is a common one that all modders should adopt, use the &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;forge&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt; domain.&lt;br /&gt;
** For example, brass ingots should be registered under the &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;forge:ingots/brass&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt; tag, and cobalt nuggets under the &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;forge:nuggets/cobalt&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt; tag.&lt;br /&gt;
&lt;br /&gt;
== Using Tags in Recipes and Advancements  ==&lt;br /&gt;
Tags are directly supported by Vanilla, see the respective Vanilla wiki pages for [https://minecraft.gamepedia.com/Recipe#JSON_format recipes] and [https://minecraft.gamepedia.com/Advancements advancements] for usage details.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Resources and Data]]&lt;/div&gt;</summary>
		<author><name>SciWhiz12</name></author>
	</entry>
	<entry>
		<id>https://forge.gemwire.uk/index.php?title=Capability&amp;diff=2980</id>
		<title>Capability</title>
		<link rel="alternate" type="text/html" href="https://forge.gemwire.uk/index.php?title=Capability&amp;diff=2980"/>
		<updated>2021-11-18T15:34:56Z</updated>

		<summary type="html">&lt;p&gt;SciWhiz12: redirect to Capabilities&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;#REDIRECT [[Capabilities]]&lt;/div&gt;</summary>
		<author><name>SciWhiz12</name></author>
	</entry>
	<entry>
		<id>https://forge.gemwire.uk/index.php?title=Configs&amp;diff=2974</id>
		<title>Configs</title>
		<link rel="alternate" type="text/html" href="https://forge.gemwire.uk/index.php?title=Configs&amp;diff=2974"/>
		<updated>2021-11-17T15:05:43Z</updated>

		<summary type="html">&lt;p&gt;SciWhiz12: change from markdown to mediawiki syntax, and mark as under construction&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Under construction}}&lt;br /&gt;
&lt;br /&gt;
Creating configs in Forge is fairly simple as Forge provides a ton of tools for configs. In addition, Forge will automatically update their values as the config files are edited and cache the values so you do not need to do so.&lt;br /&gt;
&lt;br /&gt;
To begin, create a new class file and add this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;gt;&lt;br /&gt;
public static final ForgeConfigSpec GENERAL_SPEC;&lt;br /&gt;
    &lt;br /&gt;
static {&lt;br /&gt;
    ForgeConfigSpec.Builder configBuilder = new ForgeConfigSpec.Builder();&lt;br /&gt;
    setupConfig(configBuilder);&lt;br /&gt;
    GENERAL_SPEC = configBuilder.build();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
private static void setupConfig(ForgeConfigSpec.Builder builder) { &lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
ForgeConfigSpec is what will ultimately hold all the data and info about how to make and read your config file. We will be registering this later. In the static block, this will create the builder for ForgeConfigSpec, pass it into setupConfig where we will add all the config entries we want, and then we build the final ForgeConfigSpec to store into GENERAL_SPEC.&lt;br /&gt;
 &lt;br /&gt;
Now for creating config entries, lets add an integer config entry by creating a public static field for it and use builder.defineInRange to define it. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;gt;&lt;br /&gt;
public static ForgeConfigSpec.IntValue exampleIntConfigEntry;&lt;br /&gt;
&lt;br /&gt;
private static void setupConfig(ForgeConfigSpec.Builder builder) {&lt;br /&gt;
    exampleIntConfigEntry = builder.defineInRange(&amp;quot;example_int_config_entry&amp;quot;, 5, 2, 50);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here, setupConfig method will add to the builder that there should be a &amp;quot;example_int_config_entry&amp;quot; entry in the toml file, it has a default value of 5, and will only accept a user-entered value between 2 and 50. The it assigns that resultant ForgeConfigSpec.DoubleValue to the exampleIntConfigEntry field. Now the exampleIntConfigEntry field can be call with &amp;lt;code&amp;gt;.get()&amp;lt;/code&amp;gt; anywhere in our code to get the current config value for that config entry at the time.&lt;br /&gt;
&lt;br /&gt;
There are many kinds of config entries you can make. Some of the more commonly used ones are:&lt;br /&gt;
* ForgeConfigSpec.IntValue - uses defineInRange&lt;br /&gt;
* ForgeConfigSpec.DoubleValue - uses defineInRange&lt;br /&gt;
* ForgeConfigSpec.LongValue - uses defineInRange&lt;br /&gt;
* ForgeConfigSpec.BooleanValue - uses define&lt;br /&gt;
* ForgeConfigSpec.ConfigValue&amp;lt;String&amp;gt; - uses define&lt;br /&gt;
* ForgeConfigSpec.ConfigValue&amp;lt;List&amp;lt;? extends String&amp;gt;&amp;gt; - uses defineList ('''IMPORTANT''', do not use .define for lists. Always .defineList)&lt;br /&gt;
&lt;br /&gt;
As for the methods you can use for each of these config types:&lt;br /&gt;
* .define - takes the default config value.&lt;br /&gt;
* .defineInRange - takes the default, the minimum, and maximum config values in that order.&lt;br /&gt;
* .defineList - takes the default list to use and a validator to run on each list entry when the user tries * to change the config file to make sure it is correctly edited by user.&lt;br /&gt;
&lt;br /&gt;
Furthermore, you may attach a comment or translation key to your builder that is creating the config entries. And using &amp;lt;code&amp;gt;builder.push(&amp;quot;...&amp;quot;)&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;builder.pop();&amp;lt;/code&amp;gt; before and after some config entries will put them into a category (comments can be attached to categories as well). Here is a large example of all this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
public static ForgeConfigSpec.IntValue exampleIntConfigEntry;&lt;br /&gt;
public static ForgeConfigSpec.DoubleValue exampleDoubleConfigEntry;&lt;br /&gt;
public static ForgeConfigSpec.ConfigValue&amp;lt;Double&amp;gt; exampleUnboundedDoubleConfigEntry;&lt;br /&gt;
public static ForgeConfigSpec.LongValue exampleLongConfigEntry;&lt;br /&gt;
public static ForgeConfigSpec.BooleanValue exampleBooleanConfigEntry;&lt;br /&gt;
public static ForgeConfigSpec.ConfigValue&amp;lt;String&amp;gt; exampleStringConfigEntry;&lt;br /&gt;
public static ForgeConfigSpec.ConfigValue&amp;lt;List&amp;lt;? extends String&amp;gt;&amp;gt; exampleStringListConfigEntry;&lt;br /&gt;
&lt;br /&gt;
private static void setupConfig(ForgeConfigSpec.Builder builder) {&lt;br /&gt;
    builder.comment(&amp;quot; This category holds configs that uses numbers.&amp;quot;)&lt;br /&gt;
    builder.push(&amp;quot;Numeric Config Options&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
      exampleIntConfigEntry = builder.defineInRange(&amp;quot;example_int_config_entry&amp;quot;, 5, 2, 50);&lt;br /&gt;
      exampleDoubleConfigEntry = builder.defineInRange(&amp;quot;example_double_config_entry&amp;quot;, 10D, 0D, 100D);&lt;br /&gt;
&lt;br /&gt;
      exampleUnboundedDoubleConfigEntry = builder&lt;br /&gt;
         .comment(&amp;quot;This comment will be attached to example_unbounded_double_config_entry in the config file.&amp;quot;)&lt;br /&gt;
         .define(&amp;quot;example_unbounded_double_config_entry&amp;quot;, 1000D);&lt;br /&gt;
&lt;br /&gt;
      exampleLongConfigEntry = builder.defineInRange(&amp;quot;example_long_config_entry&amp;quot;, 4L, -900L, 900L);&lt;br /&gt;
&lt;br /&gt;
    builder.pop();&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
    builder.comment(&amp;quot; This category holds configs that uses numbers.&amp;quot;)&lt;br /&gt;
    builder.push(&amp;quot;String Config Options&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
      exampleStringConfigEntry = builder&lt;br /&gt;
         .comment(&amp;quot;This config holds a single string.&amp;quot;)&lt;br /&gt;
         .define(&amp;quot;example_string_config_entry&amp;quot;, &amp;quot;player444&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
      builder.comment(&amp;quot; This category will be nested inside the String Config Options category.&amp;quot;)&lt;br /&gt;
      builder.push(&amp;quot;Nested Category&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
        exampleStringListConfigEntry = builder&lt;br /&gt;
          .comment(&amp;quot;This config entry will hold a list of strings.&amp;quot;)&lt;br /&gt;
          .defineList(&amp;quot;example_string_list_config_entry&amp;quot;, Arrays.asList(&amp;quot;pie&amp;quot;, &amp;quot;trains&amp;quot;), entry -&amp;gt; true);&lt;br /&gt;
&lt;br /&gt;
      builder.pop();&lt;br /&gt;
    builder.pop();&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now it is time to register your config file so that Forge can create and read the config file. Doing do, you simply call &amp;lt;code&amp;gt;ModLoadingContext.get().registerConfig&amp;lt;/code&amp;gt; and pass in, the &amp;lt;code&amp;gt;ModConfig.Type&amp;lt;/code&amp;gt;, the &amp;lt;code&amp;gt;GENERAL_SPEC&amp;lt;/code&amp;gt; from your config file, and the name of the config file (make sure you include &amp;lt;code&amp;gt;.toml&amp;lt;/code&amp;gt; as well. Like so:&lt;br /&gt;
&amp;lt;code&amp;gt;ModLoadingContext.get().registerConfig(ModConfig.Type.COMMON, ModConfig.GENERAL_SPEC, &amp;quot;modconfig.toml&amp;quot;);&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
NOTE: Forge will only update the values of your config fields in code after the registry events are finished. Therefore, only attempt to read the config values after the registry events are completed. (FMLCommonSetupEvent and later is safe)&lt;br /&gt;
&lt;br /&gt;
The ModConfig.Type determines where your config files goes and its behavior. While COMMON is generally used the most, the other config types do have specific uses. A simple summary is:&lt;br /&gt;
* ModConfig.Type.COMMON - Exists in the config folder above the mods folder and will apply to all worlds created. (Works for both client and servers)&lt;br /&gt;
* ModConfig.Type.CLIENT - Same as COMMON except the config file is only ever loaded on the client. Never on server.&lt;br /&gt;
* ModConfig.Type.SERVER - Exists only in a world's own config folder ona per-world basis. This is read on both server and on single player as well. &lt;br /&gt;
&lt;br /&gt;
If you are going to have many config files for organization, you make want to put them into a specific folder for your mod within the config folder. Such as &amp;lt;code&amp;gt;configs/modid/blocks.toml&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;configs/modid/entities.toml&amp;lt;/code&amp;gt; However, you would need to make that new folder first as Forge will not do it for you. Example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
FileUtils.getOrCreateDirectory(FMLPaths.CONFIGDIR.get().resolve(&amp;quot;modid&amp;quot;), &amp;quot;modid&amp;quot;);&lt;br /&gt;
ModLoadingContext.get().registerConfig(ModConfig.Type.COMMON, ModIdConfigs.GENERAL_SPEC, &amp;quot;modid/blocks.toml&amp;quot;);&lt;br /&gt;
ModLoadingContext.get().registerConfig(ModConfig.Type.COMMON, ModIdConfigs.GENERAL_SPEC, &amp;quot;modid/entities.toml&amp;quot;);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now your configs are setup, you know a decent chunk of how you can utilize Forge configs, and you are ready to go!&lt;/div&gt;</summary>
		<author><name>SciWhiz12</name></author>
	</entry>
	<entry>
		<id>https://forge.gemwire.uk/index.php?title=Access_Transformers&amp;diff=2969</id>
		<title>Access Transformers</title>
		<link rel="alternate" type="text/html" href="https://forge.gemwire.uk/index.php?title=Access_Transformers&amp;diff=2969"/>
		<updated>2021-10-17T17:00:06Z</updated>

		<summary type="html">&lt;p&gt;SciWhiz12: /* Background */ switch same-package and subclasses&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Access transformers''' (abbreviated as ''ATs'') are declarations for modifying or transforming the access visibility or finality of a class member (classes, fields, methods). These declarations are parsed by a transformer and applied to classes using the ASM library, either modifying the class files on-disk or modifying the class bytes during runtime.&lt;br /&gt;
&lt;br /&gt;
The [https://github.com/MinecraftForge/AccessTransformers AccessTransformers] library provides a pluggable ModLauncher transformation service and a command-line application for applying access transformers on class bytes during runtime and on class files on-disk.&lt;br /&gt;
&lt;br /&gt;
== Background ==&lt;br /&gt;
Java provides the mechanism of '''access level modifiers''' (or ''access modifiers''), to modify the ''visibility'' of a member with the modifier to other classes. This is commonly used to hide fields and methods from other classes, such as instance fields for [[:wikipedia:encapsulation|encapsulation]] or private methods which are part of the implementation of the class and should not be exposed to callers.&lt;br /&gt;
&lt;br /&gt;
A member can be declared with any of the modifier keywords &amp;lt;code&amp;gt;public&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;private&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;protected&amp;lt;/code&amp;gt; to set the access level of the member, or none of the keywords, which defaults to a ''package-private'' access level.&lt;br /&gt;
&lt;br /&gt;
The following table shows the different access levels and their modifiers, and what classes may access members with that access level:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;text-align:center;&amp;quot;&lt;br /&gt;
|+ Access levels&lt;br /&gt;
! Access modifier&lt;br /&gt;
! Within the same class&lt;br /&gt;
! Classes in the same package&lt;br /&gt;
! Subclasses&lt;br /&gt;
! All other classes&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;public&amp;lt;/code&amp;gt;&lt;br /&gt;
| style=&amp;quot;color:limegreen&amp;quot; | '''Yes'''&lt;br /&gt;
| style=&amp;quot;color:limegreen&amp;quot; | '''Yes'''&lt;br /&gt;
| style=&amp;quot;color:limegreen&amp;quot; | '''Yes'''&lt;br /&gt;
| style=&amp;quot;color:limegreen&amp;quot; | '''Yes'''&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;protected&amp;lt;/code&amp;gt;&lt;br /&gt;
| style=&amp;quot;color:limegreen&amp;quot; | '''Yes'''&lt;br /&gt;
| style=&amp;quot;color:limegreen&amp;quot; | '''Yes'''&lt;br /&gt;
| style=&amp;quot;color:limegreen&amp;quot; | '''Yes'''&lt;br /&gt;
| style=&amp;quot;color:indianred&amp;quot; | '''No'''&lt;br /&gt;
|-&lt;br /&gt;
| ''no modifier''&lt;br /&gt;
| style=&amp;quot;color:limegreen&amp;quot; | '''Yes'''&lt;br /&gt;
| style=&amp;quot;color:limegreen&amp;quot; | '''Yes'''&lt;br /&gt;
| style=&amp;quot;color:indianred&amp;quot; | '''No'''&lt;br /&gt;
| style=&amp;quot;color:indianred&amp;quot; | '''No'''&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;private&amp;lt;/code&amp;gt;&lt;br /&gt;
| style=&amp;quot;color:limegreen&amp;quot; | '''Yes'''&lt;br /&gt;
| style=&amp;quot;color:indianred&amp;quot; | '''No'''&lt;br /&gt;
| style=&amp;quot;color:indianred&amp;quot; | '''No'''&lt;br /&gt;
| style=&amp;quot;color:indianred&amp;quot; | '''No'''&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
For example, a field marked &amp;lt;code&amp;gt;protected&amp;lt;/code&amp;gt; cannot be accessed by a class in another package, but can be accessed by: any class within the same package, any subclass of the class (even if the subclass belongs to another package), and within the same class where the field is declared.&lt;br /&gt;
&lt;br /&gt;
Additionally to the access modifiers, there exists the &amp;lt;code&amp;gt;final&amp;lt;/code&amp;gt; keyword, which:&lt;br /&gt;
* on classes, prevents any subclassing of the class;&lt;br /&gt;
* on fields, marks it as being assignable only once during construction; and&lt;br /&gt;
* on methods, prevents any subclasses from overriding the method with their own implementation.&lt;br /&gt;
&lt;br /&gt;
Normally, Java programmers restrict access levels to be as restrictive as they need to be, controlling what is the effective publicly-available surface for the application. For example, a field may be declared as &amp;lt;code&amp;gt;private&amp;lt;/code&amp;gt; while providing setter and getter methods to access the field (a technique known as encapsulation).&lt;br /&gt;
&lt;br /&gt;
However, this convention of restricting access levels and marking members as &amp;lt;code&amp;gt;final&amp;lt;/code&amp;gt; where approriate presents a problem with modding Minecraft, because they restrict what parts of the game that modders can access or modify, usually without other means to access or modify them (such as setters and getters for fields).&lt;br /&gt;
&lt;br /&gt;
One solution is to use Java [[:wikipedia:reflection|reflection]] to reflectively access these fields and methods during runtime, but they suffer from some problems:&lt;br /&gt;
* Reflection is slower than regular method calls or field accesses, as certain optimizations done by the JVM cannot be applied.&amp;lt;ref&amp;gt;[https://docs.oracle.com/javase/tutorial/reflect/index.html The Java™ Tutorials: The Reflection API]: ''&amp;quot;Consequently, reflective operations have slower performance than their non-reflective counterparts, and should be avoided in sections of code which are called frequently in performance-sensitive applications.&amp;quot;''&amp;lt;/ref&amp;gt; This makes reflection unsuitable for performance-critical code, such as during rendering.&lt;br /&gt;
* Reflection cannot allow the modification of &amp;lt;code&amp;gt;final&amp;lt;/code&amp;gt; fields which are either marked &amp;lt;code&amp;gt;static&amp;lt;/code&amp;gt; or belong to a record class.&amp;lt;ref&amp;gt;[https://docs.oracle.com/en/java/javase/16/docs/api/java.base/java/lang/reflect/AccessibleObject.html#setAccessible(boolean) Java 16 javadocs] for &amp;lt;code&amp;gt;java.lang.reflect.AccessibleObject.setAccessible(boolean)&amp;lt;/code&amp;gt;&amp;lt;/ref&amp;gt;&lt;br /&gt;
* Runtime reflection loses the benefit of compile-time type checks, which allows dangerous operations such as trying to set a field's value to an incompatible type.&lt;br /&gt;
* The use of reflection does not allow a class to extend a non-visible class.&lt;br /&gt;
&lt;br /&gt;
These problems are solved with the use of access transformers, which allow modification of the access modifiers of members such that they can be applied on class files on-disk to allow compiling against them, and applying the same transformer declarations on class bytes during runtime to allow classes which compiled against those transformed classes to work correctly.&lt;br /&gt;
&lt;br /&gt;
== Usage ==&lt;br /&gt;
&lt;br /&gt;
To use access transformers in the development environment, ForgeGradle must be configured with the location of the access transformer configuration file (or files). Because FML is hardwired to look for the configuration file at &amp;lt;code&amp;gt;META-INF/accesstransformer.cfg&amp;lt;/code&amp;gt; within JAR files, it is recommended that the AT configuration file for the project be placed at the same location: within the resources folder of the main source set, or &amp;lt;code&amp;gt;src/main/resources/META-INF/accesstransformer.cfg&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
To configure the location of the access transformer configuration file with ForgeGradle:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;gradle&amp;quot;&amp;gt;&lt;br /&gt;
minecraft { // Within the minecraft block&lt;br /&gt;
    // Configures FG to look at the given file path for the AT configuration file&lt;br /&gt;
    accessTransformer = file(&amp;quot;src/main/resources/META-INF/accesstransformer.cfg&amp;quot;)&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Access-transformers-uncomment-this-line-in-build-gradle.png|thumb|300px]]&lt;br /&gt;
&lt;br /&gt;
The Forge-provided mod development environment's buildscript contains the above line but commented out, as the MDK does not ship with an access transformer file. Users of the MDK can therefore uncomment out the above line and create the AT configuration file at the same location. &lt;br /&gt;
&lt;br /&gt;
Once the configuration file(s) has been added and everytime the contents or location of the file(s) changes, the developer should then refresh the Gradle nature/project in their IDE of choice for ForgeGradle to apply the access transformers to the compiled source. Each change to the access transformer configuration will trigger a full decompilation of the game.&lt;br /&gt;
&lt;br /&gt;
== Declarations ==&lt;br /&gt;
&lt;br /&gt;
Access transformers are declared line-by-line in configuration files, which are then parsed by ForgeGradle in the development environment and by FML in the production or end-user environment.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;#&amp;lt;/code&amp;gt; character and any content after that up to the end of the line is considered a comment, and will be ignored by the parser. Any lines which are either empty or consist of only whitespace or comments are ignored.&lt;br /&gt;
&lt;br /&gt;
An access transformer declaration has three different variations, depending on the target to be transformed:&lt;br /&gt;
&lt;br /&gt;
* for '''classes''': &amp;lt;code&amp;gt;''&amp;lt;modifier&amp;gt;'' ''&amp;lt;class name&amp;gt;''&amp;lt;/code&amp;gt;&lt;br /&gt;
* for '''methods''': &amp;lt;code&amp;gt;''&amp;lt;modifier&amp;gt;'' ''&amp;lt;class name&amp;gt;'' ''&amp;lt;method name&amp;gt;'''''('''''[parameter descriptors]''''')'''''&amp;amp;lt;return descriptor&amp;gt;''&amp;lt;/code&amp;gt;&lt;br /&gt;
* for '''fields''': &amp;lt;code&amp;gt;''&amp;lt;modifier&amp;gt;'' ''&amp;lt;class name&amp;gt;'' ''&amp;lt;field name&amp;gt;''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The modifier consists of one of the following words:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;public&amp;lt;/code&amp;gt; for the ''public'' access level (denoted by the modifier keyword of the same name)&lt;br /&gt;
* &amp;lt;code&amp;gt;protected&amp;lt;/code&amp;gt; for the ''protected'' access level (denoted by the modifier keyword of the same name)&lt;br /&gt;
* &amp;lt;code&amp;gt;default&amp;lt;/code&amp;gt; for the ''package-private'' access level (denoted by the absence of an access modifier keyword)&lt;br /&gt;
* &amp;lt;code&amp;gt;private&amp;lt;/code&amp;gt; for the ''private'' access level (denoted by the modifier keyword of the same name)&lt;br /&gt;
* For any of the preceding words, the &amp;lt;code&amp;gt;-f&amp;lt;/code&amp;gt; suffix removes the &amp;lt;code&amp;gt;final&amp;lt;/code&amp;gt; modifier, while the &amp;lt;code&amp;gt;+f&amp;lt;/code&amp;gt; suffix adds the modifier.&lt;br /&gt;
&lt;br /&gt;
The class name is the fully qualified name of the class, using &amp;lt;code&amp;gt;.&amp;lt;/code&amp;gt; (dots) to separate between (sub)packages and classes (for example, &amp;lt;code&amp;gt;java.lang.Object&amp;lt;/code&amp;gt;). &lt;br /&gt;
&lt;br /&gt;
For methods, the method descriptor&amp;lt;ref&amp;gt;''[https://docs.oracle.com/javase/specs/jvms/se16/html/jvms-4.html#jvms-4.3.3 Java Virtual Machine Specification, Java SE 16 Edition]'', 4.3.3. Method Descriptors &amp;lt;/ref&amp;gt; of the method is included, which consists of the descriptors for each of the method's parameters and the method's return type. The method parameters descriptors can be absent if there are no parameters in the method, but the return type descriptor must be present.&lt;br /&gt;
&lt;br /&gt;
The following are the matching descriptors for each type as seen in the method declaration:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ Matching type descriptors&lt;br /&gt;
! Descriptor&lt;br /&gt;
! Source form&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;Z&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;boolean&amp;lt;/code&amp;gt; || a &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;false&amp;lt;/code&amp;gt; value&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;B&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;byte&amp;lt;/code&amp;gt; || a 8-bit signed number&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;S&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;short&amp;lt;/code&amp;gt; || a 16-bit signed number&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;C&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;char&amp;lt;/code&amp;gt; || a Unicode character code point in UTF-16&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;I&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;int&amp;lt;/code&amp;gt; || a 32-bit signed number&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;F&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;float&amp;lt;/code&amp;gt; || a single-precision floating-point value&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;J&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;long&amp;lt;/code&amp;gt; || a 64-bit signed number&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;D&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;double&amp;lt;/code&amp;gt; || a double-precision floating-point value&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;[''I''&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;''int''[]&amp;lt;/code&amp;gt; || one dimension of an array; this can be repeated, and must end with another descriptor other than an array&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;L''java/lang/Object'';&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;java.lang.Object&amp;lt;/code&amp;gt; || a reference type; the internal form of the class' binary name must be present (in the given example, the class referenced is &amp;lt;code&amp;gt;java.lang.Object&amp;lt;/code&amp;gt;). &lt;br /&gt;
Note that inner classes are separated using the &amp;lt;code&amp;gt;$&amp;lt;/code&amp;gt; (dollar sign) character, such as &amp;lt;code&amp;gt;java/lang/System$Logger&amp;lt;/code&amp;gt;.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;V&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;void&amp;lt;/code&amp;gt; || a void or no-value return type; only available for the return type of a method descriptor&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{{Tip/Danger&lt;br /&gt;
|title=Wildcard access transformers&lt;br /&gt;
|A special type of access transformers called '''wildcard ATs''' (oftentimes referred to as '''shotgun ATs''' allows transforming the access modifier and finality of ''all'' fields or methods within a class.&lt;br /&gt;
&lt;br /&gt;
To use wildcard access transformers:&lt;br /&gt;
* for all methods within a class: &amp;lt;code&amp;gt;''&amp;lt;modifier&amp;gt;'' ''&amp;lt;class name&amp;gt;'' '''*()'''&amp;lt;/code&amp;gt;&lt;br /&gt;
* for all fields within a class: &amp;lt;code&amp;gt;''&amp;lt;modifier&amp;gt;'' ''&amp;lt;class name&amp;gt;'' '''*'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Modders should avoid using this in live code.''' Access transformers should always have the fewest and narrowest targets possible, and wildcard ATs violate this convention. Use of wildcard ATs may cause problems with both the ForgeGradle setup process. Wildcard ATs may be removed in a future update of the access transformer specification.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
== Examples ==&lt;br /&gt;
&lt;br /&gt;
The following are some examples of access transformer declarations:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
# Makes public the ScreenConstructor class in MenuScreens&lt;br /&gt;
public net.minecraft.client.gui.screens.MenuScreens$ScreenConstructor&lt;br /&gt;
&lt;br /&gt;
# Makes protected the 'COLOR_WHITE' field in Gui&lt;br /&gt;
protected net.minecraft.client.gui.Gui f_168667_ # COLOR_WHITE&lt;br /&gt;
&lt;br /&gt;
# Makes protected and removes the final modifier from 'random' field in MinecraftServer&lt;br /&gt;
protected-f net.minecraft.server.MinecraftServer f_129758_ # random&lt;br /&gt;
&lt;br /&gt;
# Makes public the 'makeExecutor' method in Util,&lt;br /&gt;
# which accepts a String and returns an ExecutorService&lt;br /&gt;
public net.minecraft.Util m_137477_(Ljava/lang/String;)Ljava/util/concurrent/ExecutorService; # makeExecutor&lt;br /&gt;
&lt;br /&gt;
# Makes public the 'leastMostToIntArray' method in SerializableUUID,&lt;br /&gt;
# which accepts two longs and returns an int[]&lt;br /&gt;
public net.minecraft.core.SerializableUUID m_123274_(JJ)[I # leastMostToIntArray&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>SciWhiz12</name></author>
	</entry>
	<entry>
		<id>https://forge.gemwire.uk/index.php?title=User:SciWhiz12/sandbox&amp;diff=2967</id>
		<title>User:SciWhiz12/sandbox</title>
		<link rel="alternate" type="text/html" href="https://forge.gemwire.uk/index.php?title=User:SciWhiz12/sandbox&amp;diff=2967"/>
		<updated>2021-10-12T17:53:39Z</updated>

		<summary type="html">&lt;p&gt;SciWhiz12: test indicator tag&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;tabs&amp;gt;&lt;br /&gt;
&amp;lt;tab name=&amp;quot;Foo&amp;quot;&amp;gt;Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.&amp;lt;/tab&amp;gt;&lt;br /&gt;
&amp;lt;tab name=&amp;quot;Bar&amp;quot;&amp;gt;Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.&amp;lt;/tab&amp;gt;&lt;br /&gt;
&amp;lt;tab name=&amp;quot;Baz&amp;quot;&amp;gt;Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.&amp;lt;/tab&amp;gt;&lt;br /&gt;
&amp;lt;/tabs&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tab name=&amp;quot;My Toggle Box&amp;quot;&amp;gt;&lt;br /&gt;
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.&lt;br /&gt;
&amp;lt;/tab&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tab name=&amp;quot;My Toggle Box&amp;quot; collapsed&amp;gt;&lt;br /&gt;
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.&lt;br /&gt;
&amp;lt;/tab&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tab name=&amp;quot;Stationery&amp;quot; dropdown&amp;gt;&lt;br /&gt;
* [[Business Cards]]&lt;br /&gt;
* [[Letterheads]]&lt;br /&gt;
* [[Envelopes]]&lt;br /&gt;
&amp;lt;/tab&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;indicator name=&amp;quot;exclaim&amp;quot;&amp;gt;[[File:Exclamation.svg|20px]]&amp;lt;/indicator&amp;gt;&lt;/div&gt;</summary>
		<author><name>SciWhiz12</name></author>
	</entry>
	<entry>
		<id>https://forge.gemwire.uk/index.php?title=FCWMeta:About&amp;diff=2960</id>
		<title>FCWMeta:About</title>
		<link rel="alternate" type="text/html" href="https://forge.gemwire.uk/index.php?title=FCWMeta:About&amp;diff=2960"/>
		<updated>2021-09-26T23:27:54Z</updated>

		<summary type="html">&lt;p&gt;SciWhiz12: remove DISPLAYTITLE&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;The '''Forge Community Wiki''' (abbreviated as '''FCW''') is a community wiki about [https://github.com/MinecraftForge/MinecraftForge Minecraft Forge], the popular open-source modding API for [[wikipedia:Minecraft|Minecraft]]. &lt;br /&gt;
&lt;br /&gt;
It is created as an community-centric and more accessible alternative to the [https://mcforge.readthedocs.io/ official Forge documentation], which is actively curated by the Minecraft Forge team.&lt;br /&gt;
&lt;br /&gt;
== History ==&lt;br /&gt;
On the September 19, 2020, in the &amp;lt;tt&amp;gt;#squirrels&amp;lt;/tt&amp;gt; channel of the official Forge Project discord, user [[User:SciWhiz12|sciwhiz12]] mentioned the idea of creating a wiki for Forge documentation. An official wiki previously existed for Minecraft Forge, however the cost and burden of maintaining such a wiki was too significant on the Minecraft Forge team (which consisted of volunteers), so it was shut down.&lt;br /&gt;
&lt;br /&gt;
Another user, [[User:Curle|Curle]], offered to host a community wiki on their servers, and giving adminship over to sciwhiz12. The community wiki initially started out on the popular wiki engine [[wikipedia:MediaWiki|MediaWiki]], but due to certain technical difficulties, the decision was made to move to using a simpler wiki engine: [[wikipedia:DokuWiki|DokuWiki]].&lt;br /&gt;
&lt;br /&gt;
On October 16, 2020, the community wiki was officially made publicly open. On October 23, 2020, a regular update to the web server that ran the wiki caused severe technical issues, and the wiki staff decided to move back to using MediaWiki as the wiki engine. &lt;br /&gt;
&lt;br /&gt;
== Purpose ==&lt;br /&gt;
The Forge Community Wiki was created to serve three major purposes:&lt;br /&gt;
# To collectively keep track of features, changes, updates to Minecraft Forge and vanilla code.&lt;br /&gt;
# To create and collaborate on articles with in-depth explanations about a variety of Forge-related subjects.&lt;br /&gt;
# To contribute example code and tutorials for both simple and difficult concepts.&lt;/div&gt;</summary>
		<author><name>SciWhiz12</name></author>
	</entry>
	<entry>
		<id>https://forge.gemwire.uk/index.php?title=Mods.toml_file&amp;diff=2956</id>
		<title>Mods.toml file</title>
		<link rel="alternate" type="text/html" href="https://forge.gemwire.uk/index.php?title=Mods.toml_file&amp;diff=2956"/>
		<updated>2021-09-22T23:25:01Z</updated>

		<summary type="html">&lt;p&gt;SciWhiz12: SciWhiz12 moved page Mods.toml file to Mods.toml: remove the file suffix, it's unique enough&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;#REDIRECT [[Mods.toml]]&lt;/div&gt;</summary>
		<author><name>SciWhiz12</name></author>
	</entry>
	<entry>
		<id>https://forge.gemwire.uk/index.php?title=Mods.toml&amp;diff=2955</id>
		<title>Mods.toml</title>
		<link rel="alternate" type="text/html" href="https://forge.gemwire.uk/index.php?title=Mods.toml&amp;diff=2955"/>
		<updated>2021-09-22T23:25:00Z</updated>

		<summary type="html">&lt;p&gt;SciWhiz12: SciWhiz12 moved page Mods.toml file to Mods.toml: remove the file suffix, it's unique enough&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Under construction}}&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 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;
Example &amp;lt;code&amp;gt;mods.toml&amp;lt;/code&amp;gt; file:&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.17.1 is version 37&lt;br /&gt;
loaderVersion=&amp;quot;[37,)&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;[37,)&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.17.1,1.18)&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;
If the &amp;lt;code&amp;gt;version&amp;lt;/code&amp;gt; is specified as&amp;lt;code&amp;gt;${file.jarVersion}&amp;lt;/code&amp;gt;, Forge will replace the string with the 'Implementation Version' specified in the jar manifest at runtime. Since the userdev environment has no jar manifest to pull from, it will be &amp;lt;code&amp;gt;NONE&amp;lt;/code&amp;gt; instead. As such, it is usually recommended to leave this field alone.&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. 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;
===Non-Mod-Specific Properties===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
!|Property&lt;br /&gt;
!|Type&lt;br /&gt;
!|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;&lt;br /&gt;
|string&lt;br /&gt;
|'''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;&lt;br /&gt;
|string&lt;br /&gt;
|'''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;[37,)&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;license&amp;lt;/code&amp;gt;&lt;br /&gt;
|string&lt;br /&gt;
|'''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;&lt;br /&gt;
|boolean&lt;br /&gt;
|&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;&lt;br /&gt;
|table&lt;br /&gt;
|&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;&lt;br /&gt;
|string&lt;br /&gt;
|''nothing''&lt;br /&gt;
|A URL for an issues tracker. This should never be a blank string, as that will cause an error.&lt;br /&gt;
|&amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;&amp;quot;http://my.issue.tracker/&amp;quot;&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===Mod Properties===&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;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
!|Property&lt;br /&gt;
!|Type&lt;br /&gt;
!|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;&lt;br /&gt;
|string&lt;br /&gt;
|'''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;&lt;br /&gt;
|string&lt;br /&gt;
|value of &amp;lt;code&amp;gt;modId&amp;lt;/code&amp;gt;&lt;br /&gt;
|An override namespace. Currently, there is no use for this property&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;&lt;br /&gt;
|string&lt;br /&gt;
|&amp;lt;code&amp;gt;&amp;quot;1&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
|The mod's version, 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;&lt;br /&gt;
|string&lt;br /&gt;
|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;&lt;br /&gt;
|string&lt;br /&gt;
|&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;nowiki&amp;gt;'''&amp;lt;/nowiki&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;&lt;br /&gt;
|string&lt;br /&gt;
|''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;&lt;br /&gt;
|boolean&lt;br /&gt;
|&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;&lt;br /&gt;
|string&lt;br /&gt;
|''nothing''&lt;br /&gt;
|The update JSON URL, used by the [[Update_Checker|update checker]]. This should never be a blank string, as that will cause an error.&lt;br /&gt;
|&amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;&amp;quot;http://myurl.me/path/to/update.json&amp;quot;&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;modproperties&amp;lt;/code&amp;gt;&lt;br /&gt;
|table&lt;br /&gt;
|&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;&lt;br /&gt;
|string&lt;br /&gt;
|''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;&lt;br /&gt;
|string&lt;br /&gt;
|''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;&lt;br /&gt;
|string&lt;br /&gt;
|''nothing''&lt;br /&gt;
|A URL, displayed on the Mods listing screen. Can be any string.&lt;br /&gt;
|&amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;&amp;quot;http://example.com/&amp;quot;&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===Dependency Configurations===&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;&amp;lt;nowiki&amp;gt;[[dependencies.modid]]&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;, with &amp;lt;code&amp;gt;modid&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;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
!|Property&lt;br /&gt;
!|Type&lt;br /&gt;
!|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;&lt;br /&gt;
|string&lt;br /&gt;
|'''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;&lt;br /&gt;
|boolean&lt;br /&gt;
|'''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;&lt;br /&gt;
|string&lt;br /&gt;
|&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;&lt;br /&gt;
|string&lt;br /&gt;
|&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;&lt;br /&gt;
|string&lt;br /&gt;
|&amp;lt;code&amp;gt;&amp;quot;BOTH&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
|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;
&lt;br /&gt;
{{Tip/Warning|When specifying dependency ordering between two or more mods, beware of cyclic order!&lt;br /&gt;
An example: 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;br /&gt;
[[Category:Beginner Topics]]&lt;/div&gt;</summary>
		<author><name>SciWhiz12</name></author>
	</entry>
	<entry>
		<id>https://forge.gemwire.uk/index.php?title=MediaWiki:Citizen.css&amp;diff=2954</id>
		<title>MediaWiki:Citizen.css</title>
		<link rel="alternate" type="text/html" href="https://forge.gemwire.uk/index.php?title=MediaWiki:Citizen.css&amp;diff=2954"/>
		<updated>2021-09-07T17:22:59Z</updated>

		<summary type="html">&lt;p&gt;SciWhiz12: more contrast in diffs&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;/* All CSS here will be loaded for users of the Citizen skin */&lt;br /&gt;
@media only screen and (prefers-color-scheme:dark) {&lt;br /&gt;
code, .mw-code {&lt;br /&gt;
	color: #46C410;&lt;br /&gt;
}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.external {&lt;br /&gt;
	color: #527ECA;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
tt {&lt;br /&gt;
	font-size: 100%;&lt;br /&gt;
	padding: 0 0.1em;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/* ***************** Styling for Tabs : START ***************** */&lt;br /&gt;
&lt;br /&gt;
.tabs-dropdown .tabs-content,&lt;br /&gt;
.tabs-dropdown .tabs-container,&lt;br /&gt;
.tabs-dropdown li,&lt;br /&gt;
.tabs-dropdown ul,&lt;br /&gt;
.tabs-dropdown ol {&lt;br /&gt;
	background-color: rgba(32,32,32,0.2) !important; /* has to be !important */&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.tabs-label {&lt;br /&gt;
	background-color: #222;&lt;br /&gt;
	border-color: #666;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.tabs-tabbox &amp;gt; .tabs-container {&lt;br /&gt;
	border-color: #666;&lt;br /&gt;
}&lt;br /&gt;
.tabs-plain &amp;gt; .tabs-label {&lt;br /&gt;
	border-color: #666;&lt;br /&gt;
}&lt;br /&gt;
.tabs-togglebox &amp;gt;*&amp;gt; .tabs-content {&lt;br /&gt;
	border-color: #666;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.tabs-dropdown &amp;gt;*&amp;gt; .tabs-content,&lt;br /&gt;
.tabs-dropdown li ul,&lt;br /&gt;
.tabs-dropdown li ol {&lt;br /&gt;
	box-shadow: 2px 3px 5px #111;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.tabs-dropdown li,&lt;br /&gt;
.tabs-dropdown &amp;gt;*&amp;gt; .tabs-content&amp;gt; a,&lt;br /&gt;
.tabs-dropdown &amp;gt;*&amp;gt; .tabs-content&amp;gt;p&amp;gt; a,&lt;br /&gt;
.tabs-dropdown ol&amp;gt;li&amp;gt; a {&lt;br /&gt;
	border-top-color: #666;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.tabs-dropdown li ul,&lt;br /&gt;
.tabs-dropdown li ol {&lt;br /&gt;
	border-color: #666;&lt;br /&gt;
}&lt;br /&gt;
.tabs-dropdown li ul:before,&lt;br /&gt;
.tabs-dropdown li ol:before {&lt;br /&gt;
	color: #88F;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.tabs-label:hover {&lt;br /&gt;
	background-color: #444;&lt;br /&gt;
}&lt;br /&gt;
.tabs-label:active, .tabs-label:focus {&lt;br /&gt;
	background-color: #444;&lt;br /&gt;
}&lt;br /&gt;
.tabs-tabbox &amp;gt; .tabs-input:checked + .tabs-label,&lt;br /&gt;
.tabs-input-0:checked + .tabs-input-1 + .tabs-label {&lt;br /&gt;
	z-index: 2;&lt;br /&gt;
	background-color: #444;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.tabs-dropdown &amp;gt;*&amp;gt; .tabs-content li:hover {&lt;br /&gt;
	background-color: #444;&lt;br /&gt;
}&lt;br /&gt;
.tabs-dropdown a,&lt;br /&gt;
.tabs-dropdown a:hover,&lt;br /&gt;
.tabs-dropdown a: visited {&lt;br /&gt;
	color: #15B;&lt;br /&gt;
}&lt;br /&gt;
.tabs-dropdown a:active {&lt;br /&gt;
	color: #108;&lt;br /&gt;
}&lt;br /&gt;
.tabs-dropdown &amp;gt;*&amp;gt; .tabs-content&amp;gt; a:hover,&lt;br /&gt;
.tabs-dropdown &amp;gt;*&amp;gt; .tabs-content&amp;gt;p&amp;gt; a:hover,&lt;br /&gt;
.tabs-dropdown ol&amp;gt;li&amp;gt; a:hover {&lt;br /&gt;
	background-color: #444;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.tabs-tabbox &amp;gt; .tabs-input.checked + .tabs-label,&lt;br /&gt;
.tabs-input-0.checked + .tabs-input-1 + .tabs-label {&lt;br /&gt;
	background-color: #444;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/* ***************** Styling for Tabs : END ***************** */&lt;br /&gt;
&lt;br /&gt;
/* ************* Styling for Datatables : START ************* */&lt;br /&gt;
&lt;br /&gt;
.mw-datatable td, .mw-datatable th {&lt;br /&gt;
    background-color: transparent;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.mw-datatable table {&lt;br /&gt;
  border: 1px solid #424951;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.mw-datatable td, .mw-datatable th {&lt;br /&gt;
    border: 1px solid #424951;&lt;br /&gt;
    padding: 0.2em 0.4em;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.mw-datatable tr:hover td {&lt;br /&gt;
    background-color: #202736;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/* ************** Styling for Datatables : END ************** */&lt;br /&gt;
&lt;br /&gt;
/* Fixes the colors of diff changes for better contrast */&lt;br /&gt;
.diffchange {&lt;br /&gt;
    color: #222222;&lt;br /&gt;
}&lt;br /&gt;
.diff-deletedline {&lt;br /&gt;
    border-color: #d9c284; /* ffe49c */&lt;br /&gt;
}&lt;br /&gt;
.diff-deletedline .diffchange {&lt;br /&gt;
    background: #d9c284;&lt;br /&gt;
}&lt;br /&gt;
.diff-addedline {&lt;br /&gt;
    border-color: #8bb2d9; /* a3d3ff */&lt;br /&gt;
}&lt;br /&gt;
.diff-addedline .diffchange {&lt;br /&gt;
    background: #8bb2d9;&lt;br /&gt;
}&lt;/div&gt;</summary>
		<author><name>SciWhiz12</name></author>
	</entry>
	<entry>
		<id>https://forge.gemwire.uk/index.php?title=MediaWiki:Citizen.css&amp;diff=2953</id>
		<title>MediaWiki:Citizen.css</title>
		<link rel="alternate" type="text/html" href="https://forge.gemwire.uk/index.php?title=MediaWiki:Citizen.css&amp;diff=2953"/>
		<updated>2021-09-07T17:05:39Z</updated>

		<summary type="html">&lt;p&gt;SciWhiz12: add css to fix contrast in diffs&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;/* All CSS here will be loaded for users of the Citizen skin */&lt;br /&gt;
@media only screen and (prefers-color-scheme:dark) {&lt;br /&gt;
code, .mw-code {&lt;br /&gt;
	color: #46C410;&lt;br /&gt;
}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.external {&lt;br /&gt;
	color: #527ECA;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
tt {&lt;br /&gt;
	font-size: 100%;&lt;br /&gt;
	padding: 0 0.1em;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/* ***************** Styling for Tabs : START ***************** */&lt;br /&gt;
&lt;br /&gt;
.tabs-dropdown .tabs-content,&lt;br /&gt;
.tabs-dropdown .tabs-container,&lt;br /&gt;
.tabs-dropdown li,&lt;br /&gt;
.tabs-dropdown ul,&lt;br /&gt;
.tabs-dropdown ol {&lt;br /&gt;
	background-color: rgba(32,32,32,0.2) !important; /* has to be !important */&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.tabs-label {&lt;br /&gt;
	background-color: #222;&lt;br /&gt;
	border-color: #666;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.tabs-tabbox &amp;gt; .tabs-container {&lt;br /&gt;
	border-color: #666;&lt;br /&gt;
}&lt;br /&gt;
.tabs-plain &amp;gt; .tabs-label {&lt;br /&gt;
	border-color: #666;&lt;br /&gt;
}&lt;br /&gt;
.tabs-togglebox &amp;gt;*&amp;gt; .tabs-content {&lt;br /&gt;
	border-color: #666;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.tabs-dropdown &amp;gt;*&amp;gt; .tabs-content,&lt;br /&gt;
.tabs-dropdown li ul,&lt;br /&gt;
.tabs-dropdown li ol {&lt;br /&gt;
	box-shadow: 2px 3px 5px #111;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.tabs-dropdown li,&lt;br /&gt;
.tabs-dropdown &amp;gt;*&amp;gt; .tabs-content&amp;gt; a,&lt;br /&gt;
.tabs-dropdown &amp;gt;*&amp;gt; .tabs-content&amp;gt;p&amp;gt; a,&lt;br /&gt;
.tabs-dropdown ol&amp;gt;li&amp;gt; a {&lt;br /&gt;
	border-top-color: #666;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.tabs-dropdown li ul,&lt;br /&gt;
.tabs-dropdown li ol {&lt;br /&gt;
	border-color: #666;&lt;br /&gt;
}&lt;br /&gt;
.tabs-dropdown li ul:before,&lt;br /&gt;
.tabs-dropdown li ol:before {&lt;br /&gt;
	color: #88F;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.tabs-label:hover {&lt;br /&gt;
	background-color: #444;&lt;br /&gt;
}&lt;br /&gt;
.tabs-label:active, .tabs-label:focus {&lt;br /&gt;
	background-color: #444;&lt;br /&gt;
}&lt;br /&gt;
.tabs-tabbox &amp;gt; .tabs-input:checked + .tabs-label,&lt;br /&gt;
.tabs-input-0:checked + .tabs-input-1 + .tabs-label {&lt;br /&gt;
	z-index: 2;&lt;br /&gt;
	background-color: #444;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.tabs-dropdown &amp;gt;*&amp;gt; .tabs-content li:hover {&lt;br /&gt;
	background-color: #444;&lt;br /&gt;
}&lt;br /&gt;
.tabs-dropdown a,&lt;br /&gt;
.tabs-dropdown a:hover,&lt;br /&gt;
.tabs-dropdown a: visited {&lt;br /&gt;
	color: #15B;&lt;br /&gt;
}&lt;br /&gt;
.tabs-dropdown a:active {&lt;br /&gt;
	color: #108;&lt;br /&gt;
}&lt;br /&gt;
.tabs-dropdown &amp;gt;*&amp;gt; .tabs-content&amp;gt; a:hover,&lt;br /&gt;
.tabs-dropdown &amp;gt;*&amp;gt; .tabs-content&amp;gt;p&amp;gt; a:hover,&lt;br /&gt;
.tabs-dropdown ol&amp;gt;li&amp;gt; a:hover {&lt;br /&gt;
	background-color: #444;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.tabs-tabbox &amp;gt; .tabs-input.checked + .tabs-label,&lt;br /&gt;
.tabs-input-0.checked + .tabs-input-1 + .tabs-label {&lt;br /&gt;
	background-color: #444;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/* ***************** Styling for Tabs : END ***************** */&lt;br /&gt;
&lt;br /&gt;
/* ************* Styling for Datatables : START ************* */&lt;br /&gt;
&lt;br /&gt;
.mw-datatable td, .mw-datatable th {&lt;br /&gt;
    background-color: transparent;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.mw-datatable table {&lt;br /&gt;
  border: 1px solid #424951;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.mw-datatable td, .mw-datatable th {&lt;br /&gt;
    border: 1px solid #424951;&lt;br /&gt;
    padding: 0.2em 0.4em;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.mw-datatable tr:hover td {&lt;br /&gt;
    background-color: #202736;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/* ************** Styling for Datatables : END ************** */&lt;br /&gt;
&lt;br /&gt;
/* Fixes the text color of diff changes to better contrast against the BG */&lt;br /&gt;
.diffchange {&lt;br /&gt;
  color: #444444;&lt;br /&gt;
}&lt;/div&gt;</summary>
		<author><name>SciWhiz12</name></author>
	</entry>
	<entry>
		<id>https://forge.gemwire.uk/index.php?title=User:SciWhiz12&amp;diff=2937</id>
		<title>User:SciWhiz12</title>
		<link rel="alternate" type="text/html" href="https://forge.gemwire.uk/index.php?title=User:SciWhiz12&amp;diff=2937"/>
		<updated>2021-08-29T14:17:22Z</updated>

		<summary type="html">&lt;p&gt;SciWhiz12: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;''Hello!'' I'm one of the Administrators of this wiki. _Bring out yer banhammers, fellas!_&lt;br /&gt;
&lt;br /&gt;
If you have any concern with the operations of this wiki, please do not hesitate to talk about it on my talk page, or message me on Discord: '''sciwhiz12#1286'''. I am active on The Forge Project discord and the Minecraft Mod Development discord, and do appear from time to time on the Modded Minecraft discord.&lt;br /&gt;
&lt;br /&gt;
- [[User:SciWhiz12|&amp;lt;span style=&amp;quot;color: #d9d916; font-weight: bold&amp;quot;&amp;gt;SciWhiz12&amp;lt;/span&amp;gt;]] [[User talk:SciWhiz12|💬]] 08:55, 23 October 2020 (UTC)&lt;/div&gt;</summary>
		<author><name>SciWhiz12</name></author>
	</entry>
	<entry>
		<id>https://forge.gemwire.uk/index.php?title=Proper_Mod_Structuring&amp;diff=2936</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=2936"/>
		<updated>2021-08-29T14:09:11Z</updated>

		<summary type="html">&lt;p&gt;SciWhiz12: remove extraneous whitespace&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;
{{Tip|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;
{{Tip/Important|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. Below are a few possible methods for laying out your folder structure though you may as well come up with your own layout too.&lt;br /&gt;
&lt;br /&gt;
* '''Group by Logic''': One possible strategy is to make subpackages for logical units of your mod. For example, if you have a block called Super Furnace you would put its block, its block entity and its item all under &amp;lt;code&amp;gt;feature/superfurnace&amp;lt;/code&amp;gt;.&lt;br /&gt;
* '''Group by Function''': Another common strategy is to make subpackages 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;
No matter how your final structure looks like it is highly recommended to add a &amp;lt;code&amp;gt;client&amp;lt;/code&amp;gt; subpackage under your main package. This helps to isolate your [[Sides|client-only code]] from the rest, such as your Screens 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;
{{Tip|If you are unsure on how exactly you want to structure your mod it can be a good idea to look at the source of others to see how they did it.}}&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 have 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 have a class name of &amp;lt;code&amp;gt;NotDirtBlock&amp;lt;/code&amp;gt;.&lt;br /&gt;
* A &amp;lt;code&amp;gt;BlockEntity&amp;lt;/code&amp;gt; for a block called &amp;lt;code&amp;gt;SuperChewer&amp;lt;/code&amp;gt; would have a class name of &amp;lt;code&amp;gt;SuperChewerBlockEntity&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;
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;
Example &amp;lt;code&amp;gt;mods.toml&amp;lt;/code&amp;gt; file&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.17.1 is version 37&lt;br /&gt;
loaderVersion=&amp;quot;[37,)&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;[37,)&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.17.1,1.18)&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;
If the &amp;lt;code&amp;gt;version&amp;lt;/code&amp;gt; is specified as&amp;lt;code&amp;gt;${file.jarVersion}&amp;lt;/code&amp;gt;, Forge will replace the string with the 'Implementation Version' specified in the jar manifest at runtime. Since the userdev environment has no jar manifest to pull from, it will be &amp;lt;code&amp;gt;NONE&amp;lt;/code&amp;gt; instead. As such, it is usually recommended to leave this field alone.&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. 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;
===Non-Mod-Specific Properties===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
!|Property&lt;br /&gt;
!|Type&lt;br /&gt;
!|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;&lt;br /&gt;
|string&lt;br /&gt;
|'''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;&lt;br /&gt;
|string&lt;br /&gt;
|'''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;[37,)&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;license&amp;lt;/code&amp;gt;&lt;br /&gt;
|string&lt;br /&gt;
|'''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;&lt;br /&gt;
|boolean&lt;br /&gt;
|&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;&lt;br /&gt;
|table&lt;br /&gt;
|&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;&lt;br /&gt;
|string&lt;br /&gt;
|''nothing''&lt;br /&gt;
|A URL for an issues tracker. This should never be a blank string, as that will cause an error.&lt;br /&gt;
|&amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;&amp;quot;http://my.issue.tracker/&amp;quot;&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Mod Properties===&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;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
!|Property&lt;br /&gt;
!|Type&lt;br /&gt;
!|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;&lt;br /&gt;
|string&lt;br /&gt;
|'''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;&lt;br /&gt;
|string&lt;br /&gt;
|value of &amp;lt;code&amp;gt;modId&amp;lt;/code&amp;gt;&lt;br /&gt;
|An override namespace. Currently, there is no use for this property&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;&lt;br /&gt;
|string&lt;br /&gt;
|&amp;lt;code&amp;gt;&amp;quot;1&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
|.), ideally conforming to [[Semantic_Versioning&amp;gt;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;&lt;br /&gt;
|string&lt;br /&gt;
|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;&lt;br /&gt;
|string&lt;br /&gt;
|&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;)&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;&lt;br /&gt;
|string&lt;br /&gt;
|''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;&lt;br /&gt;
|boolean&lt;br /&gt;
|&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;&lt;br /&gt;
|string&lt;br /&gt;
|''nothing''&lt;br /&gt;
|The update JSON URL, used by the [Update_Checker update checker]. This should never be a blank string, as that will cause an error.&lt;br /&gt;
|&amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;&amp;quot;http://myurl.me/path/to/update.json&amp;quot;&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;modproperties&amp;lt;/code&amp;gt;&lt;br /&gt;
|table&lt;br /&gt;
|&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;&lt;br /&gt;
|string&lt;br /&gt;
|''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;&lt;br /&gt;
|string&lt;br /&gt;
|''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;&lt;br /&gt;
|string&lt;br /&gt;
|''nothing''&lt;br /&gt;
|A URL, displayed on the Mods listing screen. Can be any string.&lt;br /&gt;
|&amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;&amp;quot;http://example.com/&amp;quot;&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Dependency Configurations===&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;/code&amp;gt;, with &amp;lt;code&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;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
!|Property&lt;br /&gt;
!|Type&lt;br /&gt;
!|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;&lt;br /&gt;
|string&lt;br /&gt;
|'''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;&lt;br /&gt;
|boolean&lt;br /&gt;
|'''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;&lt;br /&gt;
|string&lt;br /&gt;
|&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;&lt;br /&gt;
|string&lt;br /&gt;
|&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;&lt;br /&gt;
|string&lt;br /&gt;
|&amp;lt;code&amp;gt;&amp;quot;BOTH&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
|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;
&lt;br /&gt;
{{Tip/Warning|When specifying dependency ordering between two or more mods, beware of cyclic order!&lt;br /&gt;
An example: 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;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Beginner Topics]]&lt;/div&gt;</summary>
		<author><name>SciWhiz12</name></author>
	</entry>
	<entry>
		<id>https://forge.gemwire.uk/index.php?title=Access_Transformers&amp;diff=2935</id>
		<title>Access Transformers</title>
		<link rel="alternate" type="text/html" href="https://forge.gemwire.uk/index.php?title=Access_Transformers&amp;diff=2935"/>
		<updated>2021-08-29T13:50:28Z</updated>

		<summary type="html">&lt;p&gt;SciWhiz12: add missing parenthesis&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Access transformers''' (abbreviated as ''ATs'') are declarations for modifying or transforming the access visibility or finality of a class member (classes, fields, methods). These declarations are parsed by a transformer and applied to classes using the ASM library, either modifying the class files on-disk or modifying the class bytes during runtime.&lt;br /&gt;
&lt;br /&gt;
The [https://github.com/MinecraftForge/AccessTransformers AccessTransformers] library provides a pluggable ModLauncher transformation service and a command-line application for applying access transformers on class bytes during runtime and on class files on-disk.&lt;br /&gt;
&lt;br /&gt;
== Background ==&lt;br /&gt;
Java provides the mechanism of '''access level modifiers''' (or ''access modifiers''), to modify the ''visibility'' of a member with the modifier to other classes. This is commonly used to hide fields and methods from other classes, such as instance fields for [[:wikipedia:encapsulation|encapsulation]] or private methods which are part of the implementation of the class and should not be exposed to callers.&lt;br /&gt;
&lt;br /&gt;
A member can be declared with any of the modifier keywords &amp;lt;code&amp;gt;public&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;private&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;protected&amp;lt;/code&amp;gt; to set the access level of the member, or none of the keywords, which defaults to a ''package-private'' access level.&lt;br /&gt;
&lt;br /&gt;
The following table shows the different access levels and their modifiers, and what classes may access members with that access level:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;text-align:center;&amp;quot;&lt;br /&gt;
|+ Access levels&lt;br /&gt;
! Access modifier&lt;br /&gt;
! Within the same class&lt;br /&gt;
! Subclasses&lt;br /&gt;
! Classes in the same package&lt;br /&gt;
! All other classes&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;public&amp;lt;/code&amp;gt;&lt;br /&gt;
| style=&amp;quot;color:limegreen&amp;quot; | '''Yes'''&lt;br /&gt;
| style=&amp;quot;color:limegreen&amp;quot; | '''Yes'''&lt;br /&gt;
| style=&amp;quot;color:limegreen&amp;quot; | '''Yes'''&lt;br /&gt;
| style=&amp;quot;color:limegreen&amp;quot; | '''Yes'''&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;protected&amp;lt;/code&amp;gt;&lt;br /&gt;
| style=&amp;quot;color:limegreen&amp;quot; | '''Yes'''&lt;br /&gt;
| style=&amp;quot;color:limegreen&amp;quot; | '''Yes'''&lt;br /&gt;
| style=&amp;quot;color:limegreen&amp;quot; | '''Yes'''&lt;br /&gt;
| style=&amp;quot;color:indianred&amp;quot; | '''No'''&lt;br /&gt;
|-&lt;br /&gt;
| ''no modifier''&lt;br /&gt;
| style=&amp;quot;color:limegreen&amp;quot; | '''Yes'''&lt;br /&gt;
| style=&amp;quot;color:limegreen&amp;quot; | '''Yes'''&lt;br /&gt;
| style=&amp;quot;color:indianred&amp;quot; | '''No'''&lt;br /&gt;
| style=&amp;quot;color:indianred&amp;quot; | '''No'''&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;private&amp;lt;/code&amp;gt;&lt;br /&gt;
| style=&amp;quot;color:limegreen&amp;quot; | '''Yes'''&lt;br /&gt;
| style=&amp;quot;color:indianred&amp;quot; | '''No'''&lt;br /&gt;
| style=&amp;quot;color:indianred&amp;quot; | '''No'''&lt;br /&gt;
| style=&amp;quot;color:indianred&amp;quot; | '''No'''&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
For example, a field marked &amp;lt;code&amp;gt;protected&amp;lt;/code&amp;gt; cannot be accessed by a class in another package, but can be accessed by: any class within the same package, any subclass of the class (even if the subclass belongs to another package), and within the same class where the field is declared.&lt;br /&gt;
&lt;br /&gt;
Additionally to the access modifiers, there exists the &amp;lt;code&amp;gt;final&amp;lt;/code&amp;gt; keyword, which:&lt;br /&gt;
* on classes, prevents any subclassing of the class;&lt;br /&gt;
* on fields, marks it as being assignable only once during construction; and&lt;br /&gt;
* on methods, prevents any subclasses from overriding the method with their own implementation.&lt;br /&gt;
&lt;br /&gt;
Normally, Java programmers restrict access levels to be as restrictive as they need to be, controlling what is the effective publicly-available surface for the application. For example, a field may be declared as &amp;lt;code&amp;gt;private&amp;lt;/code&amp;gt; while providing setter and getter methods to access the field (a technique known as encapsulation).&lt;br /&gt;
&lt;br /&gt;
However, this convention of restricting access levels and marking members as &amp;lt;code&amp;gt;final&amp;lt;/code&amp;gt; where approriate presents a problem with modding Minecraft, because they restrict what parts of the game that modders can access or modify, usually without other means to access or modify them (such as setters and getters for fields).&lt;br /&gt;
&lt;br /&gt;
One solution is to use Java [[:wikipedia:reflection|reflection]] to reflectively access these fields and methods during runtime, but they suffer from some problems:&lt;br /&gt;
* Reflection is slower than regular method calls or field accesses, as certain optimizations done by the JVM cannot be applied.&amp;lt;ref&amp;gt;[https://docs.oracle.com/javase/tutorial/reflect/index.html The Java™ Tutorials: The Reflection API]: ''&amp;quot;Consequently, reflective operations have slower performance than their non-reflective counterparts, and should be avoided in sections of code which are called frequently in performance-sensitive applications.&amp;quot;''&amp;lt;/ref&amp;gt; This makes reflection unsuitable for performance-critical code, such as during rendering.&lt;br /&gt;
* Reflection cannot allow the modification of &amp;lt;code&amp;gt;final&amp;lt;/code&amp;gt; fields which are either marked &amp;lt;code&amp;gt;static&amp;lt;/code&amp;gt; or belong to a record class.&amp;lt;ref&amp;gt;[https://docs.oracle.com/en/java/javase/16/docs/api/java.base/java/lang/reflect/AccessibleObject.html#setAccessible(boolean) Java 16 javadocs] for &amp;lt;code&amp;gt;java.lang.reflect.AccessibleObject.setAccessible(boolean)&amp;lt;/code&amp;gt;&amp;lt;/ref&amp;gt;&lt;br /&gt;
* Runtime reflection loses the benefit of compile-time type checks, which allows dangerous operations such as trying to set a field's value to an incompatible type.&lt;br /&gt;
* The use of reflection does not allow a class to extend a non-visible class.&lt;br /&gt;
&lt;br /&gt;
These problems are solved with the use of access transformers, which allow modification of the access modifiers of members such that they can be applied on class files on-disk to allow compiling against them, and applying the same transformer declarations on class bytes during runtime to allow classes which compiled against those transformed classes to work correctly.&lt;br /&gt;
&lt;br /&gt;
== Usage ==&lt;br /&gt;
&lt;br /&gt;
To use access transformers in the development environment, ForgeGradle must be configured with the location of the access transformer configuration file (or files). Because FML is hardwired to look for the configuration file at &amp;lt;code&amp;gt;META-INF/accesstransformer.cfg&amp;lt;/code&amp;gt; within JAR files, it is recommended that the AT configuration file for the project be placed at the same location: within the resources folder of the main source set, or &amp;lt;code&amp;gt;src/main/resources/META-INF/accesstransformer.cfg&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
To configure the location of the access transformer configuration file with ForgeGradle:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;gradle&amp;quot;&amp;gt;&lt;br /&gt;
minecraft { // Within the minecraft block&lt;br /&gt;
    // Configures FG to look at the given file path for the AT configuration file&lt;br /&gt;
    accessTransformer = file(&amp;quot;src/main/resources/META-INF/accesstransformer.cfg&amp;quot;)&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Access-transformers-uncomment-this-line-in-build-gradle.png|thumb|300px]]&lt;br /&gt;
&lt;br /&gt;
The Forge-provided mod development environment's buildscript contains the above line but commented out, as the MDK does not ship with an access transformer file. Users of the MDK can therefore uncomment out the above line and create the AT configuration file at the same location. &lt;br /&gt;
&lt;br /&gt;
Once the configuration file(s) has been added and everytime the contents or location of the file(s) changes, the developer should then refresh the Gradle nature/project in their IDE of choice for ForgeGradle to apply the access transformers to the compiled source. Each change to the access transformer configuration will trigger a full decompilation of the game.&lt;br /&gt;
&lt;br /&gt;
== Declarations ==&lt;br /&gt;
&lt;br /&gt;
Access transformers are declared line-by-line in configuration files, which are then parsed by ForgeGradle in the development environment and by FML in the production or end-user environment.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;#&amp;lt;/code&amp;gt; character and any content after that up to the end of the line is considered a comment, and will be ignored by the parser. Any lines which are either empty or consist of only whitespace or comments are ignored.&lt;br /&gt;
&lt;br /&gt;
An access transformer declaration has three different variations, depending on the target to be transformed:&lt;br /&gt;
&lt;br /&gt;
* for '''classes''': &amp;lt;code&amp;gt;''&amp;lt;modifier&amp;gt;'' ''&amp;lt;class name&amp;gt;''&amp;lt;/code&amp;gt;&lt;br /&gt;
* for '''methods''': &amp;lt;code&amp;gt;''&amp;lt;modifier&amp;gt;'' ''&amp;lt;class name&amp;gt;'' ''&amp;lt;method name&amp;gt;'''''('''''[parameter descriptors]''''')'''''&amp;amp;lt;return descriptor&amp;gt;''&amp;lt;/code&amp;gt;&lt;br /&gt;
* for '''fields''': &amp;lt;code&amp;gt;''&amp;lt;modifier&amp;gt;'' ''&amp;lt;class name&amp;gt;'' ''&amp;lt;field name&amp;gt;''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The modifier consists of one of the following words:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;public&amp;lt;/code&amp;gt; for the ''public'' access level (denoted by the modifier keyword of the same name)&lt;br /&gt;
* &amp;lt;code&amp;gt;protected&amp;lt;/code&amp;gt; for the ''protected'' access level (denoted by the modifier keyword of the same name)&lt;br /&gt;
* &amp;lt;code&amp;gt;default&amp;lt;/code&amp;gt; for the ''package-private'' access level (denoted by the absence of an access modifier keyword)&lt;br /&gt;
* &amp;lt;code&amp;gt;private&amp;lt;/code&amp;gt; for the ''private'' access level (denoted by the modifier keyword of the same name)&lt;br /&gt;
* For any of the preceding words, the &amp;lt;code&amp;gt;-f&amp;lt;/code&amp;gt; suffix removes the &amp;lt;code&amp;gt;final&amp;lt;/code&amp;gt; modifier, while the &amp;lt;code&amp;gt;+f&amp;lt;/code&amp;gt; suffix adds the modifier.&lt;br /&gt;
&lt;br /&gt;
The class name is the fully qualified name of the class, using &amp;lt;code&amp;gt;.&amp;lt;/code&amp;gt; (dots) to separate between (sub)packages and classes (for example, &amp;lt;code&amp;gt;java.lang.Object&amp;lt;/code&amp;gt;). &lt;br /&gt;
&lt;br /&gt;
For methods, the method descriptor&amp;lt;ref&amp;gt;''[https://docs.oracle.com/javase/specs/jvms/se16/html/jvms-4.html#jvms-4.3.3 Java Virtual Machine Specification, Java SE 16 Edition]'', 4.3.3. Method Descriptors &amp;lt;/ref&amp;gt; of the method is included, which consists of the descriptors for each of the method's parameters and the method's return type. The method parameters descriptors can be absent if there are no parameters in the method, but the return type descriptor must be present.&lt;br /&gt;
&lt;br /&gt;
The following are the matching descriptors for each type as seen in the method declaration:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ Matching type descriptors&lt;br /&gt;
! Descriptor&lt;br /&gt;
! Source form&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;Z&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;boolean&amp;lt;/code&amp;gt; || a &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;false&amp;lt;/code&amp;gt; value&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;B&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;byte&amp;lt;/code&amp;gt; || a 8-bit signed number&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;S&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;short&amp;lt;/code&amp;gt; || a 16-bit signed number&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;C&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;char&amp;lt;/code&amp;gt; || a Unicode character code point in UTF-16&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;I&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;int&amp;lt;/code&amp;gt; || a 32-bit signed number&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;F&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;float&amp;lt;/code&amp;gt; || a single-precision floating-point value&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;J&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;long&amp;lt;/code&amp;gt; || a 64-bit signed number&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;D&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;double&amp;lt;/code&amp;gt; || a double-precision floating-point value&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;[''I''&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;''int''[]&amp;lt;/code&amp;gt; || one dimension of an array; this can be repeated, and must end with another descriptor other than an array&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;L''java/lang/Object'';&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;java.lang.Object&amp;lt;/code&amp;gt; || a reference type; the internal form of the class' binary name must be present (in the given example, the class referenced is &amp;lt;code&amp;gt;java.lang.Object&amp;lt;/code&amp;gt;). &lt;br /&gt;
Note that inner classes are separated using the &amp;lt;code&amp;gt;$&amp;lt;/code&amp;gt; (dollar sign) character, such as &amp;lt;code&amp;gt;java/lang/System$Logger&amp;lt;/code&amp;gt;.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;V&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;void&amp;lt;/code&amp;gt; || a void or no-value return type; only available for the return type of a method descriptor&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{{Tip/Danger&lt;br /&gt;
|title=Wildcard access transformers&lt;br /&gt;
|A special type of access transformers called '''wildcard ATs''' (oftentimes referred to as '''shotgun ATs''' allows transforming the access modifier and finality of ''all'' fields or methods within a class.&lt;br /&gt;
&lt;br /&gt;
To use wildcard access transformers:&lt;br /&gt;
* for all methods within a class: &amp;lt;code&amp;gt;''&amp;lt;modifier&amp;gt;'' ''&amp;lt;class name&amp;gt;'' '''*()'''&amp;lt;/code&amp;gt;&lt;br /&gt;
* for all fields within a class: &amp;lt;code&amp;gt;''&amp;lt;modifier&amp;gt;'' ''&amp;lt;class name&amp;gt;'' '''*'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Modders should avoid using this in live code.''' Access transformers should always have the fewest and narrowest targets possible, and wildcard ATs violate this convention. Use of wildcard ATs may cause problems with both the ForgeGradle setup process. Wildcard ATs may be removed in a future update of the access transformer specification.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
== Examples ==&lt;br /&gt;
&lt;br /&gt;
The following are some examples of access transformer declarations:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
# Makes public the ScreenConstructor class in MenuScreens&lt;br /&gt;
public net.minecraft.client.gui.screens.MenuScreens$ScreenConstructor&lt;br /&gt;
&lt;br /&gt;
# Makes protected the 'COLOR_WHITE' field in Gui&lt;br /&gt;
protected net.minecraft.client.gui.Gui f_168667_ # COLOR_WHITE&lt;br /&gt;
&lt;br /&gt;
# Makes protected and removes the final modifier from 'random' field in MinecraftServer&lt;br /&gt;
protected-f net.minecraft.server.MinecraftServer f_129758_ # random&lt;br /&gt;
&lt;br /&gt;
# Makes public the 'makeExecutor' method in Util,&lt;br /&gt;
# which accepts a String and returns an ExecutorService&lt;br /&gt;
public net.minecraft.Util m_137477_(Ljava/lang/String;)Ljava/util/concurrent/ExecutorService; # makeExecutor&lt;br /&gt;
&lt;br /&gt;
# Makes public the 'leastMostToIntArray' method in SerializableUUID,&lt;br /&gt;
# which accepts two longs and returns an int[]&lt;br /&gt;
public net.minecraft.core.SerializableUUID m_123274_(JJ)[I # leastMostToIntArray&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>SciWhiz12</name></author>
	</entry>
	<entry>
		<id>https://forge.gemwire.uk/index.php?title=Key_Mappings&amp;diff=2934</id>
		<title>Key Mappings</title>
		<link rel="alternate" type="text/html" href="https://forge.gemwire.uk/index.php?title=Key_Mappings&amp;diff=2934"/>
		<updated>2021-08-29T13:35:34Z</updated>

		<summary type="html">&lt;p&gt;SciWhiz12: reword lead section&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;A '''key mapping''' or '''keybinding''' is the relation of an action to an input, such as a mouse click or a combination of key presses. The action for the keymapping is defined in the code, while the triggering input is configurable by the user through the [[:mc:Options#Controls|Controls menu]]. In the code, these key mappings are declared and represented by &amp;lt;code&amp;gt;KeyMapping&amp;lt;/code&amp;gt; instances&lt;br /&gt;
&lt;br /&gt;
A &amp;lt;code&amp;gt;KeyMapping&amp;lt;/code&amp;gt; can be declared with the following parameters:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Parameter !! Description&lt;br /&gt;
|-&lt;br /&gt;
| name || A translation key used to set the name of this key mapping (e.g. &amp;lt;code&amp;gt;key.modid.key_name&amp;lt;/code&amp;gt;).&lt;br /&gt;
|-&lt;br /&gt;
| keyConflictContext || Determines when the key mapping should conflict with another defined key mapping. By default, there are three values within &amp;lt;code&amp;gt;KeyConflictContext&amp;lt;/code&amp;gt;: &amp;lt;code&amp;gt;UNIVERSAL&amp;lt;/code&amp;gt; which are used in every context, &amp;lt;code&amp;gt;GUI&amp;lt;/code&amp;gt; which are used whenever a screen is open, and &amp;lt;code&amp;gt;IN_GAME&amp;lt;/code&amp;gt; whenever a screen is not open. Custom contexts can be created by implementing &amp;lt;code&amp;gt;IKeyConflictContext&amp;lt;/code&amp;gt;.&lt;br /&gt;
|-&lt;br /&gt;
| key || Determines the input context this mapping will declare by default. This is a combination of the input type, input code, and any additional modifiers. There are three possible values for the input type: &amp;lt;code&amp;gt;KEYSYM&amp;lt;/code&amp;gt; which represents a mapped key, &amp;lt;code&amp;gt;SCANCODE&amp;lt;/code&amp;gt; which represents the value emitted by the keyboard itself, and &amp;lt;code&amp;gt;MOUSE&amp;lt;/code&amp;gt; which represents a mouse click. The associated input codes and modifiers are based on the specified input type as mapped by &amp;lt;code&amp;gt;GLFW&amp;lt;/code&amp;gt;.&lt;br /&gt;
|-&lt;br /&gt;
| category || A translation key representing the category this key is located in (e.g. &amp;lt;code&amp;gt;key.modid.categories.category_name&amp;lt;/code&amp;gt;).&lt;br /&gt;
|}&lt;br /&gt;
{{Tip|If you would like there to be no mapping by default, use a constructor that contains &amp;lt;code&amp;gt;InputConstants$Key&amp;lt;/code&amp;gt; instead and supply &amp;lt;code&amp;gt;InputConstants#UNKNOWN&amp;lt;/code&amp;gt; as the argument.}}&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;KeyMapping&amp;lt;/code&amp;gt; can then be registered using &amp;lt;code&amp;gt;ClientRegistry::registerKeyBinding&amp;lt;/code&amp;gt; within &amp;lt;code&amp;gt;FMLClientSetupEvent&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Using Registered Mappings ==&lt;br /&gt;
&lt;br /&gt;
There are two contexts in which a key mapping can be used normally: in or not in a screen. As such, there are two ways to handle these mappings. When not in a screen, &amp;lt;code&amp;gt;ClientTickEvent&amp;lt;/code&amp;gt; should be used to determine whether the key is down using &amp;lt;code&amp;gt;KeyMapping#isDown&amp;lt;/code&amp;gt;. If within a screen, the following logic can be applied using &amp;lt;code&amp;gt;KeyMapping#isActiveAndMatches&amp;lt;/code&amp;gt; within &amp;lt;code&amp;gt;GuiEventListener#keyPressed&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;GuiEventListener#mouseClicked&amp;lt;/code&amp;gt; for mouse input. Note that the necessary &amp;lt;code&amp;gt;InputConstants$Key&amp;lt;/code&amp;gt; can be constructed using &amp;lt;code&amp;gt;InputConstants::getKey&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;InputConstants$Type::getOrCreate&amp;lt;/code&amp;gt; respectively.&lt;/div&gt;</summary>
		<author><name>SciWhiz12</name></author>
	</entry>
	<entry>
		<id>https://forge.gemwire.uk/index.php?title=Access_Transformers&amp;diff=2921</id>
		<title>Access Transformers</title>
		<link rel="alternate" type="text/html" href="https://forge.gemwire.uk/index.php?title=Access_Transformers&amp;diff=2921"/>
		<updated>2021-08-13T03:06:51Z</updated>

		<summary type="html">&lt;p&gt;SciWhiz12: whoops, switched the two wildcards&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Access transformers''' (abbreviated as ''ATs'') are declarations for modifying or transforming the access visibility or finality of a class member (classes, fields, methods). These declarations are parsed by a transformer and applied to classes using the ASM library, either modifying the class files on-disk or modifying the class bytes during runtime.&lt;br /&gt;
&lt;br /&gt;
The [https://github.com/MinecraftForge/AccessTransformers AccessTransformers] library provides a pluggable ModLauncher transformation service and a command-line application for applying access transformers on class bytes during runtime and on class files on-disk.&lt;br /&gt;
&lt;br /&gt;
== Background ==&lt;br /&gt;
Java provides the mechanism of '''access level modifiers''' (or ''access modifiers''), to modify the ''visibility'' of a member with the modifier to other classes. This is commonly used to hide fields and methods from other classes, such as instance fields for [[:wikipedia:encapsulation|encapsulation]] or private methods which are part of the implementation of the class and should not be exposed to callers.&lt;br /&gt;
&lt;br /&gt;
A member can be declared with any of the modifier keywords &amp;lt;code&amp;gt;public&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;private&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;protected&amp;lt;/code&amp;gt; to set the access level of the member, or none of the keywords, which defaults to a ''package-private'' access level.&lt;br /&gt;
&lt;br /&gt;
The following table shows the different access levels and their modifiers, and what classes may access members with that access level:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;text-align:center;&amp;quot;&lt;br /&gt;
|+ Access levels&lt;br /&gt;
! Access modifier&lt;br /&gt;
! Within the same class&lt;br /&gt;
! Subclasses&lt;br /&gt;
! Classes in the same package&lt;br /&gt;
! All other classes&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;public&amp;lt;/code&amp;gt;&lt;br /&gt;
| style=&amp;quot;color:limegreen&amp;quot; | '''Yes'''&lt;br /&gt;
| style=&amp;quot;color:limegreen&amp;quot; | '''Yes'''&lt;br /&gt;
| style=&amp;quot;color:limegreen&amp;quot; | '''Yes'''&lt;br /&gt;
| style=&amp;quot;color:limegreen&amp;quot; | '''Yes'''&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;protected&amp;lt;/code&amp;gt;&lt;br /&gt;
| style=&amp;quot;color:limegreen&amp;quot; | '''Yes'''&lt;br /&gt;
| style=&amp;quot;color:limegreen&amp;quot; | '''Yes'''&lt;br /&gt;
| style=&amp;quot;color:limegreen&amp;quot; | '''Yes'''&lt;br /&gt;
| style=&amp;quot;color:indianred&amp;quot; | '''No'''&lt;br /&gt;
|-&lt;br /&gt;
| ''no modifier''&lt;br /&gt;
| style=&amp;quot;color:limegreen&amp;quot; | '''Yes'''&lt;br /&gt;
| style=&amp;quot;color:limegreen&amp;quot; | '''Yes'''&lt;br /&gt;
| style=&amp;quot;color:indianred&amp;quot; | '''No'''&lt;br /&gt;
| style=&amp;quot;color:indianred&amp;quot; | '''No'''&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;private&amp;lt;/code&amp;gt;&lt;br /&gt;
| style=&amp;quot;color:limegreen&amp;quot; | '''Yes'''&lt;br /&gt;
| style=&amp;quot;color:indianred&amp;quot; | '''No'''&lt;br /&gt;
| style=&amp;quot;color:indianred&amp;quot; | '''No'''&lt;br /&gt;
| style=&amp;quot;color:indianred&amp;quot; | '''No'''&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
For example, a field marked &amp;lt;code&amp;gt;protected&amp;lt;/code&amp;gt; cannot be accessed by a class in another package, but can be accessed by: any class within the same package, any subclass of the class (even if the subclass belongs to another package), and within the same class where the field is declared.&lt;br /&gt;
&lt;br /&gt;
Additionally to the access modifiers, there exists the &amp;lt;code&amp;gt;final&amp;lt;/code&amp;gt; keyword, which:&lt;br /&gt;
* on classes, prevents any subclassing of the class;&lt;br /&gt;
* on fields, marks it as being assignable only once during construction; and&lt;br /&gt;
* on methods, prevents any subclasses from overriding the method with their own implementation.&lt;br /&gt;
&lt;br /&gt;
Normally, Java programmers restrict access levels to be as restrictive as they need to be, controlling what is the effective publicly-available surface for the application. For example, a field may be declared as &amp;lt;code&amp;gt;private&amp;lt;/code&amp;gt; while providing setter and getter methods to access the field (a technique known as encapsulation).&lt;br /&gt;
&lt;br /&gt;
However, this convention of restricting access levels and marking members as &amp;lt;code&amp;gt;final&amp;lt;/code&amp;gt; where approriate presents a problem with modding Minecraft, because they restrict what parts of the game that modders can access or modify, usually without other means to access or modify them (such as setters and getters for fields).&lt;br /&gt;
&lt;br /&gt;
One solution is to use Java [[:wikipedia:reflection|reflection]] to reflectively access these fields and methods during runtime, but they suffer from some problems:&lt;br /&gt;
* Reflection is slower than regular method calls or field accesses, as certain optimizations done by the JVM cannot be applied.&amp;lt;ref&amp;gt;[https://docs.oracle.com/javase/tutorial/reflect/index.html The Java™ Tutorials: The Reflection API]: ''&amp;quot;Consequently, reflective operations have slower performance than their non-reflective counterparts, and should be avoided in sections of code which are called frequently in performance-sensitive applications.&amp;quot;''&amp;lt;/ref&amp;gt; This makes reflection unsuitable for performance-critical code, such as during rendering.&lt;br /&gt;
* Reflection cannot allow the modification of &amp;lt;code&amp;gt;final&amp;lt;/code&amp;gt; fields which are either marked &amp;lt;code&amp;gt;static&amp;lt;/code&amp;gt; or belong to a record class.&amp;lt;ref&amp;gt;[https://docs.oracle.com/en/java/javase/16/docs/api/java.base/java/lang/reflect/AccessibleObject.html#setAccessible(boolean) Java 16 javadocs] for &amp;lt;code&amp;gt;java.lang.reflect.AccessibleObject.setAccessible(boolean)&amp;lt;/code&amp;gt;&amp;lt;/ref&amp;gt;&lt;br /&gt;
* Runtime reflection loses the benefit of compile-time type checks, which allows dangerous operations such as trying to set a field's value to an incompatible type.&lt;br /&gt;
* The use of reflection does not allow a class to extend a non-visible class.&lt;br /&gt;
&lt;br /&gt;
These problems are solved with the use of access transformers, which allow modification of the access modifiers of members such that they can be applied on class files on-disk to allow compiling against them, and applying the same transformer declarations on class bytes during runtime to allow classes which compiled against those transformed classes to work correctly.&lt;br /&gt;
&lt;br /&gt;
== Usage ==&lt;br /&gt;
&lt;br /&gt;
To use access transformers in the development environment, ForgeGradle must be configured with the location of the access transformer configuration file (or files). Because FML is hardwired to look for the configuration file at &amp;lt;code&amp;gt;META-INF/accesstransformer.cfg&amp;lt;/code&amp;gt; within JAR files, it is recommended that the AT configuration file for the project be placed at the same location: within the resources folder of the main source set, or &amp;lt;code&amp;gt;src/main/resources/META-INF/accesstransformer.cfg&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
To configure the location of the access transformer configuration file with ForgeGradle:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;gradle&amp;quot;&amp;gt;&lt;br /&gt;
minecraft { // Within the minecraft block&lt;br /&gt;
    // Configures FG to look at the given file path for the AT configuration file&lt;br /&gt;
    accessTransformer = file(&amp;quot;src/main/resources/META-INF/accesstransformer.cfg&amp;quot;)&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Access-transformers-uncomment-this-line-in-build-gradle.png|thumb|300px]]&lt;br /&gt;
&lt;br /&gt;
The Forge-provided mod development environment's buildscript contains the above line but commented out, as the MDK does not ship with an access transformer file. Users of the MDK can therefore uncomment out the above line and create the AT configuration file at the same location. &lt;br /&gt;
&lt;br /&gt;
Once the configuration file(s) has been added and everytime the contents or location of the file(s) changes, the developer should then refresh the Gradle nature/project in their IDE of choice for ForgeGradle to apply the access transformers to the compiled source. Each change to the access transformer configuration will trigger a full decompilation of the game.&lt;br /&gt;
&lt;br /&gt;
== Declarations ==&lt;br /&gt;
&lt;br /&gt;
Access transformers are declared line-by-line in configuration files, which are then parsed by ForgeGradle in the development environment and by FML in the production or end-user environment.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;#&amp;lt;/code&amp;gt; character and any content after that up to the end of the line is considered a comment, and will be ignored by the parser. Any lines which are either empty or consist of only whitespace or comments are ignored.&lt;br /&gt;
&lt;br /&gt;
An access transformer declaration has three different variations, depending on the target to be transformed:&lt;br /&gt;
&lt;br /&gt;
* for '''classes''': &amp;lt;code&amp;gt;''&amp;lt;modifier&amp;gt;'' ''&amp;lt;class name&amp;gt;''&amp;lt;/code&amp;gt;&lt;br /&gt;
* for '''methods''': &amp;lt;code&amp;gt;''&amp;lt;modifier&amp;gt;'' ''&amp;lt;class name&amp;gt;'' ''&amp;lt;method name&amp;gt;'''''('''''[parameter descriptors]''''')'''''&amp;amp;lt;return descriptor&amp;gt;''&amp;lt;/code&amp;gt;&lt;br /&gt;
* for '''fields''': &amp;lt;code&amp;gt;''&amp;lt;modifier&amp;gt;'' ''&amp;lt;class name&amp;gt;'' ''&amp;lt;field name&amp;gt;''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The modifier consists of one of the following words:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;public&amp;lt;/code&amp;gt; for the ''public'' access level (denoted by the modifier keyword of the same name)&lt;br /&gt;
* &amp;lt;code&amp;gt;protected&amp;lt;/code&amp;gt; for the ''protected'' access level (denoted by the modifier keyword of the same name)&lt;br /&gt;
* &amp;lt;code&amp;gt;default&amp;lt;/code&amp;gt; for the ''package-private'' access level (denoted by the absence of an access modifier keyword)&lt;br /&gt;
* &amp;lt;code&amp;gt;private&amp;lt;/code&amp;gt; for the ''private'' access level (denoted by the modifier keyword of the same name)&lt;br /&gt;
* For any of the preceding words, the &amp;lt;code&amp;gt;-f&amp;lt;/code&amp;gt; suffix removes the &amp;lt;code&amp;gt;final&amp;lt;/code&amp;gt; modifier, while the &amp;lt;code&amp;gt;+f&amp;lt;/code&amp;gt; suffix adds the modifier.&lt;br /&gt;
&lt;br /&gt;
The class name is the fully qualified name of the class, using &amp;lt;code&amp;gt;.&amp;lt;/code&amp;gt; (dots) to separate between (sub)packages and classes (for example, &amp;lt;code&amp;gt;java.lang.Object&amp;lt;/code&amp;gt;). &lt;br /&gt;
&lt;br /&gt;
For methods, the method descriptor&amp;lt;ref&amp;gt;''[https://docs.oracle.com/javase/specs/jvms/se16/html/jvms-4.html#jvms-4.3.3 Java Virtual Machine Specification, Java SE 16 Edition]'', 4.3.3. Method Descriptors &amp;lt;/ref&amp;gt; of the method is included, which consists of the descriptors for each of the method's parameters and the method's return type. The method parameters descriptors can be absent if there are no parameters in the method, but the return type descriptor must be present.&lt;br /&gt;
&lt;br /&gt;
The following are the matching descriptors for each type as seen in the method declaration:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ Matching type descriptors&lt;br /&gt;
! Descriptor&lt;br /&gt;
! Source form&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;Z&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;boolean&amp;lt;/code&amp;gt; || a &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;false&amp;lt;/code&amp;gt; value&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;B&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;byte&amp;lt;/code&amp;gt; || a 8-bit signed number&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;S&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;short&amp;lt;/code&amp;gt; || a 16-bit signed number&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;C&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;char&amp;lt;/code&amp;gt; || a Unicode character code point in UTF-16&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;I&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;int&amp;lt;/code&amp;gt; || a 32-bit signed number&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;F&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;float&amp;lt;/code&amp;gt; || a single-precision floating-point value&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;J&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;long&amp;lt;/code&amp;gt; || a 64-bit signed number&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;D&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;double&amp;lt;/code&amp;gt; || a double-precision floating-point value&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;[''I''&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;''int''[]&amp;lt;/code&amp;gt; || one dimension of an array; this can be repeated, and must end with another descriptor other than an array&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;L''java/lang/Object'';&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;java.lang.Object&amp;lt;/code&amp;gt; || a reference type; the internal form of the class' binary name must be present (in the given example, the class referenced is &amp;lt;code&amp;gt;java.lang.Object&amp;lt;/code&amp;gt;. &lt;br /&gt;
Note that inner classes are separated using the &amp;lt;code&amp;gt;$&amp;lt;/code&amp;gt; (dollar sign) character, such as &amp;lt;code&amp;gt;java/lang/System$Logger&amp;lt;/code&amp;gt;.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;V&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;void&amp;lt;/code&amp;gt; || a void or no-value return type; only available for the return type of a method descriptor&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{{Tip/Danger&lt;br /&gt;
|title=Wildcard access transformers&lt;br /&gt;
|A special type of access transformers called '''wildcard ATs''' (oftentimes referred to as '''shotgun ATs''' allows transforming the access modifier and finality of ''all'' fields or methods within a class.&lt;br /&gt;
&lt;br /&gt;
To use wildcard access transformers:&lt;br /&gt;
* for all methods within a class: &amp;lt;code&amp;gt;''&amp;lt;modifier&amp;gt;'' ''&amp;lt;class name&amp;gt;'' '''*()'''&amp;lt;/code&amp;gt;&lt;br /&gt;
* for all fields within a class: &amp;lt;code&amp;gt;''&amp;lt;modifier&amp;gt;'' ''&amp;lt;class name&amp;gt;'' '''*'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Modders should avoid using this in live code.''' Access transformers should always have the fewest and narrowest targets possible, and wildcard ATs violate this convention. Use of wildcard ATs may cause problems with both the ForgeGradle setup process. Wildcard ATs may be removed in a future update of the access transformer specification.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
== Examples ==&lt;br /&gt;
&lt;br /&gt;
The following are some examples of access transformer declarations:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
# Makes public the ScreenConstructor class in MenuScreens&lt;br /&gt;
public net.minecraft.client.gui.screens.MenuScreens$ScreenConstructor&lt;br /&gt;
&lt;br /&gt;
# Makes protected the 'COLOR_WHITE' field in Gui&lt;br /&gt;
protected net.minecraft.client.gui.Gui f_168667_ # COLOR_WHITE&lt;br /&gt;
&lt;br /&gt;
# Makes protected and removes the final modifier from 'random' field in MinecraftServer&lt;br /&gt;
protected-f net.minecraft.server.MinecraftServer f_129758_ # random&lt;br /&gt;
&lt;br /&gt;
# Makes public the 'makeExecutor' method in Util,&lt;br /&gt;
# which accepts a String and returns an ExecutorService&lt;br /&gt;
public net.minecraft.Util m_137477_(Ljava/lang/String;)Ljava/util/concurrent/ExecutorService; # makeExecutor&lt;br /&gt;
&lt;br /&gt;
# Makes public the 'leastMostToIntArray' method in SerializableUUID,&lt;br /&gt;
# which accepts two longs and returns an int[]&lt;br /&gt;
public net.minecraft.core.SerializableUUID m_123274_(JJ)[I # leastMostToIntArray&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>SciWhiz12</name></author>
	</entry>
	<entry>
		<id>https://forge.gemwire.uk/index.php?title=FCWMeta:User_access_levels&amp;diff=2920</id>
		<title>FCWMeta:User access levels</title>
		<link rel="alternate" type="text/html" href="https://forge.gemwire.uk/index.php?title=FCWMeta:User_access_levels&amp;diff=2920"/>
		<updated>2021-08-13T03:05:48Z</updated>

		<summary type="html">&lt;p&gt;SciWhiz12: add links to members list for each user group&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;The '''user access level''' of an editor determines what abilities they have and what actions they can perform. Each user access level, or '''user group''', has permissions/rights which are assigned. See [[Special:ListGroupRights]] to see all the available user groups and their permissions/rights.&lt;br /&gt;
&lt;br /&gt;
== Administrators and Moderators ==&lt;br /&gt;
'''Administrators''' and '''Moderators''' are editors who have broad rights over the whole wiki, such as protection, deletion, moving of pages, blocking and unblocking of users, and more. Administrators have more sensitive rights, and can assign and remove Moderators.&lt;br /&gt;
&lt;br /&gt;
These editors are part of the ''wiki staff'', which determine the policies of this wiki, enforce any binding decisions, keep the peace of the wiki, and moderate and curate its contents.&lt;br /&gt;
&lt;br /&gt;
The wiki staff may decide, from time to time, to grant Moderator status to active, reputable, and responsible editors. Requests for staff access level will not be entertained, however endorsements for other editors' may be considered.&lt;br /&gt;
&lt;br /&gt;
There are currently [[Special:ListUsers/administrator|'''{{NUMBERINGROUP:administrator}}''' administrators]] and [[Special:ListUsers/moderator|'''{{NUMBERINGROUP:moderator}}''' moderators]].&lt;br /&gt;
&lt;br /&gt;
== Trusted users ==&lt;br /&gt;
'''Trusted users''' are editors who have been active in their contributions or are reputable members of the community, and has the trust of the wiki staff. They have the rights to edit semi-protected pages, and patrol changes.&lt;br /&gt;
&lt;br /&gt;
If you have been especially active in contributing, a staff member may grant this access level to you. You may also request this access level by contacting one of the staff; however, repeated requests may warrant sanctions.&lt;br /&gt;
&lt;br /&gt;
There are currently [[Special:ListUsers/trusted|'''{{NUMBERINGROUP:trusted}}''' trusted users]].&lt;br /&gt;
&lt;br /&gt;
== Special access levels ==&lt;br /&gt;
These access levels are specially granted to users by decision of the wiki staff. Requests for these access levels will not be considered, and may warrant sanctions.&lt;br /&gt;
&lt;br /&gt;
==== Keepers of the Keys ====&lt;br /&gt;
The '''Keepers of the Keys''' are administrators who have the rights to assign and remove access levels from all other users, including other administarotrs. &lt;br /&gt;
&lt;br /&gt;
The origin of this access group is derived from the principle of there being multiple administrators with high-level access to the wiki, to ensure that there is always someone available to administer the wiki and if necessary, take control of the wiki if the other administrators are out-of-contact and unreachable.&lt;br /&gt;
&lt;br /&gt;
There are currently [[Special:ListUsers/root|'''{{NUMBERINGROUP:root}}''' keepers of the keys]].&lt;br /&gt;
&lt;br /&gt;
==== Interface administrators ====&lt;br /&gt;
'''Interface administrators''' are editors who are given editing access to the MediaWiki interface CSS and JS files, through the &amp;lt;code&amp;gt;MediaWiki&amp;lt;/code&amp;gt; namespace.&lt;br /&gt;
&lt;br /&gt;
There are currently [[Special:ListUsers/interface-admin|'''{{NUMBERINGROUP:interface-admin}}''' interface administrators]].&lt;br /&gt;
&lt;br /&gt;
==== Check users ====&lt;br /&gt;
'''Check users''' are editors who have access to a log that lists out usernames used by which IPs and IPs used by which usernames. As this tool can be used to personally identify users through their IP, access is restricted to those who may need need, and use of the checkuser tool is strictly monitored.&lt;br /&gt;
&lt;br /&gt;
There are currently [[Special:ListUsers/checkuser|'''{{NUMBERINGROUP:checkuser}}''' check users]].&lt;br /&gt;
&lt;br /&gt;
==== Suppressors ====&lt;br /&gt;
'''Suppressors''' are editors who can hide revisions and log entries from users (and even administrators), in cases such as personal information being posted. As this is a powerful tool, access is restricted to those who may need it, and use of the suppression tools are strictly monitored.&lt;br /&gt;
&lt;br /&gt;
There are currently [[Special:ListUsers/suppress|'''{{NUMBERINGROUP:suppress}}''' suppressors]].&lt;br /&gt;
&lt;br /&gt;
==== Autoconfirmed users ====&lt;br /&gt;
'''Autoconfirmed users''' are editors who have at least 5 edits and their account is at least 14 days old.&lt;br /&gt;
Currently, these users are only not affected by IP-based rate limits (the &amp;lt;code&amp;gt;autoconfirmed&amp;lt;/code&amp;gt; right).&lt;br /&gt;
&lt;br /&gt;
There are currently [[Special:ListUsers/autoconfirmed|'''{{NUMBERINGROUP:autoconfirmed}}''' autoconfirmed users]].&lt;br /&gt;
&lt;br /&gt;
==== Bots ====&lt;br /&gt;
'''Bots''' are programs that do automated or mass-editing tasks, which may be tedious or impossible to perform manually.&lt;br /&gt;
&lt;br /&gt;
There are currently [[Special:ListUsers/bot|'''{{NUMBERINGROUP:bot}}''' bots]].&lt;/div&gt;</summary>
		<author><name>SciWhiz12</name></author>
	</entry>
	<entry>
		<id>https://forge.gemwire.uk/index.php?title=Access_Transformers&amp;diff=2919</id>
		<title>Access Transformers</title>
		<link rel="alternate" type="text/html" href="https://forge.gemwire.uk/index.php?title=Access_Transformers&amp;diff=2919"/>
		<updated>2021-08-13T02:56:33Z</updated>

		<summary type="html">&lt;p&gt;SciWhiz12: add note about wildcard ATs&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Access transformers''' (abbreviated as ''ATs'') are declarations for modifying or transforming the access visibility or finality of a class member (classes, fields, methods). These declarations are parsed by a transformer and applied to classes using the ASM library, either modifying the class files on-disk or modifying the class bytes during runtime.&lt;br /&gt;
&lt;br /&gt;
The [https://github.com/MinecraftForge/AccessTransformers AccessTransformers] library provides a pluggable ModLauncher transformation service and a command-line application for applying access transformers on class bytes during runtime and on class files on-disk.&lt;br /&gt;
&lt;br /&gt;
== Background ==&lt;br /&gt;
Java provides the mechanism of '''access level modifiers''' (or ''access modifiers''), to modify the ''visibility'' of a member with the modifier to other classes. This is commonly used to hide fields and methods from other classes, such as instance fields for [[:wikipedia:encapsulation|encapsulation]] or private methods which are part of the implementation of the class and should not be exposed to callers.&lt;br /&gt;
&lt;br /&gt;
A member can be declared with any of the modifier keywords &amp;lt;code&amp;gt;public&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;private&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;protected&amp;lt;/code&amp;gt; to set the access level of the member, or none of the keywords, which defaults to a ''package-private'' access level.&lt;br /&gt;
&lt;br /&gt;
The following table shows the different access levels and their modifiers, and what classes may access members with that access level:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;text-align:center;&amp;quot;&lt;br /&gt;
|+ Access levels&lt;br /&gt;
! Access modifier&lt;br /&gt;
! Within the same class&lt;br /&gt;
! Subclasses&lt;br /&gt;
! Classes in the same package&lt;br /&gt;
! All other classes&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;public&amp;lt;/code&amp;gt;&lt;br /&gt;
| style=&amp;quot;color:limegreen&amp;quot; | '''Yes'''&lt;br /&gt;
| style=&amp;quot;color:limegreen&amp;quot; | '''Yes'''&lt;br /&gt;
| style=&amp;quot;color:limegreen&amp;quot; | '''Yes'''&lt;br /&gt;
| style=&amp;quot;color:limegreen&amp;quot; | '''Yes'''&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;protected&amp;lt;/code&amp;gt;&lt;br /&gt;
| style=&amp;quot;color:limegreen&amp;quot; | '''Yes'''&lt;br /&gt;
| style=&amp;quot;color:limegreen&amp;quot; | '''Yes'''&lt;br /&gt;
| style=&amp;quot;color:limegreen&amp;quot; | '''Yes'''&lt;br /&gt;
| style=&amp;quot;color:indianred&amp;quot; | '''No'''&lt;br /&gt;
|-&lt;br /&gt;
| ''no modifier''&lt;br /&gt;
| style=&amp;quot;color:limegreen&amp;quot; | '''Yes'''&lt;br /&gt;
| style=&amp;quot;color:limegreen&amp;quot; | '''Yes'''&lt;br /&gt;
| style=&amp;quot;color:indianred&amp;quot; | '''No'''&lt;br /&gt;
| style=&amp;quot;color:indianred&amp;quot; | '''No'''&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;private&amp;lt;/code&amp;gt;&lt;br /&gt;
| style=&amp;quot;color:limegreen&amp;quot; | '''Yes'''&lt;br /&gt;
| style=&amp;quot;color:indianred&amp;quot; | '''No'''&lt;br /&gt;
| style=&amp;quot;color:indianred&amp;quot; | '''No'''&lt;br /&gt;
| style=&amp;quot;color:indianred&amp;quot; | '''No'''&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
For example, a field marked &amp;lt;code&amp;gt;protected&amp;lt;/code&amp;gt; cannot be accessed by a class in another package, but can be accessed by: any class within the same package, any subclass of the class (even if the subclass belongs to another package), and within the same class where the field is declared.&lt;br /&gt;
&lt;br /&gt;
Additionally to the access modifiers, there exists the &amp;lt;code&amp;gt;final&amp;lt;/code&amp;gt; keyword, which:&lt;br /&gt;
* on classes, prevents any subclassing of the class;&lt;br /&gt;
* on fields, marks it as being assignable only once during construction; and&lt;br /&gt;
* on methods, prevents any subclasses from overriding the method with their own implementation.&lt;br /&gt;
&lt;br /&gt;
Normally, Java programmers restrict access levels to be as restrictive as they need to be, controlling what is the effective publicly-available surface for the application. For example, a field may be declared as &amp;lt;code&amp;gt;private&amp;lt;/code&amp;gt; while providing setter and getter methods to access the field (a technique known as encapsulation).&lt;br /&gt;
&lt;br /&gt;
However, this convention of restricting access levels and marking members as &amp;lt;code&amp;gt;final&amp;lt;/code&amp;gt; where approriate presents a problem with modding Minecraft, because they restrict what parts of the game that modders can access or modify, usually without other means to access or modify them (such as setters and getters for fields).&lt;br /&gt;
&lt;br /&gt;
One solution is to use Java [[:wikipedia:reflection|reflection]] to reflectively access these fields and methods during runtime, but they suffer from some problems:&lt;br /&gt;
* Reflection is slower than regular method calls or field accesses, as certain optimizations done by the JVM cannot be applied.&amp;lt;ref&amp;gt;[https://docs.oracle.com/javase/tutorial/reflect/index.html The Java™ Tutorials: The Reflection API]: ''&amp;quot;Consequently, reflective operations have slower performance than their non-reflective counterparts, and should be avoided in sections of code which are called frequently in performance-sensitive applications.&amp;quot;''&amp;lt;/ref&amp;gt; This makes reflection unsuitable for performance-critical code, such as during rendering.&lt;br /&gt;
* Reflection cannot allow the modification of &amp;lt;code&amp;gt;final&amp;lt;/code&amp;gt; fields which are either marked &amp;lt;code&amp;gt;static&amp;lt;/code&amp;gt; or belong to a record class.&amp;lt;ref&amp;gt;[https://docs.oracle.com/en/java/javase/16/docs/api/java.base/java/lang/reflect/AccessibleObject.html#setAccessible(boolean) Java 16 javadocs] for &amp;lt;code&amp;gt;java.lang.reflect.AccessibleObject.setAccessible(boolean)&amp;lt;/code&amp;gt;&amp;lt;/ref&amp;gt;&lt;br /&gt;
* Runtime reflection loses the benefit of compile-time type checks, which allows dangerous operations such as trying to set a field's value to an incompatible type.&lt;br /&gt;
* The use of reflection does not allow a class to extend a non-visible class.&lt;br /&gt;
&lt;br /&gt;
These problems are solved with the use of access transformers, which allow modification of the access modifiers of members such that they can be applied on class files on-disk to allow compiling against them, and applying the same transformer declarations on class bytes during runtime to allow classes which compiled against those transformed classes to work correctly.&lt;br /&gt;
&lt;br /&gt;
== Usage ==&lt;br /&gt;
&lt;br /&gt;
To use access transformers in the development environment, ForgeGradle must be configured with the location of the access transformer configuration file (or files). Because FML is hardwired to look for the configuration file at &amp;lt;code&amp;gt;META-INF/accesstransformer.cfg&amp;lt;/code&amp;gt; within JAR files, it is recommended that the AT configuration file for the project be placed at the same location: within the resources folder of the main source set, or &amp;lt;code&amp;gt;src/main/resources/META-INF/accesstransformer.cfg&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
To configure the location of the access transformer configuration file with ForgeGradle:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;gradle&amp;quot;&amp;gt;&lt;br /&gt;
minecraft { // Within the minecraft block&lt;br /&gt;
    // Configures FG to look at the given file path for the AT configuration file&lt;br /&gt;
    accessTransformer = file(&amp;quot;src/main/resources/META-INF/accesstransformer.cfg&amp;quot;)&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Access-transformers-uncomment-this-line-in-build-gradle.png|thumb|300px]]&lt;br /&gt;
&lt;br /&gt;
The Forge-provided mod development environment's buildscript contains the above line but commented out, as the MDK does not ship with an access transformer file. Users of the MDK can therefore uncomment out the above line and create the AT configuration file at the same location. &lt;br /&gt;
&lt;br /&gt;
Once the configuration file(s) has been added and everytime the contents or location of the file(s) changes, the developer should then refresh the Gradle nature/project in their IDE of choice for ForgeGradle to apply the access transformers to the compiled source. Each change to the access transformer configuration will trigger a full decompilation of the game.&lt;br /&gt;
&lt;br /&gt;
== Declarations ==&lt;br /&gt;
&lt;br /&gt;
Access transformers are declared line-by-line in configuration files, which are then parsed by ForgeGradle in the development environment and by FML in the production or end-user environment.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;#&amp;lt;/code&amp;gt; character and any content after that up to the end of the line is considered a comment, and will be ignored by the parser. Any lines which are either empty or consist of only whitespace or comments are ignored.&lt;br /&gt;
&lt;br /&gt;
An access transformer declaration has three different variations, depending on the target to be transformed:&lt;br /&gt;
&lt;br /&gt;
* for '''classes''': &amp;lt;code&amp;gt;''&amp;lt;modifier&amp;gt;'' ''&amp;lt;class name&amp;gt;''&amp;lt;/code&amp;gt;&lt;br /&gt;
* for '''methods''': &amp;lt;code&amp;gt;''&amp;lt;modifier&amp;gt;'' ''&amp;lt;class name&amp;gt;'' ''&amp;lt;method name&amp;gt;'''''('''''[parameter descriptors]''''')'''''&amp;amp;lt;return descriptor&amp;gt;''&amp;lt;/code&amp;gt;&lt;br /&gt;
* for '''fields''': &amp;lt;code&amp;gt;''&amp;lt;modifier&amp;gt;'' ''&amp;lt;class name&amp;gt;'' ''&amp;lt;field name&amp;gt;''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The modifier consists of one of the following words:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;public&amp;lt;/code&amp;gt; for the ''public'' access level (denoted by the modifier keyword of the same name)&lt;br /&gt;
* &amp;lt;code&amp;gt;protected&amp;lt;/code&amp;gt; for the ''protected'' access level (denoted by the modifier keyword of the same name)&lt;br /&gt;
* &amp;lt;code&amp;gt;default&amp;lt;/code&amp;gt; for the ''package-private'' access level (denoted by the absence of an access modifier keyword)&lt;br /&gt;
* &amp;lt;code&amp;gt;private&amp;lt;/code&amp;gt; for the ''private'' access level (denoted by the modifier keyword of the same name)&lt;br /&gt;
* For any of the preceding words, the &amp;lt;code&amp;gt;-f&amp;lt;/code&amp;gt; suffix removes the &amp;lt;code&amp;gt;final&amp;lt;/code&amp;gt; modifier, while the &amp;lt;code&amp;gt;+f&amp;lt;/code&amp;gt; suffix adds the modifier.&lt;br /&gt;
&lt;br /&gt;
The class name is the fully qualified name of the class, using &amp;lt;code&amp;gt;.&amp;lt;/code&amp;gt; (dots) to separate between (sub)packages and classes (for example, &amp;lt;code&amp;gt;java.lang.Object&amp;lt;/code&amp;gt;). &lt;br /&gt;
&lt;br /&gt;
For methods, the method descriptor&amp;lt;ref&amp;gt;''[https://docs.oracle.com/javase/specs/jvms/se16/html/jvms-4.html#jvms-4.3.3 Java Virtual Machine Specification, Java SE 16 Edition]'', 4.3.3. Method Descriptors &amp;lt;/ref&amp;gt; of the method is included, which consists of the descriptors for each of the method's parameters and the method's return type. The method parameters descriptors can be absent if there are no parameters in the method, but the return type descriptor must be present.&lt;br /&gt;
&lt;br /&gt;
The following are the matching descriptors for each type as seen in the method declaration:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ Matching type descriptors&lt;br /&gt;
! Descriptor&lt;br /&gt;
! Source form&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;Z&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;boolean&amp;lt;/code&amp;gt; || a &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;false&amp;lt;/code&amp;gt; value&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;B&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;byte&amp;lt;/code&amp;gt; || a 8-bit signed number&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;S&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;short&amp;lt;/code&amp;gt; || a 16-bit signed number&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;C&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;char&amp;lt;/code&amp;gt; || a Unicode character code point in UTF-16&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;I&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;int&amp;lt;/code&amp;gt; || a 32-bit signed number&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;F&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;float&amp;lt;/code&amp;gt; || a single-precision floating-point value&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;J&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;long&amp;lt;/code&amp;gt; || a 64-bit signed number&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;D&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;double&amp;lt;/code&amp;gt; || a double-precision floating-point value&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;[''I''&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;''int''[]&amp;lt;/code&amp;gt; || one dimension of an array; this can be repeated, and must end with another descriptor other than an array&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;L''java/lang/Object'';&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;java.lang.Object&amp;lt;/code&amp;gt; || a reference type; the internal form of the class' binary name must be present (in the given example, the class referenced is &amp;lt;code&amp;gt;java.lang.Object&amp;lt;/code&amp;gt;. &lt;br /&gt;
Note that inner classes are separated using the &amp;lt;code&amp;gt;$&amp;lt;/code&amp;gt; (dollar sign) character, such as &amp;lt;code&amp;gt;java/lang/System$Logger&amp;lt;/code&amp;gt;.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;V&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;void&amp;lt;/code&amp;gt; || a void or no-value return type; only available for the return type of a method descriptor&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{{Tip/Danger&lt;br /&gt;
|title=Wildcard access transformers&lt;br /&gt;
|A special type of access transformers called '''wildcard ATs''' (oftentimes referred to as '''shotgun ATs''' allows transforming the access modifier and finality of ''all'' fields or methods within a class.&lt;br /&gt;
&lt;br /&gt;
To use wildcard access transformers:&lt;br /&gt;
* for all methods within a class: &amp;lt;code&amp;gt;''&amp;lt;modifier&amp;gt;'' ''&amp;lt;class name&amp;gt;'' '''*'''&amp;lt;/code&amp;gt;&lt;br /&gt;
* for all fields within a class: &amp;lt;code&amp;gt;''&amp;lt;modifier&amp;gt;'' ''&amp;lt;class name&amp;gt;'' '''*()'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Modders should avoid using this in live code.''' Access transformers should always have the fewest and narrowest targets possible, and wildcard ATs violate this convention. Use of wildcard ATs may cause problems with both the ForgeGradle setup process. Wildcard ATs may be removed in a future update of the access transformer specification.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
== Examples ==&lt;br /&gt;
&lt;br /&gt;
The following are some examples of access transformer declarations:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
# Makes public the ScreenConstructor class in MenuScreens&lt;br /&gt;
public net.minecraft.client.gui.screens.MenuScreens$ScreenConstructor&lt;br /&gt;
&lt;br /&gt;
# Makes protected the 'COLOR_WHITE' field in Gui&lt;br /&gt;
protected net.minecraft.client.gui.Gui f_168667_ # COLOR_WHITE&lt;br /&gt;
&lt;br /&gt;
# Makes protected and removes the final modifier from 'random' field in MinecraftServer&lt;br /&gt;
protected-f net.minecraft.server.MinecraftServer f_129758_ # random&lt;br /&gt;
&lt;br /&gt;
# Makes public the 'makeExecutor' method in Util,&lt;br /&gt;
# which accepts a String and returns an ExecutorService&lt;br /&gt;
public net.minecraft.Util m_137477_(Ljava/lang/String;)Ljava/util/concurrent/ExecutorService; # makeExecutor&lt;br /&gt;
&lt;br /&gt;
# Makes public the 'leastMostToIntArray' method in SerializableUUID,&lt;br /&gt;
# which accepts two longs and returns an int[]&lt;br /&gt;
public net.minecraft.core.SerializableUUID m_123274_(JJ)[I # leastMostToIntArray&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>SciWhiz12</name></author>
	</entry>
	<entry>
		<id>https://forge.gemwire.uk/index.php?title=User:SciWhiz12/sandbox/policy&amp;diff=2918</id>
		<title>User:SciWhiz12/sandbox/policy</title>
		<link rel="alternate" type="text/html" href="https://forge.gemwire.uk/index.php?title=User:SciWhiz12/sandbox/policy&amp;diff=2918"/>
		<updated>2021-08-13T02:47:59Z</updated>

		<summary type="html">&lt;p&gt;SciWhiz12: Some formatting cleanup&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Wiki Policy =&lt;br /&gt;
&lt;br /&gt;
The Forge Community Wiki maintains this '''Wiki Policy''', which is the set of rules and principles which govern the operation, moderation, and community of the wiki.&lt;br /&gt;
&lt;br /&gt;
All wiki editors are required to follow this policy as a requirement for their contributions to this wiki. Editors which violate this policy will be sanctioned.&lt;br /&gt;
&lt;br /&gt;
== Principles ==&lt;br /&gt;
&lt;br /&gt;
The wiki operates on three main principles, which form the foundations of the this policy. Any rules and policies of the wiki will be consistent with these principles, and any interpretations of any such rule or policy should be done in the light of these three principles.&lt;br /&gt;
&lt;br /&gt;
If there is no relevant rule or policy that is applicable in a situation, wiki staff will use these three principles to guide their actions and decisions.&lt;br /&gt;
&lt;br /&gt;
=== Be respectful ===&lt;br /&gt;
All editors are expected to show and maintain a decent amount of respect to other editors. &lt;br /&gt;
&lt;br /&gt;
As with any online collaboration, there may be situations where editors will strongly disagree on some decision, topic, or other. In such situations, while both sides may be in disagreement with the other, they must remain civility in both their words and actions. Insults and derogatory remarks should always be avoided, and discussions must remain civil, especially in topics which may provoke animosity or heated debate.&lt;br /&gt;
&lt;br /&gt;
=== Assume good faith ===&lt;br /&gt;
Unless there is evidence to the contrary, actions taken by an editor should be seen as being done in good faith and without malicious intentions.&lt;br /&gt;
&lt;br /&gt;
There are cases where actions made by a well-intentioned editor could be perceived to be malicious or harmful to the wiki. Editors are not expected to be perfect, and they will make mistakes from time to time. In such situations, other editors should not immediately go on the offensive against that editor. Wiki editors make contributions to the wiki to help it, not to harm it. A civil discussion should be held to allow the editor to defend their actions.&lt;br /&gt;
&lt;br /&gt;
=== Keep on topic ===&lt;br /&gt;
As a wiki centered around the Minecraft Forge modding API, topics within the wiki should be related and kept on topic.&lt;br /&gt;
&lt;br /&gt;
Topics, articles, discussions, and the like should be related to the wiki, whether to the community or governance of the wiki or to the central topic. This is to keep this wiki directed towards its central topic and to avoid having articles which do not hold any meaningful value or relevancy to this wiki.&lt;br /&gt;
&lt;br /&gt;
== Wiki staff ==&lt;br /&gt;
The wiki staff is composed of all active [[FCWMeta:User access levels#Administrators and Moderators|moderators and administrators]], which determine the policies of this wiki, enforce any binding decisions, keep the peace within the wiki's community, and moderate and curate the wiki's contents.&lt;br /&gt;
&lt;br /&gt;
Members of wiki staff may be contacted through their emails, their talk page, or their Discord account.&lt;br /&gt;
&lt;br /&gt;
== Moderation ==&lt;br /&gt;
The wiki staff may apply sanctions to editors which violate the rules and policies of this wiki. They may use their discretion on what sanction to apply, depending on the severity of the violation and any other factors which may affect their decision.&lt;br /&gt;
&lt;br /&gt;
The following is a list of applicable sanctions, in increasing order of severity. This does not define a rigid list of possible sanctions, as the wiki staff may apply harsher or milder sanctions upon their discretion. Wiki staff may also apply multiple sanctions.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Type of Sanction&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| Warning&lt;br /&gt;
| A verbal warning is given to the violating editor, which will be logged by staff to be referenced for any future violations by the editor.&lt;br /&gt;
|-&lt;br /&gt;
| Specific block&lt;br /&gt;
| The violating editor is temporarily or permanently blocked from editing specific pages or namespaces within the wiki.&lt;br /&gt;
|-&lt;br /&gt;
| Revocation of rights&lt;br /&gt;
| Any [[FCWMeta:User access levels|special user rights]] granted previously to the violating editor are revoked, either temporarily or permanently.&lt;br /&gt;
|-&lt;br /&gt;
| Sitewide block&lt;br /&gt;
| The violating editor is temporarily or permanently blocked from any contributions to any page in the wiki.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Appeals ===&lt;br /&gt;
If an editor wishes to appeal a sanction made by a member of the wiki staff, they may appeal to an uninvolved administrator. The appealing administrator may uphold the current decision, overturn and revert the decision and action, or if necessary deliberate with the other wiki staff to make a final binding decision. Repeated attempts to appeal to administrators without any merit shall be sanctioned appropriately at their discretion.&lt;/div&gt;</summary>
		<author><name>SciWhiz12</name></author>
	</entry>
	<entry>
		<id>https://forge.gemwire.uk/index.php?title=Access_Transformers&amp;diff=2917</id>
		<title>Access Transformers</title>
		<link rel="alternate" type="text/html" href="https://forge.gemwire.uk/index.php?title=Access_Transformers&amp;diff=2917"/>
		<updated>2021-08-13T02:36:50Z</updated>

		<summary type="html">&lt;p&gt;SciWhiz12: add note about inner classes and $ separator&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Access transformers''' (abbreviated as ''ATs'') are declarations for modifying or transforming the access visibility or finality of a class member (classes, fields, methods). These declarations are parsed by a transformer and applied to classes using the ASM library, either modifying the class files on-disk or modifying the class bytes during runtime.&lt;br /&gt;
&lt;br /&gt;
The [https://github.com/MinecraftForge/AccessTransformers AccessTransformers] library provides a pluggable ModLauncher transformation service and a command-line application for applying access transformers on class bytes during runtime and on class files on-disk.&lt;br /&gt;
&lt;br /&gt;
== Background ==&lt;br /&gt;
Java provides the mechanism of '''access level modifiers''' (or ''access modifiers''), to modify the ''visibility'' of a member with the modifier to other classes. This is commonly used to hide fields and methods from other classes, such as instance fields for [[:wikipedia:encapsulation|encapsulation]] or private methods which are part of the implementation of the class and should not be exposed to callers.&lt;br /&gt;
&lt;br /&gt;
A member can be declared with any of the modifier keywords &amp;lt;code&amp;gt;public&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;private&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;protected&amp;lt;/code&amp;gt; to set the access level of the member, or none of the keywords, which defaults to a ''package-private'' access level.&lt;br /&gt;
&lt;br /&gt;
The following table shows the different access levels and their modifiers, and what classes may access members with that access level:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;text-align:center;&amp;quot;&lt;br /&gt;
|+ Access levels&lt;br /&gt;
! Access modifier&lt;br /&gt;
! Within the same class&lt;br /&gt;
! Subclasses&lt;br /&gt;
! Classes in the same package&lt;br /&gt;
! All other classes&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;public&amp;lt;/code&amp;gt;&lt;br /&gt;
| style=&amp;quot;color:limegreen&amp;quot; | '''Yes'''&lt;br /&gt;
| style=&amp;quot;color:limegreen&amp;quot; | '''Yes'''&lt;br /&gt;
| style=&amp;quot;color:limegreen&amp;quot; | '''Yes'''&lt;br /&gt;
| style=&amp;quot;color:limegreen&amp;quot; | '''Yes'''&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;protected&amp;lt;/code&amp;gt;&lt;br /&gt;
| style=&amp;quot;color:limegreen&amp;quot; | '''Yes'''&lt;br /&gt;
| style=&amp;quot;color:limegreen&amp;quot; | '''Yes'''&lt;br /&gt;
| style=&amp;quot;color:limegreen&amp;quot; | '''Yes'''&lt;br /&gt;
| style=&amp;quot;color:indianred&amp;quot; | '''No'''&lt;br /&gt;
|-&lt;br /&gt;
| ''no modifier''&lt;br /&gt;
| style=&amp;quot;color:limegreen&amp;quot; | '''Yes'''&lt;br /&gt;
| style=&amp;quot;color:limegreen&amp;quot; | '''Yes'''&lt;br /&gt;
| style=&amp;quot;color:indianred&amp;quot; | '''No'''&lt;br /&gt;
| style=&amp;quot;color:indianred&amp;quot; | '''No'''&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;private&amp;lt;/code&amp;gt;&lt;br /&gt;
| style=&amp;quot;color:limegreen&amp;quot; | '''Yes'''&lt;br /&gt;
| style=&amp;quot;color:indianred&amp;quot; | '''No'''&lt;br /&gt;
| style=&amp;quot;color:indianred&amp;quot; | '''No'''&lt;br /&gt;
| style=&amp;quot;color:indianred&amp;quot; | '''No'''&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
For example, a field marked &amp;lt;code&amp;gt;protected&amp;lt;/code&amp;gt; cannot be accessed by a class in another package, but can be accessed by: any class within the same package, any subclass of the class (even if the subclass belongs to another package), and within the same class where the field is declared.&lt;br /&gt;
&lt;br /&gt;
Additionally to the access modifiers, there exists the &amp;lt;code&amp;gt;final&amp;lt;/code&amp;gt; keyword, which:&lt;br /&gt;
* on classes, prevents any subclassing of the class;&lt;br /&gt;
* on fields, marks it as being assignable only once during construction; and&lt;br /&gt;
* on methods, prevents any subclasses from overriding the method with their own implementation.&lt;br /&gt;
&lt;br /&gt;
Normally, Java programmers restrict access levels to be as restrictive as they need to be, controlling what is the effective publicly-available surface for the application. For example, a field may be declared as &amp;lt;code&amp;gt;private&amp;lt;/code&amp;gt; while providing setter and getter methods to access the field (a technique known as encapsulation).&lt;br /&gt;
&lt;br /&gt;
However, this convention of restricting access levels and marking members as &amp;lt;code&amp;gt;final&amp;lt;/code&amp;gt; where approriate presents a problem with modding Minecraft, because they restrict what parts of the game that modders can access or modify, usually without other means to access or modify them (such as setters and getters for fields).&lt;br /&gt;
&lt;br /&gt;
One solution is to use Java [[:wikipedia:reflection|reflection]] to reflectively access these fields and methods during runtime, but they suffer from some problems:&lt;br /&gt;
* Reflection is slower than regular method calls or field accesses, as certain optimizations done by the JVM cannot be applied.&amp;lt;ref&amp;gt;[https://docs.oracle.com/javase/tutorial/reflect/index.html The Java™ Tutorials: The Reflection API]: ''&amp;quot;Consequently, reflective operations have slower performance than their non-reflective counterparts, and should be avoided in sections of code which are called frequently in performance-sensitive applications.&amp;quot;''&amp;lt;/ref&amp;gt; This makes reflection unsuitable for performance-critical code, such as during rendering.&lt;br /&gt;
* Reflection cannot allow the modification of &amp;lt;code&amp;gt;final&amp;lt;/code&amp;gt; fields which are either marked &amp;lt;code&amp;gt;static&amp;lt;/code&amp;gt; or belong to a record class.&amp;lt;ref&amp;gt;[https://docs.oracle.com/en/java/javase/16/docs/api/java.base/java/lang/reflect/AccessibleObject.html#setAccessible(boolean) Java 16 javadocs] for &amp;lt;code&amp;gt;java.lang.reflect.AccessibleObject.setAccessible(boolean)&amp;lt;/code&amp;gt;&amp;lt;/ref&amp;gt;&lt;br /&gt;
* Runtime reflection loses the benefit of compile-time type checks, which allows dangerous operations such as trying to set a field's value to an incompatible type.&lt;br /&gt;
* The use of reflection does not allow a class to extend a non-visible class.&lt;br /&gt;
&lt;br /&gt;
These problems are solved with the use of access transformers, which allow modification of the access modifiers of members such that they can be applied on class files on-disk to allow compiling against them, and applying the same transformer declarations on class bytes during runtime to allow classes which compiled against those transformed classes to work correctly.&lt;br /&gt;
&lt;br /&gt;
== Usage ==&lt;br /&gt;
&lt;br /&gt;
To use access transformers in the development environment, ForgeGradle must be configured with the location of the access transformer configuration file (or files). Because FML is hardwired to look for the configuration file at &amp;lt;code&amp;gt;META-INF/accesstransformer.cfg&amp;lt;/code&amp;gt; within JAR files, it is recommended that the AT configuration file for the project be placed at the same location: within the resources folder of the main source set, or &amp;lt;code&amp;gt;src/main/resources/META-INF/accesstransformer.cfg&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
To configure the location of the access transformer configuration file with ForgeGradle:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;gradle&amp;quot;&amp;gt;&lt;br /&gt;
minecraft { // Within the minecraft block&lt;br /&gt;
    // Configures FG to look at the given file path for the AT configuration file&lt;br /&gt;
    accessTransformer = file(&amp;quot;src/main/resources/META-INF/accesstransformer.cfg&amp;quot;)&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Access-transformers-uncomment-this-line-in-build-gradle.png|thumb|300px]]&lt;br /&gt;
&lt;br /&gt;
The Forge-provided mod development environment's buildscript contains the above line but commented out, as the MDK does not ship with an access transformer file. Users of the MDK can therefore uncomment out the above line and create the AT configuration file at the same location. &lt;br /&gt;
&lt;br /&gt;
Once the configuration file(s) has been added and everytime the contents or location of the file(s) changes, the developer should then refresh the Gradle nature/project in their IDE of choice for ForgeGradle to apply the access transformers to the compiled source. Each change to the access transformer configuration will trigger a full decompilation of the game.&lt;br /&gt;
&lt;br /&gt;
== Declarations ==&lt;br /&gt;
&lt;br /&gt;
Access transformers are declared line-by-line in configuration files, which are then parsed by ForgeGradle in the development environment and by FML in the production or end-user environment.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;#&amp;lt;/code&amp;gt; character and any content after that up to the end of the line is considered a comment, and will be ignored by the parser. Any lines which are either empty or consist of only whitespace or comments are ignored.&lt;br /&gt;
&lt;br /&gt;
An access transformer declaration has three different variations, depending on the target to be transformed:&lt;br /&gt;
&lt;br /&gt;
* for '''classes''': &amp;lt;code&amp;gt;''&amp;lt;modifier&amp;gt;'' ''&amp;lt;class name&amp;gt;''&amp;lt;/code&amp;gt;&lt;br /&gt;
* for '''methods''': &amp;lt;code&amp;gt;''&amp;lt;modifier&amp;gt;'' ''&amp;lt;class name&amp;gt;'' ''&amp;lt;method name&amp;gt;'''''('''''[parameter descriptors]''''')'''''&amp;amp;lt;return descriptor&amp;gt;''&amp;lt;/code&amp;gt;&lt;br /&gt;
* for '''fields''': &amp;lt;code&amp;gt;''&amp;lt;modifier&amp;gt;'' ''&amp;lt;class name&amp;gt;'' ''&amp;lt;field name&amp;gt;''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The modifier consists of one of the following words:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;public&amp;lt;/code&amp;gt; for the ''public'' access level (denoted by the modifier keyword of the same name)&lt;br /&gt;
* &amp;lt;code&amp;gt;protected&amp;lt;/code&amp;gt; for the ''protected'' access level (denoted by the modifier keyword of the same name)&lt;br /&gt;
* &amp;lt;code&amp;gt;default&amp;lt;/code&amp;gt; for the ''package-private'' access level (denoted by the absence of an access modifier keyword)&lt;br /&gt;
* &amp;lt;code&amp;gt;private&amp;lt;/code&amp;gt; for the ''private'' access level (denoted by the modifier keyword of the same name)&lt;br /&gt;
* For any of the preceding words, the &amp;lt;code&amp;gt;-f&amp;lt;/code&amp;gt; suffix removes the &amp;lt;code&amp;gt;final&amp;lt;/code&amp;gt; modifier, while the &amp;lt;code&amp;gt;+f&amp;lt;/code&amp;gt; suffix adds the modifier.&lt;br /&gt;
&lt;br /&gt;
The class name is the fully qualified name of the class, using &amp;lt;code&amp;gt;.&amp;lt;/code&amp;gt; (dots) to separate between (sub)packages and classes (for example, &amp;lt;code&amp;gt;java.lang.Object&amp;lt;/code&amp;gt;). &lt;br /&gt;
&lt;br /&gt;
For methods, the method descriptor&amp;lt;ref&amp;gt;''[https://docs.oracle.com/javase/specs/jvms/se16/html/jvms-4.html#jvms-4.3.3 Java Virtual Machine Specification, Java SE 16 Edition]'', 4.3.3. Method Descriptors &amp;lt;/ref&amp;gt; of the method is included, which consists of the descriptors for each of the method's parameters and the method's return type. The method parameters descriptors can be absent if there are no parameters in the method, but the return type descriptor must be present.&lt;br /&gt;
&lt;br /&gt;
The following are the matching descriptors for each type as seen in the method declaration:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ Matching type descriptors&lt;br /&gt;
! Descriptor&lt;br /&gt;
! Source form&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;Z&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;boolean&amp;lt;/code&amp;gt; || a &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;false&amp;lt;/code&amp;gt; value&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;B&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;byte&amp;lt;/code&amp;gt; || a 8-bit signed number&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;S&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;short&amp;lt;/code&amp;gt; || a 16-bit signed number&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;C&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;char&amp;lt;/code&amp;gt; || a Unicode character code point in UTF-16&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;I&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;int&amp;lt;/code&amp;gt; || a 32-bit signed number&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;F&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;float&amp;lt;/code&amp;gt; || a single-precision floating-point value&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;J&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;long&amp;lt;/code&amp;gt; || a 64-bit signed number&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;D&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;double&amp;lt;/code&amp;gt; || a double-precision floating-point value&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;[''I''&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;''int''[]&amp;lt;/code&amp;gt; || one dimension of an array; this can be repeated, and must end with another descriptor other than an array&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;L''java/lang/Object'';&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;java.lang.Object&amp;lt;/code&amp;gt; || a reference type; the internal form of the class' binary name must be present (in the given example, the class referenced is &amp;lt;code&amp;gt;java.lang.Object&amp;lt;/code&amp;gt;. &lt;br /&gt;
Note that inner classes are separated using the &amp;lt;code&amp;gt;$&amp;lt;/code&amp;gt; (dollar sign) character, such as &amp;lt;code&amp;gt;java/lang/System$Logger&amp;lt;/code&amp;gt;.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;V&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;void&amp;lt;/code&amp;gt; || a void or no-value return type; only available for the return type of a method descriptor&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Examples ==&lt;br /&gt;
&lt;br /&gt;
The following are some examples of access transformer declarations:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
# Makes public the ScreenConstructor class in MenuScreens&lt;br /&gt;
public net.minecraft.client.gui.screens.MenuScreens$ScreenConstructor&lt;br /&gt;
&lt;br /&gt;
# Makes protected the 'COLOR_WHITE' field in Gui&lt;br /&gt;
protected net.minecraft.client.gui.Gui f_168667_ # COLOR_WHITE&lt;br /&gt;
&lt;br /&gt;
# Makes protected and removes the final modifier from 'random' field in MinecraftServer&lt;br /&gt;
protected-f net.minecraft.server.MinecraftServer f_129758_ # random&lt;br /&gt;
&lt;br /&gt;
# Makes public the 'makeExecutor' method in Util,&lt;br /&gt;
# which accepts a String and returns an ExecutorService&lt;br /&gt;
public net.minecraft.Util m_137477_(Ljava/lang/String;)Ljava/util/concurrent/ExecutorService; # makeExecutor&lt;br /&gt;
&lt;br /&gt;
# Makes public the 'leastMostToIntArray' method in SerializableUUID,&lt;br /&gt;
# which accepts two longs and returns an int[]&lt;br /&gt;
public net.minecraft.core.SerializableUUID m_123274_(JJ)[I # leastMostToIntArray&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>SciWhiz12</name></author>
	</entry>
	<entry>
		<id>https://forge.gemwire.uk/index.php?title=AT&amp;diff=2916</id>
		<title>AT</title>
		<link rel="alternate" type="text/html" href="https://forge.gemwire.uk/index.php?title=AT&amp;diff=2916"/>
		<updated>2021-08-13T02:32:07Z</updated>

		<summary type="html">&lt;p&gt;SciWhiz12: redirect to access transformers page&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;#REDIRECT [[Access Transformers]]&lt;/div&gt;</summary>
		<author><name>SciWhiz12</name></author>
	</entry>
	<entry>
		<id>https://forge.gemwire.uk/index.php?title=ATs&amp;diff=2915</id>
		<title>ATs</title>
		<link rel="alternate" type="text/html" href="https://forge.gemwire.uk/index.php?title=ATs&amp;diff=2915"/>
		<updated>2021-08-13T02:31:45Z</updated>

		<summary type="html">&lt;p&gt;SciWhiz12: redirect to access transformers page&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;#REDIRECT [[Access Transformers]]&lt;/div&gt;</summary>
		<author><name>SciWhiz12</name></author>
	</entry>
	<entry>
		<id>https://forge.gemwire.uk/index.php?title=Access_Transformer&amp;diff=2914</id>
		<title>Access Transformer</title>
		<link rel="alternate" type="text/html" href="https://forge.gemwire.uk/index.php?title=Access_Transformer&amp;diff=2914"/>
		<updated>2021-08-13T02:31:07Z</updated>

		<summary type="html">&lt;p&gt;SciWhiz12: redirect to access transformers page&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;#REDIRECT [[Access Transformers]]&lt;/div&gt;</summary>
		<author><name>SciWhiz12</name></author>
	</entry>
	<entry>
		<id>https://forge.gemwire.uk/index.php?title=Access_Transformers&amp;diff=2913</id>
		<title>Access Transformers</title>
		<link rel="alternate" type="text/html" href="https://forge.gemwire.uk/index.php?title=Access_Transformers&amp;diff=2913"/>
		<updated>2021-08-13T02:29:56Z</updated>

		<summary type="html">&lt;p&gt;SciWhiz12: no to java highlighting&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Access transformers''' (abbreviated as ''ATs'') are declarations for modifying or transforming the access visibility or finality of a class member (classes, fields, methods). These declarations are parsed by a transformer and applied to classes using the ASM library, either modifying the class files on-disk or modifying the class bytes during runtime.&lt;br /&gt;
&lt;br /&gt;
The [https://github.com/MinecraftForge/AccessTransformers AccessTransformers] library provides a pluggable ModLauncher transformation service and a command-line application for applying access transformers on class bytes during runtime and on class files on-disk.&lt;br /&gt;
&lt;br /&gt;
== Background ==&lt;br /&gt;
Java provides the mechanism of '''access level modifiers''' (or ''access modifiers''), to modify the ''visibility'' of a member with the modifier to other classes. This is commonly used to hide fields and methods from other classes, such as instance fields for [[:wikipedia:encapsulation|encapsulation]] or private methods which are part of the implementation of the class and should not be exposed to callers.&lt;br /&gt;
&lt;br /&gt;
A member can be declared with any of the modifier keywords &amp;lt;code&amp;gt;public&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;private&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;protected&amp;lt;/code&amp;gt; to set the access level of the member, or none of the keywords, which defaults to a ''package-private'' access level.&lt;br /&gt;
&lt;br /&gt;
The following table shows the different access levels and their modifiers, and what classes may access members with that access level:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;text-align:center;&amp;quot;&lt;br /&gt;
|+ Access levels&lt;br /&gt;
! Access modifier&lt;br /&gt;
! Within the same class&lt;br /&gt;
! Subclasses&lt;br /&gt;
! Classes in the same package&lt;br /&gt;
! All other classes&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;public&amp;lt;/code&amp;gt;&lt;br /&gt;
| style=&amp;quot;color:limegreen&amp;quot; | '''Yes'''&lt;br /&gt;
| style=&amp;quot;color:limegreen&amp;quot; | '''Yes'''&lt;br /&gt;
| style=&amp;quot;color:limegreen&amp;quot; | '''Yes'''&lt;br /&gt;
| style=&amp;quot;color:limegreen&amp;quot; | '''Yes'''&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;protected&amp;lt;/code&amp;gt;&lt;br /&gt;
| style=&amp;quot;color:limegreen&amp;quot; | '''Yes'''&lt;br /&gt;
| style=&amp;quot;color:limegreen&amp;quot; | '''Yes'''&lt;br /&gt;
| style=&amp;quot;color:limegreen&amp;quot; | '''Yes'''&lt;br /&gt;
| style=&amp;quot;color:indianred&amp;quot; | '''No'''&lt;br /&gt;
|-&lt;br /&gt;
| ''no modifier''&lt;br /&gt;
| style=&amp;quot;color:limegreen&amp;quot; | '''Yes'''&lt;br /&gt;
| style=&amp;quot;color:limegreen&amp;quot; | '''Yes'''&lt;br /&gt;
| style=&amp;quot;color:indianred&amp;quot; | '''No'''&lt;br /&gt;
| style=&amp;quot;color:indianred&amp;quot; | '''No'''&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;private&amp;lt;/code&amp;gt;&lt;br /&gt;
| style=&amp;quot;color:limegreen&amp;quot; | '''Yes'''&lt;br /&gt;
| style=&amp;quot;color:indianred&amp;quot; | '''No'''&lt;br /&gt;
| style=&amp;quot;color:indianred&amp;quot; | '''No'''&lt;br /&gt;
| style=&amp;quot;color:indianred&amp;quot; | '''No'''&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
For example, a field marked &amp;lt;code&amp;gt;protected&amp;lt;/code&amp;gt; cannot be accessed by a class in another package, but can be accessed by: any class within the same package, any subclass of the class (even if the subclass belongs to another package), and within the same class where the field is declared.&lt;br /&gt;
&lt;br /&gt;
Additionally to the access modifiers, there exists the &amp;lt;code&amp;gt;final&amp;lt;/code&amp;gt; keyword, which:&lt;br /&gt;
* on classes, prevents any subclassing of the class;&lt;br /&gt;
* on fields, marks it as being assignable only once during construction; and&lt;br /&gt;
* on methods, prevents any subclasses from overriding the method with their own implementation.&lt;br /&gt;
&lt;br /&gt;
Normally, Java programmers restrict access levels to be as restrictive as they need to be, controlling what is the effective publicly-available surface for the application. For example, a field may be declared as &amp;lt;code&amp;gt;private&amp;lt;/code&amp;gt; while providing setter and getter methods to access the field (a technique known as encapsulation).&lt;br /&gt;
&lt;br /&gt;
However, this convention of restricting access levels and marking members as &amp;lt;code&amp;gt;final&amp;lt;/code&amp;gt; where approriate presents a problem with modding Minecraft, because they restrict what parts of the game that modders can access or modify, usually without other means to access or modify them (such as setters and getters for fields).&lt;br /&gt;
&lt;br /&gt;
One solution is to use Java [[:wikipedia:reflection|reflection]] to reflectively access these fields and methods during runtime, but they suffer from some problems:&lt;br /&gt;
* Reflection is slower than regular method calls or field accesses, as certain optimizations done by the JVM cannot be applied.&amp;lt;ref&amp;gt;[https://docs.oracle.com/javase/tutorial/reflect/index.html The Java™ Tutorials: The Reflection API]: ''&amp;quot;Consequently, reflective operations have slower performance than their non-reflective counterparts, and should be avoided in sections of code which are called frequently in performance-sensitive applications.&amp;quot;''&amp;lt;/ref&amp;gt; This makes reflection unsuitable for performance-critical code, such as during rendering.&lt;br /&gt;
* Reflection cannot allow the modification of &amp;lt;code&amp;gt;final&amp;lt;/code&amp;gt; fields which are either marked &amp;lt;code&amp;gt;static&amp;lt;/code&amp;gt; or belong to a record class.&amp;lt;ref&amp;gt;[https://docs.oracle.com/en/java/javase/16/docs/api/java.base/java/lang/reflect/AccessibleObject.html#setAccessible(boolean) Java 16 javadocs] for &amp;lt;code&amp;gt;java.lang.reflect.AccessibleObject.setAccessible(boolean)&amp;lt;/code&amp;gt;&amp;lt;/ref&amp;gt;&lt;br /&gt;
* Runtime reflection loses the benefit of compile-time type checks, which allows dangerous operations such as trying to set a field's value to an incompatible type.&lt;br /&gt;
* The use of reflection does not allow a class to extend a non-visible class.&lt;br /&gt;
&lt;br /&gt;
These problems are solved with the use of access transformers, which allow modification of the access modifiers of members such that they can be applied on class files on-disk to allow compiling against them, and applying the same transformer declarations on class bytes during runtime to allow classes which compiled against those transformed classes to work correctly.&lt;br /&gt;
&lt;br /&gt;
== Usage ==&lt;br /&gt;
&lt;br /&gt;
To use access transformers in the development environment, ForgeGradle must be configured with the location of the access transformer configuration file (or files). Because FML is hardwired to look for the configuration file at &amp;lt;code&amp;gt;META-INF/accesstransformer.cfg&amp;lt;/code&amp;gt; within JAR files, it is recommended that the AT configuration file for the project be placed at the same location: within the resources folder of the main source set, or &amp;lt;code&amp;gt;src/main/resources/META-INF/accesstransformer.cfg&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
To configure the location of the access transformer configuration file with ForgeGradle:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;gradle&amp;quot;&amp;gt;&lt;br /&gt;
minecraft { // Within the minecraft block&lt;br /&gt;
    // Configures FG to look at the given file path for the AT configuration file&lt;br /&gt;
    accessTransformer = file(&amp;quot;src/main/resources/META-INF/accesstransformer.cfg&amp;quot;)&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Access-transformers-uncomment-this-line-in-build-gradle.png|thumb|300px]]&lt;br /&gt;
&lt;br /&gt;
The Forge-provided mod development environment's buildscript contains the above line but commented out, as the MDK does not ship with an access transformer file. Users of the MDK can therefore uncomment out the above line and create the AT configuration file at the same location. &lt;br /&gt;
&lt;br /&gt;
Once the configuration file(s) has been added and everytime the contents or location of the file(s) changes, the developer should then refresh the Gradle nature/project in their IDE of choice for ForgeGradle to apply the access transformers to the compiled source. Each change to the access transformer configuration will trigger a full decompilation of the game.&lt;br /&gt;
&lt;br /&gt;
== Declarations ==&lt;br /&gt;
&lt;br /&gt;
Access transformers are declared line-by-line in configuration files, which are then parsed by ForgeGradle in the development environment and by FML in the production or end-user environment.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;#&amp;lt;/code&amp;gt; character and any content after that up to the end of the line is considered a comment, and will be ignored by the parser. Any lines which are either empty or consist of only whitespace or comments are ignored.&lt;br /&gt;
&lt;br /&gt;
An access transformer declaration has three different variations, depending on the target to be transformed:&lt;br /&gt;
&lt;br /&gt;
* for '''classes''': &amp;lt;code&amp;gt;''&amp;lt;modifier&amp;gt;'' ''&amp;lt;class name&amp;gt;''&amp;lt;/code&amp;gt;&lt;br /&gt;
* for '''methods''': &amp;lt;code&amp;gt;''&amp;lt;modifier&amp;gt;'' ''&amp;lt;class name&amp;gt;'' ''&amp;lt;method name&amp;gt;'''''('''''[parameter descriptors]''''')'''''&amp;amp;lt;return descriptor&amp;gt;''&amp;lt;/code&amp;gt;&lt;br /&gt;
* for '''fields''': &amp;lt;code&amp;gt;''&amp;lt;modifier&amp;gt;'' ''&amp;lt;class name&amp;gt;'' ''&amp;lt;field name&amp;gt;''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The modifier consists of one of the following words:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;public&amp;lt;/code&amp;gt; for the ''public'' access level (denoted by the modifier keyword of the same name)&lt;br /&gt;
* &amp;lt;code&amp;gt;protected&amp;lt;/code&amp;gt; for the ''protected'' access level (denoted by the modifier keyword of the same name)&lt;br /&gt;
* &amp;lt;code&amp;gt;default&amp;lt;/code&amp;gt; for the ''package-private'' access level (denoted by the absence of an access modifier keyword)&lt;br /&gt;
* &amp;lt;code&amp;gt;private&amp;lt;/code&amp;gt; for the ''private'' access level (denoted by the modifier keyword of the same name)&lt;br /&gt;
* For any of the preceding words, the &amp;lt;code&amp;gt;-f&amp;lt;/code&amp;gt; suffix removes the &amp;lt;code&amp;gt;final&amp;lt;/code&amp;gt; modifier, while the &amp;lt;code&amp;gt;+f&amp;lt;/code&amp;gt; suffix adds the modifier.&lt;br /&gt;
&lt;br /&gt;
The class name is the fully qualified name of the class, using &amp;lt;code&amp;gt;.&amp;lt;/code&amp;gt; (dots) to separate between (sub)packages and classes (for example, &amp;lt;code&amp;gt;java.lang.Object&amp;lt;/code&amp;gt;). &lt;br /&gt;
&lt;br /&gt;
For methods, the method descriptor&amp;lt;ref&amp;gt;''[https://docs.oracle.com/javase/specs/jvms/se16/html/jvms-4.html#jvms-4.3.3 Java Virtual Machine Specification, Java SE 16 Edition]'', 4.3.3. Method Descriptors &amp;lt;/ref&amp;gt; of the method is included, which consists of the descriptors for each of the method's parameters and the method's return type. The method parameters descriptors can be absent if there are no parameters in the method, but the return type descriptor must be present.&lt;br /&gt;
&lt;br /&gt;
The following are the matching descriptors for each type as seen in the method declaration:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ Matching type descriptors&lt;br /&gt;
! Descriptor&lt;br /&gt;
! Source form&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;Z&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;boolean&amp;lt;/code&amp;gt; || a &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;false&amp;lt;/code&amp;gt; value&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;B&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;byte&amp;lt;/code&amp;gt; || a 8-bit signed number&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;S&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;short&amp;lt;/code&amp;gt; || a 16-bit signed number&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;C&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;char&amp;lt;/code&amp;gt; || a Unicode character code point in UTF-16&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;I&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;int&amp;lt;/code&amp;gt; || a 32-bit signed number&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;F&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;float&amp;lt;/code&amp;gt; || a single-precision floating-point value&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;J&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;long&amp;lt;/code&amp;gt; || a 64-bit signed number&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;D&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;double&amp;lt;/code&amp;gt; || a double-precision floating-point value&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;[''I''&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;''int''[]&amp;lt;/code&amp;gt; || one dimension of an array; this can be repeated, and must end with another descriptor other than an array&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;L''java/lang/Object'';&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;java.lang.Object&amp;lt;/code&amp;gt; || a reference type; the internal form of the class' binary name must be present (in the given example, the class referenced is &amp;lt;code&amp;gt;java.lang.Object&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;V&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;void&amp;lt;/code&amp;gt; || a void or no-value return type; only available for the return type of a method descriptor&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Examples ==&lt;br /&gt;
&lt;br /&gt;
The following are some examples of access transformer declarations:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
# Makes public the ScreenConstructor class in MenuScreens&lt;br /&gt;
public net.minecraft.client.gui.screens.MenuScreens$ScreenConstructor&lt;br /&gt;
&lt;br /&gt;
# Makes protected the 'COLOR_WHITE' field in Gui&lt;br /&gt;
protected net.minecraft.client.gui.Gui f_168667_ # COLOR_WHITE&lt;br /&gt;
&lt;br /&gt;
# Makes protected and removes the final modifier from 'random' field in MinecraftServer&lt;br /&gt;
protected-f net.minecraft.server.MinecraftServer f_129758_ # random&lt;br /&gt;
&lt;br /&gt;
# Makes public the 'makeExecutor' method in Util,&lt;br /&gt;
# which accepts a String and returns an ExecutorService&lt;br /&gt;
public net.minecraft.Util m_137477_(Ljava/lang/String;)Ljava/util/concurrent/ExecutorService; # makeExecutor&lt;br /&gt;
&lt;br /&gt;
# Makes public the 'leastMostToIntArray' method in SerializableUUID,&lt;br /&gt;
# which accepts two longs and returns an int[]&lt;br /&gt;
public net.minecraft.core.SerializableUUID m_123274_(JJ)[I # leastMostToIntArray&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>SciWhiz12</name></author>
	</entry>
	<entry>
		<id>https://forge.gemwire.uk/index.php?title=Access_Transformers&amp;diff=2912</id>
		<title>Access Transformers</title>
		<link rel="alternate" type="text/html" href="https://forge.gemwire.uk/index.php?title=Access_Transformers&amp;diff=2912"/>
		<updated>2021-08-13T02:28:30Z</updated>

		<summary type="html">&lt;p&gt;SciWhiz12: Rewrite page to be more 'wiki' in tone and more descriptive in nature, remove under construction header&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Access transformers''' (abbreviated as ''ATs'') are declarations for modifying or transforming the access visibility or finality of a class member (classes, fields, methods). These declarations are parsed by a transformer and applied to classes using the ASM library, either modifying the class files on-disk or modifying the class bytes during runtime.&lt;br /&gt;
&lt;br /&gt;
The [https://github.com/MinecraftForge/AccessTransformers AccessTransformers] library provides a pluggable ModLauncher transformation service and a command-line application for applying access transformers on class bytes during runtime and on class files on-disk.&lt;br /&gt;
&lt;br /&gt;
== Background ==&lt;br /&gt;
Java provides the mechanism of '''access level modifiers''' (or ''access modifiers''), to modify the ''visibility'' of a member with the modifier to other classes. This is commonly used to hide fields and methods from other classes, such as instance fields for [[:wikipedia:encapsulation|encapsulation]] or private methods which are part of the implementation of the class and should not be exposed to callers.&lt;br /&gt;
&lt;br /&gt;
A member can be declared with any of the modifier keywords &amp;lt;code&amp;gt;public&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;private&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;protected&amp;lt;/code&amp;gt; to set the access level of the member, or none of the keywords, which defaults to a ''package-private'' access level.&lt;br /&gt;
&lt;br /&gt;
The following table shows the different access levels and their modifiers, and what classes may access members with that access level:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;text-align:center;&amp;quot;&lt;br /&gt;
|+ Access levels&lt;br /&gt;
! Access modifier&lt;br /&gt;
! Within the same class&lt;br /&gt;
! Subclasses&lt;br /&gt;
! Classes in the same package&lt;br /&gt;
! All other classes&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;public&amp;lt;/code&amp;gt;&lt;br /&gt;
| style=&amp;quot;color:limegreen&amp;quot; | '''Yes'''&lt;br /&gt;
| style=&amp;quot;color:limegreen&amp;quot; | '''Yes'''&lt;br /&gt;
| style=&amp;quot;color:limegreen&amp;quot; | '''Yes'''&lt;br /&gt;
| style=&amp;quot;color:limegreen&amp;quot; | '''Yes'''&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;protected&amp;lt;/code&amp;gt;&lt;br /&gt;
| style=&amp;quot;color:limegreen&amp;quot; | '''Yes'''&lt;br /&gt;
| style=&amp;quot;color:limegreen&amp;quot; | '''Yes'''&lt;br /&gt;
| style=&amp;quot;color:limegreen&amp;quot; | '''Yes'''&lt;br /&gt;
| style=&amp;quot;color:indianred&amp;quot; | '''No'''&lt;br /&gt;
|-&lt;br /&gt;
| ''no modifier''&lt;br /&gt;
| style=&amp;quot;color:limegreen&amp;quot; | '''Yes'''&lt;br /&gt;
| style=&amp;quot;color:limegreen&amp;quot; | '''Yes'''&lt;br /&gt;
| style=&amp;quot;color:indianred&amp;quot; | '''No'''&lt;br /&gt;
| style=&amp;quot;color:indianred&amp;quot; | '''No'''&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;private&amp;lt;/code&amp;gt;&lt;br /&gt;
| style=&amp;quot;color:limegreen&amp;quot; | '''Yes'''&lt;br /&gt;
| style=&amp;quot;color:indianred&amp;quot; | '''No'''&lt;br /&gt;
| style=&amp;quot;color:indianred&amp;quot; | '''No'''&lt;br /&gt;
| style=&amp;quot;color:indianred&amp;quot; | '''No'''&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
For example, a field marked &amp;lt;code&amp;gt;protected&amp;lt;/code&amp;gt; cannot be accessed by a class in another package, but can be accessed by: any class within the same package, any subclass of the class (even if the subclass belongs to another package), and within the same class where the field is declared.&lt;br /&gt;
&lt;br /&gt;
Additionally to the access modifiers, there exists the &amp;lt;code&amp;gt;final&amp;lt;/code&amp;gt; keyword, which:&lt;br /&gt;
* on classes, prevents any subclassing of the class;&lt;br /&gt;
* on fields, marks it as being assignable only once during construction; and&lt;br /&gt;
* on methods, prevents any subclasses from overriding the method with their own implementation.&lt;br /&gt;
&lt;br /&gt;
Normally, Java programmers restrict access levels to be as restrictive as they need to be, controlling what is the effective publicly-available surface for the application. For example, a field may be declared as &amp;lt;code&amp;gt;private&amp;lt;/code&amp;gt; while providing setter and getter methods to access the field (a technique known as encapsulation).&lt;br /&gt;
&lt;br /&gt;
However, this convention of restricting access levels and marking members as &amp;lt;code&amp;gt;final&amp;lt;/code&amp;gt; where approriate presents a problem with modding Minecraft, because they restrict what parts of the game that modders can access or modify, usually without other means to access or modify them (such as setters and getters for fields).&lt;br /&gt;
&lt;br /&gt;
One solution is to use Java [[:wikipedia:reflection|reflection]] to reflectively access these fields and methods during runtime, but they suffer from some problems:&lt;br /&gt;
* Reflection is slower than regular method calls or field accesses, as certain optimizations done by the JVM cannot be applied.&amp;lt;ref&amp;gt;[https://docs.oracle.com/javase/tutorial/reflect/index.html The Java™ Tutorials: The Reflection API]: ''&amp;quot;Consequently, reflective operations have slower performance than their non-reflective counterparts, and should be avoided in sections of code which are called frequently in performance-sensitive applications.&amp;quot;''&amp;lt;/ref&amp;gt; This makes reflection unsuitable for performance-critical code, such as during rendering.&lt;br /&gt;
* Reflection cannot allow the modification of &amp;lt;code&amp;gt;final&amp;lt;/code&amp;gt; fields which are either marked &amp;lt;code&amp;gt;static&amp;lt;/code&amp;gt; or belong to a record class.&amp;lt;ref&amp;gt;[https://docs.oracle.com/en/java/javase/16/docs/api/java.base/java/lang/reflect/AccessibleObject.html#setAccessible(boolean) Java 16 javadocs] for &amp;lt;code&amp;gt;java.lang.reflect.AccessibleObject.setAccessible(boolean)&amp;lt;/code&amp;gt;&amp;lt;/ref&amp;gt;&lt;br /&gt;
* Runtime reflection loses the benefit of compile-time type checks, which allows dangerous operations such as trying to set a field's value to an incompatible type.&lt;br /&gt;
* The use of reflection does not allow a class to extend a non-visible class.&lt;br /&gt;
&lt;br /&gt;
These problems are solved with the use of access transformers, which allow modification of the access modifiers of members such that they can be applied on class files on-disk to allow compiling against them, and applying the same transformer declarations on class bytes during runtime to allow classes which compiled against those transformed classes to work correctly.&lt;br /&gt;
&lt;br /&gt;
== Usage ==&lt;br /&gt;
&lt;br /&gt;
To use access transformers in the development environment, ForgeGradle must be configured with the location of the access transformer configuration file (or files). Because FML is hardwired to look for the configuration file at &amp;lt;code&amp;gt;META-INF/accesstransformer.cfg&amp;lt;/code&amp;gt; within JAR files, it is recommended that the AT configuration file for the project be placed at the same location: within the resources folder of the main source set, or &amp;lt;code&amp;gt;src/main/resources/META-INF/accesstransformer.cfg&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
To configure the location of the access transformer configuration file with ForgeGradle:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;gradle&amp;quot;&amp;gt;&lt;br /&gt;
minecraft { // Within the minecraft block&lt;br /&gt;
    // Configures FG to look at the given file path for the AT configuration file&lt;br /&gt;
    accessTransformer = file(&amp;quot;src/main/resources/META-INF/accesstransformer.cfg&amp;quot;)&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Access-transformers-uncomment-this-line-in-build-gradle.png|thumb|300px]]&lt;br /&gt;
&lt;br /&gt;
The Forge-provided mod development environment's buildscript contains the above line but commented out, as the MDK does not ship with an access transformer file. Users of the MDK can therefore uncomment out the above line and create the AT configuration file at the same location. &lt;br /&gt;
&lt;br /&gt;
Once the configuration file(s) has been added and everytime the contents or location of the file(s) changes, the developer should then refresh the Gradle nature/project in their IDE of choice for ForgeGradle to apply the access transformers to the compiled source. Each change to the access transformer configuration will trigger a full decompilation of the game.&lt;br /&gt;
&lt;br /&gt;
== Declarations ==&lt;br /&gt;
&lt;br /&gt;
Access transformers are declared line-by-line in configuration files, which are then parsed by ForgeGradle in the development environment and by FML in the production or end-user environment.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;#&amp;lt;/code&amp;gt; character and any content after that up to the end of the line is considered a comment, and will be ignored by the parser. Any lines which are either empty or consist of only whitespace or comments are ignored.&lt;br /&gt;
&lt;br /&gt;
An access transformer declaration has three different variations, depending on the target to be transformed:&lt;br /&gt;
&lt;br /&gt;
* for '''classes''': &amp;lt;code&amp;gt;''&amp;lt;modifier&amp;gt;'' ''&amp;lt;class name&amp;gt;''&amp;lt;/code&amp;gt;&lt;br /&gt;
* for '''methods''': &amp;lt;code&amp;gt;''&amp;lt;modifier&amp;gt;'' ''&amp;lt;class name&amp;gt;'' ''&amp;lt;method name&amp;gt;'''''('''''[parameter descriptors]''''')'''''&amp;amp;lt;return descriptor&amp;gt;''&amp;lt;/code&amp;gt;&lt;br /&gt;
* for '''fields''': &amp;lt;code&amp;gt;''&amp;lt;modifier&amp;gt;'' ''&amp;lt;class name&amp;gt;'' ''&amp;lt;field name&amp;gt;''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The modifier consists of one of the following words:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;public&amp;lt;/code&amp;gt; for the ''public'' access level (denoted by the modifier keyword of the same name)&lt;br /&gt;
* &amp;lt;code&amp;gt;protected&amp;lt;/code&amp;gt; for the ''protected'' access level (denoted by the modifier keyword of the same name)&lt;br /&gt;
* &amp;lt;code&amp;gt;default&amp;lt;/code&amp;gt; for the ''package-private'' access level (denoted by the absence of an access modifier keyword)&lt;br /&gt;
* &amp;lt;code&amp;gt;private&amp;lt;/code&amp;gt; for the ''private'' access level (denoted by the modifier keyword of the same name)&lt;br /&gt;
* For any of the preceding words, the &amp;lt;code&amp;gt;-f&amp;lt;/code&amp;gt; suffix removes the &amp;lt;code&amp;gt;final&amp;lt;/code&amp;gt; modifier, while the &amp;lt;code&amp;gt;+f&amp;lt;/code&amp;gt; suffix adds the modifier.&lt;br /&gt;
&lt;br /&gt;
The class name is the fully qualified name of the class, using &amp;lt;code&amp;gt;.&amp;lt;/code&amp;gt; (dots) to separate between (sub)packages and classes (for example, &amp;lt;code&amp;gt;java.lang.Object&amp;lt;/code&amp;gt;). &lt;br /&gt;
&lt;br /&gt;
For methods, the method descriptor&amp;lt;ref&amp;gt;''[https://docs.oracle.com/javase/specs/jvms/se16/html/jvms-4.html#jvms-4.3.3 Java Virtual Machine Specification, Java SE 16 Edition]'', 4.3.3. Method Descriptors &amp;lt;/ref&amp;gt; of the method is included, which consists of the descriptors for each of the method's parameters and the method's return type. The method parameters descriptors can be absent if there are no parameters in the method, but the return type descriptor must be present.&lt;br /&gt;
&lt;br /&gt;
The following are the matching descriptors for each type as seen in the method declaration:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ Matching type descriptors&lt;br /&gt;
! Descriptor&lt;br /&gt;
! Source form&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;Z&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;boolean&amp;lt;/code&amp;gt; || a &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;false&amp;lt;/code&amp;gt; value&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;B&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;byte&amp;lt;/code&amp;gt; || a 8-bit signed number&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;S&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;short&amp;lt;/code&amp;gt; || a 16-bit signed number&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;C&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;char&amp;lt;/code&amp;gt; || a Unicode character code point in UTF-16&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;I&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;int&amp;lt;/code&amp;gt; || a 32-bit signed number&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;F&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;float&amp;lt;/code&amp;gt; || a single-precision floating-point value&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;J&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;long&amp;lt;/code&amp;gt; || a 64-bit signed number&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;D&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;double&amp;lt;/code&amp;gt; || a double-precision floating-point value&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;[''I''&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;''int''[]&amp;lt;/code&amp;gt; || one dimension of an array; this can be repeated, and must end with another descriptor other than an array&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;L''java/lang/Object'';&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;java.lang.Object&amp;lt;/code&amp;gt; || a reference type; the internal form of the class' binary name must be present (in the given example, the class referenced is &amp;lt;code&amp;gt;java.lang.Object&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;V&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;void&amp;lt;/code&amp;gt; || a void or no-value return type; only available for the return type of a method descriptor&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Examples ==&lt;br /&gt;
&lt;br /&gt;
The following are some examples of access transformer declarations:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
# Makes public the ScreenConstructor class in MenuScreens&lt;br /&gt;
public net.minecraft.client.gui.screens.MenuScreens$ScreenConstructor&lt;br /&gt;
&lt;br /&gt;
# Makes protected the 'COLOR_WHITE' field in Gui&lt;br /&gt;
protected net.minecraft.client.gui.Gui f_168667_ # COLOR_WHITE&lt;br /&gt;
&lt;br /&gt;
# Makes protected and removes the final modifier from 'random' field in MinecraftServer&lt;br /&gt;
protected-f net.minecraft.server.MinecraftServer f_129758_ # random&lt;br /&gt;
&lt;br /&gt;
# Makes public the 'makeExecutor' method in Util,&lt;br /&gt;
# which accepts a String and returns an ExecutorService&lt;br /&gt;
public net.minecraft.Util m_137477_(Ljava/lang/String;)Ljava/util/concurrent/ExecutorService; # makeExecutor&lt;br /&gt;
&lt;br /&gt;
# Makes public the 'leastMostToIntArray' method in SerializableUUID,&lt;br /&gt;
# which accepts two longs and returns an int[]&lt;br /&gt;
public net.minecraft.core.SerializableUUID m_123274_(JJ)[I # leastMostToIntArray&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>SciWhiz12</name></author>
	</entry>
	<entry>
		<id>https://forge.gemwire.uk/index.php?title=Registration&amp;diff=2877</id>
		<title>Registration</title>
		<link rel="alternate" type="text/html" href="https://forge.gemwire.uk/index.php?title=Registration&amp;diff=2877"/>
		<updated>2021-08-02T20:31:56Z</updated>

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

		<summary type="html">&lt;p&gt;SciWhiz12: Created page with &amp;quot;{{ns:project}}:User_access_levels#Check_users&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{ns:project}}:User_access_levels#Check_users&lt;/div&gt;</summary>
		<author><name>SciWhiz12</name></author>
	</entry>
	<entry>
		<id>https://forge.gemwire.uk/index.php?title=FCWMeta:User_access_levels&amp;diff=2855</id>
		<title>FCWMeta:User access levels</title>
		<link rel="alternate" type="text/html" href="https://forge.gemwire.uk/index.php?title=FCWMeta:User_access_levels&amp;diff=2855"/>
		<updated>2021-08-01T17:09:59Z</updated>

		<summary type="html">&lt;p&gt;SciWhiz12: Fix unbalanced header marks&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;The '''user access level''' of an editor determines what abilities they have and what actions they can perform. Each user access level, or '''user group''', has permissions/rights which are assigned. See [[Special:ListGroupRights]] to see all the available user groups and their permissions/rights.&lt;br /&gt;
&lt;br /&gt;
== Administrators and Moderators ==&lt;br /&gt;
'''Administrators''' and '''Moderators''' are editors who have broad rights over the whole wiki, such as protection, deletion, moving of pages, blocking and unblocking of users, and more. Administrators have more sensitive rights, and can assign and remove Moderators.&lt;br /&gt;
&lt;br /&gt;
These editors are part of the ''wiki staff'', which determine the policies of this wiki, enforce any binding decisions, keep the peace of the wiki, and moderate and curate its contents.&lt;br /&gt;
&lt;br /&gt;
The wiki staff may decide, from time to time, to grant Moderator status to active, reputable, and responsible editors. Requests for staff access level will not be entertained, however endorsements for other editors' may be considered.&lt;br /&gt;
&lt;br /&gt;
There are currently '''{{NUMBERINGROUP:administrator}}''' administrators and '''{{NUMBERINGROUP:moderator}}''' moderators.&lt;br /&gt;
&lt;br /&gt;
== Trusted users ==&lt;br /&gt;
'''Trusted users''' are editors who have been active in their contributions or are reputable members of the community, and has the trust of the wiki staff. They have the rights to edit semi-protected pages, and patrol changes.&lt;br /&gt;
&lt;br /&gt;
If you have been especially active in contributing, a staff member may grant this access level to you. You may also request this access level by contacting one of the staff; however, repeated requests may warrant sanctions.&lt;br /&gt;
&lt;br /&gt;
There are currently '''{{NUMBERINGROUP:trusted}}''' trusted users.&lt;br /&gt;
&lt;br /&gt;
== Special access levels ==&lt;br /&gt;
These access levels are specially granted to users by decision of the wiki staff. Requests for these access levels will not be considered, and may warrant sanctions.&lt;br /&gt;
&lt;br /&gt;
==== Keepers of the Keys ====&lt;br /&gt;
The '''Keepers of the Keys''' are administrators who have the rights to assign and remove access levels from all other users, including other administarotrs. &lt;br /&gt;
&lt;br /&gt;
The origin of this access group is derived from the principle of there being multiple administrators with high-level access to the wiki, to ensure that there is always someone available to administer the wiki and if necessary, take control of the wiki if the other administrators are out-of-contact and unreachable.&lt;br /&gt;
&lt;br /&gt;
There are currently '''{{NUMBERINGROUP:root}}''' keepers of the keys.&lt;br /&gt;
&lt;br /&gt;
==== Interface administrators ====&lt;br /&gt;
'''Interface administrators''' are editors who are given editing access to the MediaWiki interface CSS and JS files, through the &amp;lt;code&amp;gt;MediaWiki&amp;lt;/code&amp;gt; namespace.&lt;br /&gt;
&lt;br /&gt;
There are currently '''{{NUMBERINGROUP:interface-admin}}''' interface administrators.&lt;br /&gt;
&lt;br /&gt;
==== Check users ====&lt;br /&gt;
'''Check users''' are editors who have access to a log that lists out usernames used by which IPs and IPs used by which usernames. As this tool can be used to personally identify users through their IP, access is restricted to those who may need need, and use of the checkuser tool is strictly monitored.&lt;br /&gt;
&lt;br /&gt;
There are currently '''{{NUMBERINGROUP:checkuser}}''' check users.&lt;br /&gt;
&lt;br /&gt;
==== Suppressors ====&lt;br /&gt;
'''Suppressors''' are editors who can hide revisions and log entries from users (and even administrators), in cases such as personal information being posted. As this is a powerful tool, access is restricted to those who may need it, and use of the suppression tools are strictly monitored.&lt;br /&gt;
&lt;br /&gt;
There are currently '''{{NUMBERINGROUP:suppress}}''' suppressors.&lt;br /&gt;
&lt;br /&gt;
==== Autoconfirmed users ====&lt;br /&gt;
'''Autoconfirmed users''' are editors who have at least 5 edits and their account is at least 14 days old.&lt;br /&gt;
Currently, these users are only not affected by IP-based rate limits (the &amp;lt;code&amp;gt;autoconfirmed&amp;lt;/code&amp;gt; right).&lt;br /&gt;
&lt;br /&gt;
There are currently '''{{NUMBERINGROUP:autoconfirmed}}''' autoconfirmed users.&lt;br /&gt;
&lt;br /&gt;
==== Bots ====&lt;br /&gt;
'''Bots''' are programs that do automated or mass-editing tasks, which may be tedious or impossible to perform manually.&lt;br /&gt;
&lt;br /&gt;
There are currently '''{{NUMBERINGROUP:bot}}''' bots.&lt;/div&gt;</summary>
		<author><name>SciWhiz12</name></author>
	</entry>
	<entry>
		<id>https://forge.gemwire.uk/index.php?title=FCWMeta:User_access_levels&amp;diff=2854</id>
		<title>FCWMeta:User access levels</title>
		<link rel="alternate" type="text/html" href="https://forge.gemwire.uk/index.php?title=FCWMeta:User_access_levels&amp;diff=2854"/>
		<updated>2021-08-01T17:09:06Z</updated>

		<summary type="html">&lt;p&gt;SciWhiz12: Add info on check users, clarify why keepers exist, add user counts&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;The '''user access level''' of an editor determines what abilities they have and what actions they can perform. Each user access level, or '''user group''', has permissions/rights which are assigned. See [[Special:ListGroupRights]] to see all the available user groups and their permissions/rights.&lt;br /&gt;
&lt;br /&gt;
== Administrators and Moderators ==&lt;br /&gt;
'''Administrators''' and '''Moderators''' are editors who have broad rights over the whole wiki, such as protection, deletion, moving of pages, blocking and unblocking of users, and more. Administrators have more sensitive rights, and can assign and remove Moderators.&lt;br /&gt;
&lt;br /&gt;
These editors are part of the ''wiki staff'', which determine the policies of this wiki, enforce any binding decisions, keep the peace of the wiki, and moderate and curate its contents.&lt;br /&gt;
&lt;br /&gt;
The wiki staff may decide, from time to time, to grant Moderator status to active, reputable, and responsible editors. Requests for staff access level will not be entertained, however endorsements for other editors' may be considered.&lt;br /&gt;
&lt;br /&gt;
There are currently '''{{NUMBERINGROUP:administrator}}''' administrators and '''{{NUMBERINGROUP:moderator}}''' moderators.&lt;br /&gt;
&lt;br /&gt;
== Trusted users ==&lt;br /&gt;
'''Trusted users''' are editors who have been active in their contributions or are reputable members of the community, and has the trust of the wiki staff. They have the rights to edit semi-protected pages, and patrol changes.&lt;br /&gt;
&lt;br /&gt;
If you have been especially active in contributing, a staff member may grant this access level to you. You may also request this access level by contacting one of the staff; however, repeated requests may warrant sanctions.&lt;br /&gt;
&lt;br /&gt;
There are currently '''{{NUMBERINGROUP:trusted}}''' trusted users.&lt;br /&gt;
&lt;br /&gt;
== Special access levels ==&lt;br /&gt;
These access levels are specially granted to users by decision of the wiki staff. Requests for these access levels will not be considered, and may warrant sanctions.&lt;br /&gt;
&lt;br /&gt;
==== Keepers of the Keys ====&lt;br /&gt;
The '''Keepers of the Keys''' are administrators who have the rights to assign and remove access levels from all other users, including other administarotrs. &lt;br /&gt;
&lt;br /&gt;
The origin of this access group is derived from the principle of there being multiple administrators with high-level access to the wiki, to ensure that there is always someone available to administer the wiki and if necessary, take control of the wiki if the other administrators are out-of-contact and unreachable.&lt;br /&gt;
&lt;br /&gt;
There are currently '''{{NUMBERINGROUP:root}}''' keepers of the keys.&lt;br /&gt;
&lt;br /&gt;
==== Interface administrators ====&lt;br /&gt;
'''Interface administrators''' are editors who are given editing access to the MediaWiki interface CSS and JS files, through the &amp;lt;code&amp;gt;MediaWiki&amp;lt;/code&amp;gt; namespace.&lt;br /&gt;
&lt;br /&gt;
There are currently '''{{NUMBERINGROUP:interface-admin}}''' interface administrators.&lt;br /&gt;
&lt;br /&gt;
=== Check users ====&lt;br /&gt;
'''Check users''' are editors who have access to a log that lists out usernames used by which IPs and IPs used by which usernames. As this tool can be used to personally identify users through their IP, access is restricted to those who may need need, and use of the checkuser tool is strictly monitored.&lt;br /&gt;
&lt;br /&gt;
There are currently '''{{NUMBERINGROUP:checkuser}}''' check users.&lt;br /&gt;
&lt;br /&gt;
==== Suppressors ====&lt;br /&gt;
'''Suppressors''' are editors who can hide revisions and log entries from users (and even administrators), in cases such as personal information being posted. As this is a powerful tool, access is restricted to those who may need it, and use of the suppression tools are strictly monitored.&lt;br /&gt;
&lt;br /&gt;
There are currently '''{{NUMBERINGROUP:suppress}}''' suppressors.&lt;br /&gt;
&lt;br /&gt;
==== Autoconfirmed users ====&lt;br /&gt;
'''Autoconfirmed users''' are editors who have at least 5 edits and their account is at least 14 days old.&lt;br /&gt;
Currently, these users are only not affected by IP-based rate limits (the &amp;lt;code&amp;gt;autoconfirmed&amp;lt;/code&amp;gt; right).&lt;br /&gt;
&lt;br /&gt;
There are currently '''{{NUMBERINGROUP:autoconfirmed}}''' autoconfirmed users.&lt;br /&gt;
&lt;br /&gt;
==== Bots ====&lt;br /&gt;
'''Bots''' are programs that do automated or mass-editing tasks, which may be tedious or impossible to perform manually.&lt;br /&gt;
&lt;br /&gt;
There are currently '''{{NUMBERINGROUP:bot}}''' bots.&lt;/div&gt;</summary>
		<author><name>SciWhiz12</name></author>
	</entry>
	<entry>
		<id>https://forge.gemwire.uk/index.php?title=Main_Page&amp;diff=2642</id>
		<title>Main Page</title>
		<link rel="alternate" type="text/html" href="https://forge.gemwire.uk/index.php?title=Main_Page&amp;diff=2642"/>
		<updated>2021-05-19T01:11:10Z</updated>

		<summary type="html">&lt;p&gt;SciWhiz12: Protected &amp;quot;Main Page&amp;quot;: Protect against moving the literal main page of our wiki ([Move=Allow only administrators] (indefinite))&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__NOTOC__&lt;br /&gt;
&amp;lt;templatestyles src=&amp;quot;:Main_Page/styles.css&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;center title&amp;quot;&amp;gt;Forge Community Wiki&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The Forge Community Wiki exists so that the community can:&lt;br /&gt;
&lt;br /&gt;
* collectively keep track of major changes and updates to Forge and Vanilla code;&lt;br /&gt;
* create and edit articles with in-depth explanations about a variety of Forge-related subjects; and&lt;br /&gt;
* contribute example code and tutorials for both simple and difficult concepts.&lt;br /&gt;
&lt;br /&gt;
This wiki is editable by any registered user with an account. This is to allow tracking of harmful edits, but isn't imposing any annoying limits. We welcome any edit, however small. Join the [https://discord.gg/Nn42eAh Discord] to discuss changes and edits to the wiki with others and the staff.&lt;br /&gt;
&lt;br /&gt;
''The wiki is still under heavy construction. Pages may move around, so if you bookmark a page, beware when the page is moved and your bookmarked link dies.''&lt;br /&gt;
&lt;br /&gt;
Please note that we only maintain wiki entries for the Latest and Long Term Support (LTS) releases. Once a documented release is no longer under LTS, it will be removed.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;center round_warning&amp;quot;&amp;gt;&lt;br /&gt;
Please read the [[FCWMeta:Wiki Policy|wiki policy]] before editing!&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;center&amp;quot; style=&amp;quot;margin-bottom: 2em&amp;quot;&amp;gt;&lt;br /&gt;
The current ''Latest'' version is '''1.16.5'''. The current ''Long Term Support (LTS)'' version is '''1.15.2'''.&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;box_container center&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;box&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;h3&amp;gt;Beginner Topics&amp;lt;/h3&amp;gt;&lt;br /&gt;
* [[Getting Started]]&lt;br /&gt;
* [[Proper Mod Structuring]]&lt;br /&gt;
* [[Debug Profiler|The Debug Profiler]]&lt;br /&gt;
* [[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]]&lt;br /&gt;
* [[Internationalization]]&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;box&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;h3&amp;gt;Forge Conventions&amp;lt;/h3&amp;gt;&lt;br /&gt;
* [[Semantic Versioning]]&lt;br /&gt;
* [[Stages of Modloading]]&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;box&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;h3&amp;gt;Resources and Data&amp;lt;/h3&amp;gt;&lt;br /&gt;
* [[Using Resources|Introduction]]&lt;br /&gt;
* [[Recipes]]&lt;br /&gt;
* [[Tags]]&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;box&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;h3&amp;gt;Blocks&amp;lt;/h3&amp;gt;&lt;br /&gt;
* [[Making Blocks|Creating Blocks]]&lt;br /&gt;
* [[Understanding Blockstates]] &lt;br /&gt;
* [[Interacting With Blocks|Block Interactions]]&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;box&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;h3&amp;gt;Items&amp;lt;/h3&amp;gt;&lt;br /&gt;
* [[Making Items]]&lt;br /&gt;
* [[Making Tools]]&lt;br /&gt;
* [[ItemStack TileEntityRenderer|&amp;lt;tt&amp;gt;ItemStackTileEntityRenderer&amp;lt;/tt&amp;gt;]]&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;box&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;h3&amp;gt;Data Generation&amp;lt;/h3&amp;gt;&lt;br /&gt;
* [[Datageneration|Introduction]]&lt;br /&gt;
* [[Datageneration/Recipes|Recipes]]&lt;br /&gt;
* [[Datageneration/Tags|Tags]]&lt;br /&gt;
* [[Datageneration/Loot_Tables|Loot Tables]]&lt;br /&gt;
* [[Datageneration/I18n|Localization]]&lt;br /&gt;
* [[Datageneration/States and Models|&amp;lt;tt&amp;gt;BlockState&amp;lt;/tt&amp;gt;s and Models]]&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;box&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;h3&amp;gt;Tile Entities&amp;lt;/h3&amp;gt;&lt;br /&gt;
* [[Basics of Tile Entities|Introduction]]&lt;br /&gt;
* [[Using Tile Entity Renderers]]&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;box&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;h3&amp;gt;Models&amp;lt;/h3&amp;gt;&lt;br /&gt;
* [[Introduction to Models|Introduction]]&lt;br /&gt;
* [[Model JSONs]]&lt;br /&gt;
* [[BlockState JSONs]]&lt;br /&gt;
* [[Coloring textures dynamically|Dynamically Colored Textures]]&lt;br /&gt;
* [[Item Overrides]]&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;box&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;h3&amp;gt;Handling Information&amp;lt;/h3&amp;gt;&lt;br /&gt;
* [[Understanding Networking|Introduction]]&lt;br /&gt;
* [[Using NBT|Named Binary Tag (NBT)]]&lt;br /&gt;
* [[Using PacketBuffer|Using &amp;lt;tt&amp;gt;PacketBuffer&amp;lt;/tt&amp;gt;]]&lt;br /&gt;
* [[Sending Packets|Sending and Receiving Packets]]&lt;br /&gt;
* [[Using SimpleChannel|Using &amp;lt;tt&amp;gt;SimpleChannel&amp;lt;/tt&amp;gt;]]&lt;br /&gt;
* [[Networking with Entities]]&lt;br /&gt;
* [[DynamicOps|Using DynamicOps]]&lt;br /&gt;
* [[Codecs|Using Codecs]]&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;box&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;h3&amp;gt;Data Storage&amp;lt;/h3&amp;gt;&lt;br /&gt;
* [[Capabilities|Understanding Capabilities]] &lt;br /&gt;
* [[Capabilities/Attaching|Attaching Capabilities]]&lt;br /&gt;
* [[World Saved Data]]&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;box&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;h3&amp;gt;Game Effects&amp;lt;/h3&amp;gt;&lt;br /&gt;
* [[Effects]]&lt;br /&gt;
* [[Potions]]&lt;br /&gt;
* [[Particles]]&lt;br /&gt;
* [[Sounds]]&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;box&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;h3&amp;gt;Events&amp;lt;/h3&amp;gt;&lt;br /&gt;
* [[Events|Understanding Events]]&lt;br /&gt;
* [[Entity Events]]&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;box&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;h3&amp;gt;Others&amp;lt;/h3&amp;gt;&lt;br /&gt;
* [[Dependencies]]&lt;br /&gt;
* [[Dynamic Loot Modification]]&lt;br /&gt;
* [[Text Components|Text Components and Translation Keys]]&lt;br /&gt;
* [[Key Bindings]]&lt;br /&gt;
* [[Access Transformers]]&lt;br /&gt;
* [[Toolchain]]&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;/div&gt;</summary>
		<author><name>SciWhiz12</name></author>
	</entry>
	<entry>
		<id>https://forge.gemwire.uk/index.php?title=Dependencies&amp;diff=2585</id>
		<title>Dependencies</title>
		<link rel="alternate" type="text/html" href="https://forge.gemwire.uk/index.php?title=Dependencies&amp;diff=2585"/>
		<updated>2021-05-01T08:23:49Z</updated>

		<summary type="html">&lt;p&gt;SciWhiz12: note that flatdirs should only be used temporarily&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;A '''dependency''' is the reliance of a piece of software on another piece of software. In the context of Minecraft Forge, it is a mod or library which another mod relies or ''depends'' on.&lt;br /&gt;
&lt;br /&gt;
Dependencies are declared in three ways:&lt;br /&gt;
* The &amp;lt;code&amp;gt;dependencies&amp;lt;/code&amp;gt; block in a Gradle buildscript defines compile-time and runtime dependencies, which are used by the build system and compiler when building or running the mod in the development environment.&lt;br /&gt;
* The act of using classes, fields, and methods from a library creates a dependency on the library in the compiled binaries. The library may be an explicitly declared dependency, or a dependency of an explicitly declared dependency (such as the Guava libraries that Minecraft depends on).&lt;br /&gt;
* [[Proper_Mod_Structuring#Dependency_Configurations|Dependency configurations]] are declared in the &amp;lt;tt&amp;gt;mods.toml&amp;lt;/tt&amp;gt; metafile, which is then checked by Forge on runtime on whether they are satisfied.&lt;br /&gt;
&lt;br /&gt;
== Hard and Soft Dependencies ==&lt;br /&gt;
There are two types of mod dependencies: hard dependencies, and soft dependencies.&lt;br /&gt;
&lt;br /&gt;
A '''hard dependency''' is a dependency where the dependent mod requires that the dependency is present. This may be in the form of a code dependency, wherein the JVM will crash due to the missing class, field, or method from the dependency, or it may be in the form of a dependency configuration which mandates that the dependency is present.&lt;br /&gt;
&lt;br /&gt;
Hard dependencies should be declared using a dependency configuration to allow the Forge Mod Loader to detect the missing dependency and gracefully handle it by showing an error screen to the user, rather than the JVM crashing with a non-user-friendly exception message.&lt;br /&gt;
&lt;br /&gt;
A '''soft dependency''' is a dependency where the dependent mod does not require the dependency is present, but extra features or compatibility is added in the case of the dependency being present. This often takes the form of cross-mod compatibility features, where a mod soft-depends on another mod or the mod's API.&lt;br /&gt;
&lt;br /&gt;
Soft dependencies usually take the form of isolated code dependencies, where the code that depends on the soft-dependency is isolated from the rest of the mod until the soft-dependency is detected as being present.&lt;br /&gt;
&lt;br /&gt;
== Declaring Dependencies ==&lt;br /&gt;
A mod declares a dependency on a mod or library through Gradle, through the &amp;lt;code&amp;gt;dependencies&amp;lt;/code&amp;gt; block.&amp;lt;ref&amp;gt;[https://docs.gradle.org/6.8.1/userguide/declaring_dependencies.html Gradle User Guide for 6.8.1: ''Declaring dependencies'']&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For example, to declare a dependency on the &amp;lt;code&amp;gt;net:minecraftforge:eventbus:4.0.0&amp;lt;/code&amp;gt; library from the &amp;lt;code&amp;gt;main&amp;lt;/code&amp;gt; source set:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;gradle&amp;quot;&amp;gt;&lt;br /&gt;
dependencies {&lt;br /&gt;
    // 'implementation' is for the main source set&lt;br /&gt;
    implementation &amp;quot;net.minecraftforge:eventbus:4.0.0&amp;quot;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Tip|ForgeGradle automatically adds the [https://files.minecraftforge.net/maven/ Forge Maven] and [https://maven.apache.org/repository/ Maven Central] repositories to projects. If a dependency is not present in these (such as dependencies on other mods), the repository containing the dependency must be declared in the &amp;lt;code&amp;gt;repositories&amp;lt;/code&amp;gt; block of the Gradle buildscript.&amp;lt;ref&amp;gt;[https://docs.gradle.org/6.8.1/userguide/declaring_repositories.html Gradle User Guide for 6.8.1: ''Declaring repositories'']&amp;lt;/ref&amp;gt;}}&lt;br /&gt;
&lt;br /&gt;
=== Deobfuscating Dependencies ===&lt;br /&gt;
Mods (and libraries which use Minecraft code) are usually released as an SRG-obfuscated JAR, which prevents their direct use in development environments due to mismatch between SRG names from the mod/library and the MCP/mapped names in the development environment.&lt;br /&gt;
&lt;br /&gt;
These mods/libraries must be deobfuscated to the development environment's mappings first. This is done using the &amp;lt;code&amp;gt;fg.deobf&amp;lt;/code&amp;gt; function, which creates a dependency which is dynamically remapped to the local environment's mappings.&lt;br /&gt;
&lt;br /&gt;
For example, to declare a dependency on the &amp;lt;code&amp;gt;mezz.jei:jei-1.16.5:7.6.1.75&amp;lt;/code&amp;gt; library (which is obfuscated):&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;gradle&amp;quot;&amp;gt;&lt;br /&gt;
dependencies {&lt;br /&gt;
    implementation fg.deobf(&amp;quot;mezz.jei:jei-1.16.5:7.6.1.75&amp;quot;)&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Flat Directory Repositories ===&lt;br /&gt;
There are occasions where it is needed to temporarily add a dependency on a JAR file that is not present in a Maven repository, such as to add a mod which adds some developer tools during runtime. Gradle allows declaring '''flat directory repositories''', which use a local directory as a simplified repository.&amp;lt;ref&amp;gt;[https://docs.gradle.org/current/userguide/declaring_repositories.html#sub:flat_dir_resolver Gradle User Guide for 6.8.1: ''Flat directory repository'']&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A flat directory repository is declared using a &amp;lt;code&amp;gt;flatDir&amp;lt;/code&amp;gt; block within the &amp;lt;code&amp;gt;repositories&amp;lt;/code&amp;gt; block, and specifying directories using &amp;lt;code&amp;gt;dirs&amp;lt;/code&amp;gt;:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;gradle&amp;quot;&amp;gt;&lt;br /&gt;
repositories {&lt;br /&gt;
    flatDir {&lt;br /&gt;
        dirs 'lib'&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When a dependency artifact is searched for in a flat directory repository, it will look for the following files in order (&amp;lt;code&amp;gt;''ext''&amp;lt;/code&amp;gt; defaults to &amp;lt;code&amp;gt;jar&amp;lt;/code&amp;gt;)&amp;lt;ref&amp;gt;[https://github.com/gradle/gradle/blob/v6.8.1/subprojects/core-api/src/main/java/org/gradle/api/artifacts/repositories/FlatDirectoryArtifactRepository.java gradle/gradle; tag v6.8.1; org.gradle.api.artifacts.repositories.FlatDirectoryArtifactRepository]&amp;lt;/ref&amp;gt;:&lt;br /&gt;
* &amp;lt;code&amp;gt;''&amp;lt;artifact&amp;gt;''-''&amp;lt;version&amp;gt;''.''&amp;lt;ext&amp;gt;''&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;''&amp;lt;artifact&amp;gt;''-''&amp;lt;version&amp;gt;''-''&amp;lt;classifier&amp;gt;''.''&amp;lt;ext&amp;gt;''&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;''&amp;lt;artifact&amp;gt;''.''&amp;lt;ext&amp;gt;''&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;''&amp;lt;artifact&amp;gt;''-''&amp;lt;classifier&amp;gt;''.''&amp;lt;ext&amp;gt;''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For example, for the dependency &amp;lt;code&amp;gt;junit:junit:4.8.1&amp;lt;/code&amp;gt;, it will first search for &amp;lt;code&amp;gt;junit-4.8.1.jar&amp;lt;/code&amp;gt; then &amp;lt;code&amp;gt;junit.jar&amp;lt;/code&amp;gt;. The group ID in the dependency descriptor must be present (due to the presence of non-flat directory repositories as added by ForgeGradle), but it will always be ignored.&lt;br /&gt;
&lt;br /&gt;
{{Tip/Warning&lt;br /&gt;
|Flat directory repositories should ''only'' be used temporarily in a local environment, and not used to include a required dependency for your project. For a actual dependency used by your mod, use a remote Maven repository holding the artifact.&lt;br /&gt;
}}&lt;/div&gt;</summary>
		<author><name>SciWhiz12</name></author>
	</entry>
	<entry>
		<id>https://forge.gemwire.uk/index.php?title=FCWMeta:Village_pump&amp;diff=2566</id>
		<title>FCWMeta:Village pump</title>
		<link rel="alternate" type="text/html" href="https://forge.gemwire.uk/index.php?title=FCWMeta:Village_pump&amp;diff=2566"/>
		<updated>2021-04-20T00:48:12Z</updated>

		<summary type="html">&lt;p&gt;SciWhiz12: use definitions, looks better&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__NEWSECTIONLINK__&lt;br /&gt;
&lt;br /&gt;
{{Colored box&lt;br /&gt;
|background-content-color=rgba(255, 255, 255, 0.08)&lt;br /&gt;
|style=display: block; text-align: center; font-size: 1.75rem&lt;br /&gt;
|'''Welcome to the village pump!'''&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
This is a place for the community to discuss things related to the wiki. Propose new ideas, find people to collaborate in making articles, or ask something related to wiki; don't be afraid to post here!&lt;br /&gt;
&lt;br /&gt;
Want to discuss something quicker, or find help on something? Why not join the [https://discord.gg/Nn42eAh Discord]?&lt;br /&gt;
&lt;br /&gt;
'''Please add your signature''' whenever you make a comment on a topic, by adding &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;- ~~~~&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt; to the end. When replying to a topic or other comment, use nested [[mw:Help:Lists#List basics|definitions]] (&amp;lt;code&amp;gt;:&amp;lt;/code&amp;gt;) and indent according to where you're replying.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;hr&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Tutorials page/namespace ==&lt;br /&gt;
&lt;br /&gt;
One problem often seen in the modding community is the lack of available tutorials. This becomes a hurdle for new developers, who have to scour the internet for decent tutorials, which can be outdated or contain errors.&lt;br /&gt;
&lt;br /&gt;
I propose that we add a ''Tutorials''' page or namespace, to allow the creation of tutorials here on the wiki. By being on the wiki, it can be edited and updated by anyone, allowing quick correction of errors and general improvements, the benefits on being on a publicly-editable wiki.&lt;br /&gt;
&lt;br /&gt;
We have a few questions to answer though:&lt;br /&gt;
* Should we have a singular &amp;lt;code&amp;gt;Tutorial&amp;lt;/code&amp;gt; page and have tutorials be in subpages (&amp;lt;code&amp;gt;Tutorial/Getting started&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;Tutorial/Blocks&amp;lt;/code&amp;gt;), or use a new namespace (&amp;lt;code&amp;gt;Tutorial:Getting started&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;Tutorial:Blocks&amp;lt;/code&amp;gt;)?&lt;br /&gt;
* Should we have example mods on these tutorial pages, or only have snippets? Example mods could be hosted on the [https://github.com/forgecommunitywiki/mod-examples FCW's &amp;lt;tt&amp;gt;mod-examples&amp;lt;/tt&amp;gt; GitHub repo], though this raises the barrier of creating and improving these example mods.&lt;br /&gt;
&lt;br /&gt;
Having tutorials on the wiki would improve our visibility (so people recommend the wiki's tutorials), and would benefit new developers who may be overwhelmed by other pages with the more technical details and encyclopedic tone. &lt;br /&gt;
&lt;br /&gt;
- [[User:SciWhiz12|&amp;lt;span style=&amp;quot;color: #d9d916; font-weight: bold&amp;quot;&amp;gt;SciWhiz12&amp;lt;/span&amp;gt;]] [[User talk:SciWhiz12|💬]] 04:39, 19 April 2021 (UTC)&lt;br /&gt;
&lt;br /&gt;
: It would probably be better to have a separate namespace for the pages just for better organization on our part. Another issue to address there is multiple tutorials for the same topic. We would need to handle a way for multiple users to create their own method of handling (assuming it's sane). We could neglect that and just have a common tutorial to which everyone must agree on, but I'm not sure how well that would work in this format. As for example mods on these pages, I would vote no on that. There would be a pain to handle all the different languages that the snippet has to be translated to and PR level of entry here would be quite substantial. I would still have to add the translations here, but it's much easier than having user PRs do it. - [[User:ChampionAsh5357|ChampionAsh5357]] ([[User talk:ChampionAsh5357|talk]]) 04:53, 19 April 2021 (UTC)&lt;/div&gt;</summary>
		<author><name>SciWhiz12</name></author>
	</entry>
	<entry>
		<id>https://forge.gemwire.uk/index.php?title=FCWMeta:Village_pump&amp;diff=2562</id>
		<title>FCWMeta:Village pump</title>
		<link rel="alternate" type="text/html" href="https://forge.gemwire.uk/index.php?title=FCWMeta:Village_pump&amp;diff=2562"/>
		<updated>2021-04-19T04:45:05Z</updated>

		<summary type="html">&lt;p&gt;SciWhiz12: some signature changes&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__NEWSECTIONLINK__&lt;br /&gt;
&lt;br /&gt;
{{Colored box&lt;br /&gt;
|background-content-color=rgba(255, 255, 255, 0.08)&lt;br /&gt;
|style=display: block; text-align: center; font-size: 1.75rem&lt;br /&gt;
|'''Welcome to the village pump!'''&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
This is a place for the community to discuss things related to the wiki. Propose new ideas, find people to collaborate in making articles, or ask something related to wiki; don't be afraid to post here!&lt;br /&gt;
&lt;br /&gt;
Want to discuss something quicker, or find help on something? Why not join the [https://discord.gg/Nn42eAh Discord]?&lt;br /&gt;
&lt;br /&gt;
'''Please add your signature''' whenever you make a comment on a topic, by adding &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;- ~~~~&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt; to the end. When replying to a topic or other comment, use nested [[mw:Help:Lists#List basics|unordered lists]] and indent according to where you're replying.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;hr&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Tutorials page/namespace ==&lt;br /&gt;
&lt;br /&gt;
One problem often seen in the modding community is the lack of available tutorials. This becomes a hurdle for new developers, who have to scour the internet for decent tutorials, which can be outdated or contain errors.&lt;br /&gt;
&lt;br /&gt;
I propose that we add a ''Tutorials''' page or namespace, to allow the creation of tutorials here on the wiki. By being on the wiki, it can be edited and updated by anyone, allowing quick correction of errors and general improvements, the benefits on being on a publicly-editable wiki.&lt;br /&gt;
&lt;br /&gt;
We have a few questions to answer though:&lt;br /&gt;
* Should we have a singular &amp;lt;code&amp;gt;Tutorial&amp;lt;/code&amp;gt; page and have tutorials be in subpages (&amp;lt;code&amp;gt;Tutorial/Getting started&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;Tutorial/Blocks&amp;lt;/code&amp;gt;), or use a new namespace (&amp;lt;code&amp;gt;Tutorial:Getting started&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;Tutorial:Blocks&amp;lt;/code&amp;gt;)?&lt;br /&gt;
* Should we have example mods on these tutorial pages, or only have snippets? Example mods could be hosted on the [https://github.com/forgecommunitywiki/mod-examples FCW's &amp;lt;tt&amp;gt;mod-examples&amp;lt;/tt&amp;gt; GitHub repo], though this raises the barrier of creating and improving these example mods.&lt;br /&gt;
&lt;br /&gt;
Having tutorials on the wiki would improve our visibility (so people recommend the wiki's tutorials), and would benefit new developers who may be overwhelmed by other pages with the more technical details and encyclopedic tone. &lt;br /&gt;
&lt;br /&gt;
- [[User:SciWhiz12|&amp;lt;span style=&amp;quot;color: #d9d916; font-weight: bold&amp;quot;&amp;gt;SciWhiz12&amp;lt;/span&amp;gt;]] [[User talk:SciWhiz12|💬]] 04:39, 19 April 2021 (UTC)&lt;/div&gt;</summary>
		<author><name>SciWhiz12</name></author>
	</entry>
	<entry>
		<id>https://forge.gemwire.uk/index.php?title=FCWMeta:Village_pump&amp;diff=2561</id>
		<title>FCWMeta:Village pump</title>
		<link rel="alternate" type="text/html" href="https://forge.gemwire.uk/index.php?title=FCWMeta:Village_pump&amp;diff=2561"/>
		<updated>2021-04-19T04:42:59Z</updated>

		<summary type="html">&lt;p&gt;SciWhiz12: add mention of using nested lists&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__NEWSECTIONLINK__&lt;br /&gt;
&lt;br /&gt;
{{Colored box&lt;br /&gt;
|background-content-color=rgba(255, 255, 255, 0.08)&lt;br /&gt;
|style=display: block; text-align: center; font-size: 1.75rem&lt;br /&gt;
|'''Welcome to the village pump!'''&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
This is a place for the community to discuss things related to the wiki. Propose new ideas, find people to collaborate in making articles, or ask something related to wiki; don't be afraid to post here!&lt;br /&gt;
&lt;br /&gt;
Want to discuss something quicker, or find help on something? Why not join the [https://discord.gg/Nn42eAh Discord]?&lt;br /&gt;
&lt;br /&gt;
'''Please add your signature''' whenever you make a comment on a topic, by adding &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;~~~~&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt; to the end. When replying to a topic or other comment, use nested [[mw:Help:Lists#List basics|unordered lists]] and indent according to where you're replying.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;hr&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Tutorials page/namespace ==&lt;br /&gt;
&lt;br /&gt;
One problem often seen in the modding community is the lack of available tutorials. This becomes a hurdle for new developers, who have to scour the internet for decent tutorials, which can be outdated or contain errors.&lt;br /&gt;
&lt;br /&gt;
I propose that we add a ''Tutorials''' page or namespace, to allow the creation of tutorials here on the wiki. By being on the wiki, it can be edited and updated by anyone, allowing quick correction of errors and general improvements, the benefits on being on a publicly-editable wiki.&lt;br /&gt;
&lt;br /&gt;
We have a few questions to answer though:&lt;br /&gt;
* Should we have a singular &amp;lt;code&amp;gt;Tutorial&amp;lt;/code&amp;gt; page and have tutorials be in subpages (&amp;lt;code&amp;gt;Tutorial/Getting started&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;Tutorial/Blocks&amp;lt;/code&amp;gt;), or use a new namespace (&amp;lt;code&amp;gt;Tutorial:Getting started&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;Tutorial:Blocks&amp;lt;/code&amp;gt;)?&lt;br /&gt;
* Should we have example mods on these tutorial pages, or only have snippets? Example mods could be hosted on the [https://github.com/forgecommunitywiki/mod-examples FCW's &amp;lt;tt&amp;gt;mod-examples&amp;lt;/tt&amp;gt; GitHub repo], though this raises the barrier of creating and improving these example mods.&lt;br /&gt;
&lt;br /&gt;
Having tutorials on the wiki would improve our visibility (so people recommend the wiki's tutorials), and would benefit new developers who may be overwhelmed by other pages with the more technical details and encyclopedic tone. [[User:SciWhiz12|&amp;lt;span style=&amp;quot;color: #d9d916; font-weight: bold&amp;quot;&amp;gt;SciWhiz12&amp;lt;/span&amp;gt;]] [[User talk:SciWhiz12|💬]] 04:39, 19 April 2021 (UTC)&lt;/div&gt;</summary>
		<author><name>SciWhiz12</name></author>
	</entry>
	<entry>
		<id>https://forge.gemwire.uk/index.php?title=FCWMeta:Village_pump&amp;diff=2560</id>
		<title>FCWMeta:Village pump</title>
		<link rel="alternate" type="text/html" href="https://forge.gemwire.uk/index.php?title=FCWMeta:Village_pump&amp;diff=2560"/>
		<updated>2021-04-19T04:39:10Z</updated>

		<summary type="html">&lt;p&gt;SciWhiz12: add my signature&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__NEWSECTIONLINK__&lt;br /&gt;
&lt;br /&gt;
{{Colored box&lt;br /&gt;
|background-content-color=rgba(255, 255, 255, 0.08)&lt;br /&gt;
|style=display: block; text-align: center; font-size: 1.75rem&lt;br /&gt;
|'''Welcome to the village pump!'''&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
This is a place for the community to discuss things related to the wiki. Propose new ideas, find people to collaborate in making articles, or ask something related to wiki; don't be afraid to post here!&lt;br /&gt;
&lt;br /&gt;
Want to discuss something quicker, or find help on something? Why not join the [https://discord.gg/Nn42eAh Discord]?&lt;br /&gt;
&lt;br /&gt;
'''Please add your signature''' whenever you make a comment on a topic, by adding &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;~~~~&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt; to the end.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;hr&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Tutorials page/namespace ==&lt;br /&gt;
&lt;br /&gt;
One problem often seen in the modding community is the lack of available tutorials. This becomes a hurdle for new developers, who have to scour the internet for decent tutorials, which can be outdated or contain errors.&lt;br /&gt;
&lt;br /&gt;
I propose that we add a ''Tutorials''' page or namespace, to allow the creation of tutorials here on the wiki. By being on the wiki, it can be edited and updated by anyone, allowing quick correction of errors and general improvements, the benefits on being on a publicly-editable wiki.&lt;br /&gt;
&lt;br /&gt;
We have a few questions to answer though:&lt;br /&gt;
* Should we have a singular &amp;lt;code&amp;gt;Tutorial&amp;lt;/code&amp;gt; page and have tutorials be in subpages (&amp;lt;code&amp;gt;Tutorial/Getting started&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;Tutorial/Blocks&amp;lt;/code&amp;gt;), or use a new namespace (&amp;lt;code&amp;gt;Tutorial:Getting started&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;Tutorial:Blocks&amp;lt;/code&amp;gt;)?&lt;br /&gt;
* Should we have example mods on these tutorial pages, or only have snippets? Example mods could be hosted on the [https://github.com/forgecommunitywiki/mod-examples FCW's &amp;lt;tt&amp;gt;mod-examples&amp;lt;/tt&amp;gt; GitHub repo], though this raises the barrier of creating and improving these example mods.&lt;br /&gt;
&lt;br /&gt;
Having tutorials on the wiki would improve our visibility (so people recommend the wiki's tutorials), and would benefit new developers who may be overwhelmed by other pages with the more technical details and encyclopedic tone. [[User:SciWhiz12|&amp;lt;span style=&amp;quot;color: #d9d916; font-weight: bold&amp;quot;&amp;gt;SciWhiz12&amp;lt;/span&amp;gt;]] [[User talk:SciWhiz12|💬]] 04:39, 19 April 2021 (UTC)&lt;/div&gt;</summary>
		<author><name>SciWhiz12</name></author>
	</entry>
	<entry>
		<id>https://forge.gemwire.uk/index.php?title=FCWMeta:Village_pump&amp;diff=2559</id>
		<title>FCWMeta:Village pump</title>
		<link rel="alternate" type="text/html" href="https://forge.gemwire.uk/index.php?title=FCWMeta:Village_pump&amp;diff=2559"/>
		<updated>2021-04-19T04:38:46Z</updated>

		<summary type="html">&lt;p&gt;SciWhiz12: /* Tutorials page/namespace */ new section&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__NEWSECTIONLINK__&lt;br /&gt;
&lt;br /&gt;
{{Colored box&lt;br /&gt;
|background-content-color=rgba(255, 255, 255, 0.08)&lt;br /&gt;
|style=display: block; text-align: center; font-size: 1.75rem&lt;br /&gt;
|'''Welcome to the village pump!'''&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
This is a place for the community to discuss things related to the wiki. Propose new ideas, find people to collaborate in making articles, or ask something related to wiki; don't be afraid to post here!&lt;br /&gt;
&lt;br /&gt;
Want to discuss something quicker, or find help on something? Why not join the [https://discord.gg/Nn42eAh Discord]?&lt;br /&gt;
&lt;br /&gt;
'''Please add your signature''' whenever you make a comment on a topic, by adding &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;~~~~&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt; to the end.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;hr&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Tutorials page/namespace ==&lt;br /&gt;
&lt;br /&gt;
One problem often seen in the modding community is the lack of available tutorials. This becomes a hurdle for new developers, who have to scour the internet for decent tutorials, which can be outdated or contain errors.&lt;br /&gt;
&lt;br /&gt;
I propose that we add a ''Tutorials''' page or namespace, to allow the creation of tutorials here on the wiki. By being on the wiki, it can be edited and updated by anyone, allowing quick correction of errors and general improvements, the benefits on being on a publicly-editable wiki.&lt;br /&gt;
&lt;br /&gt;
We have a few questions to answer though:&lt;br /&gt;
* Should we have a singular &amp;lt;code&amp;gt;Tutorial&amp;lt;/code&amp;gt; page and have tutorials be in subpages (&amp;lt;code&amp;gt;Tutorial/Getting started&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;Tutorial/Blocks&amp;lt;/code&amp;gt;), or use a new namespace (&amp;lt;code&amp;gt;Tutorial:Getting started&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;Tutorial:Blocks&amp;lt;/code&amp;gt;)?&lt;br /&gt;
* Should we have example mods on these tutorial pages, or only have snippets? Example mods could be hosted on the [https://github.com/forgecommunitywiki/mod-examples FCW's &amp;lt;tt&amp;gt;mod-examples&amp;lt;/tt&amp;gt; GitHub repo], though this raises the barrier of creating and improving these example mods.&lt;br /&gt;
&lt;br /&gt;
Having tutorials on the wiki would improve our visibility (so people recommend the wiki's tutorials), and would benefit new developers who may be overwhelmed by other pages with the more technical details and encyclopedic tone.&lt;/div&gt;</summary>
		<author><name>SciWhiz12</name></author>
	</entry>
	<entry>
		<id>https://forge.gemwire.uk/index.php?title=FCWMeta:Village_pump&amp;diff=2558</id>
		<title>FCWMeta:Village pump</title>
		<link rel="alternate" type="text/html" href="https://forge.gemwire.uk/index.php?title=FCWMeta:Village_pump&amp;diff=2558"/>
		<updated>2021-04-19T04:23:17Z</updated>

		<summary type="html">&lt;p&gt;SciWhiz12: some small edits&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__NEWSECTIONLINK__&lt;br /&gt;
&lt;br /&gt;
{{Colored box&lt;br /&gt;
|background-content-color=rgba(255, 255, 255, 0.08)&lt;br /&gt;
|style=display: block; text-align: center; font-size: 1.75rem&lt;br /&gt;
|'''Welcome to the village pump!'''&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
This is a place for the community to discuss things related to the wiki. Propose new ideas, find people to collaborate in making articles, or ask something related to wiki; don't be afraid to post here!&lt;br /&gt;
&lt;br /&gt;
Want to discuss something quicker, or find help on something? Why not join the [https://discord.gg/Nn42eAh Discord]?&lt;br /&gt;
&lt;br /&gt;
'''Please add your signature''' whenever you make a comment on a topic, by adding &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;~~~~&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt; to the end.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;hr&amp;gt;&lt;/div&gt;</summary>
		<author><name>SciWhiz12</name></author>
	</entry>
	<entry>
		<id>https://forge.gemwire.uk/index.php?title=FCWMeta:Village_pump&amp;diff=2557</id>
		<title>FCWMeta:Village pump</title>
		<link rel="alternate" type="text/html" href="https://forge.gemwire.uk/index.php?title=FCWMeta:Village_pump&amp;diff=2557"/>
		<updated>2021-04-19T04:20:30Z</updated>

		<summary type="html">&lt;p&gt;SciWhiz12: create the page&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__NEWSECTIONLINK__&lt;br /&gt;
&lt;br /&gt;
{{Colored box&lt;br /&gt;
|background-content-color=rgba(255, 255, 255, 0.08)&lt;br /&gt;
|style=display: block; text-align: center; font-size: 1.75rem&lt;br /&gt;
|'''Welcome to the village pumps!'''&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
This is a place for the community to discuss things related to the wiki. Propose new ideas, find people to collaborate in making articles, or ask something related to wiki; don't be afraid to post here!&lt;br /&gt;
&lt;br /&gt;
Want to discuss something quicker, or find help on something? Why not join the [https://discord.gg/Nn42eAh Discord]?&lt;br /&gt;
&lt;br /&gt;
'''Please add your signature''' whenever you make a comment on a topic, by adding &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;~~~~&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt; to the end.&lt;/div&gt;</summary>
		<author><name>SciWhiz12</name></author>
	</entry>
	<entry>
		<id>https://forge.gemwire.uk/index.php?title=Template:Tabs/Tab/Code_Snippet&amp;diff=2546</id>
		<title>Template:Tabs/Tab/Code Snippet</title>
		<link rel="alternate" type="text/html" href="https://forge.gemwire.uk/index.php?title=Template:Tabs/Tab/Code_Snippet&amp;diff=2546"/>
		<updated>2021-04-08T20:47:32Z</updated>

		<summary type="html">&lt;p&gt;SciWhiz12: Add lang attribute to code snippet template call&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{#tag:tab&lt;br /&gt;
|{{#if:{{{file_name|}}}|{{{file_name}}}{{#if:{{{ext|}}}|.{{{ext|}}}|}}|}}&lt;br /&gt;
{{Template:Code_Snippet&lt;br /&gt;
|content={{{content|{{{1}}}}}}&lt;br /&gt;
|lang={{#if:{{{lang|}}}|{{{lang}}}|}}&lt;br /&gt;
}}&lt;br /&gt;
|lang={{#if:{{{lang|}}}|{{{lang}}}|}}&lt;br /&gt;
|name=&amp;quot;{{#if:{{{lang|}}}|{{ucfirst:{{{lang}}}}}|Tab}}&amp;quot;&lt;br /&gt;
|style=&amp;quot;width:100%;&amp;quot;&lt;br /&gt;
}}&lt;/div&gt;</summary>
		<author><name>SciWhiz12</name></author>
	</entry>
	<entry>
		<id>https://forge.gemwire.uk/index.php?title=Category:Under_construction&amp;diff=2545</id>
		<title>Category:Under construction</title>
		<link rel="alternate" type="text/html" href="https://forge.gemwire.uk/index.php?title=Category:Under_construction&amp;diff=2545"/>
		<updated>2021-04-08T11:01:02Z</updated>

		<summary type="html">&lt;p&gt;SciWhiz12: SciWhiz12 moved page Category:Under construction to Category:Pages under construction: imo, a better name&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;#REDIRECT [[:Category:Pages under construction]]&lt;/div&gt;</summary>
		<author><name>SciWhiz12</name></author>
	</entry>
	<entry>
		<id>https://forge.gemwire.uk/index.php?title=Category:Pages_under_construction&amp;diff=2544</id>
		<title>Category:Pages under construction</title>
		<link rel="alternate" type="text/html" href="https://forge.gemwire.uk/index.php?title=Category:Pages_under_construction&amp;diff=2544"/>
		<updated>2021-04-08T11:01:02Z</updated>

		<summary type="html">&lt;p&gt;SciWhiz12: SciWhiz12 moved page Category:Under construction to Category:Pages under construction: imo, a better name&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;All pages marked with [[Template:Under construction]] are listed here. Editors are encouraged to edit and improve these pages, and to remove the template once the page looks complete.&lt;/div&gt;</summary>
		<author><name>SciWhiz12</name></author>
	</entry>
	<entry>
		<id>https://forge.gemwire.uk/index.php?title=Template:Under_construction&amp;diff=2543</id>
		<title>Template:Under construction</title>
		<link rel="alternate" type="text/html" href="https://forge.gemwire.uk/index.php?title=Template:Under_construction&amp;diff=2543"/>
		<updated>2021-04-08T11:00:13Z</updated>

		<summary type="html">&lt;p&gt;SciWhiz12: change category to :Category:Pages under construction&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Colored box&lt;br /&gt;
|icon=Under_construction.svg&lt;br /&gt;
|border-color=#f6c800&lt;br /&gt;
|title={{{title|This page is under construction.}}}&lt;br /&gt;
|{{{1|This page is incomplete, and needs more work. Feel free to edit and improve this page!}}}&lt;br /&gt;
}}&lt;br /&gt;
&amp;lt;includeonly&amp;gt;[[Category:Pages under construction]]&amp;lt;/includeonly&amp;gt;&lt;/div&gt;</summary>
		<author><name>SciWhiz12</name></author>
	</entry>
</feed>