最美情侣中文字幕电影,在线麻豆精品传媒,在线网站高清黄,久久黄色视频

歡迎光臨散文網(wǎng) 會(huì)員登陸 & 注冊(cè)

Forge/Fabric通用模組開發(fā)教程

2023-06-18 20:40 作者:reserveword  | 我要投稿

在Forge端是Forge模組,在Fabric端是Fabric模組


本教程適用于至少使用過Forge或Fabric開發(fā)環(huán)境(之一)的人。同時(shí)需要涉及到一些gradle知識(shí)。

(教程見置頂評(píng)論)

TL;DR

見置頂評(píng)論

Forge和Fabric的區(qū)別,以及為什么他們可以兼容

任何一個(gè)有一定時(shí)長(zhǎng)的mod玩家都知道一個(gè)常識(shí),那就是Forge和Fabric是不能兼容的,他們不能裝在同一個(gè)客戶端上。這是因?yàn)镕orge和Fabric對(duì)游戲代碼的修改都非常復(fù)雜,同時(shí)應(yīng)用二者的修改難以避免沖突。但是對(duì)于mod作者而言,想要制作一個(gè)同時(shí)兼容Forge和Fabric端的模組則有完全不同的挑戰(zhàn)。這是因?yàn)镕orge和Fabric端的模組加載方式有根本上的區(qū)別。

Forge模組是如何加載的

Forge在啟動(dòng)時(shí)會(huì)掃描所有class文件,并且從中選取擁有 @Mod 注解的類作為模組的主類,以主類作為入口點(diǎn)啟動(dòng)mod程序。 Forge還提供一個(gè)通過 META-INF/coremods.json 文件加載js mixin的功能。

Fabric模組是如何加載的

Fabric在啟動(dòng)時(shí)會(huì)讀取所有mod的 fabric.mod.json 文件,并根據(jù)其內(nèi)容加載mod。其中包含F(xiàn)abric模組的主類和mixin類,還支持根據(jù)可選依賴mod加載對(duì)應(yīng)的接口類??偠灾蠪abric模組加載的東西都能直接或間接地從 fabric.mod.mixin 文件中找到。

如何讓兩個(gè)mod兼容

我們知道Java是在需要使用一個(gè)類的時(shí)候才會(huì)加載這個(gè)類的,因此只要我們?cè)贔orge端不加載Fabric相關(guān)的類、在Fabric端不加載Forge相關(guān)的類就能兼容了。具體來說,就是 @Mod 注解的類(和其他涉及Forge API的類)不要在 fabric.mod.json 直接或間接引用,反過來也一樣。

一般來說,我們可以把所有代碼分為三部分:涉及Forge的部分、涉及Fabric的部分、通用的部分。Forge部分和Fabric部分可以調(diào)用通用部分,而通用部分不能調(diào)用另外兩部分。我們盡量壓縮Forge和Fabric的部分,只把直接和他們相關(guān)的代碼放在這里。如果確實(shí)有通用部分調(diào)用Forge/Fabric功能的需求,我們可以在通用部分添加一個(gè)接口,讓Forge/Fabric部分主動(dòng)提供對(duì)應(yīng)的實(shí)現(xiàn)(比如放到通用部分里的一個(gè)靜態(tài)字段里),間接調(diào)用通用部分。

如何編譯一個(gè)兼容的mod

我們現(xiàn)在已經(jīng)知道一個(gè)兼容mod長(zhǎng)什么樣了,但是要怎么編譯出一個(gè)這樣的mod呢?這就要求我們知道m(xù)od編譯的流程了。Fabric和Forge兩個(gè)框架的mod編譯都是使用gradle的:

Forge編譯流程

Forge編譯總的來說是先編譯Java類,再將編譯結(jié)果和資源文件放到一起打包,最后將打包結(jié)果反混淆。

Fabric編譯流程

Fabric編譯總的來說是先編譯Java類,再將編譯結(jié)果和資源文件放到一起打包,最后將打包結(jié)果反混淆。


還真不一樣

