====== Minecraft 模组编写基础 ====== //注意:本页假定你没有任何编写模组的经验。但是,你应该先会一点 Java 语言以使用 Minecraft(参见“前提”段落)。如果你是从其他模组加载器(如 Forge)来的,可以直接阅读 [[introduction]]。// 本文档是给模组编写的初学者使用的,比如还不知道 ''BlockState'' 和 ''BlockPos'' 的玩家。如果你有编写数据包的经验并想要将技巧提升到更高水平,或者需要学习面向对象的语言并开启一个有趣的项目,那么本文档适合你。首先从你需要了解的几个概念开始: ===== Minecraft 模组编写的前提 ===== * 你必须知道代码编写的基础。如果你从没接触过代码,你应该先知道如何使用代码。这里所说的基础,包括变量、函数、类和方法等,以及一些面向对象的概念,如继承、多态、类型强转。要是不知道,先搜索。 * 你应该要有一些编程语言的经验,例如 Java、C、C++ 和 C#。Java 的语法和 C 系列的比较类似。 * 熟悉 Java 的语法,例如 lambda 方法、泛型(你应该知道这些是什么),以及一些语法糖,这些语法应该会在学习的时候一并遇到。 * 你必须知道如何使用 Internet 查找问题与答案,以及如何在网络论坛或者群里提问求助。 ===== 模组编写是什么? ===== 模组编写(Modding)是指的往程序的源代码里面**增添**或者**修改**内容,这个程序就是指的 Minecraft。你制作的所有模组都需要增添或者修改内容。 ===== Fabric 是什么? ===== Fabric 是一系列用于编写 Minecraft 模组的工具,包括: * **Fabric Loader**-- 往基于 Java 的游戏(如 Minecraft)加载修改后的代码的框架。 * **Fabric Loom**,用于使用 Fabric 编写模组的构建系统 * Fabric 的 **语言模块** 允许你使用其他的 JVM 语言(例如 Kotlin 或 Scala)来编写你的模组。注意:建议初学者还是先从 Java 开始,因为 Minecraft 就是用这种语言编写的,Java 也是最容易寻求帮助的。 * **Fabric API**-- 一系列能让添加或修改 Minecraft 共同特性更简单的工具。 * **Fabric Installer**-- 将 Fabric Loader 安装到最终用户的 Minecraft 安装的工具。 为了更好的理解 Minecraft 的代码干了什么,当你使用 Fabric 进行模组编写时,你有机会接触到 Minecraft 的源代码。由于 Java 是编译型语言,我们需要反编译来获得我们能够读懂的代码。这一过程会将它从 Java 字节码转变为人类可读的 Java 源代码。然而,为了阻止盗版,Mojang **混淆** 了 Minecraft 的代码。这意味着代码中所有的类、方法和字段的名称是随机的。你可以通过 zip 解压工具中打开 Minecraft 的 .jar 文件亲眼看到这一点 —— 所有的文件都会以类似 ''abc.class'' 的形式出现。此外,我们无法保证两个版本同一个对象拥有相同的名称 —— 可能上个版本还是 ''abc'',下个版本就是 ''adb'' 了。所以这使得在不知道对象名称的情况下修改游戏十分困难,因为我们无法知道不同变量的作用。为了解决这个问题,Fabric 使用了一套映射工具来给所有东西起一个人类可读的名称。 * **intermediary **映射器是一个程序,它将会给予 Minecraft 源码中所有被混淆的对象一个名称,类似 “field_10832” 和 “method_12991()”。关键的是,这个程序将总是给予一个对象相同的名称,所以一个在不同版本之间没有变化的方法将总是会拥有相同的中介名称。 * **Yarn** 是反混淆过程中的最后一步。Yarn 是一个自由的、开源的社区驱动的 Minecraft 中所有方法和类的名称库。当你看 Minecraft 的源代码时,对于任何类、变量或方法,描述其作用的名称都是由 Yarn 编写的。社区中会有人分析并决定为其命名。每次有新的更新或快照出现时,社区就会开始工作,梳理代码,看看有哪些新的对象需要命名。((注意:虽然 Mojang 发布了所有 Minecraft 版本的官方映射,但在模组编写中使用这些映射的合法性在未来可能会改变。而 Yarn 映射是自由的,每个人都可以使用,并且足以满足大多数模组编写的目的,所以不鼓励你使用官方的映射。)) 但是,在反编译的 Minecraft 代码库中,并不是所有的对象都被 Yarn 映射了 —— 有时你会看到一些变量仍然有中介名称。如果你弄清楚了它们的作用,你可以为 Yarn 贡献一个名称((关于官方映射的另一个说明:不要通过查询官方映射来帮助 Yarn 映射。这很可能违反了知识产权法 —— **所有的 Yarn 映射必须是原创的,并且是独立于 Mojang 的。**))。查看 [[mappings]] 页面,了解更多关于使用和贡献映射的信息。 ===== 代码结构 ===== Minecraft Java 版是一个巨大的项目,多年来的代码都是建立在彼此之上的。它可能看起来很混乱(因为它就是的),但有几个关键的概念是(大部分)一致的,贯穿始终。 ==== 注册表 ==== 很多游戏中的(方块、物品、UI、实体、区块生成器等的)“特性”(你想添加的)在游戏被加载时候将会被加载进注册表。比如,每一个''物品''类型都有一个静态的实例,这些实例将在游戏开始的时候被初始化,接着就会被加载进物品类型的注册表。游戏使用这些实例去获取物品类型的 ''ItemStack''(所持有物品在物品栏中的内存表示)属性。**如果你要添加一些对象到游戏内,你可能需要注册它。**然而,这条规定也有例外:Minecraft 中的一些功能是**数据驱动的**,这意味着它们可以纯粹地用数据(而不是代码)来定义。如果你想知道为什么数据包可以添加一些对象而有些对象不行,这就是原因:数据包只能添加数据驱动的内容。例如在 Minecraft 中,数据驱动的内容包括生物群落、纹理、*一些*区块生成器和制作配方。当一个带有数据包的世界被加载时,游戏会自动将这些功能添加到一个特殊的暂存器中,只会在该世界被加载完毕后使用。如果你以前开发过数据包,你可以非常容易地将数据包整合到你的模组中,这使得一些内容更容易创建。你甚至可以添加你自己的数据驱动规则,从而其他人可以使用 Codecs 为其制作数据包。 ==== 端 ==== Minecraft 运行在两个线程上,通常称为 "端":服务器端和客户端。客户端总是运行在玩家的电脑上,处理渲染和输入。服务器端可以在专用服务器上独立运行(你可能认为是“Minecraft 服务器”),或者在单人游戏中,与客户端一起在玩家的计算机上运行,作为一个集成服务器。服务器端处理客户端没有处理的一切 —— 物品栏、世界本身,等等。客户端和服务器端必须就某些事情达成一致:世界上有哪些区块,箱子里有什么,玩家的位置等等。由于这些都是由服务器端处理的,所以它向客户端规定这些值应该是什么,而客户端则向玩游戏的人展现这些值。任何由客户端处理的东西都不需要告诉服务器 —— 这包括区块和实体的样子(资源包),以及如何绘制世界(着色器)。这就是客户端模组(如着色器)、服务器端模组(如那些运行小游戏的模组)和双方模组(那些添加机器或新方块和物品的模组)之间的区别。重要的是,不要在服务器端上调用只针对客户端的代码(即与渲染有关),而在客户端调用只针对服务器端的代码。这就是你在 Minecraft 模组制作中经常看到的无处不在的 ''world.isClient()'' 检查的原因。 ===== 下一步 ===== 一旦你达到了先决条件并阅读了本文档,就可以开始了!查看 [[introduction]] 介绍以更深入了解 Fabric 这个平台,阅读 [[setup]] 文档以设置 IDE 来修改 Minecraft,然后前往 [[items]] 教程来添加第一个物品!