= 创作分享 =
编程开发
【模组开发实记1】创建一个新物品(原理讲解) ...
Wu_tian

【模组开发实记1】创建一个新物品(原理讲解)

Wu_tian 于 2022-5-15 01:01 ( 2年前 ) [复制链接] [只看楼主] [打印]
1638 1
【注】本帖并不能说是完全意义上的教程片,因为我是学生的缘故,没有办法非常专注于模组的研究,最多只能将我的收获与大家一起分享。(本来想去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
在里面输入以下代码:
  1. package wutian.test.Items;

  2. import net.minecraft.world.item.Item;
  3. import net.minecraftforge.event.RegistryEvent;
  4. import net.minecraftforge.eventbus.api.SubscribeEvent;
  5. import net.minecraftforge.fml.common.Mod;

  6. @Mod.EventBusSubscriber(bus = Mod.EventBusSubscriber.Bus.MOD)
  7. public class ItemRegisterHandler {


  8.     @SubscribeEvent
  9.     public static void register(RegistryEvent.Register<Item> event)
  10.     {
  11.         event.getRegistry().registerAll(
  12.                  new Pear() //Pear为我新建的一个继承Item的类
  13.         );
  14.     }
  15. }
复制代码
其中的@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自动化的帮我们在事件总线中注册了一个类,其用代码可以等价为:
  1. public Test()//作者主类的构造函数
  2.     {
  3.         FMLJavaModLoadingContext.get().getModEventBus().register(ItemRegisterHandler.class);
复制代码
而@SubscribeEvent相当于是声明这个方法为观察者,以此让forge为这个方法变为观察者。
4.总结:
其实注册物品的内容远不止这些,有两个注册方式(这为其中一种),还有一种则使用DeferredRegistry,还有对于如何添加物品材质的,以及Item类中的各个方法该如何使用(如设置本地名、最大堆叠数等等),这些都值得我们继续去研究,今天限于时间原因,只能先写到这里。
如果有希望我能写写前面如配置环境,gradle之类的内容的话,也可以留言评论

评分

参与人数 1RF +4 Vis +2 收起 理由
QQ酱29797 + 4 + 2 好!

查看全部评分

发表于 2022-5-15 01:01:52 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式

回复 | 举报

该帖共收到 1 条回复!
北斗余晖
新人看不懂,老手不用看

评分

参与人数 1RF +2 收起 理由
QQ酱178083 + 2

查看全部评分

发表于 2022-5-15 10:42:55 | 只看该作者

回复 | 举报

百科目前不允许匿名发帖哦~ 请先 [ 登陆 ][ 注册 ] 吧~

本版积分规则

发新帖
  • 回复
  • 点评
  • 评分

[ MC百科(mcmod.cn) 除另有声明,所有开放公共编辑的内容均使用 BY-NC-SA 3.0 协议 ]

Minecraft百科CC协议
快速回复 返回顶部 返回列表