NeoForge 26.1 Docs
  • 문서
  • 노트
NeoForge 26.1
NeoForge 26.1
v26.1
학습 진도
0 / 77 챕터 완료방문 0
첫 블록 등록 — first_blockBlockBehaviour.Properties — strength, lightLevel, sound, requiresCorrectToolForDropsblockstate JSON과 모델 JSON특수 블록 타입 (계단·슬랩·펜스)블록 이벤트 — use, onPlace, onRemove루트 테이블 — 블록 드롭 JSON 직접 작성
블록

특수 블록 타입 (계단·슬랩·펜스)

StairBlock, SlabBlock, FenceBlock을 등록하고 각 타입에 맞는 blockstate variant 패턴을 작성하는 방법을 학습합니다. variant 누락 시 보라/검정 큐브가 나타나는 원인과 해결법도 다룹니다.

특수 블록 타입 (계단·슬랩·펜스)

단순 정육면체 블록을 넘어서면 Minecraft가 제공하는 특수 블록 서브클래스를 활용할 수 있습니다. 이 챕터에서는 가장 자주 쓰이는 세 가지를 다룹니다.

클래스용도blockstate 방식
StairBlock계단 형태variants (facing × half × shape)
SlabBlock반 블록variants (type)
FenceBlock펜스 연결multipart (방향 boolean)

세 클래스 모두 바닐라 구현을 그대로 상속하므로, 등록 코드는 짧고 blockstate JSON 작성이 핵심입니다.


1. StairBlock 등록

1-1. 등록 코드

public static final Supplier<StairBlock> RUBY_STAIRS = BLOCKS.register("ruby_stairs",
    () -> new StairBlock(RUBY_BLOCK.get().defaultBlockState(),
        BlockBehaviour.Properties.ofFullCopy(RUBY_BLOCK.get())));

StairBlock 생성자의 첫 번째 인자는 기준 블록의 기본 상태입니다. 계단이 "이 블록의 계단 버전"임을 Minecraft에 알려주는 역할을 합니다. 두 번째 인자는 기준 블록의 속성을 그대로 복사합니다.

1-2. blockstate JSON

계단은 facing(4방향) × half(bottom/top) × shape(5가지) 조합으로 총 40가지 variant가 필요합니다.

