Minecraft 1.12.2 Mod开发笔记——基础概念

Forge是什么

  • Minecraft是商业软件,源代码不公开
  • MCP项目反编译了Minecraft,为我们提供了Minecraft的“源代码”,即便并不是Mojang工作室写的那样
  • Forge是MinecraftForge和Forge Mod Loader(FML)的总称。MinecraftForge基于MCP,提供了Minecraft中的各种机制的实现接口,如事件系统,物品注册等等。而FML,顾名思义,Mod加载器,开始游戏加载界面右下角不断敲打的铁砧就是它了。

Side

Minecraft拥有双客户端/服务端的结构,具体来说,就是:

  • Minecraft有显然的物理客户端,即我们运行的Minecraft本体,还有显然的物理服务端,即多人服务器运行的server.jar。
  • 在每一个物理客户端内部,还有所谓的逻辑客户端和逻辑服务端,比如,所有的游戏逻辑放在逻辑服务端,而实体渲染等放在逻辑客户端。

事件

和 Java 中 AWT 和 Swing 类似,Minecraft 中的行为也是事件驱动的,我们需要为事件挂载事件监听器,当相应事件触发时,对应的监听器中的代码就会执行。

Mod开发中有两大类事件:

  1. FML事件(FML 生命周期)

    主要分为 preinit,init 和 postinit 等,顾名思义,就是加载 Mod 的三个阶段,通常来讲,preinit 阶段进行物品、方块等的注册,init 阶段进行合成表的注册,postinit 进行 Mod 之间的关联处理。

  2. Forge事件

    Forge 事件需要挂载到事件总线上,主要有:

    • 一般事件总线(MinecraftForge.EVENT_BUS)
    • 矿物生成总线(MinecraftForge.ORE_GEN_BUS)
    • 地形生成总线(MinecraftForge.TERRAIN_GEN_BUS)

    挂载方法:

    EventListener 类

    @SubscribeEvent
    public static void onSomeEventHappened(AEvent event) {
        // 当然这个 AEvent 要换成某个存在的事件。
    }
    // 注册
    MinecraftForge.EVENT_BUS.register(EventListener.class);

    或者

    @SubscribeEvent
    public void onSomeEventHappened(AEvent event) {
        // 当然这个 AEvent 要换成某个存在的事件。
    }
    // 注册
    MinecraftForge.EVENT_BUS.register(new EventListener());

    有没有感觉很熟悉呢?

    public void actionPerformed(ActionEvent e){
        // TODO
    }
    new JButton().addActionListener(this);

    个人认为,Minecraft Forge 的事件系统就可以类比 AWT/Swing 里的监听器来理解。

    其中,注解 @SubscribeEvent 表明下面的方法是一个事件监听器,也就是说监听器方法的名字不是固定的,监听的事件由参数指定。

    此外,也可以这么写,用于将事件直接注册到 EVENT_BUS 上:

    // 这个注解的意思是“将这个类注册到事件总线中去,该事件监听器属于 mymod 这个 Mod”
    // 它相当于 MinecraftForge.EVENT_BUS.register(MyEventListener.class)
    @Mod.EventBusSubscriber(modid = "mymod")
    public final class MyEventListener {
        @SubscribeEvent
        public static void onEventFired(ACertainEvent event) {
    
        }
    }

Mod的基本框架

  1. 首先,在src/main/java/目录下新建项目所在包,比如 moonfan.mymod
  2. 在mymod包内新建Java类,建议类名即Mod名的驼峰命名形式,这就是Mod的主类了,这里就是 MyMod.java 。
  3. 复制以下代码,包名和modid自行修改。

    MyMod.java

     @Mod(modid = MyMod.MODID, name = MyMod.NAME, version = MyMod.VERSION, acceptedMinecraftVersions = "1.12.2")
     public class MyMod {
         public static final String MODID = "mymod";
         public static final String NAME = "My Mod";
         public static final String VERSION = "1.0.0";
    
         @Mod.Instance(MyMod.MODID)
         public static MyMod instance;
    
         @SidedProxy(clientSide = "moonfan.mymod.client.ClientProxy",
                 serverSide = "moonfan.mymod.common.CommonProxy")
         public static CommonProxy proxy;
    
         @Mod.EventHandler
         public void preInit(FMLPreInitializationEvent event) {
             proxy.preInit(event);
         }
         @Mod.EventHandler
         public void init(FMLInitializationEvent event) {
             proxy.init(event);
         }
         @Mod.EventHandler
         public void postInit(FMLPostInitializationEvent event) {
             proxy.postInit(event);
         }
     }
  • @Mod 和 @Mod.Instance 注解对mod信息进行引用
  • 前面介绍了Forge中的Side概念,@SidedProxy即为对Common(Server)和Client的引用,这是之后要创建的两个类。
  • 前面介绍了Forge的事件系统,@Mod.EventHandler 则标识了三个FML事件,三个方法分别对应三个事件,调用proxy的对应方法。
  1. 新建 moonfan.mymod.common.CommonProxymoonfan.mymod.client.ClientProxy 类,且ClientProxy继承自CommonProxy:

    CommonProxy.java

     public class CommonProxy {
         @Mod.EventHandler
         public void preInit(FMLPreInitializationEvent event) {
             // TODO
         }
         @Mod.EventHandler
         public void init(FMLInitializationEvent event) {
             // TODO
         }
         @Mod.EventHandler
         public void postInit(FMLPostInitializationEvent event) {
             // TODO
         }
     }

    ClientProxy.java

     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);
         }
     }

这样,Mod的基本框架完成了。

上一篇:Minecraft 国际版 无法登录 xbox live


下一篇:Minecraft 1.12.2 Mod 开发笔记