zh_cn:documentation:fabric_loom

Fabric Loom

Fabric Loom,或者简称为 Loom,是个 Gradle 插件,用于 Fabric 生态系统的模组开发中。Loom 提供了在开发环境中安装 Minecraft 和模组的一系列工具,所以你可以针对 Minecraft 混淆及其发行版和版本之间的差异来将 Loom 与 Minecraft 链接起来。Loom 还提供了用于 Fabric 加载器的运行配置、mixin 编译处理,以及用于 Fabric Loader 的 jar-in-jar 系统的工具。

常用任务

  • migrateMappings:将当前源代码合并到指定的映射中。见 migratemappings
  • remapJar:产生包含 jar 任务的重映射的输出的 jar。同时也会将 jar-in-jar 包含在模组中。运行 build 时会调用。
  • genSources:使用默认的反编译器(CFR)反编译 Minecraft jar。
  • downloadAssets:下载配置的 Minecraft 版本的资源索引和对象,下载到用户缓存中。
  • genEclipseRuns:安装 Eclipse 运行配置并创建运行目录(如果还不存在)。
  • vscode:生成或覆盖 Visual Studio Code 的 launch.json 文件,启动配置在 .vscode 文件夹中,并创建运行目录,如果还不存在。
  • ideaSyncTask:生成(但是不会覆盖)Intellij IDEA 的启动配置,包括客户端和服务器。
  • remapSourcesJar:只有在 AbstractArchiveTask sourcesJar 存在时存在。将 sourcesJar 任务的输出重映射。
  • runClient:将 Fabric Loader 作为 Minecraft 客户端运行的 JavaExec 任务。
  • runServer:将 Fabric Loader 作为 Minecraft 专用服务器运行的 JavaExec 任务。

依赖子项目

设立依赖其他 loom 项目的多项目构建时,你应该在依赖其他项目时使用 namedElements 配置。默认情况下,项目的“输出”会映射到中间名。namedElements 配置包含还未重映射的项目输出。

dependencies {
    implementation project(path: ":name", configuration: "namedElements")
}

如果你在多项目构建中使用分离源集,你还需要为其他项目客户端源集添加依赖项。

dependencies {
    clientImplementation project(":name").sourceSets.client.output
}

分离客户端与常规代码

多年来,服务器崩溃往往是因为安装在服务器上时意外调用客户端代码。最新的 loom 和 loader 版本提供了一个选项,要求将所有客户端代码移动到其自己的源集中。这样做是为了提供编译时的保证,以防止在服务器上调用仅限客户端的 Minecraft 代码或仅限客户端的 API。在客户端和服务器上都可以使用的单个 jar 文件仍然是从两个源集构建的。

以下 build.gradle 文件片段展示了如何为您的模组启用此功能。由于您的模组现在将拆分为两个源集,因此您将需要使用新的 DSL 来定义您的模组源集。这将会让 Fabric Loader 将您的模组类路径组合在一起,对于其他一些复杂的多项目设置也有用。

要分享客户端与服务器的代码,需要 Minecraft 1.18(建议 1.19)、Loader 0.14 和 Loom 1.0 以上的版本。

loom {
	splitEnvironmentSourceSets()

	mods {
        	modid {
            		sourceSet sourceSets.main
            		sourceSet sourceSets.client
        	}
	}
 }

多项目优化

如果你的 Gradle 项目有多个子项目并使用相同的 Minecraft 版本,如 Fabric API,从 Loom 1.1 开始,你可以选择使用高级的优化。在 gradle.properties 中加入

fabric.loom.multiProjectOptimisation=true

从而减少构建时间和内存使用,因为会在重映射多个输出的 jar 时在项目之间共享 Tiny Remapper 实例。

选项