{
  "variants": {
    "facing=east,half=bottom,shape=inner_left":   { "model": "examplemod:block/ruby_stairs_inner", "y": 270, "uvlock": true },
    "facing=east,half=bottom,shape=inner_right":  { "model": "examplemod:block/ruby_stairs_inner" },
    "facing=east,half=bottom,shape=outer_left":   { "model": "examplemod:block/ruby_stairs_outer", "y": 270, "uvlock": true },
    "facing=east,half=bottom,shape=outer_right":  { "model": "examplemod:block/ruby_stairs_outer" },
    "facing=east,half=bottom,shape=straight":     { "model": "examplemod:block/ruby_stairs" },
    "facing=east,half=top,shape=inner_left":      { "model": "examplemod:block/ruby_stairs_inner", "x": 180, "uvlock": true },
    "facing=east,half=top,shape=inner_right":     { "model": "examplemod:block/ruby_stairs_inner", "x": 180, "y": 90, "uvlock": true },
    "facing=east,half=top,shape=outer_left":      { "model": "examplemod:block/ruby_stairs_outer", "x": 180, "uvlock": true },
    "facing=east,half=top,shape=outer_right":     { "model": "examplemod:block/ruby_stairs_outer", "x": 180, "y": 90, "uvlock": true },
    "facing=east,half=top,shape=straight":        { "model": "examplemod:block/ruby_stairs", "x": 180, "uvlock": true },
    "facing=north,half=bottom,shape=inner_left":  { "model": "examplemod:block/ruby_stairs_inner", "y": 180, "uvlock": true },
    "facing=north,half=bottom,shape=inner_right": { "model": "examplemod:block/ruby_stairs_inner", "y": 270, "uvlock": true },
    "facing=north,half=bottom,shape=outer_left":  { "model": "examplemod:block/ruby_stairs_outer", "y": 180, "uvlock": true },
    "facing=north,half=bottom,shape=outer_right": { "model": "examplemod:block/ruby_stairs_outer", "y": 270, "uvlock": true },
    "facing=north,half=bottom,shape=straight":    { "model": "examplemod:block/ruby_stairs", "y": 270, "uvlock": true },
    "facing=north,half=top,shape=inner_left":     { "model": "examplemod:block/ruby_stairs_inner", "x": 180, "y": 270, "uvlock": true },
    "facing=north,half=top,shape=inner_right":    { "model": "examplemod:block/ruby_stairs_inner", "x": 180, "uvlock": true },
    "facing=north,half=top,shape=outer_left":     { "model": "examplemod:block/ruby_stairs_outer", "x": 180, "y": 270, "uvlock": true },
    "facing=north,half=top,shape=outer_right":    { "model": "examplemod:block/ruby_stairs_outer", "x": 180, "uvlock": true },
    "facing=north,half=top,shape=straight":       { "model": "examplemod:block/ruby_stairs", "x": 180, "y": 270, "uvlock": true },
    "facing=south,half=bottom,shape=inner_left":  { "model": "examplemod:block/ruby_stairs_inner" },
    "facing=south,half=bottom,shape=inner_right": { "model": "examplemod:block/ruby_stairs_inner", "y": 90, "uvlock": true },
    "facing=south,half=bottom,shape=outer_left":  { "model": "examplemod:block/ruby_stairs_outer" },
    "facing=south,half=bottom,shape=outer_right": { "model": "examplemod:block/ruby_stairs_outer", "y": 90, "uvlock": true },
    "facing=south,half=bottom,shape=straight":    { "model": "examplemod:block/ruby_stairs", "y": 90, "uvlock": true },
    "facing=south,half=top,shape=inner_left":     { "model": "examplemod:block/ruby_stairs_inner", "x": 180, "y": 90, "uvlock": true },
    "facing=south,half=top,shape=inner_right":    { "model": "examplemod:block/ruby_stairs_inner", "x": 180, "y": 180, "uvlock": true },
    "facing=south,half=top,shape=outer_left":     { "model": "examplemod:block/ruby_stairs_outer", "x": 180, "y": 90, "uvlock": true },
    "facing=south,half=top,shape=outer_right":    { "model": "examplemod:block/ruby_stairs_outer", "x": 180, "y": 180, "uvlock": true },
    "facing=south,half=top,shape=straight":       { "model": "examplemod:block/ruby_stairs", "x": 180, "y": 90, "uvlock": true },
    "facing=west,half=bottom,shape=inner_left":   { "model": "examplemod:block/ruby_stairs_inner", "y": 90, "uvlock": true },
    "facing=west,half=bottom,shape=inner_right":  { "model": "examplemod:block/ruby_stairs_inner", "y": 180, "uvlock": true },
    "facing=west,half=bottom,shape=outer_left":   { "model": "examplemod:block/ruby_stairs_outer", "y": 90, "uvlock": true },
    "facing=west,half=bottom,shape=outer_right":  { "model": "examplemod:block/ruby_stairs_outer", "y": 180, "uvlock": true },
    "facing=west,half=bottom,shape=straight":     { "model": "examplemod:block/ruby_stairs", "y": 180, "uvlock": true },
    "facing=west,half=top,shape=inner_left":      { "model": "examplemod:block/ruby_stairs_inner", "x": 180, "y": 180, "uvlock": true },
    "facing=west,half=top,shape=inner_right":     { "model": "examplemod:block/ruby_stairs_inner", "x": 180, "y": 270, "uvlock": true },
    "facing=west,half=top,shape=outer_left":      { "model": "examplemod:block/ruby_stairs_outer", "x": 180, "y": 180, "uvlock": true },
    "facing=west,half=top,shape=outer_right":     { "model": "examplemod:block/ruby_stairs_outer", "x": 180, "y": 270, "uvlock": true },
    "facing=west,half=top,shape=straight":        { "model": "examplemod:block/ruby_stairs", "x": 180, "y": 180, "uvlock": true }
  }
}

40개 항목이 많아 보이지만 패턴은 단순합니다. facing마다 y 회전값이 달라지고, half=top이면 x: 180이 추가됩니다.

💡 참고: 바닐라 data/minecraft/blockstates/oak_stairs.json을 복사한 뒤 모델 경로만 교체하는 방법이 가장 빠릅니다.

1-3. 모델 JSON (3종)

계단은 세 가지 모델이 필요합니다.

