coding-1ab / mega-modpack

⛏️ Coding Lab 공식 마인크래프트 서버 모드팩 소스
1 stars 0 forks source link

모드간 종속성 에러 #3

Closed tmvkrpxl0 closed 5 months ago

tmvkrpxl0 commented 5 months ago

업스트림 이슈: https://github.com/dima-dencep/rubidium-extra/issues/76 embeddium과 rubidium-extra를 composite build로 같이 빌드하면 터진다.

includeBuild로 포함한 모든 모드가 Forge를 제외한 마크 관련 종속성을 아예 사용하지 못함. ./gradlew build 실행시 아래와 같은 오류가 매우 많이 발생함:

Could not resolve: appeng:appliedenergistics2-forge:15.0.9-beta_mapped_parchment_2023.09.03-1.20.1
Could not resolve: top.theillusivec4.curios:curios-forge:5.2.0+1.20.1_mapped_parchment_2023.09.03-1.20.1
Could not resolve: mekanism:Mekanism:1.20.1-10.4.2.16_mapped_parchment_2023.09.03-1.20.1
Could not resolve: curse.maven:ae2things-609977:4616683-sources_mapped_parchment_2023.09.03-1.20.1
.............

빈 gradle 프로젝트에서 아무 모드나 아래처럼 다운받고:

git clone https://github.com/IntelligenceModding/AdvancedPeripherals.git -b dev/1.20.1

settings.gradle.kts에 다음 내용을 적고:

plugins {
    id("org.gradle.toolchains.foojay-resolver-convention") version "0.8.0"
}
includeBuild("AdvancedPeripherals")

build.gradle.kts에서 다음처럼 다운받은 모드를 추가하고:

implementation("de.srendi.advancedperipherals:AdvancedPeripherals")

./gradlew build 돌리면 펑. 근데 모드 폴더에 들어가서(예: cd AdvancedPeripherals) 실행하면 ./gradlew build 성공.

tmvkrpxl0 commented 5 months ago

문제 원인

마인크래프트 모드 개발 환경 설정 및 빌드 과정 전체를 총괄하는 Forge Gradle이 동적으로 패치한 라이브러리를 찾을 수 없어 발생한 것.

   > Could not find thedarkcolour:kotlinforforge:4.10.0_mapped_parchment_2023.09.03-1.20.1.
     Searched in the following locations:
       - https://repo.maven.apache.org/maven2/thedarkcolour/kotlinforforge/4.10.0_mapped_parchment_2023.09.03-1.20.1/kotlinforforge-4.10.0_mapped_parchment_2023.09.03-1.20.1.pom
       - https://thedarkcolour.github.io/KotlinForForge/thedarkcolour/kotlinforforge/4.10.0_mapped_parchment_2023.09.03-1.20.1/kotlinforforge-4.10.0_mapped_parchment_2023.09.03-1.20.1.pom

마인크래프트 모드가 Kotlin을 쓸 수 있게 해주는 KotlinForForge(KFF)를 예로 들자면, Kotlin을 사용하는 모드는 당연히 KFF를 종속성으로 사용하니 빌드 과정에서 다운받을 것, 그러나 KFF를 다운받기 위해 https://thedarkcolour.github.io를 수색했으나 찾을 수 없었다고 함. thedarkcolour는 KFF의 제작자고 나도 제작에 참여했기 때문에 저 사이트로 KFF가 업로드 될 것은 확실한데 찾을 수 없다며 오류 발생. 근데 왜 찾을 수 없는가? 라이브러리 버전을 보면 알겠지만, 4.10.0이 아니라 4.10.0_mapped_parchment_2023.09.03-1.20.1을 찾으려고 했음. 버전이 이상한 이유는 저 라이브러리를 다운받아서 바로 쓰는게 아니라 ForgeGradle이 패치한 파일을 쓰기 때문. 근데 그 패치한 파일을 찾을 수 없어서 오류가 발생했음. 패치된 jar 파일은 ForgeGradle 기준으로 /home/tmvkrpxl0/.gradle/caches/forge_gradle/deobf_dependencies/thedarkcolour/kotlinforforge/4.10.0_mapped_parchment_2023.09.03-1.20.1/에 들어있음. ForgeGradle이 원래는 자동으로 이 폴더를 추가해주기 때문에 문제가 날 리가 없지만 모종의 이유로 이곳이 유실되는 것 같음.

Jar을 왜 패치하는가?

Jar을 패치하는 이유는 각 라이브러리가 사용하는 매핑 파일의 종류가 달라서 그럼. 매핑은 소스코드의 여러 심볼(함수,클래스,변수 이름)을 가져다가 다른 단어로 교체하는 과정을 뜻함. 마인크래프트는 난독화된 채로 배포되기 때문에 원본 소스코드로 되돌릴려면 무조건 필요함. 이때, 어떤 난독화된 이름이 본래 무슨 이름이었나를 전부 기록하고 있는 파일을 매핑 파일이라 하며, 난독화된 마인크래프트를 디컴파일 하고, 여기다 이 파일을 사용해 매핑을 적용하면 원래 소스코드를 복원할 수 있음. 그러나 사용하는 매핑 파일의 종류가 여러가지임:

Forge Gradle 및 Loom은 개발자가 선택한 매핑에 맞추어, 마인크래프트 및 종속성 라이브러리들의 모든 심볼을 매핑하여 갈아 엎어버림 그니까, Yarn 매핑을 사용한다고 하면, 마인크래프트 전체, 그리고 종속성으로 사용하는 모든 모드들의 심볼들을 Yarn 매핑으로 전환한단 소리. 당연히 이 과정을 거치면 라이브러리의 jar 파일 자체가 수정될 것이고, 이 수정된 파일을 thedarkcolour:kotlinforforge:4.10.0mappedparchment_2023.09.03-1.20.1 형식으로 따로 저장하는 것.(parchment_2023.09.03-1.20.1은 매핑 파일의 버전)

tmvkrpxl0 commented 5 months ago

도구에 들어가는 흑마법의 양이랑 사용자의 정신 건강은 반비례다

tmvkrpxl0 commented 5 months ago

여담으로 플러그인들은 자체 매핑 파일을 사용하는데, 마인크래프트의 클래스를 직접 사용하는 것을 지양하고 자기들 API를 사용하도록 권장하니 매핑 파일을 열심히 관리하지 않는다. 요즘이야 다른 매핑 파일을 사용하는 방법이 생겼지만, 옛날에는(1.7.10 시절) 그런거도 없어 마인크래프트 클래스를 직접 사용한다면 아래와 같이 (고통스럽게) 작업했어야 했다:

public static void controlEntity(Entity e) {
    Position pos = e.f();
    e.n(e.a, e.b + 1.2f, pos.f());
}
63byeongchan commented 5 months ago

ㅎㄷㄷ 자유도 놓은 yarn 매핑의 폐해인가요?

tmvkrpxl0 commented 5 months ago

ㅎㄷㄷ 자유도 놓은 yarn 매핑의 폐해인가요?

아니요 Gradle이 만악의 근원이라 그렇습니다

tmvkrpxl0 commented 5 months ago

이분 덕분에 해결했습니다 ./gradlew :build를 실행해도 원인이 똑같았음이 단서였습니다 - :build는 그냥 build와 다르게 하위 프로젝트를 건들지 않습니다. 아마 하위 프로젝트의 종속성이 루트로 그대로 복사된거 같은데, 아래처럼 isTransitive를 꺼서 해결했습니다.

implementation("com.builtbroken.aiimprovements:AI-Improvements") { isTransitive = false }

생각보다 간단했네요 ㅎ...