2.3 第一个Mod的构建与运行
2.3.1 运行Mod
众所周知,在通常情况下,一个Mod的发布,往往要支持多人联机(即服务端)。因此运行Mod也有两个选择:依赖Minecraft客户端启动,或者依赖Minecraft服务端启动。
在控制台输入下面两个命令中的一个:
runClient用于启动客户端,runServer用于启动服务端。如果你使用的不是Windows系统,而是Linux或者macOS,那么同样请把gradlew.bat换成./gradlew。
依赖控制台,除了使用命令行启动,也可以在IDE中启动。IntelliJ IDEA支持基于IDE本身直接执行相关任务,Eclipse的相关操作也应大同小异。按下Ctrl+Shift+A组合键,打开执行相关任务的选项框,并在搜索框中输入Execute并选择Execute Gradle Task(执行Gradle任务)。
然后我们会看到IntelliJ IDEA弹出一个界面。在其中Command line处输入待执行的任务,也就是runClient或者runServer。
耐心等待就能看到IntelliJ IDEA启动游戏了。
只要执行过一次相关的任务,IntelliJ IDEA便会在其主界面右上角的选项框自动添加相关的选项和相应的快捷按钮。选项本身是可以编辑的。
可以给执行任务选项换个诸如Minecraft Client等更有意义的名字。
2.3.2 Mod源文件的文件结构
我们这次把目标投向IntelliJ IDEA的Project栏,并注意其中的src目录。Mod的源代码、资源文件等描述Mod行为逻辑和外观的文件将全部位于这个目录下。
src/main/java目录存放Mod的Java源代码。
src/main/resources目录存放Mod的资源文件。
Mod的资源文件包括但不限于方块物品材质、模型、声音、语言文件(方便国际化)等,大部分的文件结构和材质包的结构差不多。资源文件中有一个名为mcmod.info的文件,位于资源文件夹的根目录,是描述Mod的关键文件,里面存放着Mod的若干相关信息,后续章节会再次提到。这个目录中还有一个名为pack.mcmeta的文件,这是由于FML是将Mod中的资源文件以材质包的方式加载的,这个文件是材质包的描述文件。
再来讲Java源代码。Java源代码是以包(Package)的形式来组织的。包的通常表现形式就是由小数点分隔的一系列字符串的集合。比如上图中com.example.examplemod就是一个包。包可以是其他包的子包(SubPackage),比如com.example.examplemod就是com.example的子包,而com.example就是com的子包。包之间通过子包的关系形成一个树形结构,这个树形结构在源代码中是以文件目录树的形式展现的。如包com.example.examplemod代表com/example/examplemod目录。
在Java中,大量的代码都是以包的形式组织的,比如:
● Java官方提供的很多代码都位于java包下,作为java包的子包,如java.lang、java.util等。
● 所有和Minecraft有关的代码都位于net.minecraft包下,而所有和MinecraftForge有关的代码都位于net.minecraftforge包下,其中有一个名为net.minecraftforge.fml的子包,存放的是所有FML的代码。
在通常情况下,为方便开发者使用,一些被认为有通用用途的,位于若干个包中的代码会打包压缩,形成了我们熟知的JAR(Java Archive,Java归档文件),并被开发者作为第三方代码库引用,在通常情况下,位于同一个JAR里的包都是同一个包的子包。实际上,读者也很容易想到,写出来的Mod代码也会以JAR的形式打包压缩。对于包的命名,为尽可能避免两部分功能不同的代码包名相同,包名通常以倒置的域名开头,比如:
● Minecraft官方网站的域名是minecraft.net,其包名均以net.minecraft开头。
● MinecraftForge官方网站的域名是minecraftforge.net,其包名均以net.minecraftforge开头。
● Google提供的一些第三方库的包名均以com.google开头,后面偶尔能够遇到在这一包名下的代码。
● Forge提供的示例Mod包名以com.example开头,因为example.com是专门作为示例网站使用的保留域名。
如果不存在域名,或者不方便使用域名,那么通常包名会以项目名称开头,如刚刚提到的包名以java开头的代码。有时会以“作者名称/id+项目名称”开头,实际上,大量的Mod使用的就是这两种方式。
包名通常有以下规定:
● 包名不应该使用数字和小写字母之外的字符,包名由小数点分隔的每一节的第一个字符不应该是数字。
● 如果包名的每一节中有多个单词,那么应该简单地拼接在一起,而不应使用下画线等字符分隔。
比如,blusunrize.immersiveengineering就是一个很好的包名,代表这个Mod名为ImmersiveEngineering(沉浸工程),其作者是BluSunrize。而Reika.RotaryCraft,就是不合适的包名,因为其出现了大写字母。
那么,把包名修改为一个更合适的名字显然会更好。作者使用的是zzzz.fmltutor。这时候我们使用IDE的一个简单的功能:修改名字。这里以IntelliJ IDEA为例,Eclipse的使用方法大同小异。
右击出现com.example.examplemod的地方,然后把鼠标移动到Refactor(重构)。
能够在Refactor的下级菜单中找到Rename(重命名),单击Rename,在弹出的对话框中输入想要修改的包名就完成了。
可能还有一个名为com.example的空包,删除(Delete)就可以了。
能够察觉到IDE在这里的优势:把一些常用的、十分频繁的,但完成步骤特别多的,而且还容易出错的操作集中起来,变成只要单击几下鼠标,敲敲键盘就可以搞定的。在大部分情况下,这些操作的主要目的是让代码结构更清楚,条理更清晰。这类操作有一个统称:重构(Refactor),在后面还会遇到更多这样的操作。
2.3.3 构建Mod
打开控制台,输入下面这一命令:
当然,如果你不是Windows用户,那么同样按照前面提到的做法,把gradlew.bat换成./gradlew。直到出现BUILD SUCCESSFUL的字样时去build\libs目录下查看:
理论上应该有两个文件,以source.jar结尾的是源代码,不需要发布,而另一个文件,就可以发布并且放进mods目录下作为Mod运行。如果想把这两个文件和一些相关的生成文件清除,那么请执行以下的命令:
该命令通常会将build目录直接删除,从而实现文件清除。