// models/block/ruby_stairs.json (기본 계단)
{
  "parent": "minecraft:block/stairs",
  "textures": {
    "bottom": "examplemod:block/ruby_block",
    "top":    "examplemod:block/ruby_block",
    "side":   "examplemod:block/ruby_block"
  }
}
// models/block/ruby_stairs_inner.json (안쪽 모서리)
{
  "parent": "minecraft:block/inner_stairs",
  "textures": {
    "bottom": "examplemod:block/ruby_block",
    "top":    "examplemod:block/ruby_block",
    "side":   "examplemod:block/ruby_block"
  }
}
// models/block/ruby_stairs_outer.json (바깥쪽 모서리)
{
  "parent": "minecraft:block/outer_stairs",
  "textures": {
    "bottom": "examplemod:block/ruby_block",
    "top":    "examplemod:block/ruby_block",
    "side":   "examplemod:block/ruby_block"
  }
}

2. SlabBlock 등록

2-1. 등록 코드

public static final Supplier<SlabBlock> RUBY_SLAB = BLOCKS.register("ruby_slab",
    () -> new SlabBlock(BlockBehaviour.Properties.ofFullCopy(RUBY_BLOCK.get())));

SlabBlock은 기준 블록 상태가 필요 없습니다. 속성 복사만으로 충분합니다.

2-2. blockstate JSON

슬랩은 type 속성 하나로 3가지 variant만 있습니다.

{
  "variants": {
    "type=bottom": { "model": "examplemod:block/ruby_slab" },
    "type=top":    { "model": "examplemod:block/ruby_slab_top" },
    "type=double": { "model": "examplemod:block/ruby_block" }
  }
}
  • type=bottom — 아래쪽 반 블록
  • type=top — 위쪽 반 블록
  • type=double — 두 개 쌓인 상태. 기준 블록 모델을 그대로 참조합니다.

2-3. 모델 JSON (2종)

// models/block/ruby_slab.json (아래쪽)
{
  "parent": "minecraft:block/slab",
  "textures": {
    "bottom": "examplemod:block/ruby_block",
    "top":    "examplemod:block/ruby_block",
    "side":   "examplemod:block/ruby_block"
  }
}
// models/block/ruby_slab_top.json (위쪽)
{
  "parent": "minecraft:block/slab_top",
  "textures": {
    "bottom": "examplemod:block/ruby_block",
    "top":    "examplemod:block/ruby_block",
    "side":   "examplemod:block/ruby_block"
  }
}

type=double은 별도 모델 없이 ruby_block 모델을 재사용합니다.


3. FenceBlock 등록

3-1. 등록 코드

public static final Supplier<FenceBlock> RUBY_FENCE = BLOCKS.register("ruby_fence",
    () -> new FenceBlock(BlockBehaviour.Properties.ofFullCopy(RUBY_BLOCK.get())));

3-2. blockstate JSON (multipart)

펜스는 variants 대신 multipart를 씁니다. 인접 블록 연결 여부에 따라 부분 모델을 조합하기 때문입니다.

{
  "multipart": [
    { "apply": { "model": "examplemod:block/ruby_fence_post" } },
    {
      "when":  { "north": "true" },
      "apply": { "model": "examplemod:block/ruby_fence_side", "uvlock": true }
    },
    {
      "when":  { "east": "true" },
      "apply": { "model": "examplemod:block/ruby_fence_side", "y": 90, "uvlock": true }
    },
    {
      "when":  { "south": "true" },
      "apply": { "model": "examplemod:block/ruby_fence_side", "y": 180, "uvlock": true }
    },
    {
      "when":  { "west": "true" },
      "apply": { "model": "examplemod:block/ruby_fence_side", "y": 270, "uvlock": true }
    }
  ]
}
  • 첫 번째 항목(when 없음) — 항상 렌더링되는 중앙 기둥
  • 나머지 4개 — 해당 방향 이웃이 연결 가능할 때만 추가

3-3. 모델 JSON (2종)

// models/block/ruby_fence_post.json (기둥)
{
  "parent": "minecraft:block/fence_post",
  "textures": {
    "texture": "examplemod:block/ruby_block"
  }
}
// models/block/ruby_fence_side.json (연결 부분)
{
  "parent": "minecraft:block/fence_side",
  "textures": {
    "texture": "examplemod:block/ruby_block"
  }
}

4. 안티패턴 — blockstate variant 누락

⚠️ blockstate variant 누락

StairBlock의 facing variant 일부를 빠뜨리면:

// ❌ facing=west 항목 전체 누락
{
  "variants": {
    "facing=east,half=bottom,shape=straight":  { "model": "..." },
    "facing=north,half=bottom,shape=straight": { "model": "..." },
    "facing=south,half=bottom,shape=straight": { "model": "..." }
    // facing=west 없음
  }
}

