MCBBS Wiki欢迎您共同参与编辑!在参与编辑之前请先阅读Wiki方针

如果在编辑的过程中遇到了什么问题,可以去讨论板提问。

为了您能够无阻碍地参与编辑 未验证/绑定过邮箱的用户,请尽快绑定/验证

MCBBS Wiki GitHub群组已上线!

您可以在回声洞中发表吐槽!

服务器状态监控。点击进入

本站由MCBBS用户自行搭建,与MCBBS及东银河系漫游指南(北京)科技有限公司没有从属关系。点此了解 MCBBS Wiki 不是什么>>

用户:MashKJo/1.12.2模组开发教程/3.Mod主类与代理详解

来自MCBBS Wiki
MashKJo留言 | 贡献2024年12月3日 (二) 19:54的版本
(差异) ←上一版本 | 最后版本 (差异) | 下一版本→ (差异)
跳到导航 跳到搜索

从这一节开始,我们终于可以真正地写代码了!

你可能会注意到,在路径src/main/java路径下有com.example.examplemod这个包,在这个包里有个文件ExampleMod.java。这是Forge给你做的示例,删掉即可。

然后你再根据你的项目具体情况创建一个新的包,由于笔者要写的是Mod开发教程的示例代码,因此笔者把包名定为net.tutorial_mod,并在该包下创建Mod主类源文件:

src/main/java/net/tutorial_mod/TutorialMod.java:

package net.tutorial_mod;

import net.minecraftforge.fml.common.Mod;
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;

@Mod(modid = TutorialMod.MODID, name = TutorialMod.NAME, version = TutorialMod.VERSION)
public class TutorialMod{
   public static final String MODID = "tutorial_mod";
   public static final String NAME = "Tutorial Mod";
   public static final String VERSION = "1.0";

   @Mod.Instance
   public static TutorialMod INSTANCE;

   @SidedProxy(clientSide = "net.tutorial_mod.client.ClientProxy", serverSide = "net.tutorial_mod.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);
   }
}

src/main/java/net/tutorial_mod/CommonProxy.java:

package net.tutorial_mod;

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){

   }
}

src/main/java/net/tutorial_mod/client/ClientProxy.java:

package net.tutorial_mod.client;

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

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主类打上了@Mod这个注解,这个注解用于告知FML:这个类是一个Mod的主类,这里我们还传入了三个参数:modid、Mod的英文名称和Mod的当前版本,且这三个参数实际上以静态字段的形式存在于我们的Mod主类中。其中,modid要求只包含小写字母、数字、下划线,且长度不得超过64个字符。FML会自动将这个类实例化。

不过我们有的时候还需要获取我们的模组主类的实例,这个时候,@Mod.Instance的作用就体现出来了:它会将相应的对象赋给被它修饰的字段。

那么,Mod.EventHandler的作用又是什么?这牵扯到后面的事件的相关知识。不过这里先提一下:这三个被它修饰的方法实际上都是事件监听器,分别对应FML加载Mod的三个阶段:PreInitialization、Initialization和PostInitialization。在这三个阶段中,FML会自动执行对应监听器中的代码。注意:按照约定俗成的一个惯例,跨Mod交互应该在PostInitialization阶段完成。

所以那个proxy又是什么?这是为了区分物理端之间的不同而出现的。我们要让我们的模组做到在物理客户端和物理服务端上的表现不同,比如:不在物理服务端进行渲染操作。所以我们使用@SidedProxy注解给proxy字段自动赋值,FML会根据当前物理端决定到底实例化哪个类并赋给它,而Mod主类中的三个监听器方法全部代理给proxy来做,本身看不见任何实现。

可能有读者会疑惑:怎么没有ServerProxy,而是给物理服务端用CommonProxy?之前说过,我们的模组里不该有@SideOnly(Side.SERVER)的代码啊,所以实际上物理服务端该执行的代码,物理客户端一定会执行。因此,直接给物理服务端用CommonProxy就行。

另外,读者应该注意到了,ClientProxy.java被笔者新建了一个文件夹client来存放。这种只在物理客户端有意义的类,通常就会放在client文件夹中,这是一个好习惯。