Community코딩 & 개발github.com

qad3n/modport

Minecraft Java 모드(모든 버전, jar 또는 소스)를 b1.7.3_rewrite 모드 로더로 포팅하여 클라이언트와 서버에서 실행되는 하나의 .b173mod 파일로 만듭니다. 사용자가 /modport, /port, "이 모드를 포팅해줘"라고 말하거나 모드 jar 파일을 건네줄 때 사용합니다.

modport란 무엇인가요?

이 스킬은 Minecraft Java 모드를 b1.7.3_rewrite 모드 로더용 Rust 기반 Wasm 게스트 모드로 포팅하는 완전한 자동화 워크플로우를 제공합니다. 주요 목표는 디컴파일된 Java 모드를 명세(spec)로 삼아 원본 모드의 외관, 느낌, 게임플레이를 b1.7.3 버전에서 그대로 재현하는 단일 .b173mod 파일을 생성하는 것입니다. 포팅 과정은 Vineflower 디컴파일러를 사용한 소스 역컴파일, 블록/아이템/엔티티 인벤토리 분석, 모델 변환, 그리고 b173_api SDK를 활용한 순차적 모듈 구현으로 구성됩니다. 이 스킬은 다양한 도구(예: new_port.sh, inventory.sh, api.sh, convert_models.py)를 제공하며, 테스트 체계를 통해 각 모듈을 서버 콘솔 명령어로 검증합니다. 포팅 과정에서 로더나 SDK 확장이 필요할 경우 일반 기능만 추가하도록 제한하며, 사용자 모드에서는 변경 사항을 로컬 작업 트리에만 유지하고 LOADER_CHANGES.md에 기록합니다. 완성된 포트 폴더는 Rust 소스, 도구, 메니페스트만 포함하며, 에셋이나 참조 파일은 포함하지 않습니다.

지원 대상✓Claude Code~Codex CLI~Cursor
npx skills add https://github.com/qad3n/b1.7.3-modport/tree/HEAD/skills/modport

Installed? Explore more 코딩 & 개발 skills: steipete/bluebubbles, steipete/eightctl, steipete/blucli · View all 6 →

즐겨 사용하는 AI에게 물어보기

이 에이전트 스킬이 미리 로드된 새 채팅을 엽니다.

문서

모드를 b1.7.3_rewrite 로더로 포팅하기

Java 모드는 실행할 수 없습니다. 포트는 디컴파일된 모드를 명세로 사용하는 Rust 재작성(Wasm 게스트, b173_api SDK)입니다. 목표: b1.7.3 내에서 동일한 외관, 느낌 및 게임플레이를 클라이언트와 서버 모두의 mods/ 폴더에 있는 하나의 파일로 제공합니다. 소스 버그를 수정하고 외관과 게임플레이가 동일하게 유지되는 한 자유롭게 최적화합니다. 절대 바닐라 화면을 교체하지 마세요: 추가 UI는 전환 가능한 오버레이입니다.

이 파일은 전체 지도입니다. 방향을 잡기 위해 로더 설계 문서, 진행 문서, 가이드 또는 전체 SDK 파일을 읽지 마세요. 도구를 사용한 다음, 단계에 필요한 단 하나의 예시 파일만 여세요.

작업 공간

경로는 작업 공간 루트, 즉 b1.7.3_rewrite/, ports/ 및 키트 저장소 b1.7.3_modport/가 있는 폴더를 기준으로 합니다. 키트의 install.sh는 도구를 tools/modport/(아래에서는 T/로 표기)에 링크하고 이 스킬을 .claude/skills/modport에 링크합니다. 포트 폴더에서 T/는 ../../tools/modport/입니다. b1.7.3_modport/에서 도구를 수정하거나 확장하고, 포트 내부에서는 절대 수정하지 마세요. 새 머신에서 도구가 종속성 부족으로 실패하면 T/doctor.sh를 실행하세요: 각 문제를 해결하는 명령어를 출력합니다. 모든 도구는 bash입니다: Windows에서는 Git Bash(Claude Code for Windows의 Bash 도구)에서 실행되며 .exe, py 및 경로를 자체적으로 처리합니다. Python 도구는 T/py.sh를 통해 호출하고, python3를 직접 사용하지 마세요.

