新建一个主类

新建一个包(这里是com.github.ustc_zzzz.fmltutor),并在其中新建一个类(强烈建议这个类的类名和你的Mod名称相同),这就是这个Mod的主类了。

把下面的代码抄进你新建的类中,下面我会解释为什么要这么做。

src/main/java/com/github/ustc_zzzz/fmltutor/FMLTutor.java:

package com.github.ustc_zzzz.fmltutor;

import com.github.ustc_zzzz.fmltutor.common.CommonProxy;

import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.common.Mod.EventHandler;
import net.minecraftforge.fml.common.Mod.Instance;
import net.minecraftforge.fml.common.SidedProxy;
import net.minecraftforge.fml.common.event.FMLInitializationEvent;
import net.minecraftforge.fml.common.event.FMLPostInitializationEvent;
import net.minecraftforge.fml.common.event.FMLPreInitializationEvent;

/**
 * @author ustc_zzzz
 */
@Mod(modid = FMLTutor.MODID, name = FMLTutor.NAME, version = FMLTutor.VERSION, acceptedMinecraftVersions = "1.8.9")
public class FMLTutor
{
    public static final String MODID = "fmltutor";
    public static final String NAME = "FML Tutor";
    public static final String VERSION = "1.0.0";

    @Instance(FMLTutor.MODID)
    public static FMLTutor instance;

    @EventHandler
    public void preInit(FMLPreInitializationEvent event)
    {
        // TODO
    }

    @EventHandler
    public void init(FMLInitializationEvent event)
    {
        // TODO
    }

    @EventHandler
    public void postInit(FMLPostInitializationEvent event)
    {
        // TODO
    }
}

packageimport部分含义显而易见。

src/main/java/com/github/ustc_zzzz/fmltutor/FMLTutor.java(部分):

@Mod(modid = FMLTutor.MODID, name = FMLTutor.NAME, version = FMLTutor.VERSION, acceptedMinecraftVersions = "1.8.9")

上面这一行是Java从JDK1.5引入的一种机制:注解。注解的功能类似于代码中的注释,不同的是,注解不仅提供代码功能的说明,还是实现程序功能的重要组成部分。Java注解已经在很多框架中得到了广泛的使用,用来简化程序中的配置。

比如下面三个最常见的注解:

  • @Override 用于声明该方法覆写了父类方法,使用该注解,如果(由于拼写错误等)没有覆写,编译器会报错
  • @SuppressWarning 用于显式忽略警告,使用该注解,编译器不会产生对应代码的警告
  • @Deprecated 用于标记一个方法不应该再被使用,使用该注解,如果在代码中调用了该方法,编译器会产生一个警告

因为注解中可以添加键-值对,所以动态查看一个注解的内容是有意义的,也是可行的。比如这个注解,FML在加载这个Mod的时候,就会去自动寻找含有@Mod注解的类,并读取下面的数据:

  • modid指的就是该Mod的唯一标识符
  • name指的是该Mod的名称
  • version指的是该Mod的版本号,在Mod间的依赖关系时可能会用作识别
  • acceptedMinecraftVersions指的是Mod接受的Minecraft版本,当版本不对时,FML会优雅地抛出一个错误而不是继续加载这个Mod

acceptedMinecraftVersions约定的版本声明如下:

  • 1.8.9(本教程)表示该Mod只支持Minecraft 1.8.9
  • [1.8,1.9)表示该Mod支持从1.8(包含)到1.9(不包含)的所有Minecraft版本
  • [1.8,1.10]表示该Mod支持从1.8(包含)到1.10(包含)的所有Minecraft版本
  • [1.8,)表示该Mod支持从1.8(包含)之后出现的所有Minecraft版本
  • (,1.8],[1.9,)表示该Mod支持1.8(包含)之前出现的所有Minecraft版本和从1.9(包含)之后出现的所有Minecraft版本

当然这个注解也有着其他数据(没有声明的数据作为默认值),比如该Mod依赖于什么Mod等等,有些比较有必要的数据会在后面部分讲到。

下面的三个方法带有@EventHandler注解,它们的作用也是类似。Forge在找到这个类后,会检查这个类中所有含有@EventHandler注解的方法,并通过方法的参数类型来判定到底应该在何时调用它们:

  • 含有FMLPreInitializationEvent参数的方法(这里是preInit)在所有Mod初始化之前调用,这时候应该加载配置文件,实例化物品和方块,并注册它们
  • 含有FMLInitializationEvent参数的方法(这里是init)用于该Mod的初始化,这时候应该为Mod进行设置,如注册合成表和烧炼系统,并且向其他Mod发送交互信息
  • 含有FMLPostInitializationEvent参数的方法(这里是postInit)在所有Mod都初始化之后调用,这时候应该接收其他Mod发送的交互信息,并完成对Mod的设置

