본문으로 건너뛰기
버전: 1.20.x

Access Transformer

Access Transformer(줄여서 AT)는 클래스, 메서드, 필드의 가시성 및 불변 여부를 변경하는 시스템 입니다. 모드가 접근 불가능한 멤버를 사용 및 수정할 수 있도록 해 줍니다.

무엇의 가시성을 변경할지 지정하는 AT 설정 파일 규격은 이곳에 나와있습니다.

AT 추가하기

AT를 활성화 하려면 아래와 같이 build.gradle에 설정 파일을 추가하세요. 이 파일이 컴파일 출력 폴더의 resources로 복사되기만 한다면 어디에 저장하셔도 상관 없습니다.

// build.gradle
// 여기서 매핑 채널과 버전도 지정할 수 있습니다.
minecraft {
accessTransformers {
file('src/main/resources/META-INF/accesstransformer.cfg')
}
}

네오 포지는 기본적으로 AT 설정 파일을 META-INF/accesstransformer.cfg에서 찾습니다. 만약 다른 곳에 설정 파일을 저장하셨다면 아래와 같이 neoforge.mods.toml에서 위치를 지정해 주세요:

# neoforge.mods.toml에서:
[[accessTransformers]]
## 아래 주소는 컴파일 출력 폴더의 resources, 또는 배포 jar의 루트 폴더에서 출발합니다
## 프로젝트의 'resources' 폴더는 컴파일 출력 폴더의 resources의 최상위 폴더가 됩니다
file="META-INF/accesstransformer.cfg"

AT 설정 파일을 여러개 지정하면 순서대로 적용됩니다. 모드가 거대해 여러 패키지로 나눌 때 용이합니다.

// build.gradle에서:
minecraft {
accessTransformers {
file('src/main/resources/accesstransformer_main.cfg')
file('src/additions/resources/accesstransformer_additions.cfg')
}
}
# neoforge.mods.toml에서:
[[accessTransformers]]
file="accesstransformer_main.cfg"

[[accessTransformers]]
file="accesstransformer_additions.cfg"

AT 설정 파일을 수정하거나 추가한 이후, Gradle 프로젝트를 다시 불러와야만 적용됩니다.

AT 설정 파일 문법

주석

#로 시작하는 줄은 주석으로 처리되며 무시됩니다.

접근 수정자

접근 수정자(Access Modifier)는 멤버의 새로운 가시성을 지정하는 키워드를 뜻합니다. Java와 똑같이 아래 네 개의 키워드를 지원합니다:

  • public - 패키지 안, 또는 밖에 있는 모든 클래스에서 접근할 수 있음
  • protected - 패키지 안에 있는 클래스, 또는 자식 클래스에서만 접근할 수 있음
  • default - 패키지 내부에 있는 클래스에서만 접근할 수 있음
  • private - 클래스 내부에서만 접근할 수 있음

위 키워드에 +f 또는 -f를 추가하여 가시성 뿐 아니라 final 키워드도 추가 및 제거할 수 있습니다. 기존에는 불가능하던 자식 클래스 생성이나, 메서드 재정의, 또는 필드 값 변경 등을 가능하게 해 줍니다.

위험

메서드의 가시성을 변경할 때, 지정된 메서드만 변경됩니다; 만약 자식 클래스에서 해당 메서드를 재정의한다면 똑같은 가시성 수정이 이루어지지 않아, 자식 메서드가 부모 메서드보다 더 낮은 가시성을 가져 JVM 오류가 발생할 수 있으니, 가시성을 변경하고자 하는 메서드가 다른 곳에서 재정의되면 안 됩니다!

private 메서드나 final 메서드(또는 final 클래스에 정의된 메서드), 그리고 static (정적) 메서드들은 재정의가 불가능하기에 안전하게 가시성을 변경할 수 있습니다.

변환 타깃

클래스

클래스의 가시성을 바꾼다면:

<접근 수정자> <완전한 클래스 이름>

내부 클래스들은, 외부 클래스의 전체 이름과 내부 클래스의 이름을 $로 분리하여 표시합니다.

필드

필드의 가시성을 바꾼다면:

<접근 수정자> <완전한 클래스 이름> <필드 이름>

메서드

메서드는 아래와 같이 가시성 뿐 아니라 인자들과 반환값의 타입까지 표시합니다:

<접근 수정자> <완전한 클래스 이름> <메서드 이름>(<인자의 타입들>)<반환 타입>
메서드 타입

메서드의 인자 및 반환값의 타입은 "descriptor"라고 불리기도 합니다. 자세한 사항은 Oracle 기술 문서에서 확인하세요(Java Virtual Machine Specification, SE 21, sections 4.3.2 and 4.3.3)

  • B - byte, 부호가 있는 바이트
  • C - char, UTF-16 유니코드 문자 번호
  • D - double, 배정밀도 부동 소수점
  • F - float, 단정밀도 부동 소수점
  • I - integer, 32비트 정수
  • J - long, 64비트 정수
  • S - short, 부호가 있는 16비트 정수
  • Z - boolean, true 또는 false 인 값
  • [ - 배열의 차원 1개를 표시함
    • 예: [[Sshort[][]
  • L<class name>; - 참조 타입, 모든 클래스가 해당됨
    • 예: Ljava/lang/String;는 참조 타입 java.lang.String를 가리킴 (빗금 대신 마침표로 패키지 구분)
  • ( - 메서드 디스크립터, 메서드의 인자들은 괄호 안에 적음, 반환 타입은 괄호 뒤에 적음
    • 예: <method>(I)Zint를 받고 boolean을 반환하는 메서드
  • V - 메서드 반환 타입이 void일 때 사용
    • 예: <method>()V는 인자 및 반환 값이 없는 메서드

예시

# Crypt 클래스의 ByteArrayToKeyFunction의 가시성을 public으로 변경합니다.
public net.minecraft.util.Crypt$ByteArrayToKeyFunction

# MinecraftServer의 'random' 필드를 protected로 만들고 final 키워드를 제거합니다
protected-f net.minecraft.server.MinecraftServer random

# String을 인자로 받고 ExecutorService를 반환하는 'Util#makeExecutor' 메서드를 public으로 만듭니다
public net.minecraft.Util makeExecutor(Ljava/lang/String;)Ljava/util/concurrent/ExecutorService;

# 2개의 long을 인자로 받고 int[]를 반환하는 'UUIDUtil#leastMostToIntArray' 메서드를 public으로 만듭니다
public net.minecraft.core.UUIDUtil leastMostToIntArray(JJ)[I