Forge和Fabric使用的混淆方式不同,F(xiàn)orge在開發(fā)時(shí)會(huì)使用MCP名(似乎現(xiàn)在改成官方反混淆名了),而運(yùn)行時(shí)會(huì)使用Srg名;Fabric在開發(fā)時(shí)會(huì)使用yarn名,在運(yùn)行時(shí)會(huì)使用intermediary名。如果你的代碼當(dāng)中有涉及到minecraft的類、字段或方法,那么Forge和Fabric在運(yùn)行時(shí)的叫法是不同的。

那怎么辦呢

我們可以先編譯出來,讓Fabric和Forge分別反混淆一次。。但是這樣做有一定的風(fēng)險(xiǎn),MCP名和yarn名都使用自然語言取名,難免有沖突的可能。如果有一個(gè)類的MCP名和yarn名一樣,那么它在Fabric和Forge上都會(huì)被反混淆,最終得到的結(jié)果就是不確定的了。這種方式還有一個(gè)問題,就是Forge官方的編譯插件和Fabric官方的編譯插件不兼容,修補(bǔ)起來很麻煩。

我最終采取的做法是讓三個(gè)模塊(forge、fabric、common)分別編譯打包反混淆,都打包出最終結(jié)果后再將其拆包合并到一個(gè)最終產(chǎn)物上。具體做法:


allprojects {

?? tasks.register('feedbackClass', Copy) {

? ? ?? dependsOn "jar"

? ? ?? dependsOn ":forge:reobfJar"

? ? ?? dependsOn ":fabric:remapJar"

? ? ?? from (zipTree(new File(buildDir, "libs/${project.name}.jar"))) {

? ? ? ? ?? include '**/*.class'

? ? ?? }

? ? ?? into new File(rootProject.buildDir, 'classes/java/main')

?? }

?? tasks.register('feedbackResource', Copy) {

? ? ?? dependsOn "jar"

? ? ?? dependsOn ":forge:reobfJar"

? ? ?? dependsOn ":fabric:remapJar"

? ? ?? from (zipTree(new File(buildDir, "libs/${project.name}.jar"))) {

? ? ? ? ?? exclude '**/*.class'

? ? ?? }

? ? ?? into new File(rootProject.buildDir, 'resources/main')

?? }

?? tasks.register('feedback') {

? ? ?? dependsOn("feedbackClass")

? ? ?? dependsOn("feedbackResource")

?? }}

project.jar {

?? dependsOn ':common:feedback'

?? dependsOn ':forge:feedback'

?? dependsOn ':fabric:feedback'

}

這里給每個(gè)子模塊都定義了一個(gè)feedback任務(wù),其中包含處理java類的feedbackClass和處理資源文件的feedbackResource。feedback任務(wù)將打包好的文件解包復(fù)制到主模塊的構(gòu)建目錄下。每個(gè)子任務(wù)都在forge和fabric反混淆完成之后執(zhí)行,主模塊只要在三個(gè)feedback任務(wù)之后再打包jar就可以了。

最后

以上給出了編譯一個(gè)forge/fabric兼容mod的原理和核心代碼,完整實(shí)現(xiàn)還需要進(jìn)一步的工作,包括為forge和fabric模塊進(jìn)行進(jìn)一步的配置和優(yōu)化。這部分可以參考我的mod,或者下載TLDR中的示例代碼。注意我的mod和示例代碼都沒有使用forge推薦的反混淆表,因?yàn)镸ojang官方提供的反混淆表存在法律問題 。如果你已知曉風(fēng)險(xiǎn)并仍然希望使用官方反混淆表,可以將


mapping_channel=snapshot

mapping_version=20210309-1.16.5

改成


mapping_channel=official

mapping_version=1.20



Forge/Fabric通用模組開發(fā)教程的評(píng)論 (共 條)

分享到微博請(qǐng)遵守國(guó)家法律
靖安县| 宁强县| 滦平县| 抚顺市| 余姚市| 江源县| 马鞍山市| 乌兰浩特市| 阿坝| 祥云县| 佛山市| 汤阴县| 密山市| 特克斯县| 江油市| 霞浦县| 探索| 祁阳县| 阜宁县| 乌海市| 西乡县| 张北县| 梁平县| 泽州县| 武隆县| 尚义县| 浮梁县| 托里县| 芦溪县| 隆子县| 霍林郭勒市| 泸西县| 文水县| 淮阳县| 若羌县| 扶沟县| 安溪县| 奉节县| 柘城县| 林周县| 隆德县|