# Forge Concept Registries

> Forge 注册机制：DeferredRegister（DeferredRegister.create、RegistryObject）、RegisterEvent（RegisterEvent#register）、RegistryObject（#get 方法）、@ObjectHolder 注入、ForgeRegistries 注册表、ResourceLocation/Identifier 键、自定义注册表（RegistryBuilder、NewRegistryEvent、DataPackRegistryEvent$NewRegistry）、动态注册表（数据文件注册）、静态注册表（Registries.LOOT_CONDITION_TYPE）、MissingMappingsEvent 映射处理（IGNORE/WARN/FAIL/REMAP）、注册表查找（lookupOrThrow）、1.21.11+ getModBusGroup()、注册名唯一性、覆盖机制。

- Skill: `zmjjkk123-hub/forge-concept-registries` (Agent Skill)
- Install (CLI): `npx skillmds@latest add zmjjkk123-hub/forge-concept-registries`
- Raw SKILL.md: https://api.skillmd.com/api/skills/zmjjkk123-hub/forge-concept-registries/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- Author: ZMJJKK123-hub (https://skillmd.com/u/zmjjkk123-hub)
- Updated: 2026-09-22
- Page: https://skillmd.com/skills/zmjjkk123-hub/forge-concept-registries

---


# Registries

Registration makes a mod's objects known to the game. Registries map `ResourceLocation` keys to values; each registrable type has its own registry (`ForgeRegistries` lists Forge-wrapped ones). Names must be unique within a registry; different registries don't collide. Registering a second object with the same name overrides the first.

## Methods for registering

### DeferredRegister (recommended)

Maintains suppliers and registers during `RegisterEvent`:

```java
private static final DeferredRegister<Block> BLOCKS = DeferredRegister.create(ForgeRegistries.BLOCKS, MODID);
public static final RegistryObject<Block> ROCK_BLOCK = BLOCKS.register("rock", () -> new Block(BlockBehaviour.Properties.of().mapColor(MapColor.STONE)));

public ExampleMod(FMLJavaModLoadingContext context) {
  // 1.21.11: use getModBusGroup() (NOT getModEventBus)
  BLOCKS.register(FMLJavaModLoadingContext.get().getModBusGroup());
}
import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext;
```

### RegisterEvent

Fired for each registry after mod constructors, before config loading. Register via `#register(registryKey, helper)` on the mod event bus:

```java
event.register(ForgeRegistries.Keys.BLOCKS, helper -> {
  helper.register(Identifier.fromNamespaceAndPath(MODID, "example_block_1"), new Block(...));
});
```

### Registries that aren't Forge registries

- Static registries (e.g. `LootItemConditionType`): safe; use `DeferredRegister.create(Registries.LOOT_CONDITION_TYPE, MODID)`.
- Dynamic registries (worldgen JSON registries): **only registerable via data files, never in code**.

Some classes register `*Type` factories instead (e.g. `BlockEntityType`, `EntityType`), created via their builders:

```java
REGISTER.register("example_block_entity", () -> BlockEntityType.Builder.of(ExampleBlockEntity::new, EXAMPLE_BLOCK.get()).build(null));
```

## Referencing registered objects

Never store registered objects in fields at registration; always reference via `RegistryObject` or `@ObjectHolder`.

- `RegistryObject#create(resourceLocation, registry)` → store in `public static final` fields, call `#get()`.
- `@ObjectHolder(registryName = "...", value = "...")` on `public static` fields injects objects after `RegisterEvent`. Class-level `@ObjectHolder` or `@Mod` provides the default namespace. Missing registry/name → compile-time exception; missing object at injection → debug log, no injection.

## Creating custom Forge registries

Use `RegistryBuilder` via `NewRegistryEvent` or `DeferredRegister`:

- `NewRegistryEvent#create(builder)` returns a supplier-wrapped registry (null before the event finishes).
- `DeferredRegister#makeRegistry(builder)` (must be called before `#register` on the bus).
- Datapack registries: `DataPackRegistryEvent$NewRegistry#dataPackRegistry(resourceKey, codec, optionalSyncCodec)` — **cannot** use `DeferredRegister`.

## Missing entries

`MissingMappingsEvent` (fired on the **Forge** bus) handles removed registry objects: `#getMappings(registryKey, modid)` / `#getAllMappings`. Per `Mapping`, choose: `IGNORE` (abandon), `WARN` (log warning), `FAIL` (block world load), `REMAP` (remap to an existing non-null object). Default action asks the user whether to load the world.

## 1.21.11+ registry note

- `ResourceLocation` is renamed to `Identifier` (`net.minecraft.resources.Identifier`) in 1.21.11.
- Use `FMLJavaModLoadingContext.get().getModBusGroup()` (not `getModEventBus()`) to register `DeferredRegister`s.
- Registry lookups use `lookupOrThrow`, not `registryOrThrow`.
