Skip to content

Instantly share code, notes, and snippets.

@BraXon-Devs
Last active April 20, 2019 04:48
Show Gist options
  • Save BraXon-Devs/da4c37f5126e0ea2721dbd32ed9efc5d to your computer and use it in GitHub Desktop.
Save BraXon-Devs/da4c37f5126e0ea2721dbd32ed9efc5d to your computer and use it in GitHub Desktop.
Welcome file

Courtesy of MCForge

Structuring Your Mod

We’ll look at how to organize your mod into different files and what those files should do.

Packaging

Pick a unique package name. If you own a URL associated with your project, you can use it as your top level package. For example if you own “example.com”, you may use com.example as your top level package.

Important

If you do not own a domain, do not use it for your top level package. It is perfectly acceptable to start your package with anything, such as your name/nickname, or the name of the mod.

After the top level package (if you have one) you append a unique name for your mod, such as examplemod. In our case it will end up as com.example.examplemod.

The mcmod.info file

This file defines the metadata of your mod. Its information may be viewed by users from the main screen of the game through the Mods button. A single info file can describe several mods. When a mod is annotated by the @Mod annotation, it may define the useMetadata property, which defaults to false. When useMetadata is true, the metadata within mcmod.info overrides whatever has been defined in the annotation.

The mcmod.info file is formatted as JSON, where the root element is a list of objects and each object describes one modid. It should be stored as src/main/resources/mcmod.info. A basic mcmod.info, describing one mod, may look like this:

[{
  "modid": "examplemod",
  "name": "Example Mod",
  "description": "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.",
  "version": "1.0.0.0",
  "mcversion": "1.10.2",
  "logoFile": "assets/examplemod/textures/logo.png",
  "url": "minecraftforge.net/",
  "updateJSON": "minecraftforge.net/versions.json",
  "authorList": ["Author"],
  "credits": "I'd like to thank my mother and father."
}]

The default Gradle configuration replaces ${version} with the project version, and ${mcversion} with the Minecraft version, but only within mcmod.info, so you should use those instead of directly writing them out. Here is a table of attributes that may be given to a mod, where required means there is no default and the absence of the property causes an error. In addition to the required properties, you should also define descriptionversionmcversionurl, and authorList.

Property Type Default Description
modid string required The modid this description is linked to. If the mod is not loaded, the description is ignored.
name string required The user-friendly name of this mod.
description string "" A description of this mod in 1-2 paragraphs.
version string "" The version of the mod.
mcversion string "" The Minecraft version.
url string "" A link to the mod’s homepage.
updateUrl string "" Defined but unused. Superseded by updateJSON.
updateJSON string "" The URL to a version JSON.
authorList [string] [] A list of authors to this mod.
credits string "" A string that contains any acknowledgements you want to mention.
logoFile string "" The path to the mod’s logo. It is resolved on top of the classpath, so you should put it in a location where the name will not conflict, maybe under your own assets folder.
screenshots [string] [] A list of images to be shown on the info page. Currently unimplemented.
parent string "" The modid of a parent mod, if applicable. Using this allows modules of another mod to be listed under it in the info page, like BuildCraft.
useDependencyInformation boolean false If true and Mod.useMetadata, the below 3 lists of dependencies will be used. If not, they do nothing.
requiredMods [string] [] A list of modids. If one is missing, the game will crash. This does not affect the ordering of mod loading! To specify ordering as well as requirement, have a coupled entry in dependencies.
dependencies [string] [] A list of modids. All of the listed mods will load before this one. If one is not present, nothing happens.
dependants [string] [] A list of modids. All of the listed mods will load after this one. If one is not present, nothing happens.

A good example mcmod.info that uses many of these properties is BuildCraft.

The Mod File

Generally, we’ll start with a file named after your mod, and put into your package. This is the entry point to your mod and will contain some special indicators marking it as such.

What is @Mod?

This is an annotation indicating to the Forge Mod Loader that the class is a Mod entry point. It contains various metadata about the mod. It also designates the class that will receive @EventHandler events.

Here is a table of the properties of @Mod:

Property Type Default Description
modid String required A unique identifier for the mod. It must be lowercased, and will be truncated to 64 characters in length.
name String ”“ A user-friendly name for the mod.
version String ”“ The version of the mod. It should be just numbers seperated by dots, ideally conforming to Semantic Versioning. Even if useMetadata is set to true, it’s a good idea to put the version here anyways.
dependencies String ”“ Dependencies for the mod. The specification is described in the Forge @Mod javadoc:
			<blockquote>

				<p>A dependency string can start with the following four prefixes:&nbsp;<code>&quot;before&quot;</code>,&nbsp;<code>&quot;after&quot;</code>,&nbsp;<code>&quot;required-before&quot;</code>,&nbsp;<code>&quot;required-after&quot;</code>; then&nbsp;<code>&quot;:&quot;</code> and the&nbsp;<code>modid</code>.</p>

				<p>Optionally, a version range can be specified for the mod by adding&nbsp;<code>&quot;@&quot;</code> and then the version range.<a href="https://mcforge.readthedocs.io/en/latest/gettingstarted/structuring/#version-ranges">*</a></p>

				<p>If a &ldquo;required&rdquo; mod is missing, or a mod exists with a version outside the specified range, the game will not start and an error screen will tell the player which versions are required.</p>
			</blockquote>
		</td>
	</tr>
	<tr>
		<td align="right">useMetadata</td>
		<td align="center">boolean</td>
		<td align="center">false</td>
		<td align="left">If set to true, properties in&nbsp;<code>@Mod</code> will be overridden by&nbsp;<code>mcmod.info</code>.</td>
	</tr>
	<tr>
		<td align="right">clientSideOnly
			<br>serverSideOnly</td>
		<td align="center">boolean
			<br>boolean</td>
		<td align="center">false
			<br>false</td>
		<td align="left">If either is set to&nbsp;<code>true</code>, the jar will be skipped on the other side, and the mod will not load. If both are true, the game crashes.</td>
	</tr>
	<tr>
		<td align="right">acceptedMinecraftVersions</td>
		<td align="center">String</td>
		<td align="center">&rdquo;&ldquo;</td>
		<td align="left">The version range of Minecraft the mod will run on.<a href="https://mcforge.readthedocs.io/en/latest/gettingstarted/structuring/#version-ranges">*</a> An empty string will match all versions.</td>
	</tr>
	<tr>
		<td align="right">acceptableRemoteVersions</td>
		<td align="center">String</td>
		<td align="center">&rdquo;&ldquo;</td>
		<td align="left">Specifies a remote version range that this mod will accept as valid.<a href="https://mcforge.readthedocs.io/en/latest/gettingstarted/structuring/#version-ranges">*</a> <code>&quot;&quot;</code> Matches the current version, and&nbsp;<code>&quot;*&quot;</code> matches all versions. Note that&nbsp;<code>&quot;*&quot;</code>matches even when the mod is not present on the remote side at all.</td>
	</tr>
	<tr>
		<td align="right">acceptableSaveVersions</td>
		<td align="center">String</td>
		<td align="center">&rdquo;&ldquo;</td>
		<td align="left">A version range specifying compatible save version information.<a href="https://mcforge.readthedocs.io/en/latest/gettingstarted/structuring/#version-ranges">*</a> If you follow an unusual version convention, use&nbsp;<code>SaveInspectionHandler</code> instead.</td>
	</tr>
	<tr>
		<td align="right">certificateFingerprint</td>
		<td align="center">String</td>
		<td align="center">&rdquo;&ldquo;</td>
		<td align="left">See the tutorial on&nbsp;<a href="https://mcforge.readthedocs.io/en/latest/concepts/jarsigning/">jar signing</a>.</td>
	</tr>
	<tr>
		<td align="right">modLanguage</td>
		<td align="center">String</td>
		<td align="center">&ldquo;java&rdquo;</td>
		<td align="left">The programming language the mod is written in. Can be either&nbsp;<code>&quot;java&quot;</code> or&nbsp;<code>&quot;scala&quot;</code>.</td>
	</tr>
	<tr>
		<td align="right">modLanguageAdapter</td>
		<td align="center">String</td>
		<td align="center">&rdquo;&ldquo;</td>
		<td align="left">Path to a language adapter for the mod. The class must have a default constructor and must implement&nbsp;<code>ILanguageAdapter</code>. If it doesn&rsquo;t, Forge will crash. If set, overrides&nbsp;<code>modLanguage</code>.</td>
	</tr>
	<tr>
		<td align="right">canBeDeactivated</td>
		<td align="center">boolean</td>
		<td align="center">false</td>
		<td align="left">This is not implemented, but if the mod could be deactivated (e.g. a minimap mod), this would be set to&nbsp;<code>true</code> and the mod would&nbsp;<a href="https://mcforge.readthedocs.io/en/latest/events/intro/#creating-an-event-handler">receive</a><code>FMLDeactivationEvent</code> to perform cleanup tasks.</td>
	</tr>
	<tr>
		<td align="right">guiFactory</td>
		<td align="center">String</td>
		<td align="center">&rdquo;&ldquo;</td>
		<td align="left">Path to the mod&rsquo;s GUI factory, if one exists. GUI factories are used to make custom config screens, and must implement&nbsp;<code>IModGuiFactory</code>. For an example, look at&nbsp;<code>FMLConfigGuiFactory</code>.</td>
	</tr>
	<tr>
		<td align="right">updateJSON</td>
		<td align="center">String</td>
		<td align="center">&rdquo;&ldquo;</td>
		<td align="left">URL to an update JSON file. See&nbsp;<a href="https://mcforge.readthedocs.io/en/latest/gettingstarted/autoupdate/">Forge Update Checker</a></td>
	</tr>
</tbody>

* All version ranges use the Maven Version Range Specification.

You can find an example mod in the Forge src download.

Keeping Your Code Clean Using Sub-packages

Rather than clutter up a single class and package with everything, it is recommended you break your mod into subpackages.

A common subpackage strategy has packages for common and client code, which is code that can be run on server/client and client, respectively. Inside the common package would go things like Items, Blocks, and Tile Entities (which can each in turn be another subpackage). Things like GUIs and Renderers would go inside the client package.

Note

This package style is only a suggestion, though it is a commonly used style. Feel free to use your own packaging system.

By keeping your code in clean subpackages, you can grow your mod much more organically.

Class Naming Schemes

A common class naming scheme allows easier deciphering of what a class is, and also makes it easier for someone developing with your mod to find things.

For Example:

  • An Item called PowerRing would be in an item package, with a class name of ItemPowerRing.
  • Block called NotDirt would be in a block package, with a class name of BlockNotDirt.
  • Finally, a TileEntity for a block called SuperChewer would be a tile or tileentity package, with a class name of TileSuperChewer.

Prepending your class names with what kind of object they are makes it easier to figure out what a class is, or guess the class for an object.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment