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

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

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

MCBBS Wiki GitHub群组已上线!

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

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

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

用户:MashKJo/1.12.2模组开发教程/2.基础概念:修订间差异

跳到导航 跳到搜索
→‎享元设计模式:​ // Edit via Wikiplus
(创建页面,内容为“这一节,会讲述一些非常重要的前置概念。 == ResourceLocation == 这是一个位于<code>net.minecraft.util</code>包下的一个类。这个类的用途的其中之一,顾名思义,就是用来表示文件在assets文件夹中的路径。在开发环境中,assets文件夹在<code>src/main/resources</code>路径下;而在打包好的.jar文件的中,assets文件夹点进去就能看到。 ResourceLocation总共有3个构造器,我…”)
 
→‎享元设计模式:​ // Edit via Wikiplus
 
(未显示同一用户的1个中间版本)
第70行: 第70行:
所以我们需要用Forge提供的注册表,我们不需要显式指定数字ID。另外它接管了原版的注册表,且是基于Forge的事件系统的,事件系统会在后面讲到。
所以我们需要用Forge提供的注册表,我们不需要显式指定数字ID。另外它接管了原版的注册表,且是基于Forge的事件系统的,事件系统会在后面讲到。


所有注册项的类都实现了IForgeRegistry<V>这一接口,这个接口主要规定了关于注册名的一些规范,实际上这个接口有个静态内部类:Impl<T> implements IForgeRegistry<T>,所以实际上所有注册项的类是继承了这个类,这个类提供了IForgeRegistry<V>的默认实现。也就是说,理论上你可以通过T extends IForgeRegistry.Impl<T>来设定:可以用Forge的注册表系统给你的某个自定义的游戏元素进行注册,不过一般没必要这么做。
所有注册项的类都实现了IForgeRegistryEntry<V>这一接口,这个接口主要规定了关于注册名的一些规范,实际上这个接口有个静态内部类:Impl<T> implements IForgeRegistryEntry<T>,所以实际上所有注册项的类是继承了这个类,这个类提供了IForgeRegistryEntry<V>的默认实现。也就是说,理论上你可以通过T extends IForgeRegistryEntry.Impl<T>来设定:可以用Forge的注册表系统给你的某个自定义的游戏元素进行注册,不过一般没必要这么做。


使用原版的注册表时,没有“注册名”这一说——但是我们用的是Forge的注册表,所以必须在注册对象前,设定该对象的注册名:通过setRegistryName这个方法设定。这个方法可以接受一个ResourceLocation,但也可以接受这样两种形参列表:<code>(String name)</code>和<code>(String modid, String name)</code>,用法可以类比ResourceLocation的那两个构造方法,笔者这里就不细说了。如果你尝试注册未设定注册名的注册项对象(即注册名为null),则肯定会崩游戏,抛NullPointerException。
使用原版的注册表时,没有“注册名”这一说——但是我们用的是Forge的注册表,所以必须在注册对象前,设定该对象的注册名:通过setRegistryName这个方法设定。这个方法可以接受一个ResourceLocation,但也可以接受这样两种形参列表:<code>(String name)</code>和<code>(String modid, String name)</code>,用法可以类比ResourceLocation的那两个构造方法,笔者这里就不细说了。如果你尝试注册未设定注册名的注册项对象(即注册名为null),则肯定会崩游戏,抛NullPointerException。
=== @ObjectHolder ===
=== @ObjectHolder ===
利用<code>@GameRegistry.ObjectHolder</code>这个注解,我们可以自动给某个类型为<T extends IForgeRegistry<T>>的变量赋值。
利用<code>@GameRegistry.ObjectHolder</code>这个注解,我们可以自动给某个类型为<T extends IForgeRegistryEntry<T>>的变量赋值。


那么具体怎么用呢?看个例子就知道了:
那么具体怎么用呢?看个例子就知道了:
第89行: 第89行:
意义就是:节省内存开销啊。如果不重复利用实例,你确定你的电脑有那么大内存去分配给数量爆炸的对象吗?
意义就是:节省内存开销啊。如果不重复利用实例,你确定你的电脑有那么大内存去分配给数量爆炸的对象吗?


提一句,既然要重复利用实例,那么显然我们需要缓存这些注册项的对象。你可以在<code>net.minecraft.init</code>包下找到一些类:Items、Blocks、PotionTypes等等,这些类中有许多的静态字段,都是对这些需要重复利用的对象的引用,需要的时候直接拿来用即可。不过也有例外——比如,没有Potions这个类,实际上Potion的注册是在Potion类本身中完成的,它注册的时候根本就没有保有对对象的引用,而是直接new的。
提一句,既然要重复利用实例,那么显然我们需要缓存这些注册项的对象。你可以在<code>net.minecraft.init</code>包下找到一些类:Items、Blocks、PotionTypes等等,这些类中有许多的静态字段,都是对这些需要重复利用的对象的引用,需要的时候直接拿来用即可。不过也有例外——比如,没有Potions这个类,实际上我们如果想要获取原版中的Potion实例,应该用MobEffects这个类。


那又有人要问了:那么Minecraft在处理性质不同、但是代表的对象相同的事物的逻辑的时候,如何区分呢?对于这个问题,不同种类的注册项的处理都不同。对于Item来说,Minecraft会随建随用一个ItemStack对象;对于Block来说,有BlockPos这个类可以用。这些在后面会具体讲到。
那又有人要问了:那么Minecraft在处理性质不同、但是代表的对象相同的事物的逻辑的时候,如何区分呢?对于这个问题,不同种类的注册项的处理都不同。对于Item来说,Minecraft会随建随用一个ItemStack对象;对于Block来说,有BlockPos这个类可以用。这些在后面会具体讲到。
行政员、​优秀编辑者、​界面管理员、​监督员、​管理员、​小部件编辑者
3,417

个编辑

我们提供服务需要使用Cookie。您使用我们的服务,即表示您同意我们使用Cookie。

导航菜单