모드

세션당 한 번 확인: 작업 공간 루트에서 test -f .modport-maintainer를 실행합니다.

  • 유지보수자 모드(마커 파일 존재): 로더, SDK 및 키트 저장소는 사용자 자신의 것입니다. 아래 단계에서 요청할 때만 커밋하고 푸시하세요.
  • 사용자 모드(마커 없음, 기본값): 로더, SDK 및 키트 저장소는 업스트림 작성자에게 속합니다.
    • 로더 및 SDK 확장은 로컬 작업 트리에 남아 있습니다. 해당 저장소에 절대 커밋하지 말고, 원격 저장소에 푸시하지 말며, "공유" 또는 "업스트림" 변경을 요청받더라도 gh pr create, gh issue create 또는 기타 gh 쓰기 명령을 실행하지 마세요. 사용자에게 직접 하도록 안내하세요.
    • 각 로더 또는 SDK 변경 사항을 ports/<modid>/LOADER_CHANGES.md에 기록하세요: 추가된 내용, 이유, 해당 파일.
    • 로컬 로더 변경이 필요한 포트는 기본 로더가 아닌 패치된 로더에서만 실행된다는 점을 사용자에게 알리세요.
    • 포트 폴더는 사용자 자신의 저장소입니다: 요청 시 커밋하고, 사용자가 설정한 원격 저장소에만 푸시하세요.
    • 마커 파일을 절대 생성하지 마세요.

도구

도구사용 시기출력
T/new_port.sh <modid> <jar> [name]포트 시작 시. 메니페스트 작성, git 초기화, reference/src로 역컴파일(Vineflower, 첫 사용 시 다운로드 및 확인), 인벤토리 실행ports/<modid>/
T/inventory.sh <src>모드가 등록하는 항목 나열: 클래스, 타일, 모델, 렌더러, GUI, 월드젠, 이벤트가 있는 블록, 아이템 및 엔티티대형 모드의 경우 약 15KB, reference/inventory.txt에 보관
T/api.shSDK에 대해 코드를 작성하기 전. sdk <file>(world, register, screen, behavior, events, terrain, config, services), spec <Struct>, enum <Name>(HostCall, EntityField, ModelOp), templates, events, console, hooksSDK 라인 번호와 함께 시그니처당 한 줄
T/py.sh extract_assets.py <jar> <modid>포트 폴더에서 한 번. 텍스처, 사운드 및 언어를 assets/<modid>로, 언어 키를 tile.<modid>.x.name, item.<modid>.x.name, <modid>.<key>로 매핑절대 커밋되지 않음
T/py.sh convert_models.py --out src/models/generated.rs <Model.java>... [--arg Model.scale=0.5]모델. ModelBase 생성자(SRG 또는 MCP 이름)를 부품 및 상자로 변환. 호출을 포트의 tools/convert_models.sh로 래핑생성된 Rust, 수동 편집 금지
T/test.sh deploy ports/<modid> [--game]모든 테스트 주기. 빌드, 테스트 서버 중지, 모드만 설치, 서버 시작. --game은 먼저 게임과 cargo-b173을 다시 빌드(로더 또는 SDK 변경 후). 테스트 서버가 실행 중이면 거부: 다른 세션이 소유하고 있을 수 있음, --force 전에 물어보기서버 콘솔 꼬리
T/test.sh errors [n]실패 후 첫 번째 작업두 로그의 패닉, 트랩 및 오류 줄
T/modtest.sh cmd <console line> / log server 80서버 구동 및 확인응답 줄만
T/modtest.sh client / shot <png>시각적 확인만. 클라이언트 시작 전에 사용자에게 물어보기: 데스크톱에 창이 열림게임 창 PNG

