템플릿 디렉토리 구조와 핵심 파일
examplemod-template-26.1.2의 디렉토리 구조를 파악하고 build.gradle, settings.gradle, ExampleMod.java, neoforge.mods.toml 등 핵심 파일의 역할을 이해합니다.
템플릿 디렉토리 구조와 핵심 파일
IntelliJ에서 프로젝트를 열었다면 왼쪽 Project 패널에 파일 트리가 펼쳐져 있을 겁니다. 처음 보면 파일이 꽤 많아 보이지만, 실제로 모딩을 시작할 때 손대는 파일은 다섯 개 정도입니다. 이 챕터에서는 그 다섯 파일이 무엇인지, 왜 존재하는지를 짚어봅니다.
전체 디렉토리 구조
루트에는 Gradle 빌드 파일 세 개가 있고, 실제 모드 코드는 src/main/java/ 아래에 있습니다. 리소스(텍스처, 모델, 언어 파일)는 src/main/resources/ 아래에 들어갑니다.
핵심 파일 5개
build.gradle
프로젝트의 빌드 설정 파일입니다. NeoForge ModDev Gradle 플러그인을 선언하고, Java 25 툴체인을 지정하며, 게임 실행 구성(runClient, runServer, data)을 정의합니다.
plugins {
id 'java-library'
id 'maven-publish'
id 'net.neoforged.moddev' version '2.0.141'
}
// Mojang이 26.1.2에서 Java 25를 배포하므로 모드도 Java 25를 타깃으로 합니다
java.toolchain.languageVersion = JavaLanguageVersion.of(25)
neoForge {
version = project.neo_version
runs {
client { client() }
server {
server()
programArgument '--nogui'
}
data {
clientData()
programArguments.addAll '--mod', project.mod_id, '--all',
'--output', file('src/generated/resources/').absolutePath,
'--existing', file('src/main/resources/').absolutePath
}
}
}version = project.neo_version처럼 project. 접두사로 참조하는 값들은 모두 gradle.properties에서 옵니다.
settings.gradle
Gradle 빌드 자체의 설정 파일입니다. 플러그인 저장소와 툴체인 리졸버를 선언합니다. 일반적으로 이 파일은 거의 수정하지 않습니다.
pluginManagement {
repositories {
gradlePluginPortal()
}
}
plugins {
id 'org.gradle.toolchains.foojay-resolver-convention' version '1.0.0'
}gradle.properties
모드의 핵심 변수들을 한 곳에 모아둔 파일입니다. build.gradle과 neoforge.mods.toml이 여기서 값을 읽어갑니다.
# NeoForge / Minecraft 버전
minecraft_version=26.1.2
neo_version=26.1.2.64-beta
# 모드 식별 정보
mod_id=examplemod
mod_name=Example Mod
mod_license=All Rights Reserved
mod_version=1.0.0
mod_group_id=com.example.examplemod새 모드를 만들 때 가장 먼저 수정하는 파일입니다. mod_id를 바꾸면 연쇄적으로 다른 파일도 맞춰야 합니다.
⚠️ 파일 직접 수정 시 주의
gradle.properties의mod_id를 변경하면neoforge.mods.toml의modId와@Mod어노테이션 값도 모두 동일하게 수정해야 합니다. 하나라도 불일치하면 모드 로드 실패.
ExampleMod.java
모드의 진입점입니다. @Mod 어노테이션이 붙은 클래스가 NeoForge에 의해 로드됩니다.
@Mod(ExampleMod.MODID)
public class ExampleMod {
public static final String MODID = "examplemod";
public ExampleMod(IEventBus modEventBus, ModContainer modContainer) {
// 이벤트 버스에 리스너 등록
modEventBus.addListener(this::commonSetup);
// DeferredRegister를 이벤트 버스에 연결
BLOCKS.register(modEventBus);
ITEMS.register(modEventBus);
CREATIVE_MODE_TABS.register(modEventBus);
// 서버/게임 이벤트 수신
NeoForge.EVENT_BUS.register(this);
}
}생성자에서 이벤트 버스를 받아 리스너를 등록하는 패턴이 NeoForge 모딩의 핵심입니다. 이 패턴은 phase-1에서 자세히 다룹니다.
neoforge.mods.toml
모드의 메타데이터 파일입니다. 게임이 모드를 로드할 때 이 파일을 읽어 모드 이름, 버전, 의존성을 확인합니다. 실제 파일은 src/main/templates/META-INF/neoforge.mods.toml에 있으며, 빌드 시 gradle.properties의 변수로 치환됩니다.
license="${mod_license}"
[[mods]]
modId="${mod_id}"
version="${mod_version}"
displayName="${mod_name}"
description='''
Example mod description.
'''
[[dependencies.${mod_id}]]
modId="neoforge"
type="required"
versionRange="[${neo_version},)"
ordering="NONE"
side="BOTH"
[[dependencies.${mod_id}]]
modId="minecraft"
type="required"
versionRange="${minecraft_version_range}"
ordering="NONE"
side="BOTH"${mod_id} 같은 표기는 Groovy 문자열 보간이 아니라 Gradle ProcessResources 태스크가 치환하는 플레이스홀더입니다.
assets/ 디렉토리
src/main/resources/assets/examplemod/ 아래에는 모드의 시각적 리소스가 들어갑니다.
| 경로 | 내용 |
|---|---|
textures/block/ | 블록 텍스처 PNG |
textures/item/ | 아이템 텍스처 PNG |
models/block/ | 블록 모델 JSON |
models/item/ | 아이템 모델 JSON |
lang/en_us.json | 영어 번역 텍스트 |
lang/ko_kr.json | 한국어 번역 텍스트 |
지금 당장 이 파일들을 수정할 필요는 없습니다. phase-2 이후 블록과 아이템을 추가할 때 하나씩 채워나갑니다.
정리
| 파일 | 역할 | 수정 빈도 |
|---|---|---|
gradle.properties | 모드 ID, 버전, NeoForge 버전 변수 | 프로젝트 시작 시 1회 |
build.gradle | 빌드 설정, 실행 구성 | 의존성 추가 시 |
settings.gradle | Gradle 플러그인 저장소 | 거의 없음 |
ExampleMod.java | 모드 진입점, 이벤트 버스 등록 | 새 기능 추가 시 |
neoforge.mods.toml | 모드 메타데이터, 의존성 선언 | 의존 모드 추가 시 |
다음 챕터에서는 실제로 runClient를 실행해 게임이 뜨는지 확인합니다.