@Mod(MasterCapstoneMod.MOD_ID)public class MasterCapstoneMod { public static final String MOD_ID = "master_capstone"; public static final Logger LOGGER = LogUtils.getLogger(); public static final DeferredRegister.Items ITEMS = DeferredRegister.createItems(MOD_ID); /** * MagicCore — GemGuardian 처치 시 드롭되는 특별 아이템. * 희귀도 EPIC, 최대 16개 스택. */ public static final Supplier<Item> MAGIC_CORE = ITEMS.registerItem("magic_core", props -> new Item(props .rarity(Rarity.EPIC) .stacksTo(16))); public MasterCapstoneMod(IEventBus modEventBus, ModContainer container) { LOGGER.info("Master Capstone Mod 로드 — 4개 모드 통합"); ITEMS.register(modEventBus); }}
DeferredRegister.Items는 아이템 레지스트리를 위한 전용 팩토리 메서드입니다. DeferredRegister.create(ForgeRegistries.ITEMS, MOD_ID)와 달리 타입 안전성이 높습니다.
26.1.2부터 @EventBusSubscriber의 bus 속성과 EventBusSubscriber.Bus enum이 삭제되었습니다. 더 이상 어노테이션에서 버스를 지정하지 않으며, 각 이벤트는 자신이 게시되는 버스가 정해져 있습니다.
이벤트 종류
게시 버스
예시
모드 로딩 이벤트
모드 버스 (mod event bus)
RegisterEvent, FMLCommonSetupEvent
게임 플레이 이벤트
게임 버스 (NeoForge.EVENT_BUS)
LivingDeathEvent, PlayerInteractEvent
LivingDeathEvent와 PlayerInteractEvent는 모두 게임 버스 이벤트이고, @EventBusSubscriber(modid = MasterCapstoneMod.MOD_ID)로 등록한 정적 핸들러가 자동으로 게임 버스에 연결됩니다. 레지스트리 이벤트(RegisterEvent, FMLCommonSetupEvent)는 모드 버스에 게시됩니다.
CapstoneEventHandler는 master_tools의 RUBY 아이템과 PURITY DataComponent를 직접 import하지 않습니다. 대신 태그와 런타임 레지스트리 조회를 사용합니다.
// ✅ 태그로 느슨하게 연결 — master_tools 내부 클래스 import 없음public static final TagKey<Item> RUBY_ITEM_TAG = ItemTags.create(Identifier.fromNamespaceAndPath("master_tools", "ruby_items"));// ✅ 런타임 조회 — DataComponentType 직접 import 없음@SuppressWarnings("unchecked")public static final DataComponentType<Integer> PURITY_COMPONENT = (DataComponentType<Integer>) BuiltInRegistries.DATA_COMPONENT_TYPE .getValue(Identifier.fromNamespaceAndPath("master_tools", "purity"));
이렇게 하면 master_tools JAR 없이 캡스톤 모드가 컴파일됩니다. 런타임에 master_tools가 없으면 PURITY_COMPONENT는 null이 되어 has() 검사를 통과하지 못하므로 안전합니다.
💡 더 견고한 방법 master_tools가 공개 API 클래스를 제공한다면 직접 참조하는 것이 더 명확합니다.
예: MasterToolsMod.RUBY.get(), MasterToolsMod.PURITY.get()
이 챕터는 JAR 간 느슨한 연결 패턴을 보여주기 위해 태그/레지스트리 조회 방식을 택했습니다.
// ❌ 두 EventBusSubscriber에서 같은 이벤트 처리@EventBusSubscriber(modid = MOD_ID)public class Handlers1 { @SubscribeEvent public static void onDeath(LivingDeathEvent e) { /* 드롭 1회 */ }}@EventBusSubscriber(modid = MOD_ID)public class Handlers2 { @SubscribeEvent public static void onDeath(LivingDeathEvent e) { /* 드롭 또 1회 */ }}
→ 이벤트 두 번 호출 → 드롭 2배, 메시지 중복
핸들러는 한 클래스에 정리하거나 책임을 명확히 분리하세요.
CapstoneEventHandler처럼 모든 캡스톤 이벤트를 한 파일에 모으는 것을 권장합니다.