loom {
	// 设置访问加宽的路径,参见 https://fabricmc.net/wiki/zh_cn:tutorial:accesswideners
	accessWidenerPath = file("src/main/resources/modid.accesswidener")

	// 添加额外的 log4j 配置文件。
	log4jConfigs.from(file("log4j.xml"))

	// 若启用,输出的存档会自动重映射。
	remapArchives = true
	// 若启用,*Elements 配置中的 -dev jars 会被替换为重映射的 jar。
	setupRemappedVariants = true
	// 若启用,传递性的访问加宽会从依赖中应用。
	enableTransitiveAccessWideners = true
	// 若启用,log4j 只会在运行时类路径中,强制使用 SLF4j。
	runtimeOnlyLog4j = false

	// 若启用,只有与服务器有关的特性和 jars 会被设置。
	serverOnlyMinecraftJar()
	// 若设置,minecraft jar 会分为常规和仅客户端。这只是实验性的。Fabric 加载器暂时还不支持这个功能。
	splitMinecraftJar()

	// 用于配置存在的或者新的运行配置
	runs {
		client {
			// 添加 VM 变量
			vmArgs "-Dexample=true"
			// 添加 JVM 属性
			property("example", "true")
			// 添加 program 变量
			programArg "--example"
			// 需要运行的环境(或端),通常是 client 或 server。
			environment = "client"
			// 运行配置的完整名称,例如“Minecraft 客户端”。默认由基础名称决定。
			configName = "Minecraft 客户端"
			// 运行配置的默认主类。使用带有 fabric_installer.json 文件的模组加载器时,就会覆盖这个。
			defaultMainClass = ""
			// 此配置的运行目录,与根项目目录有关。
			runDir = "run"
			// 运行的源集,通常设为 sourceSets.test
			source = sourceSets.main
			// 若为 true,运行配置会为 IDE 生成。默认仅对根项目为 true。
			ideConfigGenerated = true

			// 配置以默认的客户端选项运行配置。
			client()

			// 配置以默认的服务器选项运行配置。
			server()
		}

		// 为测试创建基本运行配置的示例
		testClient {
			// 从另一个运行配置复制设置。
			inherit client

			configName = "测试 Minecraft 客户端"
			source = sourceSets.test
		}

		// 删除内置服务器配置的示例
                remove server
	}

	// 配置所有运行配置以生成 ide 运行配置。对子项目很有用。
	runConfigs.configureEach {
		ideConfigGenerated = true
	}

	// 用于配置 mixin 选项,或应用到额外的源集。
	mixin {
		// 若禁用,会使用 tiny remapper 来重映射 Mixin 而非 AP。实验性。
		useLegacyMixinAp = true
		// 设置默认的 refmap 名称
		defaultRefmapName = "example.refmap.json"

		// 关于添加额外资源集的选项,参见 https://github.com/FabricMC/fabric-loom/blob/dev/0.11/src/main/java/net/fabricmc/loom/api/MixinExtensionAPI.java
	}

	// 配置或添加新的反编译器
	decompilers {
		// 配置默认的反编译器,cfr 或 fernflower
		cfr {
			// 将额外选项传递到编译器
			options += [
				key: "value"
			]
			// 设置分叉 JVM 时使用的内存量(以兆字节为单位)
			memory = 4096
			// 设置反编译器可以使用的最大线程数。
			maxThreads = 8
		}
	}

	interfaceInjection {
		// 若启用,将会应用配置的注入的接口。
		enableDependencyInterfaceInjection = true
	}

	// 将 Minecraft jar 和传入的依赖项拆分到 main(common)和仅限客户端的源集。
	// 这可以在编译期间就确保访问仅限客户端的代码时的安全。
	splitEnvironmentSourceSets()

	// 这个 mods 语句块用于将由多个类路径的项组合在一起。
	mods {
		modid {
			// 使用分离的资源时,你应该添加 main 和 common 源集
			sourceSet sourceSets.main
			sourceSet sourceSets.client
		}
	}

	// 创建 modExampleImplementation 和重映射 mods 的相关配置。
	createRemapConfigurations(sourceSets.example)
}

