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

사운드 등록과 재생

NeoForge 26에서 커스텀 사운드를 DeferredRegister로 등록하고, sounds.json과 OGG 파일을 구성한 뒤 양 사이드에서 올바르게 재생하는 방법을 설명합니다.

Minecraft의 사운드 시스템은 단순히 파일을 재생하는 것 이상입니다. 등록, 메타데이터 선언, 클라이언트/서버 분기까지 세 단계를 모두 올바르게 처리해야 소리가 제대로 납니다. 이 챕터에서는 커스텀 사운드를 처음부터 끝까지 구현합니다.


사운드 시스템 개요

NeoForge의 사운드 파이프라인은 세 요소로 구성됩니다.

요소역할
SoundEvent 레지스트리사운드 식별자 등록 (서버/클라 공유)
sounds.json실제 OGG 파일 매핑 + 카테고리 선언
OGG 파일assets/<modid>/sounds/ 아래 실제 오디오

세 요소 중 하나라도 빠지면 사운드가 재생되지 않거나 콘솔에 경고가 쌓입니다.


1단계: SoundEvent DeferredRegister

SoundEvent도 다른 게임 오브젝트와 동일하게 DeferredRegister로 등록합니다.

// src/main/java/com/example/examplemod/ModSounds.java
public class ModSounds {
 
    public static final DeferredRegister<SoundEvent> SOUND_EVENTS =
        DeferredRegister.create(Registries.SOUND_EVENT, ExampleMod.MODID);
 
    // 26.1.2: ResourceLocation 삭제 → Identifier.fromNamespaceAndPath 사용.
    public static final Supplier<SoundEvent> MAGIC_CHIME = SOUND_EVENTS.register(
        "magic_chime",
        () -> SoundEvent.createVariableRangeEvent(
            Identifier.fromNamespaceAndPath(ExampleMod.MODID, "magic_chime")
        )
    );
}

createVariableRangeEvent는 거리에 따라 볼륨이 자동으로 감쇠하는 사운드를 만듭니다. 고정 범위가 필요하면 createFixedRangeEvent(Identifier, float)를 사용하세요.

메인 모드 클래스에서 버스에 등록합니다.

// ExampleMod.java
@Mod("examplemod")
public class ExampleMod {
    public ExampleMod(IEventBus modEventBus) {
        ModSounds.SOUND_EVENTS.register(modEventBus);
    }
}

2단계: sounds.json 작성

SoundEvent를 등록했다고 해서 실제 파일이 연결되지는 않습니다. sounds.json이 그 다리 역할을 합니다.

// src/main/resources/assets/examplemod/sounds.json
{
  "magic_chime": {
    "category": "block",
    "subtitle": "subtitles.examplemod.magic_chime",
    "sounds": [
      {
        "name": "examplemod:magic_chime",
        "stream": false
      }
    ]
  }
}

각 필드의 의미:

필드설명
category게임 설정의 볼륨 슬라이더 분류
subtitle자막 표시용 번역 키
sounds[].name<modid>:<경로> 형식. assets/<modid>/sounds/<경로>.ogg 파일을 가리킴
streamtrue면 스트리밍 재생 (긴 음악용). 짧은 효과음은 false

사운드 카테고리 목록

Minecraft가 제공하는 카테고리는 다음과 같습니다.

카테고리용도
master전체 볼륨 (모든 사운드에 영향)
music배경 음악
record음반 (주크박스)
weather날씨 효과음
block블록 상호작용
hostile적대적 몹
neutral중립 몹
player플레이어 동작
ambient환경음
voice대화/내레이션

3단계: OGG 파일 배치

파일 경로는 sounds.json의 name 필드와 정확히 일치해야 합니다.

src/main/resources/
└── assets/
    └── examplemod/
        ├── sounds.json
        └── sounds/
            └── magic_chime.ogg   ← 여기

"name": "examplemod:magic_chime"이면 assets/examplemod/sounds/magic_chime.ogg를 찾습니다. 하위 폴더도 가능합니다. "name": "examplemod:ui/click"이면 sounds/ui/click.ogg입니다.

⚠️ OGG 외 포맷 사용 금지

Minecraft는 OGG Vorbis만 지원합니다.

  • MP3, WAV 파일을 넣으면 로드 자체가 실패합니다.
  • OGG 파일의 샘플레이트는 44100Hz 또는 22050Hz를 권장합니다.

다른 포맷을 변환할 때는 ffmpeg를 사용하세요.

ffmpeg -i input.wav -c:a libvorbis output.ogg

4단계: 자막 번역 키 추가