有些Mod会把注册方块、物品等等操作放在Mod初始化阶段完成,这种做法是不推荐的,Forge推荐在preInit阶段完成

@Instance注解的作用是将生成的该Mod的实例,注册到对应的Mod的id,同时,也可以访问其他Mod的id对应的实例,当然,这里的id要和本Mod的id相同

代理?那是什么

众所周知,Minecraft Mod有客户端和服务端两种使用方式,而两种方式的差异足够大使得Mod需要采用两种初始化方式,而两种方式的差异又足够小使得Mod没有必要制作客户端和服务端两个版本。这时候代理便起到了区别两种初始化方式的作用。在单机运行时,Minecraft也会生成一个本地服务端。服务端和客户端之间的差异十分复杂,甚至很多都只是经验之谈,然而有一点往往是通用的,服务端的代码,往往客户端都会执行

在主类中添加以下代码:

src/main/java/com/github/ustc_zzzz/fmltutor/FMLTutor.java(部分):

    @SidedProxy(clientSide = "com.github.ustc_zzzz.fmltutor.client.ClientProxy", 
            serverSide = "com.github.ustc_zzzz.fmltutor.common.CommonProxy")
    public static CommonProxy proxy;

Forge会在加载Mod的时候自动使用上面的类名对这个代理进行实例化。

当然,我们需要创建上面所说的CommonProxy,和ClientProxy

新建一个包com.github.ustc_zzzz.fmltutor.common,在其中新建一个类CommonProxy

src/main/java/com/github/ustc_zzzz/fmltutor/common/CommonProxy.java:

package com.github.ustc_zzzz.fmltutor.common;

import net.minecraftforge.fml.common.event.FMLInitializationEvent;
import net.minecraftforge.fml.common.event.FMLPostInitializationEvent;
import net.minecraftforge.fml.common.event.FMLPreInitializationEvent;

public class CommonProxy
{
    public void preInit(FMLPreInitializationEvent event)
    {

    }

    public void init(FMLInitializationEvent event)
    {

    }

    public void postInit(FMLPostInitializationEvent event)
    {

    }
}

新建包com.github.ustc_zzzz.fmltutor.client,新建类ClientProxy,并继承类CommonProxy

src/main/java/com/github/ustc_zzzz/fmltutor/client/ClientProxy.java:

package com.github.ustc_zzzz.fmltutor.client;

import com.github.ustc_zzzz.fmltutor.common.CommonProxy;

import net.minecraftforge.fml.common.event.FMLInitializationEvent;
import net.minecraftforge.fml.common.event.FMLPostInitializationEvent;
import net.minecraftforge.fml.common.event.FMLPreInitializationEvent;


public class ClientProxy extends CommonProxy
{
    @Override
    public void preInit(FMLPreInitializationEvent event)
    {
        super.preInit(event);
    }

    @Override
    public void init(FMLInitializationEvent event)
    {
        super.init(event);
    }

    @Override
    public void postInit(FMLPostInitializationEvent event)
    {
        super.postInit(event);
    }
}

主类的调整:

src/main/java/com/github/ustc_zzzz/fmltutor/FMLTutor.java(部分):

    @EventHandler
    public void preInit(FMLPreInitializationEvent event)
    {
        proxy.preInit(event);
    }

    @EventHandler
    public void init(FMLInitializationEvent event)
    {
        proxy.init(event);
    }

    @EventHandler
    public void postInit(FMLPostInitializationEvent event)
    {
        proxy.postInit(event);
    }

很明显,当服务端被初始化时,CommonProxy类中对应方法会被调用,如果是客户端,ClientProxy类中对应方法会被调用,这样我们就可以实现服务端和客户端的差异。

完善你的Mod信息

一个Mod的信息在其jar根目录下的mcmod.info文件里,这里是src/main/resources/mcmod.info,打开就可以完善你的Mod信息。注意:versionmcversion字段不应修改,它们会在Gradle构建Mod的时候被自动替换掉。你应该更改build.gradle文件。

比如,本教程的mcmod.info文件是这个样子的:

src/main/resources/mcmod.info:

[
{
  "modid": "fmltutor",
  "name": "FML Tutor",
  "description": "A Minecraft 1.8 Forge Mod Loader Tutorial by ustc_zzzz.",
  "version": "${version}",
  "mcversion": "${mcversion}",
  "url": "https://github.com/ustc-zzzz/fmltutor/wiki",
  "updateUrl": "https://github.com/ustc-zzzz/fmltutor/tags",
  "authorList": ["ustc_zzzz"],
  "credits": "Notch, Cpw, etc.",
  "logoFile": "",
  "screenshots": [],
  "dependencies": []
}
]

results matching ""

    No results matching ""