첫 아이템 등록 — first_item
DeferredRegister.Items로 첫 아이템을 등록하고 텍스처/모델/lang 파일을 추가해 인게임에서 보이게 만드는 전체 과정을 학습합니다.
첫 아이템 등록 — first_item
이 챕터에서는 아이템을 처음으로 게임에 추가하는 전체 과정을 다룹니다. DeferredRegister.Items로 아이템을 등록하고, 텍스처 PNG · 모델 JSON · 언어 파일 세 가지 리소스를 추가하면 인게임 크리에이티브 탭에서 실제로 아이템을 볼 수 있습니다.
1. 아이템 등록 코드
1-1. ITEMS DeferredRegister 선언
DeferredRegister.Items는 이미 ExampleMod.java에 선언되어 있습니다.
// examplemod-template-26.1.2/src/main/java/com/example/examplemod/ExampleMod.java, ITEMS 필드
// "examplemod" 네임스페이스로 아이템 레지스트리 바구니 생성
public static final DeferredRegister.Items ITEMS = DeferredRegister.createItems(MODID);1-2. first_item 등록
ITEMS.registerSimpleItem()을 호출해 새 아이템을 등록합니다. 기존 EXAMPLE_ITEM 선언 아래에 추가합니다.
// examplemod-template-26.1.2/src/main/java/com/example/examplemod/ExampleMod.java, FIRST_ITEM 필드
// 가장 단순한 아이템 — registerSimpleItem 이 기본 Item + 기본 Properties 를 한 번에 등록 (64개, 내구도 없음)
public static final DeferredItem<Item> FIRST_ITEM = ITEMS.registerSimpleItem("first_item");ITEMS.registerSimpleItem("first_item")을 호출하면:
- 아이템의
Identifier가examplemod:first_item으로 결정됩니다. registerSimpleItem은 내부에서Properties.setId(ResourceKey)를 호출한 뒤Item::new팩토리를 사용합니다. 이 팩토리는 즉시 실행되지 않으며RegisterEvent시점에 FML이 실행합니다.- 반환되는
DeferredItem<Item>은 나중에.get()으로 실제Item인스턴스를 꺼내는 핸들입니다.
💡 NeoForge 26.1.2 부터는 아이템 등록에
registerSimpleItem/registerItem계열을 사용해야 합니다. 이 메서드들이 내부에서Properties.setId(ResourceKey)를 호출하므로, 람다 밖에서new Item.Properties()를 만들던 옛register(name, () -> new Item(new Item.Properties()))패턴은 "id not set" 으로 크래시합니다. Properties 를 변형하려면registerSimpleItem("first_item", props -> props.stacksTo(16))처럼 람다를 넘깁니다.
1-3. modEventBus 연결 확인
생성자에서 ITEMS.register(modEventBus)가 반드시 호출되어 있어야 합니다.
// ExampleMod.java 생성자 (이미 작성되어 있음)
public ExampleMod(IEventBus modEventBus, ModContainer modContainer) {
// ...
ITEMS.register(modEventBus); // ← 이 줄이 없으면 아이템이 등록되지 않음
// ...
}2. 필요한 리소스 파일 4종
아이템이 인게임에서 보이려면 텍스처·모델·lang 세 가지 리소스가 모두 있어야 합니다. 리소스 위치는 src/main/resources/assets/examplemod/ 아래입니다.
2-1. 텍스처 PNG
경로: src/main/resources/assets/examplemod/textures/item/first_item.png
- 반드시 16×16 픽셀 PNG 파일이어야 합니다.
- 32×32, 64×64 등 다른 해상도도 렌더링은 되지만, 바닐라 스타일과 다를 수 있습니다.
- 아이콘 편집기(예: Piskel, GIMP, Aseprite)로 직접 그리거나 임시 placeholder PNG를 사용할 수 있습니다.
디렉토리가 없으면 직접 생성합니다:
src/main/resources/assets/examplemod/
└── textures/
└── item/
└── first_item.png ← 여기에 16×16 PNG 저장
2-2. 모델 JSON
경로: src/main/resources/assets/examplemod/models/item/first_item.json
{
"parent": "minecraft:item/generated",
"textures": {
"layer0": "examplemod:item/first_item"
}
}parent: "minecraft:item/generated"— 평면 2D 아이템 렌더링 기본 모델입니다. 대부분의 단순 아이템에 적합합니다.layer0— 텍스처 레이어 이름."네임스페이스:item/파일명"형식으로 PNG를 참조합니다.
디렉토리:
src/main/resources/assets/examplemod/
└── models/
└── item/
└── first_item.json ← 모델 파일
2-3. 영어 언어 키 (en_us.json)
경로: src/main/resources/assets/examplemod/lang/en_us.json
기존 파일에 "item.examplemod.first_item" 키를 추가합니다:
{
"itemGroup.examplemod": "Example Mod Tab",
"block.examplemod.example_block": "Example Block",
"item.examplemod.example_item": "Example Item",
"item.examplemod.first_item": "First Item"
}2-4. 한국어 언어 키 (ko_kr.json) — 선택
경로: src/main/resources/assets/examplemod/lang/ko_kr.json (없으면 새로 생성)
{
"item.examplemod.first_item": "첫 아이템"
}3. 크리에이티브 탭에 추가
first_item을 크리에이티브 탭에서 볼 수 있으려면 두 가지 방법 중 하나를 씁니다.
방법 A — 기존 EXAMPLE_TAB에 추가 (권장)
EXAMPLE_TAB 선언의 displayItems 람다에 FIRST_ITEM을 추가합니다:
// ExampleMod.java — EXAMPLE_TAB 선언부 수정
public static final DeferredHolder<CreativeModeTab, CreativeModeTab> EXAMPLE_TAB =
CREATIVE_MODE_TABS.register("example_tab", () -> CreativeModeTab.builder()
.title(Component.translatable("itemGroup.examplemod"))
.withTabsBefore(CreativeModeTabs.COMBAT)
.icon(() -> EXAMPLE_ITEM.get().getDefaultInstance())
.displayItems((parameters, output) -> {
output.accept(EXAMPLE_ITEM.get());
output.accept(FIRST_ITEM.get()); // ← 추가
}).build());방법 B — BuildCreativeModeTabContentsEvent 이벤트 사용
다른 모드의 탭에 아이템을 끼워넣거나, 이벤트 기반으로 처리하고 싶을 때 사용합니다:
// addCreative 메서드에 추가
private void addCreative(BuildCreativeModeTabContentsEvent event) {
if (event.getTabKey() == CreativeModeTabs.BUILDING_BLOCKS) {
event.accept(EXAMPLE_BLOCK_ITEM);
}
// 자신의 탭에 아이템 추가 (이벤트 방식)
if (event.getTabKey() == EXAMPLE_TAB.getKey()) {
event.accept(FIRST_ITEM);
}
}💡 자신의 탭에 아이템을 추가할 때는
displayItems람다(방법 A)가 더 직관적입니다.BuildCreativeModeTabContentsEvent는 외부 탭에 아이템을 추가할 때 주로 사용합니다.
4. 안티패턴 — 모델 파일 누락 시 보라/검정 텍스처
⚠️ 모델 파일 누락 시 보라/검정 텍스처
assets/examplemod/models/item/first_item.json파일이 누락되면:
- 인게임에서 보라/검정 체크 패턴 텍스처가 표시됩니다 (Vanilla fallback 렌더).
- 콘솔에
"Unable to load model 'examplemod:first_item#inventory'"로그가 출력됩니다.해결:
parent를"minecraft:item/generated"로 두고,layer0텍스처 경로를"examplemod:item/first_item"으로 정확히 지정하세요.
5. 리소스 파일 경로 전체 정리
src/main/resources/assets/examplemod/
├── lang/
│ ├── en_us.json ← "item.examplemod.first_item": "First Item" 추가
│ └── ko_kr.json ← "item.examplemod.first_item": "첫 아이템" (선택)
├── models/
│ └── item/
│ └── first_item.json ← parent: minecraft:item/generated, layer0 텍스처 참조
└── textures/
└── item/
└── first_item.png ← 16×16 PNG 텍스처
6. 인게임 검증
6-1. runClient로 실행
IntelliJ Gradle 패널 → mod development → runClient 더블클릭으로 클라이언트를 실행합니다.
6-2. 크리에이티브 탭에서 확인
- 세계를 생성하거나 기존 세계에 접속합니다.
E키로 인벤토리를 열고 검색창에first를 입력합니다.- First Item (한국어 설정: 첫 아이템)이 나타나면 성공입니다.
6-3. 명령어로 지급
/give @p examplemod:first_item
위 명령어로 직접 아이템을 받아볼 수도 있습니다.
📌 인게임 실제 캡처는 phase-2 통합 검증 단계에서 진행합니다. 현재 단계에서는 코드와 리소스 파일 준비에 집중합니다. 인게임 확인은
04-run-client챕터 또는 phase-2 마지막 챕터에서 통합 검증합니다.
요약
| 단계 | 파일 | 내용 |
|---|---|---|
| 1 | ExampleMod.java | FIRST_ITEM = ITEMS.registerSimpleItem("first_item") 추가 |
| 2 | textures/item/first_item.png | 16×16 PNG 텍스처 |
| 3 | models/item/first_item.json | parent: minecraft:item/generated, layer0 텍스처 참조 |
| 4 | lang/en_us.json | "item.examplemod.first_item": "First Item" 추가 |
| 5 | lang/ko_kr.json | "item.examplemod.first_item": "첫 아이템" (선택) |
| 6 | EXAMPLE_TAB | displayItems에 FIRST_ITEM.get() 추가 |
다음 챕터에서는 Item.Properties를 활용해 아이템에 내구도·최대 스택·음식 속성 등을 설정하는 방법을 학습합니다.