두 버스는 완전히 분리된 채널입니다. Mod EventBus에 등록한 핸들러는 NeoForge EventBus 이벤트를 받지 못하고, 반대도 마찬가지입니다. NeoForge 26.1.2부터는 핸들러가 어느 버스에 등록될지 이벤트 타입을 보고 자동으로 결정되므로, 더 이상 @EventBusSubscriber에 버스를 직접 지정하지 않습니다.
별도 클래스에 이벤트 핸들러를 모아두고 싶을 때 사용합니다. FML이 자동으로 등록해줍니다.
// ModEvents.java — Mod EventBus 이벤트 전용 클래스// FMLCommonSetupEvent·FMLClientSetupEvent는 Mod EventBus 이벤트이므로 자동으로 Mod 버스에 등록됩니다.@EventBusSubscriber(modid = ExampleMod.MODID)public class ModEvents { @SubscribeEvent public static void onCommonSetup(FMLCommonSetupEvent event) { ExampleMod.LOGGER.info("공통 셋업 이벤트 처리"); } @SubscribeEvent public static void onClientSetup(FMLClientSetupEvent event) { // 클라이언트 전용 초기화 }}
// GameEvents.java — NeoForge EventBus 이벤트 전용 클래스// ServerStartingEvent·EntityJoinLevelEvent는 NeoForge EventBus 이벤트이므로 자동으로 NeoForge 버스에 등록됩니다.@EventBusSubscriber(modid = ExampleMod.MODID)public class GameEvents { @SubscribeEvent public static void onServerStarting(ServerStartingEvent event) { ExampleMod.LOGGER.info("서버 시작!"); } @SubscribeEvent public static void onEntityJoin(EntityJoinLevelEvent event) { // 엔티티 스폰 처리 }}
@SubscribeEvent 메서드는 반드시 public static이어야 합니다. 인스턴스 메서드로 만들면 동작하지 않습니다. NeoForge 26.1.2부터는 bus 속성이 삭제되어, 핸들러가 받는 이벤트 타입을 보고 어느 버스에 등록될지 자동으로 결정됩니다(net.neoforged.fml.common.EventBusSubscriber).
인스턴스 메서드로 핸들러를 작성하고 싶을 때 사용합니다. ExampleMod.java의 onServerStarting이 이 방식으로 동작합니다.
// ExampleMod.java 생성자에서NeoForge.EVENT_BUS.register(this);// 같은 클래스 안에서 @SubscribeEvent 인스턴스 메서드@SubscribeEventpublic void onServerStarting(ServerStartingEvent event) { LOGGER.info("서버 시작 이벤트 수신");}
또는 별도 핸들러 클래스를 만들어 등록할 수도 있습니다.
// 생성자에서NeoForge.EVENT_BUS.register(new GameEventHandler());// GameEventHandler.javapublic class GameEventHandler { @SubscribeEvent public void onPlayerInteract(PlayerInteractEvent event) { // 플레이어 상호작용 처리 }}
NeoForge 26.1.2부터 @EventBusSubscriber의 bus 속성과 EventBusSubscriber.Bus enum이 삭제되었습니다. 핸들러가 받는 이벤트 타입을 보고 Mod 버스인지 NeoForge 버스인지 자동으로 결정됩니다. 클라이언트 전용으로 제한하려면 value = Dist.CLIENT만 지정합니다.
// ❌ 잘못됨 — bus 속성과 Bus enum은 26.1.2에서 삭제됨 (컴파일 실패)@EventBusSubscriber(modid = "examplemod", bus = EventBusSubscriber.Bus.MOD)public class ModEvents { @SubscribeEvent public static void onClientSetup(FMLClientSetupEvent event) { ... }}// ✅ 올바름 — bus 미지정, 이벤트 타입으로 자동 결정. 클라이언트 전용이면 value = Dist.CLIENT@EventBusSubscriber(modid = "examplemod", value = Dist.CLIENT)public class ModEvents { @SubscribeEvent public static void onClientSetup(FMLClientSetupEvent event) { ... }}
⚠️ @SubscribeEvent 메서드를 static으로 만들지 않음
@EventBusSubscriber로 자동 등록할 때 핸들러 메서드는 반드시 public static이어야 합니다.
examplemod-template-26.1.2/src/main/java/com/example/examplemod/ExampleMod.java를 열고 생성자를 확인하세요.
public ExampleMod(IEventBus modEventBus, ModContainer modContainer) { modEventBus.addListener(this::commonSetup); // Mod Bus — 라이프사이클 BLOCKS.register(modEventBus); // Mod Bus — 레지스트리 ITEMS.register(modEventBus); // Mod Bus — 레지스트리 CREATIVE_MODE_TABS.register(modEventBus); // Mod Bus — 레지스트리 NeoForge.EVENT_BUS.register(this); // NeoForge Bus — 런타임 modEventBus.addListener(this::addCreative); // Mod Bus — 크리에이티브 탭 modContainer.registerConfig(ModConfig.Type.COMMON, Config.SPEC);}
NeoForge.EVENT_BUS.register(this)가 있기 때문에 아래 @SubscribeEvent 메서드가 동작합니다.
@SubscribeEventpublic void onServerStarting(ServerStartingEvent event) { LOGGER.info("HELLO from server starting");}
이 메서드를 modEventBus.addListener(this::onServerStarting)으로 바꾸면 서버 시작 시 로그가 출력되지 않습니다. 직접 바꿔보고 확인해보세요.