remapJar {
	// 设置任务的输出 jar,同样对 remapSourcesJar 有效
	inputFile = file("example.jar")
	// 设置资源命名空间,同样对 remapSourcesJar 有效
	sourceNamespace = "named"
	// 设置目标命名空间,同样对 remapSourcesJar 有效
	targetNamespace = "intermediary"
	// 给重映射类路径添加额外的 jar,同样对 remapSourcesJar 有效
	classpath.from file("classpath.jar")

	// 将嵌套的模组 jar 添加到该任务,include 配置应该用于 maven 库和模组。
	nestedJars.from file("nested.jar")
	// 若启用,输出的 jar 中会包含嵌套的 jar。
	addNestedDependencies = true
}

dependencies {
	// 设置 Minecraft 版本。
	minecraft "com.mojang:minecraft:1.18.1"

	// 使用 maven 中的映射。
	mappings "net.fabricmc:yarn:1.18.1+build.22:v2"

	// 使用官方 mojang 映射
	mappings loom.officialMojangMappings()

	// 使用官方 mojang 映射和 parchment 的分层映射。
	mappings loom.layered() {
		officialMojangMappings()
		// 使用 parchment 映射。注意:必须手动添加 Parchment maven(https://maven.parchmentmc.org)
		parchment("org.parchmentmc.data:parchment-1.17.1:2021.09.05@zip")
	}

	// 从 maven 中重映射一个模组,并应用到 gradle 的 implementation 配置
	// (小的细节:不会准确地应用*到*配置,但是会克隆一份以用于模组依赖)
	modImplementation "net.fabricmc.fabric-api:fabric-api:0.46.2+1.18"

	// 从 maven 中重映射一个模组,并应用到 gradle 的 api 配置
	modApi "net.fabricmc.fabric-api:fabric-api:0.46.2+1.18"

	// 从 maven 中重映射一个模组,并应用到 gradle 的 compileOnly 配置
	modCompileOnly "net.fabricmc.fabric-api:fabric-api:0.46.2+1.18"

	// 从 maven 中重映射一个模组,并应用到 gradle 的 compileOnlyApi 配置
	modCompileOnlyApi "net.fabricmc.fabric-api:fabric-api:0.46.2+1.18"

	// 从 maven 中重映射一个模组,并应用到 gradle 的 runtimeOnly配置
	modRuntimeOnly "net.fabricmc.fabric-api:fabric-api:0.46.2+1.18"

	// 从 maven 中重映射一个模组,并应用到 loom 的 localRuntime 配置。
	// 和 runtimeOnly 的做法类似,但是不会暴露到依赖项中。有点像 testRuntimeOnly,不过是对于模组的。
	modLocalRuntime "net.fabricmc.fabric-api:fabric-api:0.46.2+1.18"

	// 在重映射的 jar 中包含一个模组 jar。不可传递。
	include "example:example-mod:1.1.1"

	// 在重映射的 jar 中包含一个空模组库。会生成空模组。不可传递。
	include "example:example-lib:1.1.1"

	// 根据特定的结构 api 版本提供帮助的助手。
	modImplementation fabricApi.module("fabric-api-base", "0.46.2+1.18")

	// 使用 namedElements 配置,依赖一个 loom 子项目。
	implementation project(path: ":name", configuration: "namedElements")
}

解决问题

Loom 或者 gradle 可能会由于缓存文件有问题而失败。运行 ./gradlew build –refresh-dependencies 将强制 gradle 和 loom 重新下载并重新创建所有文件。这可能需要几分钟,但是处理与缓存有关的问题时非常有用。

开发环境设置

