• Forums

Navigation

  • Home
  • Style Guide
  • Getting Started
    • Home
    • Structuring Your Mod
    • Forge Update Checker
    • Dependency Management
    • Debug Profiler
  • Concepts
    • Sides
    • Resources
    • Registries
      • Registering Things
      • Creating Registries
      • Injecting Registry Values Into Fields
    • The Fingerprint Violation Event
    • Internationalization and localization
  • Blocks
    • Home
    • Intro to Blockstates
    • Interaction
  • Animation API
    • Intro to the Animation API
    • Armatures
    • Animation State Machines
    • Using the API
  • Tile Entities
    • Home
    • Renderer
  • Items
    • Home
    • Loot Tables
  • Models
    • Intro to Models
    • Model Files
    • Blockstates
      • Intro to Blockstate JSONs
      • Forge Blockstate JSON
    • Connecting Blocks and Items to Models
    • Coloring Textures
    • Item Property Overrides
    • Advanced Models
      • Intro to Advanced Models
      • IModel
      • IModelState and IModelPart
      • IBakedModel
      • Extended Blockstates
      • Perspective
      • ItemOverrideList
      • ICustomModelLoader
  • Rendering
    • TileEntityItemStackRenderer
  • Events
    • Basic Usage
  • Networking
    • Home
    • Overview
    • SimpleImpl
    • Entities
  • Data Storage
    • Capabilities
    • World Saved Data
    • Extended Entity Properties
    • Config Annotations
  • Utilities
    • Recipes
    • Tags
    • PermissionAPI
  • Effects
    • Sounds
  • Conventions
    • Versioning
    • Locations
    • Loading Stages
  • Contributing to Forge
    • Getting Started
    • PR Guidelines

Registries

Registration is the process of taking the objects of a mod (items, blocks, sounds, etc.) and making them known to the game. Registering things is important, as without registration the game will simply not know about these objects in a mod and will exhibit great amounts of unexplainable behavior (and probably crash). Some examples of things that need to be registered are Blocks, Items, Biomes.

Most things that require registration in the game are handled by the Forge registries. A registry is a simple object similar to a map that assigns values to keys. Additionally, they automatically assign integer IDs to values. Forge uses registries with ResourceLocation keys to register objects. This allows the ResourceLocation to act like a “registry name” for the object. The registry name for an object may be accessed with get/setRegistryName. The setter can only ever be called once, and calling it twice results in an exception. Every type of registrable object has its own registry, and names in two different registries will not collide. (E.g. there’s a registry for Blocks, and a registry for Items, and a Block and an Item may be registered with the same name mod:example without colliding. However, if two blocks were registered with that name, an exception would be thrown.)

Registering Things

The recommended way to register things is through the RegistryEvents. These events are fired right after preinitialization, In RegistryEvent.NewRegistry, registries should be created. Later, RegistryEvent.Register is fired once for each registered registry. Because Register is a generic event, the event handler should set the type parameter to the type of the object being registered. The event will contain the registry to register things to (getRegistry), and things may be registered with register (or registerAll) on the registry. Here’s an example of an event handler that registers blocks:

@SubscribeEvent
public void registerBlocks(RegistryEvent.Register<Block> event) {
    event.getRegistry().registerAll(block1, block2, ...);
}

The order in which RegistryEvent.Register events fire is alphabetically, with the exception that Block will always fire first, and Item will always fire second, right after Block. After the Register<Block> event has fired, all ObjectHolder annotations are refreshed, and after Register<Item> has fired they are refreshed again. They are refreshed for a third time after all of the other Register events have fired.

RegistryEvents are currently supported for the following types: Block, Item, Potion, Biome, SoundEvent, PotionType, Enchantment, IRecipe, VillagerProfession, EntityEntry

There is another, older way of registering objects into registries, using GameRegistry.register. Anytime something suggests using this method, it should be replaced with an event handler for the appropriate registry event. This method simply finds the registry corresponding to an IForgeRegistryEntry with IForgeRegistryEntry::getRegistryType, and then registers the object to the registry. There is also a convenience overload that takes an IForgeRegistryEntry and a ResourceLocation, which is equivalent to calling IForgeRegistryEntry::setRegistryName, followed by a GameRegistry.register call.

Information

Registering an Entity might be a little bit confusing at first as it doesn’t use the Entity class, but an EntityEntry. These are created by making use of EntityEntryBuilder. EntityEntryBuilder#id() is equivalent to the setRegistryName() method from IForgeRegistryEntry, with the difference that it also takes a mod internal int ID. A simple counter during registration is enough as this ID is only used for networking.

