<?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=Paint+Ninja</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=Paint+Ninja"/>
	<link rel="alternate" type="text/html" href="https://forge.gemwire.uk/wiki/Special:Contributions/Paint_Ninja"/>
	<updated>2026-06-04T22:23:00Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.35.0</generator>
	<entry>
		<id>https://forge.gemwire.uk/index.php?title=Getting_Started&amp;diff=2983</id>
		<title>Getting Started</title>
		<link rel="alternate" type="text/html" href="https://forge.gemwire.uk/index.php?title=Getting_Started&amp;diff=2983"/>
		<updated>2021-11-30T07:21:35Z</updated>

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

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

		<summary type="html">&lt;p&gt;Paint Ninja: Add Groovy language code examples&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Many blocks and items in vanilla change their texture color depending on where they are, such as grass. Models support specifying “tint indices” on faces, which are integers that can then be handled by &amp;lt;code&amp;gt;BlockColor&amp;lt;/code&amp;gt;s and &amp;lt;code&amp;gt;IItemColor&amp;lt;/code&amp;gt;s. See the wiki for information on how tint indices are defined in vanilla models.&lt;br /&gt;
&lt;br /&gt;
=== BlockColor / ItemColor ===&lt;br /&gt;
Both of these are single-method interfaces. &amp;lt;code&amp;gt;BlockColor&amp;lt;/code&amp;gt; takes a &amp;lt;code&amp;gt;BlockState&amp;lt;/code&amp;gt;, a (&amp;lt;code&amp;gt;nullable&amp;lt;/code&amp;gt;) &amp;lt;code&amp;gt;BlockAndTintGetter&amp;lt;/code&amp;gt;, and a (&amp;lt;code&amp;gt;nullable&amp;lt;/code&amp;gt;) &amp;lt;code&amp;gt;BlockPos&amp;lt;/code&amp;gt;. &amp;lt;code&amp;gt;ItemColor&amp;lt;/code&amp;gt; takes an &amp;lt;code&amp;gt;ItemStack&amp;lt;/code&amp;gt;. Both of them take a parameter &amp;lt;code&amp;gt;tintIndex&amp;lt;/code&amp;gt;, which is the tint index of the face being colored. Both of them return an &amp;lt;code&amp;gt;int&amp;lt;/code&amp;gt;, a color multiplier. This int is treated as four unsigned bytes, alpha, red, green, and blue, in that order, from most significant byte to least. For each pixel in the tinted face, the value of each color channel is &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;(int)((float)base * multiplier / 255)&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;, where &amp;lt;code&amp;gt;base&amp;lt;/code&amp;gt; is the original value for the channel, and &amp;lt;code&amp;gt;multiplier&amp;lt;/code&amp;gt; is the associated byte from the color multiplier. Note that blocks do not use the alpha channel. For example, the grass texture, untinted, looks white and gray. The &amp;lt;code&amp;gt;BlockColor&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;ItemColor&amp;lt;/code&amp;gt; for grass return color multipliers with low red and blue components, but high alpha and green components, (at least in warm biomes) so when the multiplication is performed, the green is brought out and the red/blue diminished.&lt;br /&gt;
&lt;br /&gt;
If an item inherits from the &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;builtin/generated&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt; model, each layer (“layer0”, “layer1”, etc.) has a tint index corresponding to its layer index. For blocks, the “particle” layer is index 0.&lt;br /&gt;
&lt;br /&gt;
=== Creating Color Handlers ===&lt;br /&gt;
&amp;lt;code&amp;gt;BlockColor&amp;lt;/code&amp;gt;s need to be registered to the &amp;lt;code&amp;gt;BlockColors&amp;lt;/code&amp;gt; instance of the game. &amp;lt;code&amp;gt;BlockColors&amp;lt;/code&amp;gt; can be acquired through &amp;lt;code&amp;gt;ColorHandlerEvent$Block&amp;lt;/code&amp;gt;, and an &amp;lt;code&amp;gt;BlockColor&amp;lt;/code&amp;gt; can be registered by &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;BlockColors#register&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;. Note that this does not cause the &amp;lt;code&amp;gt;BlockItem&amp;lt;/code&amp;gt; for the given block to be colored. &amp;lt;code&amp;gt;BlockItem&amp;lt;/code&amp;gt; are items and need to colored with an &amp;lt;code&amp;gt;ItemColor&amp;lt;/code&amp;gt;.&lt;br /&gt;
{{Template:Tabs/Code_Snippets&lt;br /&gt;
|java=public void registerBlockColors(final ColorHandlerEvent.Block event) {&lt;br /&gt;
    event.getBlockColors().register(myBlockColor, coloredBlock1, coloredBlock2, ...);&lt;br /&gt;
}&lt;br /&gt;
|groovy=void registerBlockColors(final ColorHandlerEvent.Block event) {&lt;br /&gt;
    event.blockColors.register(myBlockColor, coloredBlock1, coloredBlock2, ...);&lt;br /&gt;
}&lt;br /&gt;
|}}&lt;br /&gt;
&amp;lt;code&amp;gt;ItemColor&amp;lt;/code&amp;gt;s need to be registered to the &amp;lt;code&amp;gt;ItemColors&amp;lt;/code&amp;gt; instance of the game. &amp;lt;code&amp;gt;ItemColors&amp;lt;/code&amp;gt; can be acquired through &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;ColorHandlerEvent$Item&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;, and an &amp;lt;code&amp;gt;ItemColor&amp;lt;/code&amp;gt; can be registered by &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;ItemColors#register&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;. This method is overloaded to also take &amp;lt;code&amp;gt;Block&amp;lt;/code&amp;gt;s, which simply registers the color handler for the item &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;Block#asItem&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt; (i.e. the block’s &amp;lt;code&amp;gt;BlockItem&amp;lt;/code&amp;gt;).&lt;br /&gt;
{{Template:Tabs/Code_Snippets&lt;br /&gt;
|java=public void registerItemColors(final ColorHandlerEvent.Item event) {&lt;br /&gt;
    event.getItemColors().register(myItemColor, coloredItem1, coloredItem2, ...);&lt;br /&gt;
}&lt;br /&gt;
|groovy=void registerBlockColors(final ColorHandlerEvent.Item event) {&lt;br /&gt;
    event.itemColors.register(myItemColor, coloredItem1, coloredItem2, ...);&lt;br /&gt;
}&lt;br /&gt;
|}}&lt;br /&gt;
This registration must be done client-side, in the initialization phase.&lt;/div&gt;</summary>
		<author><name>Paint Ninja</name></author>
	</entry>
	<entry>
		<id>https://forge.gemwire.uk/index.php?title=Registration&amp;diff=2978</id>
		<title>Registration</title>
		<link rel="alternate" type="text/html" href="https://forge.gemwire.uk/index.php?title=Registration&amp;diff=2978"/>
		<updated>2021-11-17T16:37:59Z</updated>

		<summary type="html">&lt;p&gt;Paint Ninja: Add a couple of Groovy language examples&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Under construction}}&lt;br /&gt;
&lt;br /&gt;
Registration is the process of making an object (such as an item or block) known to the game during runtime. If some objects are not registered, this could cause crashes even before the game is fully loaded or arbitrary behaviors such as bottlenecking mod compatibility for world generation.&lt;br /&gt;
&lt;br /&gt;
Most objects that are known within the game are handled by a &amp;lt;code&amp;gt;Registry&amp;lt;/code&amp;gt;. Each registry uniquely defines each object through a &amp;quot;registry name&amp;quot; via a [[Using Resources#ResourceLocation|ResourceLocation]]. This &amp;quot;registry name&amp;quot; can be accessed with its respective getter and setter: &amp;lt;code&amp;gt;#getRegistryName&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;#setRegistryName&amp;lt;/code&amp;gt;. You can only set the &amp;quot;registry name&amp;quot; of a given object once; otherwise, an exception will be thrown.&lt;br /&gt;
&lt;br /&gt;
{{Tip|In a global context, each object is universally unique through its &amp;lt;code&amp;gt;ResourceKey&amp;lt;/code&amp;gt;: a concatenation of its registry's id and the object's registry name.}}&lt;br /&gt;
&lt;br /&gt;
Due to the inconsistent ordering and registration process vanilla uses, Forge wraps most vanilla registries using &amp;lt;code&amp;gt;IForgeRegistry&amp;lt;/code&amp;gt;. This guarantees that the loading order for these wrapped registries will be &amp;lt;code&amp;gt;Block&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;Item&amp;lt;/code&amp;gt;, and then the rest of the wrapped registries in alphabetical order. All registries supported by Forge can be found within the &amp;lt;code&amp;gt;ForgeRegistries&amp;lt;/code&amp;gt; class. Since all registry names are unique to a specific registry, different registry objects within different registries can have the same name (e.g. a &amp;lt;code&amp;gt;Block&amp;lt;/code&amp;gt; and an &amp;lt;code&amp;gt;Item&amp;lt;/code&amp;gt; each hold a registry object named &amp;lt;code&amp;gt;examplemod:object&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
{{Tip/Warning|If two registry objects within the same registry have the same name, the second object will override the first. The only registry that will throw an &amp;lt;code&amp;gt;IllegalArgumentException&amp;lt;/code&amp;gt; is the &amp;lt;code&amp;gt;DataSerializerEntry&amp;lt;/code&amp;gt; registry.}}&lt;br /&gt;
&lt;br /&gt;
== Methods for Registering ==&lt;br /&gt;
&lt;br /&gt;
There are two proper ways to register objects within an associated wrapped Forge registry: the &amp;lt;code&amp;gt;DeferredRegister&amp;lt;/code&amp;gt; class, and the &amp;lt;code&amp;gt;RegistryEvent$Register&amp;lt;/code&amp;gt; lifecycle event.&lt;br /&gt;
&lt;br /&gt;
For objects with '''no''' associated Forge registry, you can register the associated entry during the &amp;lt;code&amp;gt;FMLCommonSetupEvent&amp;lt;/code&amp;gt; lifecycle event. In some cases, although not recommended, you may also statically initialize and register these entries.&lt;br /&gt;
&lt;br /&gt;
=== DeferredRegister ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;DeferredRegister&amp;lt;/code&amp;gt; is an abstraction layer over the registry event used to register objects. It maintains a map of &amp;quot;registry name&amp;quot; to their associated suppliers and resolves those suppliers during the proper &amp;lt;code&amp;gt;RegistryEvent$Register&amp;lt;/code&amp;gt; event. This method is the currently recommended, and documented, way to handle these objects as it provides convenience and safety for those who want to statically initialize objects while avoiding some issues associated with it. &lt;br /&gt;
&lt;br /&gt;
An example of a mod registering a custom block:&lt;br /&gt;
&lt;br /&gt;
{{Template:Tabs/Code_Snippets&lt;br /&gt;
|java=private static final DeferredRegister&amp;lt;Block&amp;gt; BLOCKS = DeferredRegister.create(ForgeRegistries.BLOCKS, MODID);&lt;br /&gt;
&lt;br /&gt;
public static final RegistryObject&amp;lt;Block&amp;gt; EXAMPLE_BLOCK = BLOCKS.register(&amp;quot;example_block&amp;quot;, () -&amp;gt; new Block(BlockBehaviour.Properties.of(Material.STONE)));&lt;br /&gt;
&lt;br /&gt;
public ExampleMod() {&lt;br /&gt;
    BLOCKS.register(FMLJavaModLoadingContext.get().getModEventBus());&lt;br /&gt;
}&lt;br /&gt;
|kotlin=private val BLOCKS = DeferredRegister.create(ForgeRegistries.BLOCKS, MODID)&lt;br /&gt;
&lt;br /&gt;
val EXAMPLE_BLOCK: RegistryObject&amp;lt;Block&amp;gt; = BLOCKS.register(&amp;quot;example_block&amp;quot;) { Block(BlockBehaviour.Properties.of(Material.ROCK)) }&lt;br /&gt;
&lt;br /&gt;
internal class ExampleMod {&lt;br /&gt;
    init {&lt;br /&gt;
        BLOCKS.register(FMLJavaModLoadingContext.get().modEventBus)&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
|scala=object ExampleMod {&lt;br /&gt;
    private final val BLOCKS = DeferredRegister.create(ForgeRegistries.BLOCKS, MODID)&lt;br /&gt;
&lt;br /&gt;
    final val EXAMPLE_BLOCK = registerBlock(&amp;quot;example_block&amp;quot;, () =&amp;gt; new Block(BlockBehaviour.Properties.of(Material.ROCK)))&lt;br /&gt;
}&lt;br /&gt;
class ExampleMod {&lt;br /&gt;
    BLOCKS.register(FMLJavaModLoadingContext.get.getModEventBus)&lt;br /&gt;
}&lt;br /&gt;
|groovy=private static final DeferredRegister&amp;lt;Block&amp;gt; BLOCKS = DeferredRegister.create(ForgeRegistries.BLOCKS, MODID);&lt;br /&gt;
&lt;br /&gt;
public static final RegistryObject&amp;lt;Block&amp;gt; EXAMPLE_BLOCK = BLOCKS.register(&amp;quot;example_block&amp;quot;, () -&amp;gt; new Block(BlockBehaviour.Properties.of(Material.STONE)));&lt;br /&gt;
&lt;br /&gt;
ExampleMod() {&lt;br /&gt;
    BLOCKS.register(FMLJavaModLoadingContext.get().modEventBus);&lt;br /&gt;
}&lt;br /&gt;
|}}&lt;br /&gt;
&lt;br /&gt;
{{Tip|When using a &amp;lt;code&amp;gt;DeferredRegister&amp;lt;/code&amp;gt; to register any object, the name inputted will be automatically prefixed with the mod id passed in, giving the above object a &amp;quot;registry name&amp;quot; of &amp;lt;code&amp;gt;examplemod:example_block&amp;lt;/code&amp;gt;.}}&lt;br /&gt;
&lt;br /&gt;
=== RegistryEvent.Register ===&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;RegistryEvent&amp;lt;/code&amp;gt;s are another, more slightly flexible way to register objects. These [[Events|events]] are fired synchronously after &amp;lt;code&amp;gt;FMLConstructModEvent&amp;lt;/code&amp;gt; and before the configs are loaded.&lt;br /&gt;
&lt;br /&gt;
The event used to register objects is &amp;lt;code&amp;gt;RegistryEvent.Register&amp;lt;T&amp;gt;&amp;lt;/code&amp;gt;, where the type parameter &amp;lt;code&amp;gt;T&amp;lt;/code&amp;gt; is the object type being registered. You can grab the associated registry using &amp;lt;code&amp;gt;#getRegistry&amp;lt;/code&amp;gt; and register the objects within using either &amp;lt;code&amp;gt;#register&amp;lt;/code&amp;gt; (pass in a single object) or &amp;lt;code&amp;gt;#registerAll&amp;lt;/code&amp;gt; (pass in ''varargs'' or an array of objects). The latter is useful for minimizing calls to &amp;lt;code&amp;gt;#register&amp;lt;/code&amp;gt;, although it provides no benefit time-complexity wise.&lt;br /&gt;
&lt;br /&gt;
{{Tip/Important|The type parameter specified must be the exact class used within the Forge registry, not its superclass nor its subclass. If the class specified is not referenced as a type parameter within the associated Forge registries, then the event will not be called.}}&lt;br /&gt;
&lt;br /&gt;
Here is an example: (the event handler is registered on the '''mod event bus''')&lt;br /&gt;
&lt;br /&gt;
{{Template:Tabs/Code_Snippets&lt;br /&gt;
|java=@SubscribeEvent&lt;br /&gt;
public void registerBlocks(RegistryEvent.Register&amp;lt;Block&amp;gt; event) {&lt;br /&gt;
    event.getRegistry().registerAll(new Block(...).setRegistryName(new ResourceLocation(MODID, &amp;quot;example_block1&amp;quot;)), new Block(...).setRegistryName(new ResourceLocation(MODID, &amp;quot;example_block2&amp;quot;)), ...);&lt;br /&gt;
}&lt;br /&gt;
|kotlin=@JvmStatic&lt;br /&gt;
@SubscribeEvent&lt;br /&gt;
private fun registerBlocks(event: RegistryEvent.Register&amp;lt;Block&amp;gt;) =&lt;br /&gt;
    event.registry.registerAll(Block(...).setRegistryName(new ResourceLocation(MODID, &amp;quot;example_block1&amp;quot;)), Block(...).setRegistryName(new ResourceLocation(MODID, &amp;quot;example_block2&amp;quot;)), ...)&lt;br /&gt;
|scala=@SubscribeEvent&lt;br /&gt;
def registerBlocks(event: RegistryEvent.Register[Block]): Unit =&lt;br /&gt;
    event.getRegistry.registerAll(new Block(...).setRegistryName(new ResourceLocation(MODID, &amp;quot;example_block1&amp;quot;)), new Block(...).setRegistryName(new ResourceLocation(MODID, &amp;quot;example_block2&amp;quot;)), ...)&lt;br /&gt;
|}}&lt;br /&gt;
&lt;br /&gt;
{{Tip/Important|Since all objects registered must be singleton, some classes cannot by themselves be registered. Instead, &amp;lt;code&amp;gt;*Type&amp;lt;/code&amp;gt; classes are registered and used in the formers' constructors to wrap the flyweight objects. For example, a [[Basics_of_Block_Entities|&amp;lt;code&amp;gt;BlockEntity&amp;lt;/code&amp;gt;]] is wrapped via &amp;lt;code&amp;gt;BlockEntityType&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;Entity&amp;lt;/code&amp;gt; is wrapped via &amp;lt;code&amp;gt;EntityType&amp;lt;/code&amp;gt;. These &amp;lt;code&amp;gt;*Type&amp;lt;/code&amp;gt; classes hold factories that simply create the containing type on demand.&lt;br /&gt;
&lt;br /&gt;
These factory holders are created through the use of their &amp;lt;code&amp;gt;*Type$Builder&amp;lt;/code&amp;gt; classes. An example: (&amp;lt;code&amp;gt;REGISTER&amp;lt;/code&amp;gt; here refers to a &amp;lt;code&amp;gt;DeferredRegister&amp;lt;BlockEntityType&amp;lt;?&amp;gt;&amp;gt;&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
{{Template:Tabs/Code_Snippets&lt;br /&gt;
|java=public static final RegistryObject&amp;lt;BlockEntityType&amp;lt;ExampleBlockEntity&amp;gt;&amp;gt; EXAMPLE_BLOCK_ENTITY = REGISTER.register(&lt;br /&gt;
    &amp;quot;example_block_entity&amp;quot;, () -&amp;gt; BlockEntityType.Builder.of(ExampleBlockEntity::new, EXAMPLE_BLOCK.get()).build(null)&lt;br /&gt;
);&lt;br /&gt;
|kotlin=val EXAMPLE_BLOCK_ENTITY: RegistryObject&amp;lt;BlockEntityType&amp;lt;ExampleBlockEntity&amp;gt;&amp;gt; = REGISTER.register(&amp;quot;example_block_entity&amp;quot;) { BlockEntityType.Builder.of(::ExampleBlockEntity, EXAMPLE_BLOCK.get()).build(null)) }&lt;br /&gt;
|scala=final val EXAMPLE_BLOCK_ENTITY = REGISTER.register(&amp;quot;example_block_entity&amp;quot;, () =&amp;gt; BlockEntityType.Builder.of(() =&amp;gt; new ExampleBlockEntity(), GeneralRegistrar.EXAMPLE_BLOCK.get).build(null))&lt;br /&gt;
|}}&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
=== Non-Forge Registries ===&lt;br /&gt;
&lt;br /&gt;
Not all vanilla registries are wrapped as a Forge registry. This is because the registry is fully independent from any other registry, completely data driven, or just has not been wrapped yet.&lt;br /&gt;
&lt;br /&gt;
These registries include:&lt;br /&gt;
* Custom Stats (a &amp;lt;code&amp;gt;ResourceLocation&amp;lt;/code&amp;gt; registry)&lt;br /&gt;
* &amp;lt;code&amp;gt;RuleTestType&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;PosRuleTestType&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;RecipeType&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;GameEvent&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;PositionSourceType&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;VillagerType&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;LootPoolEntryType&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;LootItemFunctionType&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;LootItemConditionType&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;LootNumberProviderType&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;LootNbtProviderType&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;LootScoreProviderType&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;FloatProviderType&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;IntProviderType&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;HeightProviderType&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;StructurePieceType&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;TrunkPlacerType&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;FeatureSizeType&amp;lt;/code&amp;gt;&lt;br /&gt;
* A &amp;lt;code&amp;gt;Codec&amp;lt;/code&amp;gt; of &amp;lt;code&amp;gt;BiomeSource&amp;lt;/code&amp;gt;&lt;br /&gt;
* A &amp;lt;code&amp;gt;Codec&amp;lt;/code&amp;gt; of &amp;lt;code&amp;gt;ChunkGenerator&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;StructureProcessorType&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;StructurePoolElementType&amp;lt;/code&amp;gt;&lt;br /&gt;
* All registries within &amp;lt;code&amp;gt;BuiltinRegistries&amp;lt;/code&amp;gt; excluding &amp;lt;code&amp;gt;Biome&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To register objects to any one of these registries, 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;
|groovy=public static final RecipeType&amp;lt;ExampleRecipe&amp;gt; EXAMPLE_RECIPE = RecipeType.register(&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 Supplier&amp;lt;IForgeRegistry&amp;lt;ExampleRegistry&amp;gt;&amp;gt; REGISTRY = 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;
{{Template:Tabs/Code_Snippets&lt;br /&gt;
|java=// This will ignore any missing test items from the specified world&lt;br /&gt;
@SubscribeEvent&lt;br /&gt;
public void onMissingItems(final RegistryEvent.MissingMappings&amp;lt;Item&amp;gt; event) {&lt;br /&gt;
    event.getMappings(MODID).stream()&lt;br /&gt;
        .filter(mapping -&amp;gt; mapping.key.getPath().contains(&amp;quot;test&amp;quot;))&lt;br /&gt;
            .forEach(Mapping::ignore);&lt;br /&gt;
}&lt;br /&gt;
|groovy=// This will ignore any missing test items from the specified world&lt;br /&gt;
@SubscribeEvent&lt;br /&gt;
void onMissingItems(final RegistryEvent.MissingMappings&amp;lt;Item&amp;gt; event) {&lt;br /&gt;
    event.getMappings(MODID).stream()&lt;br /&gt;
        .filter(mapping -&amp;gt; mapping.key.path.contains(&amp;quot;test&amp;quot;))&lt;br /&gt;
            .forEach(Mapping::ignore);&lt;br /&gt;
}&lt;br /&gt;
|}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Common Concepts]]&lt;/div&gt;</summary>
		<author><name>Paint Ninja</name></author>
	</entry>
	<entry>
		<id>https://forge.gemwire.uk/index.php?title=Stages_of_Modloading&amp;diff=2951</id>
		<title>Stages of Modloading</title>
		<link rel="alternate" type="text/html" href="https://forge.gemwire.uk/index.php?title=Stages_of_Modloading&amp;diff=2951"/>
		<updated>2021-09-06T19:08:44Z</updated>

		<summary type="html">&lt;p&gt;Paint Ninja: Document config loading stage&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;The FML mod loading process is broken into several stages, with each stage having associated events fired alongside with it on the mod-specific event bus. These events are known as the &amp;lt;code&amp;gt;mod lifecycle events&amp;lt;/code&amp;gt;, as they are fired during the different phases of a mod's life.&lt;br /&gt;
&lt;br /&gt;
The different mod loading stages are represented each by a value in the enum class &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;net.minecraftforge.fml.ModLoadingStage&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;. Their states are split between the &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;net.minecraftforge.fml.core.ModStateProvider&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt; for mod states (construct, common setup, etc.) and &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;net.minecraftforge.fmllegacy.ForgeStatesProvider&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt; for forge injected states (creating registries, injecting capabilities, etc.) Most of the mod lifecycle events are stored in the &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;net.minecraftforge.fml.event.lifecycle&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt; package.&lt;br /&gt;
&lt;br /&gt;
== Parallelism ==&lt;br /&gt;
&lt;br /&gt;
The mod loading system is parallelized to some extent. While all of the stages are changed at the same time across all mods, most of the events are fired in parallel to each mod. That is, all mods will concurrently receive the event, then FML will wait until all mods have processed the event before moving to the next stage and firing the next event. These concurrently dispatched events are distinguished by them extending &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;ParallelDispatchEvent&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
This does means that in these parallel mod lifecycle events, care must be taken to be thread-safe, like when calling external methods which are backed by non-thread-safe collections. Most of the systems in Forge are protected for this; however, vanilla systems and external mods' APIs may not be thread-safe. FML provides a way for mods to defer tasks/work until the event is finished dispatching, where it will be run sequentially along with other events on the main thread. This is done with the &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;#enqueueWork&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt; method, which is a member of all events which extend &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;ParallelDispatchEvent&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Common Transition Stages and Events ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable sortable&amp;quot; border=1&lt;br /&gt;
!  Name  !!  Enum Constant  !!  Lifecycle Event  !!  Parallel?  !! Description &lt;br /&gt;
|-&lt;br /&gt;
|   Construction   ||   &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;CONSTRUCT&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;   ||   &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;FMLConstructModEvent&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;   ||   Yes   ||  Fired when the mod's constructor has been called. Can be used to initialize listeners outside of the constructor. There is usually no reason to use this event, as any code should be placed in the mod constructor instead.&lt;br /&gt;
|-&lt;br /&gt;
|   Registry Creation   ||   &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;CREATE_REGISTRIES&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;   ||   &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;RegistryEvent.NewRegistry&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;   ||   No   ||  Fired for mods to create and initialize their custom registries. &lt;br /&gt;
|-&lt;br /&gt;
|   Registry Population   ||   &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;LOAD_REGISTRIES&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;   ||   &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;RegistryEvent.Register&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;   ||   No   ||  Fired when a registry is open to registrations for any registrable objects, such as blocks, items, etc. &lt;br /&gt;
|-&lt;br /&gt;
|   Config Loading   ||   &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;CONFIG_LOAD&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;   ||   (inlined in &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;ModStateProvider&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;)   ||   ?   ||   Loads config files associated with registered mod configs. Before this stage, mod config values only return their default values unless manually loaded earlier.&lt;br /&gt;
|-&lt;br /&gt;
|   Common Setup   ||   &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;COMMON_SETUP&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;   ||   &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;FMLCommonSetupEvent&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;   ||   Yes   ||  Used for doing any work or action that should be run on both '''physical''' sides. &lt;br /&gt;
|-&lt;br /&gt;
|   Sided Setup   ||   &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;SIDED_SETUP&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;   ||   &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;FMLClientSetupEvent&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt; for physical client, &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;FMLDedicatedServerSetupEvent&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt; for physical server   ||   Yes   ||  Used for doing any physical side-specific initialization work. &lt;br /&gt;
|-&lt;br /&gt;
|   IMC Enqueue   ||   &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;ENQUEUE_IMC&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;   ||   &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;InterModEnqueueEvent&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;   ||   Yes   ||  Fired for mods to enqueue messages for other mods using the &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;InterModComms&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt; system. &lt;br /&gt;
|-&lt;br /&gt;
|   IMC Processing   ||   &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;PROCESS_IMC&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;   ||   &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;InterModProcessEvent&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;   ||   Yes   ||  Fired for mods to process messages from other mods sent using the &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;InterModComms&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt; system in the previous stage. &lt;br /&gt;
|-&lt;br /&gt;
|   Loading Complete   ||   &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;COMPLETE&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;   ||   &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;FMLLoadCompleteEvent&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;   ||   Yes   ||  Fired when mod loading is complete, before handing control back to the main game. There is usually no reason to use this event, as most actions can be done during the Common or Sided Setup stages.&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;/div&gt;</summary>
		<author><name>Paint Ninja</name></author>
	</entry>
	<entry>
		<id>https://forge.gemwire.uk/index.php?title=User_talk:Paint_Ninja/Installer&amp;diff=2595</id>
		<title>User talk:Paint Ninja/Installer</title>
		<link rel="alternate" type="text/html" href="https://forge.gemwire.uk/index.php?title=User_talk:Paint_Ninja/Installer&amp;diff=2595"/>
		<updated>2021-05-13T00:30:37Z</updated>

		<summary type="html">&lt;p&gt;Paint Ninja: Created page with &amp;quot;see &amp;lt;code&amp;gt;Actions.java&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;Action.java&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;ClientInstall/ServerInstall/ExtractAction.java&amp;lt;/code&amp;gt;  example with &amp;lt;code&amp;gt;ExtractAction&amp;lt;/code&amp;gt;: &amp;lt;code&amp;gt;final Acti...&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;see &amp;lt;code&amp;gt;Actions.java&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;Action.java&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;ClientInstall/ServerInstall/ExtractAction.java&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
example with &amp;lt;code&amp;gt;ExtractAction&amp;lt;/code&amp;gt;:&lt;br /&gt;
&amp;lt;code&amp;gt;final Actions action = Actions.EXTRACT;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;action.getAction(installProfile, monitor)&amp;lt;/code&amp;gt; will refer to the &amp;lt;code&amp;gt;BiFunction&amp;lt;Install, ProgressCallback, Action&amp;gt;&amp;lt;/code&amp;gt; action&lt;br /&gt;
inside the &amp;lt;code&amp;gt;Actions.java&amp;lt;/code&amp;gt; enum which &amp;lt;code&amp;gt;Actions.EXTRACT&amp;lt;/code&amp;gt; specifically populates as a new instance of&lt;br /&gt;
&amp;lt;code&amp;gt;ExtractAction.java&amp;lt;/code&amp;gt; as the &amp;lt;code&amp;gt;BiFunction&amp;lt;/code&amp;gt; (a &amp;lt;code&amp;gt;BiFunction&amp;lt;/code&amp;gt; being an &amp;lt;code&amp;gt;Object&amp;lt;/code&amp;gt; that takes two inputs, can do some work and has one output).&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;Install installProfile&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;ProgressCallback monitor&amp;lt;/code&amp;gt; arguments are then applied to the &amp;lt;code&amp;gt;BiFunction&amp;lt;/code&amp;gt;,&lt;br /&gt;
which causes &amp;lt;code&amp;gt;ExtractAction&amp;lt;/code&amp;gt;'s constructor to be called with those arguments.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;ExtractAction&amp;lt;/code&amp;gt;'s constructor calls its parent constructor (Action.java) with &amp;lt;code&amp;gt;super(profile, monitor, true)&amp;lt;/code&amp;gt;.&lt;br /&gt;
true being &amp;lt;code&amp;gt;isClient&amp;lt;/code&amp;gt; here.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;Action.java&amp;lt;/code&amp;gt;'s constructor populates some variables and instantiates &amp;lt;code&amp;gt;PostProcessors.java&amp;lt;/code&amp;gt;, which calls&lt;br /&gt;
the &amp;lt;code&amp;gt;installProfile&amp;lt;/code&amp;gt;'s &amp;lt;code&amp;gt;getProcessors(&amp;quot;client&amp;quot;)&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;getData(true)&amp;lt;/code&amp;gt; methods and stores their results in a&lt;br /&gt;
&amp;lt;code&amp;gt;List&amp;lt;Processor&amp;gt;&amp;lt;/code&amp;gt; and a &amp;lt;code&amp;gt;Map&amp;lt;String, String&amp;gt;&amp;lt;/code&amp;gt;, respectively. &amp;lt;code&amp;gt;Install#getProcessors()&amp;lt;/code&amp;gt; will return an empty list&lt;br /&gt;
and &amp;lt;code&amp;gt;Install#getData()&amp;lt;/code&amp;gt; will return a new, empty &amp;lt;code&amp;gt;HashMap&amp;lt;/code&amp;gt;, this is just to set things up for when the action&lt;br /&gt;
is ran.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;action.getAction(installProfile, monitor).run(target, a -&amp;gt; true)&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;ExtractAction.java&amp;lt;/code&amp;gt; overrides the &amp;lt;code&amp;gt;run(File, Predicate&amp;lt;String&amp;gt;)&amp;lt;/code&amp;gt; method. In this case, the args from the&lt;br /&gt;
run method invocation above provide the target directory to extract to and what's basically an unused&lt;br /&gt;
truthy boolean value.&lt;br /&gt;
&lt;br /&gt;
This run method returns true if successful and false otherwise. It gets the &amp;lt;code&amp;gt;path&amp;lt;/code&amp;gt; variable from the parsed&lt;br /&gt;
&amp;lt;code&amp;gt;installProfile&amp;lt;/code&amp;gt;, which is the Maven artifact path for the 'main' jar and is an instance of &amp;lt;code&amp;gt;Artifact.java&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;Artifact.java&amp;lt;/code&amp;gt; uses an &amp;lt;code&amp;gt;Adapter&amp;lt;/code&amp;gt; subclass that implements a JSON deserializer and serializer that gets the&lt;br /&gt;
JSON primitive String and calls the Artifact#from(String) to split the maven descriptor into its parts and&lt;br /&gt;
build a path to it inside the Installer jar.&lt;br /&gt;
&lt;br /&gt;
It then calls DownloadUtils#extractFile(Artifact, File, String) with the Maven artifact path to extract from,&lt;br /&gt;
the target path to put it in when extracted and a &amp;lt;code&amp;gt;null&amp;lt;/code&amp;gt; (meaning don't verify its checksum after extracting it).&lt;br /&gt;
&lt;br /&gt;
Extracting the &amp;lt;code&amp;gt;Artifact&amp;lt;/code&amp;gt; is easier than it sounds, it just grabs a file embedded within the jar under the&lt;br /&gt;
maven folder (similar to how the install_profile.json is obtained) and copies it to the target path,&lt;br /&gt;
overwriting any existing files there and creating directories to put them in when necessary.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;if (action.getAction(installProfile, monitor).run(target, a -&amp;gt; true)) {&amp;lt;/code&amp;gt;&lt;/div&gt;</summary>
		<author><name>Paint Ninja</name></author>
	</entry>
	<entry>
		<id>https://forge.gemwire.uk/index.php?title=User:Paint_Ninja&amp;diff=2594</id>
		<title>User:Paint Ninja</title>
		<link rel="alternate" type="text/html" href="https://forge.gemwire.uk/index.php?title=User:Paint_Ninja&amp;diff=2594"/>
		<updated>2021-05-13T00:18:29Z</updated>

		<summary type="html">&lt;p&gt;Paint Ninja: Created blank page&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Paint Ninja</name></author>
	</entry>
</feed>