Loom 旨在通过简单地在用户选择的 IDE 中设置工作区来开箱即用,因此背后做了很多事以创建带有 Minecraft 的开发环境:

  1. 从官方渠道下载指定版本 Minecraft 的客户端和服务器 jar。
  2. 将客户端和服务器 jar 合并到一起以生成一个合并的 jar,并加上 @Environment@EnvironmentInterface 注解。
  3. 下载配置的映射。
  4. 使用中间映射重映射合并的 jar 产生一个中间 jar。
  5. 使用 yarn 映射重映射合并的 jar 产生一个映射的 jar。
  6. 可选的:反编译映射了的 jar,产生一个映射的源 jar 和行映射,并将行映射应用到合并的 jar。
  7. 添加 Minecraft 的依赖。
  8. 下载 Minecraft 资源文件(assets)。
  9. 处理并包含模组增强的依赖。

缓存

  • ${GRADLE_HOME}/caches/fabric-loom:用户缓存,用户所有 Loom 项目共用的缓存。用来缓存 Minecraft 资源文件(assets)、jars、合并的 jars、中间 jars 和映射的 jars。
  • .gradle/loom-cache:根项目持久缓存,项目和子项目共用的缓存。用来缓存重映射的模组以及生成的包含的模组 JAR。
  • build/loom-cache:根项目构建缓存。
  • **/build/loom-cache:项目和子项目的构建缓存。

依赖配置

  • minecraft:定义用于开发环境的 Minecraft 版本。
  • mappings:定义用于开发环境的映射。
  • modCompilemodImplementationmodApimodRuntime:相当于compileimplementationapiruntime的增强型变种,用于模组依赖。会被重映射以对应开发环境,并且会移除嵌套的 JAR。
  • include:生命一个应在 remapJar 输出中包含的 jar-in-jar 依赖。该依赖配置是不可传递的。对于非模组依赖,Loom 会生成一个模组 JAR,其中 fabric.mod.json 使用模组 ID 的名称和相同版本。

默认配置

  • 应用以下插件:javaeclipseidea
  • 添加以下的 Maven 仓库:Fabric https://maven.fabricmc.net/、Mojang https://libraries.minecraft.net/ 和 Maven Central。
  • 配置 idea 扩展以排除目录 .gradlebuild.ideaout,以下载 javadocs 源,并继承输出目录。
  • 配置 idea 任务,并由 genIdeaWorkspace 任务确定。
  • 配置 eclipse 任务,并由 genEclipseRuns 任务确定。
  • 如果根项目存在 .idea 文件夹,下载资源(如果没有及时更新)并在 .idea/runConfigurations 安装 run 配置。
  • 添加 net.fabricmc:fabric-mixin-compile-extensions 以及其依赖,使用 annotationProcessor 依赖配置。
  • 配置所有的非 test JavaCompile 任务,使用 Mixin 注解处理器的配置。
  • 配置 remapJar 任务,输出名称与 jar 任务输出的相同的 JAR,然后给 jar 任务添加一个“dev”分类器。
  • 配置 remapSourcesJar 任务,以处理 sourcesJar 任务输出,如果该任务存在。
  • remapJar 任务和 remapSourcesJar 任务添加为 build 任务的依赖。
  • 配置 remapJar 任务和 remapSourcesJar 任务以在执行时将其输出添加为 archives 成品。
  • 为每个 MavenPublication (从 maven-publish 插件):
    • 手动将依赖附加到 POM 之后,以进行模组增强的依赖配置,前提是依赖配置具有 Maven 范围。

所有的运行配置都有运行目录 ${projectDir}/run 和 VM 参数 -Dfabric.development=true。运行配置的主类通常是由 Fabric 加载器 JAR 文件的根部的 fabric-installer.json 文件定义的(如果该文件包含在模组依赖中的话),但是文件可以由模组依赖定义。如果没有找到这样的文件,则主类默认为 net.fabricmc.loader.launch.knot.KnotClientnet.fabricmc.loader.launch.knot.KnotServer

客户端运行配置是使用 –assetsIndex–assetsDir 程序参数配置的,指向包含资源文件和配置的 Minecraft 版本的索引文件的 loom 缓存目录。在 OSX 上运行时,添加了 -XstartOnFirstThread VM 参数。

zh_cn/documentation/fabric_loom.txt · Last modified: 2024/08/17 11:07 by jeffreyg1228