NeoForge 26.1 Docs
  • 문서
  • 노트
NeoForge 26.1
NeoForge 26.1
v26.1
학습 진도
0 / 77 챕터 완료방문 0
이벤트 핸들러와 @SubscribeEventModBus vs NeoForge EventBus — 두 버스 완전 정복플레이어 이벤트틱 이벤트 — 매 tick 실행되는 로직 작성커맨드 등록 — Brigadier로 /명령어 만들기사운드 등록과 재생파티클 등록과 스폰 — 시각 효과 직접 만들기
이벤트

ModBus vs NeoForge EventBus — 두 버스 완전 정복

모드 라이프사이클 이벤트를 처리하는 ModBus와 게임 런타임 이벤트를 처리하는 NeoForge EventBus의 차이를 이벤트 매핑 표와 안티패턴으로 명확히 정리합니다.

ModBus vs NeoForge EventBus — 두 버스 완전 정복

NeoForge에는 이벤트 버스가 두 개 있습니다. 이 사실을 모르면 핸들러를 등록해도 아무 반응이 없는 상황을 마주하게 됩니다. 에러 메시지도 없고, 그냥 조용히 무시됩니다.

두 버스의 차이를 한 번에 정리합니다.


1. 핵심 차이 한눈에

항목Mod EventBusNeoForge EventBus
접근 방법modEventBus (생성자 인자로 전달)NeoForge.EVENT_BUS 정적 필드
이벤트 발생 시점모드 초기화 (라이프사이클)게임 런타임
@EventBusSubscriber 등록modid만 지정 (버스 자동 판별)modid만 지정 (버스 자동 판별)
대표 이벤트FMLCommonSetupEvent, RegisterEventServerStartingEvent, LivingHurtEvent

Mod EventBus는 게임이 시작되기 전, 모드가 초기화되는 짧은 시간 동안만 활성화됩니다. 레지스트리 등록, 클라이언트/서버 셋업, 크리에이티브 탭 구성 같은 작업이 여기에 속합니다.

NeoForge EventBus는 게임이 실행되는 내내 살아 있습니다. 플레이어 접속, 엔티티 데미지, 블록 파괴처럼 실제 플레이 중에 발생하는 모든 것이 여기를 통합니다.


2. 코드로 보는 차이

Mod EventBus 등록

// examplemod-template-26.1.2/src/main/java/com/example/examplemod/ExampleMod.java
@Mod(ExampleMod.MOD_ID)
public class ExampleMod {
 
    public ExampleMod(IEventBus modEventBus) {
        // modEventBus는 생성자 인자로 주입됨
        modEventBus.addListener(this::onCommonSetup);
        modEventBus.addListener(this::onClientSetup);
    }
 
    private void onCommonSetup(FMLCommonSetupEvent event) {
        // 모드 초기화 시점 — 레지스트리 등록 완료 후 실행
    }
 
    private void onClientSetup(FMLClientSetupEvent event) {
        // 클라이언트 전용 초기화
    }
}

NeoForge EventBus 등록

// examplemod-template-26.1.2/src/main/java/com/example/examplemod/ExampleMod.java
@Mod(ExampleMod.MOD_ID)
public class ExampleMod {
 
    public ExampleMod(IEventBus modEventBus) {
        // NeoForge.EVENT_BUS는 정적 필드로 어디서든 접근 가능
        NeoForge.EVENT_BUS.addListener(this::onServerStarting);
        NeoForge.EVENT_BUS.addListener(this::onEntityJoin);
    }
 
    private void onServerStarting(ServerStartingEvent event) {
        // 서버 시작 시점 — 게임 런타임
    }
 
    private void onEntityJoin(EntityJoinLevelEvent event) {
        // 엔티티가 월드에 진입할 때마다 호출
    }
}

@EventBusSubscriber 어노테이션 방식