콘솔(T/modtest.sh cmd loader ..., T/api.sh console의 구문): gen, map(상단 다운 PNG), slice(수직 절단 PNG), column(tp 전에 확인: 지형으로 순간이동된 플레이어는 질식함), fill, tp, use, interact, close, entities, summon, slot, tile. PNG는 Read 도구로 읽습니다. 반복되는 확인 체인은 다시 입력하는 대신 ports/<modid>/tools/의 작은 스크립트에 넣습니다.

워크플로우

  1. 설정. 베타에 가장 가까운 소스 버전 선택(1.21보다 1.12보다 1.7.10): 모델, 텍스처 및 데이터 형태가 거의 1:1로 매핑됩니다. 1.7.10 jar는 SRG 이름(func_, field_)을 사용합니다: 사용법에서 의미를 읽고, 매핑을 찾지 마세요. new_port.sh를 실행한 다음 extract_assets.py를 실행합니다. 모드 모델이 확장하는 바닐라 모델 클래스를 변환기를 위해 reference/vanilla/에 복사합니다. 포트별 자산 추가 항목(3D 렌더러의 스프라이트)은 포트 자체의 tools/ 스크립트에 들어갑니다.
  2. 계획. reference/inventory.txt를 PORT_STATUS.md 할 일 행으로 종속성 순서대로 변환: 블록 및 아이템, 레시피, 월드젠 및 차원, 엔티티, 기계 및 GUI, 구조물, 보스, 플레이어 시스템, 추가 슬롯, 아이템 동작, 사운드 및 입자, 설정. 마일스톤은 배포와 콘솔 확인으로 끝납니다.
  3. 모듈별로 포팅. 모드의 클래스를 읽고, api.sh로 SDK를 확인하고, 예시의 패턴을 복사합니다. PORT_STATUS.md에 소스 클래스를 인용하고, 코드 주석에는 쓰지 마세요.
  4. 로더 확장은 api.sh에서 방법이 없을 때만(아래 체크리스트) 수행합니다.
  5. 테스트 각 모듈 후 deploy, cmd, errors로 수행합니다. PORT_STATUS.md에 버그 목록을 유지하고 하나의 문제에 반복하지 마세요; 마지막에 목록을 수정합니다.
  6. 완료. PORT_STATUS.md를 업데이트합니다. 포트에서 cargo +nightly fmt를 실행하고 b1.7.3_rewrite에서 cargo clippy를 실행합니다. 요청 시에만 커밋: 포트는 Rust 소스, 도구 및 메니페스트를 보관하며, 자산, reference/ 또는 AI 파일은 절대 보관하지 않습니다. ports/는 포트당 하나의 git 저장소이거나 모드당 하나의 폴더가 있는 단일 저장소입니다; new_port.sh가 감지합니다. 사용자 모드에서는 최종 보고서에서 포트에 필요한 로컬 로더 변경 사항을 LOADER_CHANGES.md에서 나열합니다.

예시

항상 존재하는 SDK 예시: b1.7.3_rewrite/vendor/b1.7.3-modding-sdk/examples/에는 testmod(하나의 파일에 모든 API 모듈), ruby(데이터 전용 콘텐츠), energy, energy_api, machines(모드 간 서비스)가 있습니다.

완성된 포트(작업 공간에 있을 때)는 더 빠른 지도입니다. Aether 포트(ports/aether/src):

