본문으로 건너뛰기
버전: Minecraft 26.2

태그와 창작 탭

태그​

태그는 한 레지스트리의 항목을 #minecraft:mineable/pickaxe 같은 이름으로 묶은 것입니다. 태그 API는 dev.polymodloader.api.tag 패키지에 있습니다.

static final TagKey WARDED = TagKey.block(ResourceId.of("my_mod", "warded"));
static final TagKey SPARKLY = TagKey.item(ResourceId.of("my_mod", "sparkly"));
static final TagKey PICKAXE_MINEABLE = TagKey.block(ResourceId.minecraft("mineable/pickaxe"));
static final TagKey SKELETONS = TagKey.entityType(ResourceId.minecraft("skeletons"));
  • TagKey는 이름일 뿐입니다. TagRegistry(BLOCK, ITEM, ENTITY_TYPE)와 #을 뺀 ID로 이루어집니다. 키는 한 번 만들어 상수로 두세요.
  • 항목은 데이터 팩과 모드 jar의 data/<namespace>/tags/<block|item|entity_type>/<path>.json, 그리고 addToTag에서 옵니다. /reload하면 바뀝니다.
  • 블록, 아이템, 엔티티 타입 태그를 지원합니다.

태그 조회​

world.isBlockIn(pos, WARDED); // 그 위치의 블록
player.mainHandStack().isIn(SPARKLY); // 아이템 스택(ItemStackRef)
entity.isIn(SKELETONS); // 엔티티의 타입
world.tags().contains(SPARKLY, ResourceId.of("my_mod", "spark")); // 아무 항목
world.tags().entries(SPARKLY); // 모든 항목
메서드뜻
WorldView.tags()이 월드가 있는 쪽에서 불러온 태그를 읽는 TagView
TagView.contains(tag, entry)블록·아이템·엔티티 타입 ID가 태그에 들어 있는지(중첩 태그 포함)
TagView.entries(tag)중첩 태그를 풀어 낸 모든 항목(게임의 순서). 모르는 태그면 빈 목록
WorldView.isBlockIn(pos, tag)pos의 블록이 블록 태그에 들어 있는지
ItemStackRef.isIn(tag)스택의 아이템이 아이템 태그에 들어 있는지
EntityView.isIn(tag)엔티티의 타입이 엔티티 타입 태그에 들어 있는지
  • 서버는 자신의 데이터 팩에서 불러온 태그를 읽고, 클라이언트는 서버가 보낸 사본을 읽습니다.
  • 모르는 태그나 항목은 그냥 "들어 있지 않음"으로 답합니다.
  • 블록 위치에 아이템 태그를 묻는 것처럼 종류가 다른 태그를 주면 IllegalArgumentException이 납니다.
  • TagView는 월드가 로드된 뒤, 그것을 넘겨준 월드의 스레드에서 씁니다. /reload 뒤에는 결과가 바뀌므로 리로드를 넘어 결과를 캐시하지 마세요.

코드로 항목 추가​

mod.content().addToTag(WARDED, ResourceId.of("my_mod", "warded_block"));
mod.content().addToTag(SPARKLY, ResourceId.of("my_mod", "spark"), ResourceId.of("my_mod", "glow_block"));
mod.content().addToTag(PICKAXE_MINEABLE, ResourceId.of("my_mod", "warded_block")); // 게임 태그
  • addToTag는 다른 선언처럼 common 엔트리포인트에서 부릅니다. 등록이 닫힌 뒤에 부르면 IllegalStateException(POLY-CONTENT-002), 항목 없이 부르면 IllegalArgumentException이 납니다.
  • 모드 jar에 "replace": false 태그 파일을 둔 것과 같습니다. Poly 모드 로더가 항목을 생성 데이터 팩(.poly/generated-pack)에 씁니다. 태그의 이름 공간은 어느 것이든 됩니다. 여러 번 부르거나 여러 모드가 더하면 합쳐지고, 모드 jar의 태그 파일도 그대로 적용됩니다.
  • 항목은 선택 항목으로 쓰이고, 레지스트리가 얼 때 확인합니다. 그때 등록되지 않은 항목은 POLY-CONTENT-007로 알리고 뺍니다. 태그의 나머지는 그대로 불러옵니다.

창작 탭​

게임의 탭​

게임의 탭 끝에 아이템을 넣으려면 아이템 정의에서 creativeTab(CreativeTab.…)을 씁니다. 탭 목록은 블록에 있습니다.

모드 전용 탭​

ContentHandle tab = mod.content().creativeTab("showcase", CreativeTabDefinition.builder()
.icon(ResourceId.of("my_mod", "glow_block")) // 없으면 첫 항목
.entries(ResourceId.of("my_mod", "glow_block"), ResourceId.of("my_mod", "spark"))
.entry(ResourceId.minecraft("amethyst_shard")) // 게임 아이템도 됨
.build());
assets/my_mod/lang/ko_kr.json
{"itemGroup.my_mod.showcase": "내 모드"}
  • creativeTab(path, definition)은 common 엔트리포인트에서 <모드 ID>:<path> 탭을 선언합니다. 탭 제목은 itemGroup.<모드 ID>.<path>의 번역입니다.
  • CreativeTabDefinition.builder()에는 icon(item)(선택)과 항목을 순서대로(entry, entries) 넣습니다. 모드 아이템도 게임 아이템도 됩니다. 항목을 하나도 넣지 않으면 build()가 IllegalArgumentException을 던집니다.
  • 잘못되었거나 이미 쓴 경로는 IllegalArgumentException(POLY-CONTENT-001), 등록이 닫힌 뒤에는 IllegalStateException(POLY-CONTENT-002)입니다.
  • 항목과 아이콘은 레지스트리가 얼 때 확인합니다. 그때 등록된 아이템이 아닌 것은 POLY-CONTENT-008로 알리고 뺍니다. 아이콘이 빠지면 첫 번째 올바른 항목으로 대신하고, 항목이 하나도 남지 않은 탭은 등록하지 않습니다.
  • 탭의 아이템은 창작 검색 탭에도 나옵니다.

페이지​

게임의 창작 화면에는 탭 자리가 14개뿐이고, 모두 게임이 씁니다. 그래서 Poly 모드 로더는 모드 탭을 추가 페이지에 놓습니다.

  • 모드 탭은 선언 순서대로 1, 2, … 페이지에 들어갑니다. 페이지마다 위·아래 줄 왼쪽 다섯 칸씩, 10개입니다.
  • 오른쪽에 있는 게임 탭(저장한 핫바, 검색, 관리자 아이템, 인벤토리)은 모든 페이지에 보입니다.
  • 모드 탭이 있으면 탭 줄 위에 <·> 버튼이 생깁니다. 페이지를 넘기면 그 페이지의 첫 탭이 선택됩니다.
검증 범위

등록과 페이지별 위치 검사는 게임 테스트 서버에서 확인했습니다. 클라이언트 쪽 변환 규칙과 훅은 실제 26.2 클래스에 대고 단위 테스트로 확인했습니다. 페이지로 나뉜 화면이 어떻게 보이는지(버튼 위치, 탭 그림)는 창을 여는 테스트를 돌리지 않아 아직 사람이 확인하지 않았습니다.

Buy me a coffee