// 26.1.2: @EventBusSubscriber 에는 modid 만 지정한다.
// bus 속성과 Bus enum 은 삭제됐고, 핸들러가 어느 버스로 갈지는
// 이벤트 타입(@SubscribeEvent 파라미터)을 보고 자동으로 판별된다.
@EventBusSubscriber(modid = ExampleMod.MOD_ID)
public class ModEventHandlers {
 
    // RegisterEvent 는 Mod 버스 이벤트 → 자동으로 Mod 버스에 등록
    @SubscribeEvent
    public static void onRegister(RegisterEvent event) {
        // 레지스트리 등록
    }
}
 
// 런타임 이벤트도 동일하게 modid 만 지정한다.
@EventBusSubscriber(modid = ExampleMod.MOD_ID)
public class GameEventHandlers {
 
    // LivingHurtEvent 는 런타임 이벤트 → 자동으로 NeoForge 버스에 등록
    @SubscribeEvent
    public static void onLivingHurt(LivingHurtEvent event) {
        // 엔티티 데미지 처리
    }
}

3. 이벤트 → 버스 매핑 표

어떤 이벤트가 어느 버스에 속하는지 한 번에 정리합니다.

이벤트버스발생 시점
FMLCommonSetupEventMOD모드 공통 초기화
FMLClientSetupEventMOD클라이언트 전용 초기화
RegisterEventMOD레지스트리 등록
BuildCreativeModeTabContentsEventMOD크리에이티브 탭 아이템 구성
EntityAttributeCreationEventMOD엔티티 속성 등록
RegisterPayloadHandlersEventMOD네트워크 페이로드 등록
ServerStartingEventNEOFORGE서버 시작 직전
ServerStartedEventNEOFORGE서버 시작 완료
EntityJoinLevelEventNEOFORGE엔티티 월드 진입
PlayerEvent.PlayerLoggedInEventNEOFORGE플레이어 접속
LivingHurtEventNEOFORGE엔티티 데미지
LivingDeathEventNEOFORGE엔티티 사망
PlayerInteractEvent.RightClickItemNEOFORGE아이템 우클릭
RegisterCommandsEventNEOFORGE명령어 등록 (서버 시작 시)
BlockEvent.BreakEventNEOFORGE블록 파괴

4. 헷갈리는 케이스

두 가지가 특히 자주 혼동됩니다.

RegisterCommandsEvent — NeoForge 버스

이름에 "Register"가 들어가서 Mod 버스라고 착각하기 쉽습니다. 하지만 명령어 등록은 서버가 시작될 때 런타임에 일어납니다. NeoForge EventBus를 써야 합니다.

// ✅ 올바른 등록
NeoForge.EVENT_BUS.addListener(this::onRegisterCommands);
 
private void onRegisterCommands(RegisterCommandsEvent event) {
    // 명령어 등록
}

RegisterEvent — Mod 버스

반대로 RegisterEvent는 이름이 비슷해도 모드 초기화 시점에 발생합니다. Mod EventBus에 등록해야 합니다.

// ✅ 올바른 등록
modEventBus.addListener(this::onRegister);
 
private void onRegister(RegisterEvent event) {
    // 레지스트리 등록
}

가장 확실한 판단 기준: 이벤트 클래스가 net.neoforged.fml.event.IModBusEvent를 구현하는지 봅니다. 구현하면 Mod 버스 이벤트, 구현하지 않으면 NeoForge(게임) 버스 이벤트입니다. NeoForge의 모든 Mod 버스 이벤트는 이 마커 인터페이스를 구현하며, @EventBusSubscriber의 버스 자동 판별도 바로 이 인터페이스를 기준으로 동작합니다. IDE에서 이벤트 클래스를 열어 상속 계층에 IModBusEvent가 있는지만 확인하면 됩니다.

예: FMLCommonSetupEvent·FMLClientSetupEvent·RegisterEvent는 IModBusEvent를 구현 → Mod 버스. ServerStartingEvent·LivingHurtEvent는 구현하지 않음 → NeoForge 버스.

그래도 애매하면 NeoForge 소스에서 해당 이벤트가 어디서 post()되는지 — EVENT_BUS.post(...)(NeoForge 버스) vs modEventBus.post(...)(Mod 버스) — 확인합니다.


