【注】本帖并不能说是完全意义上的教程片,因为我是学生的缘故,没有办法非常专注于模组的研究,最多只能将我的收获与大家一起分享。(本来想去MCBBS试试结果改密码愣是改不了。。)
在配置完配置后,我们的第一部内容便是创建第一个属于自己的物品。这就相当于是学习编程语言的第一句话Hello World吧,不过创建物品里内在的学问却复杂了很多。要详细的了解一个物品是怎么被创建的,首先要知道Minecraft的事件系统。
1.什么是事件系统?
事件系统实际上是一种设计模式,即观察者模式。就好比一个监控摄像头一直看着某个人的一举一动,当那个人做了特定的事情后,他的行为会转变为信息并传递给观察者,最后监控对应获取的信息作出相应的回应。
在我的世界中,也是如此,我的世界中分两种事件线:
一种是 FML Mod 加载事件,在 FMLJavaModLoadingContext.get().getModEventBus() 中注册;另一种是游戏内事件,在 MinecraftForge.EVENT_BUS 中注册。·一下用Mod总线来称第一个FML加载总线,Forge总线来称第二个游戏内事件
接下来再展示下我的世界的mod加载顺序:
LifeCycleEvent:CONSTRUCT (不能监听)
这里是执行你的 Mod 主类的构造函数
用来注册事件侦听器
Mod.EventBusSubscriber 注解的事件侦听器也是在这时候被注册的
在这里注册 Mod 的 配置文件
RegistryEvent.NewRegistry
用于新建 Registry
RegistryEvent.Register<T>
这里 T 是注册项的基类
具体顺序:引用自 Forge 文档
RegistryEvents are currently supported for the following types: Block, Item, Potion, Biome, SoundEvent, PotionType, Enchantment, IRecipe, VillagerProfession, EntityEntry
最后是 Mod 自定义的 Registry
不建议用事件的 register 方法注册,建议使用 DeferredRegister 注册
DeferredRegister<T> 开始注册,并为 RegistryObject<T> 填充实例
生成、读取 Mod 配置文件(无事件)
先生成 Client 的配置文件
后生成 Common 的配置文件
FMLCommonSetupEvent
Capability 在这时注册
LifecycleEvent:SIDED_SETUP
这里区分启动的端,如果是服务端,则触发 FMLDedicatedServerSetupEvent
如果是客户端,则触发 FMLClientSetupEvent
Forge Version Check
这里会检查 Forge 和 Mod 的版本是否为最新
InterModEnqueueEvent
InterModProcessEvent
FMLLoadCompleteEvent
冻结所有的 Registry (无事件)
这之后,所有的 Registry 将不能变动
进入游戏主界面
--------摘抄自https://blog.csdn.net/qq_41228599/article/details/107463365
今天的任务是注册一个物品,所以我们用到的事件线只有Mod总线。
2.如何声明观察者/监听者(Listenr)
在编程中在事件总线中注册观察者并非一件难事,我们可以用注解(Annotation)来标记类或其下的方法,来让forge自动注册监听者,举个例子,我们在新建的Items文件夹下创建ItemRegistryHandler.class
在里面输入以下代码:
- package wutian.test.Items;
- import net.minecraft.world.item.Item;
- import net.minecraftforge.event.RegistryEvent;
- import net.minecraftforge.eventbus.api.SubscribeEvent;
- import net.minecraftforge.fml.common.Mod;
- @Mod.EventBusSubscriber(bus = Mod.EventBusSubscriber.Bus.MOD)
- public class ItemRegisterHandler {
- @SubscribeEvent
- public static void register(RegistryEvent.Register<Item> event)
- {
- event.getRegistry().registerAll(
- new Pear() //Pear为我新建的一个继承Item的类
- );
- }
- }
复制代码 其中的@Mod.EventBusSubscriber注解是用来修饰类的,它拥有3个常用属性,value、bus、modid。
其中modid最好理解,它是String类型的属性。声明这个事件检听是属于哪个mod的,并且是可选的,这是官方文本:
Optional value, only necessary if this annotation is not on the same class that has a @Mod annotation. Needed to prevent early classloading of classes not owned by your mod.
也就是说是为了防止报错的。
而bus代表的是要将观察者注册在哪个事件总线中,属于枚举类型(ENUM),Mod.EventBusSubscriber.Bus.MOD为Mod总线,而Mod.EventBusSubscriber.Bus.FORGE为Forge总线。默认值是FORGE总线。
最后的value是Dist(也是枚举类)的数组类型,枚举选择为Dist.CLIENT和Dist.DEDICATED_SERVER。其默认值为{Dist.Client,Dist.DEDICATED_SERVER}
不过我们既然是注册物品,只需要把bus改为Mod总线就行了。
至于@SubscribeEvent注解嘛,这是用于修饰方法的,凡是被他修饰的方法,只要有特殊的形参,就可以作为观察者被注册入总线。
在这里还有一个值得注意的,就是@SubscribeEvent只能用来修饰静态的方法。
3.注解是如何运作的
实际上,@Mod.EventBusSubscriber.Bus.MOD可以说是forge自动化的帮我们在事件总线中注册了一个类,其用代码可以等价为:
- public Test()//作者主类的构造函数
- {
- FMLJavaModLoadingContext.get().getModEventBus().register(ItemRegisterHandler.class);
复制代码 而@SubscribeEvent相当于是声明这个方法为观察者,以此让forge为这个方法变为观察者。
4.总结:
其实注册物品的内容远不止这些,有两个注册方式(这为其中一种),还有一种则使用DeferredRegistry,还有对于如何添加物品材质的,以及Item类中的各个方法该如何使用(如设置本地名、最大堆叠数等等),这些都值得我们继续去研究,今天限于时间原因,只能先写到这里。
如果有希望我能写写前面如配置环境,gradle之类的内容的话,也可以留言评论
|