sounds.json에 subtitle을 지정했다면 lang 파일에도 추가해야 자막이 표시됩니다.

// assets/examplemod/lang/ko_kr.json
{
  "subtitles.examplemod.magic_chime": "마법 종소리"
}
// assets/examplemod/lang/en_us.json
{
  "subtitles.examplemod.magic_chime": "Magic Chime"
}

자막은 게임 설정에서 "자막 표시"를 켜야 화면에 나타납니다.


5단계: 사운드 재생

양 사이드 재생 (권장)

Level.playSound는 서버에서 호출하면 주변 클라이언트에 자동으로 패킷을 전송합니다. 첫 번째 인자를 null로 넘기면 호출한 플레이어를 포함한 모든 주변 플레이어에게 들립니다.

// 서버 사이드에서 호출 — 클라이언트에 자동 동기화
level.playSound(
    null,                        // 제외할 플레이어 (null = 모두에게)
    pos,                         // BlockPos 또는 double x, y, z
    ModSounds.MAGIC_CHIME.get(), // SoundEvent
    SoundSource.BLOCKS,          // 카테고리
    1.0f,                        // 볼륨 (0.0 ~ 1.0+)
    1.0f                         // 피치 (0.5 = 낮음, 2.0 = 높음)
);

이벤트 핸들러 안에서 사용하는 예시입니다.

@SubscribeEvent
public static void onBlockActivated(UseItemOnBlockEvent event) {
    Level level = event.getLevel();
    BlockPos pos = event.getPos();
 
    if (!level.isClientSide()) {
        level.playSound(null, pos, ModSounds.MAGIC_CHIME.get(),
            SoundSource.BLOCKS, 1.0f, 1.0f);
    }
}

⚠️ 클라이언트 전용 재생 함수 혼용 주의

Minecraft.getInstance().getSoundManager().play(...)는 클라이언트 사이드에서만 호출할 수 있습니다. 서버 스레드에서 호출하면 크래시가 발생합니다.

// 클라이언트 전용 — @OnlyIn(Dist.CLIENT) 또는 isClientSide() 확인 필수
if (level.isClientSide()) {
    Minecraft.getInstance().getSoundManager().play(
        SimpleSoundInstance.forUI(ModSounds.MAGIC_CHIME.get(), 1.0f)
    );
}

멀티플레이어에서 모든 플레이어에게 들려야 한다면 Level.playSound를 서버 사이드에서 호출하는 것이 올바른 방법입니다.

볼륨과 피치 조절

// 랜덤 피치로 자연스러운 변주 효과
float pitch = 0.8f + level.random.nextFloat() * 0.4f; // 0.8 ~ 1.2
level.playSound(null, pos, ModSounds.MAGIC_CHIME.get(),
    SoundSource.BLOCKS, 1.0f, pitch);

전체 흐름 요약

ModSounds.java          sounds.json             OGG 파일
DeferredRegister   →    파일 경로 매핑      →   실제 오디오 데이터
(레지스트리 등록)        (카테고리/자막)          (assets/.../sounds/)
        ↓
level.playSound() 호출
        ↓
서버가 주변 클라이언트에 패킷 전송
        ↓
클라이언트 SoundManager가 OGG 재생

정리

  • DeferredRegister<SoundEvent>로 사운드 식별자를 등록한다.
  • sounds.json에서 OGG 파일 경로와 카테고리를 선언한다.
  • OGG 파일은 assets/<modid>/sounds/ 아래에 배치한다. MP3/WAV는 지원하지 않는다.
  • 멀티플레이어 동기화가 필요하면 서버 사이드에서 Level.playSound(null, ...)를 호출한다.
  • 클라이언트 전용 SoundManager.play()는 반드시 isClientSide() 확인 후 사용한다.

커맨드 등록 — Brigadier로 /명령어 만들기

RegisterCommandsEvent와 Brigadier 빌더 패턴을 사용해 커스텀 슬래시 커맨드를 등록하는 방법을 배웁니다. 인자 타입, 권한 레벨, 실행 로직까지 단계별로 익힙니다.

파티클 등록과 스폰 — 시각 효과 직접 만들기

DeferredRegister로 커스텀 파티클 타입을 등록하고, 파티클 JSON과 텍스처를 구성한 뒤 서버에서 모든 클라이언트로 파티클을 전파하는 방법을 배웁니다.

On this page

사운드 시스템 개요1단계: SoundEvent DeferredRegister2단계: sounds.json 작성사운드 카테고리 목록3단계: OGG 파일 배치4단계: 자막 번역 키 추가5단계: 사운드 재생양 사이드 재생 (권장)볼륨과 피치 조절전체 흐름 요약정리
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