마스터차원
포탈 블록 + 점화 아이템
MagicPortalBlock(Block 상속, 4×5 프레임 내부)과 MagicIgniter(점화 아이템)를 구현하고 DeferredRegister로 등록합니다. 포탈 형태 검사와 차원 이동은 후속 챕터에서 완성됩니다.
포탈 블록 + 점화 아이템
이 챕터에서는 마법 차원 포탈의 두 핵심 요소를 구현합니다.
- MagicPortalBlock — 포탈 프레임 내부를 채우는 블록 (충돌 없음, 폭발 저항 최대)
- MagicIgniter — 포탈 프레임에 우클릭해 불을 붙이는 아이템
포탈 형태(4×5) 검사 로직은 03-portal-shape 챕터에서, 엔티티가 포탈을 통과하는 로직은 04-dimension-entry 챕터에서 추가됩니다. 이 챕터는 블록·아이템 등록 토대를 마련하는 단계입니다.
1. MagicPortalBlock
왜 Block을 상속하는가?
⚠️ NetherPortalBlock 직접 상속 금지
// ❌ Vanilla 구현에 의존 — NeoForge 업데이트 시 호환성이 깨질 수 있음 public class MyPortalBlock extends NetherPortalBlock { ... } // ✅ Block 상속 + entityInside 오버라이드로 차원 이동 직접 구현 public class MyPortalBlock extends Block { ... }
NetherPortalBlock은 내부 상태가 복잡하고 NeoForge 버전마다 구현이 달라질 수 있습니다.Block을 직접 상속하고 필요한 메서드만 오버라이드하면 버전 간 안정성이 높아집니다.
구현
// examplemod-master-projects/dimension/src/main/java/com/example/master/dimension/block/MagicPortalBlock.java
package com.example.master.dimension.block;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.state.BlockBehaviour;
public class MagicPortalBlock extends Block {
public MagicPortalBlock(BlockBehaviour.Properties props) {
super(props
.noCollission() // 엔티티가 블록을 통과 가능
.strength(-1.0F, 3600000.0F) // 폭발 저항 최대 (흑요석 수준)
.noLootTable()); // 파괴해도 드롭 없음
}
// 다음 챕터(03-portal-shape)에서 점화 시 호출되는 로직 추가
// entityInside 는 04-dimension-entry 에서 추가
}Properties 설명
| 속성 | 의미 |
|---|---|
noCollission() | 플레이어/엔티티가 블록을 통과 — 포탈 내부를 걸어 들어가는 효과 |
strength(-1.0F, 3600000.0F) | 채굴 불가(-1) · 폭발 저항 최대(3,600,000) — 베드록 수준 |
noLootTable() | 파괴해도 아이템을 드롭하지 않음 |
2. MagicIgniter
점화 아이템은 우클릭한 블록의 바로 위 공기 슬롯에 포탈 블록을 배치합니다. 이번 챕터에서는 단일 블록만 배치하며, 03-portal-shape에서 프레임 전체를 채우도록 교체됩니다.
// examplemod-master-projects/dimension/src/main/java/com/example/master/dimension/item/MagicIgniter.java
package com.example.master.dimension.item;
import com.example.master.dimension.MasterDimensionMod;
import net.minecraft.core.BlockPos;
import net.minecraft.sounds.SoundEvents;
import net.minecraft.sounds.SoundSource;
import net.minecraft.world.InteractionResult;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.context.UseOnContext;
import net.minecraft.world.level.Level;
public class MagicIgniter extends Item {
public MagicIgniter(Properties props) {
super(props);
}
@Override
public InteractionResult useOn(UseOnContext context) {
Level level = context.getLevel();
BlockPos pos = context.getClickedPos();
// 클라이언트 측은 시각 효과만 — 서버에서 실제 처리
if (level.isClientSide()) return InteractionResult.SUCCESS;
// 프레임 검사는 03-portal-shape 챕터에서 PortalShape.isValidFrame() 으로 교체
BlockPos firePos = pos.above();
if (level.getBlockState(firePos).isAir()) {
level.setBlock(
firePos,
MasterDimensionMod.MAGIC_PORTAL.get().defaultBlockState(),
11 // UPDATE | NOTIFY_CLIENTS
);
level.playSound(
null,
firePos,
SoundEvents.FLINTANDSTEEL_USE,
SoundSource.BLOCKS,
1.0f,
1.0f
);
return InteractionResult.SUCCESS;
}
return InteractionResult.PASS;
}
}useOn 흐름
우클릭 (서버측)
│
├─ pos.above() 가 Air 인가?
│ ├─ YES → MAGIC_PORTAL 블록 배치 + 부싯돌 사운드 → SUCCESS
│ └─ NO → PASS (아무 동작 없음)
│
└─ 클라이언트 → 즉시 SUCCESS (서버 결과 대기 없이 피드백)
InteractionResult 선택 이유
| 값 | 의미 | 언제 사용 |
|---|---|---|
SUCCESS | 동작 완료, 아이템 내구도 소모 | 포탈 블록을 배치했을 때 |
PASS | 아무 동작 없음, 기본 블록 상호작용으로 fall-through | 위 슬롯이 비어있지 않을 때 |
3. MasterDimensionMod에 등록
DeferredRegister로 BLOCKS와 ITEMS를 선언하고, 생성자에서 이벤트 버스에 등록합니다.
// examplemod-master-projects/dimension/src/main/java/com/example/master/dimension/MasterDimensionMod.java
package com.example.master.dimension;
import com.example.master.dimension.block.MagicPortalBlock;
import com.example.master.dimension.item.MagicIgniter;
import com.mojang.logging.LogUtils;
import net.minecraft.world.item.Item;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.state.BlockBehaviour;
import net.neoforged.bus.api.IEventBus;
import net.neoforged.fml.ModContainer;
import net.neoforged.fml.common.Mod;
import net.neoforged.neoforge.registries.DeferredRegister;
import org.slf4j.Logger;
import java.util.function.Supplier;
@Mod(MasterDimensionMod.MOD_ID)
public class MasterDimensionMod {
public static final String MOD_ID = "master_dimension";
public static final Logger LOGGER = LogUtils.getLogger();
public static final DeferredRegister.Blocks BLOCKS =
DeferredRegister.createBlocks(MOD_ID);
public static final DeferredRegister.Items ITEMS =
DeferredRegister.createItems(MOD_ID);
/** 포탈 내부 블록 */
public static final Supplier<Block> MAGIC_PORTAL = BLOCKS.registerBlock("magic_portal",
MagicPortalBlock::new);
/** 점화 아이템 — 스택 1, 내구도 64 */
public static final Supplier<Item> MAGIC_IGNITER = ITEMS.registerItem("magic_igniter",
props -> new MagicIgniter(props
.stacksTo(1)
.durability(64)));
public MasterDimensionMod(IEventBus modEventBus, ModContainer container) {
LOGGER.info("Master Dimension Mod 로드");
BLOCKS.register(modEventBus);
ITEMS.register(modEventBus);
}
}등록 체크리스트
| 항목 | 확인 사항 |
|---|---|
DeferredRegister.Blocks | createBlocks(MOD_ID) 사용 — Blocks 전용 팩토리 |
DeferredRegister.Items | createItems(MOD_ID) 사용 — Items 전용 팩토리 |
BLOCKS.register(modEventBus) | 생성자에서 반드시 호출 — 빠뜨리면 블록이 게임에 등록되지 않음 |
ITEMS.register(modEventBus) | 생성자에서 반드시 호출 |
stacksTo(1) | 점화 아이템은 단 1개만 들 수 있음 |
durability(64) | 64회 사용 후 소모 |
4. 텍스처 플레이스홀더
이 챕터에서는 실제 텍스처 없이 보라색 16×16 PNG로 블록/아이템을 식별합니다. 텍스처 완성은 후속 챕터에서 진행합니다.
텍스처 파일 위치:
examplemod-master-projects/dimension/src/main/resources/
└── assets/master_dimension/
├── textures/block/magic_portal.png ← 보라색 플레이스홀더 16×16
├── textures/item/magic_igniter.png ← 보라색 플레이스홀더 16×16
├── models/block/magic_portal.json
└── models/item/magic_igniter.json
5. 인게임 검증 안내
포탈 블록과 점화 아이템의 인게임 동작 검증은 다음 챕터들에서 순차적으로 수행합니다.
| 챕터 | 검증 내용 |
|---|---|
| 03-portal-shape | 4×5 흑요석 프레임 완성 후 MagicIgniter로 점화 → 프레임 내부가 포탈 블록으로 채워짐 |
| 04-dimension-entry | 포탈 블록 안에 들어가면 마법 차원으로 이동 |
| 05-finish-build | 전체 Gradle 빌드 + 인게임 종합 검증 |
다음 단계
이번 챕터에서 포탈 블록과 점화 아이템의 뼈대를 완성했습니다.
- 03-portal-shape —
PortalShape유틸리티로 4×5 흑요석 프레임 검증 + 포탈 블록 전체 배치 - 04-dimension-entry —
entityInside오버라이드로 플레이어 차원 이동 로직 - 05-finish-build — 통합 빌드 & 인게임 종합 검증