필요파일
블록 테이블, 템플릿, 동작blocks.rs(종류당 하나의 const 행 배열)
아이템, 도구, 갑옷, 음식, 레시피items.rs, tools.rs, gear.rs, recipes.rs
설정 옵션config.rs(모든 생성 확률 롤을 포팅, 누락 시 세계가 범람함)
엔티티 등록 및 도우미entities/mod.rs
수동적 몹 및 탈것, 적대적, 비행체, 발사체entities/phyg.rs + mount.rs, cockatrice.rs, zephyr.rs, projectile.rs
클라이언트에 표시되는 엔티티 상태entities/swet.rs, entities/moa.rs(setSynced/synced)
모델 및 애니메이션models/mod.rs(part, cuboid, Program; 새 포트에 복사)
보스, 보스 바 HUD, 대화 화면entities/bosses/mod.rs, valkyrie_queen.rs(transparent() 화면 및 서버바운드 채널)
GUI 및 타일 데이터가 있는 기계machines.rs(ScreenBuilder, #[tile_behavior])
추가 장비 슬롯, 렌더 레이어accessories.rs(screens().overlay("GuiInventory", ..), playerLayer)
로컬 플레이어 이동player.rs(클라이언트 측 TickPost, 서버 상태는 엔티티 ID별 thread_local 맵)
차원, 지형, 장식world/mod.rs, world/terrain.rs, world/decorate.rs
구조물world/dungeons/mod.rs, writer.rs(terrain::structure::candidates, StructureBox::populated으로 클리핑, 256 높이를 128로 압축)
포탈 및 이동portal.rs

항상 적용되는 형태: 렌더러 GL 호출은 엔티티의 pose에서 Program 연산(push, translate, rotate, scale, texture, blend, lighting)이 됩니다; onLivingUpdate/updateEntityActionState는 onAi(템플릿 AI 대체) 또는 onTick으로 이동합니다; terrain::Random 및 노이즈 포트는 시드를 동일하게 유지합니다; 세계를 변경하기 전에 isAuthority()를 확인합니다(싱글 플레이어는 패킷을 다시 루프백, 양쪽에서 동일한 코드); 모든 서버바운드 페이로드 검증; translate("<modid>.gui.…")을 통한 채팅; <modid>.<path.with.dots> 형식의 사운드; <modid>:<path> 형식의 텍스처.

데이터 형태(로더 API 1.1, ABI 3). ID는 항상 이름에 의해 결정되며 숫자 ID가 아닙니다:

  • 블록 변형 및 방향. 소스 메타데이터 또는 블록 상태는 명명된 상태가 됩니다: ctx.blocks().states(name, BlockStatesSpec) 또는 data/<modid>/states/<block>.toml.

    • 소스의 메타데이터 순서대로 각 속성의 값을 나열하여 ctx.meta() 코드가 계속 작동하도록 합니다.
    • 16개 이상의 상태를 가진 블록은 로더에서 추가 숨겨진 ID를 얻습니다. 해당 블록은 world.blockState/setBlockState 또는 ctx.state()/setState()를 통해서만 읽고 씁니다.
    • 상태별 텍스처는 variants에 들어갑니다.
  • 스택별 데이터. 아이템 NBT 및 기능은 데이터 컴포넌트가 됩니다: StackRef와 함께 stackComponent/setStackComponent.

    • 모드는 <modid>:* 컴포넌트만 씁니다.
    • 다른 컴포넌트를 가진 스택은 절대 병합되지 않습니다.
    • 내구도는 그대로 유지됩니다. 손상 하위 유형 대신 변형당 하나의 아이템을 사용합니다.
  • 모드가 소유하지 않은 항목의 데이터. 엔티티, 플레이어, 타일, 청크 및 세계 NBT 또는 기능은 모드별 슬롯이 됩니다:

    • 엔티티: entity.setData 또는 setSynced
    • 플레이어: player.setData(key, ..)
    • 타일 엔티티: world.setTileAttachment
    • 청크: world.setChunkAttachment
    • 세계: setWorldData

    모든 슬롯은 모드 ID로 키가 지정되므로 두 모드가 충돌하지 않습니다.

  • 바닐라 또는 다른 모드의 콘텐츠 편집. 속성 편집(경도, 광도, 가연성, 도구)은 ctx.blocks().modify(BlockModifySpec) 또는 data/<modid>/modify/blocks/*.toml이 됩니다. 생성 목록 편집은 modifySpawns 또는 modify/spawns/*.toml이 됩니다. 도구 클래스의 채굴 속도는 minecraft:mineable/<pickaxe|axe|shovel> 태그에서 가져옵니다. 충돌하는 편집은 Mod Loader 화면에 보고됩니다. 속성 변경을 위해 전체 바닐라 블록을 교체하지 마세요.

  • 월드젠 및 명령어.

    • 각 월드젠 피처에 고유한 이름을 지정합니다. 이름이 랜덤 시드를 결정하므로 다른 모드가 절대 이동시키지 않습니다.
    • 명령어는 /<modid>:<name>에 응답합니다. 짧은 /<name>은 먼저 등록한 모드로 이동합니다.

로더 확장

일반 기능만, 절대 단일 모드 핵이 아닙니다. 아래 경로는 b1.7.3_rewrite/ 내부입니다. 접점, 순서대로:

  1. 프로토콜: vendor/b1.7.3-modding-sdk/mod_protocol/src/abi.rs의 HostCall, GuestCall, GuestReply 또는 EntityField 끝에 변형을 추가합니다; spec.rs의 새 spec 필드는 Option 또는 Default 유형으로 추가합니다(spec 구조체는 #[serde(default)]이므로 이전 모드도 로드됨). 릴리스된 계약은 절대 변경되지 않습니다: 변경된 계약은 새 버전을 얻습니다.
  2. 호스트: crates/modloader/src/host/world.rs(런타임 호출) 또는 host/register.rs(등록 단계)의 match arm; 더 큰 시스템은 자체 crates/modloader/src/<system>.rs 또는 extensions.rs에 있습니다. 새 템플릿은 crates/modloader/src/entities.rs(ENTITY_TEMPLATES) 또는 content/templates.rs(BLOCK_TEMPLATES)의 행입니다.
  3. SDK 래퍼는 b173_api/src/{world,register,screen}.rs에 있는 형제 옆에, 모드가 모든 곳에서 사용하는 경우 프렐류드에 추가합니다.
  4. 클라이언트 측은 crates/client/src/modded/에 있습니다. 바닐라 코드는 // rewrite: 주석이 있는 한 줄 훅을 통해 새 동작을 호출하며, crates/modloader/hooks.toml에 버전과 함께 나열됩니다.
  5. Dev 콘솔 도구는 crates/modloader/src/devtools.rs에 있습니다(USAGE에 추가).
  6. cargo build 및 cargo clippy, 그 다음 T/test.sh deploy ports/<modid> --game. 작업 공간이 로더 노트를 보관하는 위치에 추가 사항을 기록합니다. 유지보수자 모드: SDK 변경 사항은 SDK 서브모듈에 커밋된 다음, 사용자가 요청할 때만 rewrite에서 범프됩니다. 사용자 모드: 거기에 커밋되는 것은 없으며, 변경 사항은 LOADER_CHANGES.md에 들어갑니다.

예시 체인, World::lightning: HostCall::Lightning(abi.rs)에서 host/world.rs의 arm, b173_api/src/world.rs의 래퍼로.

알려진 함정

  • HostCall, HostReply 및 spec 구조체는 postcard로 인코딩됩니다. 기존 구조체에 필드를 절대 추가하지 마세요: ABI 2 게스트는 디코딩을 중단합니다. 새 데이터는 새 변형 또는 새 구조체가 필요합니다.

  • T/modtest.sh는 하나의 공유 테스트 서버와 클라이언트(b1.7.3_rewrite/target/modtest, 서버는 server/ 내)를 구동합니다. 사용자에게 묻지 않고 다른 세션이 시작한 것을 중지, 재설정 또는 인수하지 마세요.

  • cargo b173 build는 이미 wasm 빌드를 실행합니다; 별도의 cargo build 단계는 없습니다.

  • deploy --game 없이 로더 또는 SDK 변경: 서버는 새 호스트 호출 없이 이전 바이너리를 계속 실행합니다.

  • 테스트 클라이언트의 창은 포커스를 잃고 일시 중지 메뉴를 엽니다; 이것은 포트가 아닌 하네스입니다.

관련 스킬