Creating Registries

There’s a global registry where all the other registries are stored. By taking a Class that a registry is supposed to store or its ResourceLocation name, one can retrieve a registry from this registry. For example, one can use GameRegistry.findRegistry(Block.class) to get the registry for blocks. Any mod can create their own registries, and any mod can register things to registries from any other mod. Registries are created by using RegistryBuilder inside a RegistryEvent.NewRegistry event handler. This class takes certain parameters for the registry it will generate, such as the name, the Class of it’s values, and various callbacks for when the registry is changed. Upon calling RegistryBuilder::create, the registry is built, registered to the metaregistry, and returned to the caller.

In order for a class to have a registry, it needs to implement IForgeRegistryEntry. This interface defines getRegistryName(ResourceLocation), setRegistryName(ResourceLocation), and getRegistryType(). getRegistryType is the base Class of the registry the object is to be registered to. It is recommended to extend the default IForgeRegistryEntry.Impl class instead of implementing IForgeRegistryEntry directly. This class also provides two convenience implementations of setRegistryName: one where the parameter is a single string, and one where there are two string parameters. The overload that takes a single string checks whether the input contains a : (i.e. it checks whether the passed in stringified ResourceLocation has a namespace), and if it doesn’t, it uses the current modid as the resource namespace. The two argument overload simply constructs the registry name using the modID as the namespace and name as the path.

Injecting Registry Values Into Fields

It is possible to have Forge inject values from registries into public static final fields of classes. This is done by annotating classes and fields with @ObjectHolder. If a class has this annotation, all the public static final fields within are taken to be object holders too, and the value of the annotation is the namespace of the holder (i.e. every field uses it as the default namespace for the registry name of the object to inject). If a field has this annotation, and the value does not contain a namespace, the namespace is chosen from the surrounding class’s @ObjectHolder annotation. If the class is not annotated in this situation, the field is ignored with a warning. If it does contain a namespace, then the object to inject into the field is the object with that name. If the class has the annotation and one of the public static final fields does not, then the resource path of the object’s name is taken to be the field’s name. The type of the registry is taken from the type of the field.

Note

If an object is not found, either because the object itself hasn’t been registered or because the registry does not exist, a debug message is logged and the field is left unchanged.

As these rules are rather complicated, here are some examples:

@ObjectHolder("minecraft") // Resource namespace "minecraft"
class AnnotatedHolder {
    public static final Block diamond_block = null; // public static final is required.
                                                    // Type Block means that the Block registry will be queried.
                                                    // diamond_block is the field name, and as the field is not annotated it is taken to be the resource path.
                                                    // As there is no explicit namespace, "minecraft" is inherited from the class.
                                                    // Object to be injected: "minecraft:diamond_block" from the Block registry.

    @ObjectHolder("ender_eye")
    public static final Item eye_of_ender = null;   // Type Item means that the Item registry will be queried.
                                                    // As the annotation has the value "ender_eye", that overrides the field's name.
                                                    // As the namespace is not explicit, "minecraft" is inherited from the class.
                                                    // Object to be injected: "minecraft:ender_eye" from the Item registry.

    @ObjectHolder("neomagicae:coffeinum")
    public static final ManaType coffeinum = null;  // Type ManaType means that the ManaType registry will be queried. This is obviously a registry made by a mod.
                                                    // As the annotation has the value "neomagicae:coffeinum", that overrides the field's name.
                                                    // The namespace is explicit, and is "neomagicae", overriding the class's "minecraft" default.
                                                    // Object to be injected: "neomagicae:coffeinum" from the ManaType registry.

    public static final Item ENDER_PEARL = null;    // Note that the actual name is "minecraft:ender_pearl", not "minecraft:ENDER_PEARL".
                                                    // However, since constructing a ResourceLocation lowercases the value, this will work.
}

class UnannotatedHolder { // Note lack of annotation on this class.
    @ObjectHolder("minecraft:flame")
    public static final Enchantment flame = null;   // No annotation on the class means that there is no preset namespace to inherit.
                                                    // Field annotation supplies all the information for the object.
                                                    // Object to be injected: "minecraft:flame" from the Enchantment registry.

    public static final Biome ice_flat = null;      // No annotation on the class or the field.
                                                    // Therefore this just gets ignored.

    @ObjectHolder("levitation")
    public static final Potion levitation = null;   // No resource namespace in annotation, and no default specified by class annotation.
                                                    // Therefore, THIS WILL FAIL. The field annotation needs a namespace, or the class needs an annotation.
}
Built with MkDocs using a custom theme. Hosted by Read the Docs.
Enable Dark Theme