5. 안티패턴 — 잘못된 버스 등록

⚠️ 잘못된 버스 등록

// ❌ ServerStartingEvent를 modEventBus에 등록 → 절대 호출 안 됨
modEventBus.addListener(this::onServerStarting);
 
// ✅ NeoForge.EVENT_BUS 사용
NeoForge.EVENT_BUS.addListener(this::onServerStarting);

두 방향의 실패 양상이 다릅니다.

  • 런타임 이벤트를 Mod 버스에 등록(위 예시) → 그 이벤트는 Mod 버스에서 post()되지 않으므로 핸들러가 호출되지 않습니다. 뚜렷한 에러 없이 조용히 넘어갈 수 있으니, 핸들러가 동작하지 않으면 가장 먼저 버스를 의심하세요.
  • Mod 버스 이벤트(IModBusEvent)를 게임 버스(NeoForge.EVENT_BUS)에 등록 → NeoForge가 등록을 거부하며 예외를 던집니다: IModBusEvent events are not allowed on the common NeoForge bus! Use a mod bus instead.

어느 쪽이든 사전 예방책은 같습니다 — 이벤트가 IModBusEvent를 구현하는지부터 확인하세요.

같은 핸들러를 양쪽 버스에 모두 등록하는 것도 금지입니다. 이중 호출이 발생해 예측 불가능한 동작을 만듭니다.

// ❌ 이중 등록 — 절대 하지 말 것
modEventBus.addListener(this::onSomeEvent);
NeoForge.EVENT_BUS.addListener(this::onSomeEvent);

6. 버스 선택 체크리스트

핸들러를 작성하기 전에 이 순서로 확인합니다.

  1. 이 이벤트는 모드 초기화 중에 발생하는가? → Mod EventBus (modEventBus)
  2. 이 이벤트는 게임 플레이 중에 발생하는가? → NeoForge EventBus (NeoForge.EVENT_BUS)
  3. 확실하지 않으면 → 이벤트가 IModBusEvent를 구현하는지 확인 (구현 = Mod 버스)
  4. 그래도 애매하면 → NeoForge 소스에서 post() 호출 위치 확인

정리

  • Mod EventBus: 모드 초기화 시점, modEventBus 인자로 접근
  • NeoForge EventBus: 게임 런타임, NeoForge.EVENT_BUS 정적 접근
  • @EventBusSubscriber 에는 modid 만 지정 — 버스는 이벤트가 net.neoforged.fml.event.IModBusEvent를 구현하는지로 자동 판별 (26.1.2에서 bus 속성·Bus enum 삭제)
  • 잘못된 버스: Mod 버스 이벤트(IModBusEvent)를 게임 버스에 등록하면 예외로 거부되고, 반대로 런타임 이벤트를 Mod 버스에 등록하면 조용히 호출되지 않습니다
  • RegisterCommandsEvent는 NeoForge 버스, RegisterEvent는 Mod 버스

다음 챕터에서는 이벤트 우선순위(EventPriority)와 취소 가능한 이벤트(Cancelable)를 다룹니다.

이벤트 핸들러와 @SubscribeEvent

NeoForge 26의 이벤트 핸들러 3가지 패턴(@EventBusSubscriber, addListener, register)과 올바른 핸들러 시그니처 규칙을 설명합니다.

플레이어 이벤트

PlayerLoggedInEvent, LivingHurtEvent, LivingDeathEvent 등 주요 플레이어/Living 이벤트를 구현하고, 사이드 분기 처리로 클라이언트-서버 동기화 문제를 예방합니다.

On this page

ModBus vs NeoForge EventBus — 두 버스 완전 정복1. 핵심 차이 한눈에2. 코드로 보는 차이Mod EventBus 등록NeoForge EventBus 등록@EventBusSubscriber 어노테이션 방식3. 이벤트 → 버스 매핑 표4. 헷갈리는 케이스5. 안티패턴 — 잘못된 버스 등록6. 버스 선택 체크리스트정리
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