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

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

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

MCBBS Wiki GitHub群组已上线!

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

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

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

用户:MashKJo/1.12.2模组开发教程/11.高级物品和方块 - 前置概念:修订间差异

跳到导航 跳到搜索
// Edit via Wikiplus
→‎在世界中放置方块:​ // Edit via Wikiplus
(// Edit via Wikiplus)
第3行: 第3行:
很简单,如果我们排除掉使用TileEntity的方块,那么剩下的那些高级的物品/方块,几乎都是通过覆写Item类或Block类下的若干方法实现的,这些方法有的是Minecraft原生支持的,还有一些是Forge塞进去的。你可能会看到Minecraft有些原生支持的方法被@Deprecated了,那可能是因为Forge觉得这个方法提供的形参不够多,对于对应功能的控制还不够精细,因此patch了一个更为强大的同功能重载方法。另外,如果你实在找不到可以覆写的方法,那么可以考虑监听一些事件。
很简单,如果我们排除掉使用TileEntity的方块,那么剩下的那些高级的物品/方块,几乎都是通过覆写Item类或Block类下的若干方法实现的,这些方法有的是Minecraft原生支持的,还有一些是Forge塞进去的。你可能会看到Minecraft有些原生支持的方法被@Deprecated了,那可能是因为Forge觉得这个方法提供的形参不够多,对于对应功能的控制还不够精细,因此patch了一个更为强大的同功能重载方法。另外,如果你实在找不到可以覆写的方法,那么可以考虑监听一些事件。


然而,覆写这些方法通常涉及到一些很重要也比较复杂的类,这些类比较琐碎,应用也非常广泛,如果真的按照“讲到了对应的专题再详细讲”这个原则安排内容,会导致一系列问题——例如,World类是一个非常重要的类,用到的地方超级多,但是读者想必也不希望掌握如何创建一个新维度后,再回来写高级的物品/方块吧?因此这一节就专门讲这些琐碎的类以及它们涉及到的一些重要概念。
对于高级物品,Item类有如下常用的方法值得覆写:
* onItemUseFirst、onItemUse:在物品被玩家手持,且右键非空气方块时触发,均返回一个EnumActionResult,前者先于后者被触发。对于前者而言,返回EnumActionResult.PASS,则代表会继续执行原版的相关逻辑。
* onItemUseFinish:该方法和上述2个方法有所区别——该方法限定的实体并不仅仅是玩家(EntityPlayer)了,而是所有生物(EntityLivingBase)。它返回一个ItemStack,代表某个ItemStack被使用后的结果。
* onItemRightClick:该方法会在玩家手持物品右键时触发——没错,它不要求玩家必须选中某个非空气方块,只要右键就行,实际上它也先于onItemUseFirst和onItemUse触发。Minecraft本身只提供了修改右键物品的逻辑的该方法,那么如果我们想干涉左键逻辑怎么办?考虑监听这两个事件:PlayerInteractEvent.LeftClickBlock和PlayerInteractEvent.LeftClickEmpty,具体在监听时可以判断玩家的手持物品,再写入相关逻辑,即可。
* canHarvestBlock:返回一个布尔值,注意该方法有2个重载,其中一个是原版的,还有一个是Forge塞进来的,当然推荐使用后者。用于判断某个BlockState是否可以被该Item对应的某个ItemStack挖掘并产生掉落物,原版中该方法的实现很丑陋,全是面向结果编程的味道,且鉴于Forge patch的<code>Block#setHarvestLevel</code>这一方法的存在,一般你不该动这个方法,不过如果你想做出像剪刀那样比较特殊的挖掘、掉落效果,就可以覆写这个方法。
* onUpdate:这是一个比较重要的方法,它在游戏主循环中,每一tick都会被调用一次,也就是说理想状态下每秒钟内两个逻辑端各会调用该方法20次。因此如果我们覆写了该方法,便可以赋予相应的ItemStack一秒刷新20次的能力,我们利用它可以做出一些很高级的物品,例如计时器之类的东西。从该方法中我们可以拿到持有该ItemStack的实体(没错,Entity,甚至都非EntityLivingBase),以及“该物品是否被选中”(isSelected)。
* onEntityItemUpdate:决定当前ItemStack对应的EntityItem的刷新逻辑。
* onCreated:在该物品被合成出来后触发。
* getMaxItemUseDuration:用于指定物品被右键按住使用后,持续的最长时间——如右键弓后弓会逐渐拉伸至蓄满力状态,蓄满力后一段时间内,如果不松开右键,弓会一直紧绷着。注意这个方法的返回值是一个int值,单位实际上是tick。
* onPlayerStoppedUsing:配合着getMaxItemUseDuration使用的——即玩家松开右键后执行的游戏逻辑,原版的弓在这里即会召唤出一发箭矢实体(EntityArrow)。
* addInformation:@SideOnly(Side.CLIENT),用于给ItemStack添加tooltip,具体为向一个List<String>中添加新元素的过程,一般是搭配<code>I18n#format</code>实现,甚至我们可以通过当前ItemStack的附加NBT信息来决定添加的tooltip。
* hasEffect:@SideOnly(Side.CLIENT),用于决定该ItemStack是否有附魔光泽——没错,ItemStack有无附魔和有无附魔光泽的对应关系并不是写死的,只是Item类对该方法的默认实现即为:有附魔才有附魔光泽,你大可给你的Item子类在这里无脑返回一个true。
* getItemBurnTime:如果你想添加熔炉燃料,那么覆写这个方法即可。返回一个正整数,则默认它是一个熔炉燃料,且单位为tick;若返回0,则代表它不可燃;返回-1,则代表它的可燃状态交给原版Minecraft去决定。
* getIsRepairable:用于决定该ItemStack可被什么ItemStack修复。两个参数中,toRepair是被修复的,repair是修复材料。
想必读者也看到了,覆写这些方法通常涉及到一些很重要也比较复杂的类,这些类比较琐碎,应用也非常广泛,如果真的按照“讲到了对应的专题再详细讲”这个原则安排内容,会导致一系列问题——例如,World类是一个非常重要的类,用到的地方超级多,但是读者想必也不希望掌握如何创建一个新维度后,再回来写高级的物品/方块吧?因此这一节就专门讲这些琐碎的类以及它们涉及到的一些重要概念。
== 一些枚举类 ==
== 一些枚举类 ==
在给我们的高级的物品/方块实现一些功能时,我们会和很多枚举类打交道,如:
在给我们的高级的物品/方块实现一些功能时,我们会和很多枚举类打交道,如:
* EnumAction:这个枚举类专用于物品,具体地说,是表示物品被使用时,产生的动画效果的“类型”(说是动画效果,实际上就是一层薄薄的贴图转了个角度后的一堆平移、伸缩或旋转变换而已),由<code>Item#getItemUseAction</code>决定。原版有5种EnumAction,分别是:NONE、EAT、DRINK、BLOCK、BOW。很显然,后四者分别用于食物、水瓶和药水、方块的物品形式、弓。那么可能会有读者问了:如果我想自定义物品使用时的动画效果,怎么办,如何去做到?答案是通常情况下做不到,除非你用黑魔法。一般而言,新的EnumAction可以通过Forge提供的EnumHelper来通过反射生成,但是Minecraft具体处理这个EnumAction并实际产生动画的代码中,Forge实际上没有发布任何事件,所以理论上我们无法新增自定义的物品使用动画,除非你用Mixin大法,但除非你Modding水平够高,否则执意在Forge框架下开发时用Mixin实现自己的需求,还不如自己换个需求。
* EnumAction:这个枚举类专用于物品,具体地说,是表示物品被使用时,产生的动画效果的“类型”(说是动画效果,实际上就是一层薄薄的贴图转了个角度后的一堆平移、伸缩或旋转变换而已),由<code>Item#getItemUseAction</code>决定。原版有5种EnumAction,分别是:NONE、EAT、DRINK、BLOCK、BOW。很显然,后四者分别用于食物、水瓶和药水、方块的物品形式、弓。那么可能会有读者问了:如果我想自定义物品使用时的动画效果,怎么办,如何去做到?答案是通常情况下做不到,除非你用黑魔法。一般而言,新的EnumAction可以通过Forge提供的EnumHelper来通过反射生成,但是Minecraft具体处理这个EnumAction并实际产生动画的代码中,Forge实际上没有发布任何事件,所以理论上我们无法新增自定义的物品使用动画,除非你用Mixin大法,但除非你Modding水平够高,否则执意在Forge框架下开发时用Mixin实现自己的需求,还不如自己换个需求。
* EnumActionResult:这个枚举类有3个实例:SUCCESS、PASS和FAIL,它用于描述某个交互逻辑进行后,返回的结果(或者说执行结果)。其实它的意义不是那么大,因为它也就只是一个返回值而已,你可以在写一堆你自己的自定义逻辑后返回FAIL,本质上就是一个标记而已。不过对于物品的使用而言,SUCCESS和FAIL都不会在执行完主手上的物品的相关逻辑后,继续执行副手上对应物品的相关逻辑,而PASS则会,这个特性需要小小地注意一下。
* EnumActionResult:这个枚举类有3个实例:SUCCESS、PASS和FAIL,它用于描述某个交互逻辑进行后,返回的结果(或者说执行结果)。其实它的意义不是那么大,因为它也就只是一个返回值而已,你可以在写一堆你自己的自定义逻辑后返回FAIL,本质上就是一个标记而已。3个返回值没有固定的含义,读者在使用前请先查看相关的代码。
* EnumBlockRenderType:顾名思义,这个枚举类用于描述方块的渲染类型——INVISIBLE、LIQUID、ENTITYBLOCK_ANIMATED、MODEL。
* EnumBlockRenderType:顾名思义,这个枚举类用于描述方块的渲染类型——INVISIBLE、LIQUID、ENTITYBLOCK_ANIMATED、MODEL。
** MODEL:默认值,就是最普通的渲染类型——从指定的模型文件中读取出一个模型(实际上是通过一个ICustomModelLoader得到了一个IModel),并经历一系列加工过程,最后渲染出来。
** MODEL:默认值,就是最普通的渲染类型——从指定的模型文件中读取出一个模型(实际上是通过一个ICustomModelLoader得到了一个IModel),并经历一系列加工过程,最后渲染出来。
第21行: 第35行:


== 一些向量类 ==
== 一些向量类 ==
Minecraft在<code>net.minecraft.util.math</code>包下提供了三个向量类:Vec2f、Vec3f和Vec3d。实际上读者应该能很清楚地看出来,数字代表空间维度数,第一个是平面向量,后两个是空间向量;而字母代表坐标精度,f代表float,d代表double。一般而言,我们用的都是Vec3d。
Minecraft在<code>net.minecraft.util.math</code>包下提供了三个向量类:Vec2f、Vec3i和Vec3d。实际上读者应该能很清楚地看出来,数字代表空间维度数,第一个是平面向量,后两个是空间向量;而字母代表坐标精度,i代表int,f代表float,d代表double。一般而言,我们用的都是Vec3d。


合理运用向量类能给不少问题中的数学运算带来极大的便利,如Vec3d下就有很多简化计算过程的好用方法,读者可以去自行察看。
合理运用向量类能给不少问题中的数学运算带来极大的便利,如Vec3d下就有很多简化计算过程的好用方法,读者可以去自行察看。
行政员、​优秀编辑者、​界面管理员、​监督员、​管理员、​小部件编辑者
3,417

个编辑

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

导航菜单