서쪽을 향해 계단을 설치하면 보라/검정 큐브가 나타납니다.

콘솔에 "Missing variant" 경고가 출력됩니다.

해결: 바닐라 data/minecraft/blockstates/oak_stairs.json을 참조해 40개 항목을 모두 채우세요.


5. 전체 파일 구조 정리

src/main/resources/assets/examplemod/
├── blockstates/
│   ├── ruby_stairs.json          ← 40가지 variant
│   ├── ruby_slab.json            ← 3가지 variant
│   └── ruby_fence.json           ← multipart 5항목
├── models/block/
│   ├── ruby_stairs.json          ← parent: stairs
│   ├── ruby_stairs_inner.json    ← parent: inner_stairs
│   ├── ruby_stairs_outer.json    ← parent: outer_stairs
│   ├── ruby_slab.json            ← parent: slab
│   ├── ruby_slab_top.json        ← parent: slab_top
│   ├── ruby_fence_post.json      ← parent: fence_post
│   └── ruby_fence_side.json      ← parent: fence_side
└── models/item/
    ├── ruby_stairs.json
    ├── ruby_slab.json
    └── ruby_fence.json

아이템 모델은 각각 블록 모델을 참조합니다.

// models/item/ruby_stairs.json
{ "parent": "examplemod:block/ruby_stairs" }
 
// models/item/ruby_slab.json
{ "parent": "examplemod:block/ruby_slab" }
 
// models/item/ruby_fence.json
{ "parent": "examplemod:block/ruby_fence_post" }

6. 인게임 검증

6-1. 계단 4방향 + 상하 설치

  1. runClient로 클라이언트 실행
  2. 크리에이티브 탭에서 ruby_stairs 꺼내기
  3. 북/동/남/서 방향으로 각각 설치 (바닥 설치 = half=bottom)
  4. Shift+클릭으로 천장에 설치 (half=top)
  5. 두 계단을 L자로 붙여 shape=inner_right / outer_right 확인

6-2. 슬랩 상하 설치

  1. ruby_slab을 바닥에 설치 (type=bottom)
  2. 같은 위치 위쪽 절반을 클릭해 type=top 설치
  3. 두 슬랩이 합쳐져 type=double이 되는지 확인

6-3. 펜스 연결 동작

  1. ruby_fence를 일렬로 설치
  2. 인접 블록(돌 등)을 옆에 붙여 연결 여부 확인
  3. F3 화면에서 north=true, east=false 등 boolean 값 대조

요약

클래스등록 특이사항blockstate 방식variant 수
StairBlock기준 블록 상태 필요variants40개
SlabBlock속성 복사만variants3개
FenceBlock속성 복사만multipart5항목

다음 챕터에서는 블록에 BlockEntity를 붙여 데이터를 저장하는 방법을 학습합니다.

blockstate JSON과 모델 JSON

블록 상태(blockstate)에 따라 어떤 모델을 표시할지 정의하는 blockstate JSON과, 실제 3D 형태를 결정하는 모델 JSON의 구조와 parent 종류를 학습합니다.

블록 이벤트 — use, onPlace, onRemove

커스텀 Block 클래스를 만들어 use(우클릭), onPlace(설치), onRemove(제거) 이벤트를 오버라이드하는 방법을 학습합니다. 사이드 분기 가드 패턴도 함께 다룹니다.

On this page

특수 블록 타입 (계단·슬랩·펜스)1. StairBlock 등록1-1. 등록 코드1-2. blockstate JSON1-3. 모델 JSON (3종)2. SlabBlock 등록2-1. 등록 코드2-2. blockstate JSON2-3. 모델 JSON (2종)3. FenceBlock 등록3-1. 등록 코드3-2. blockstate JSON (multipart)3-3. 모델 JSON (2종)4. 안티패턴 — blockstate variant 누락5. 전체 파일 구조 정리6. 인게임 검증6-1. 계단 4방향 + 상하 설치6-2. 슬랩 상하 설치6-3. 펜스 연결 동작요약
NeoForge 26.1 Docs

NeoForge 26.1 모딩 개발 문서 사이트

GitHubDiscord

문서

  • 문서
  • 노트

GitHub

  • GitHub
  • Discord

© 2026 NeoForge 26.1 Docs. 콘텐츠는 MIT 라이선스로 제공됩니다.

Built with Next.js · Tailwind CSS · shadcn/ui