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

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

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

MCBBS Wiki GitHub群组已上线!

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

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

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

用户:MashKJo/1.12.2模组开发教程/13.高级物品(一) - 食物和饮料

来自MCBBS Wiki
跳到导航 跳到搜索

在1.13+的Minecraft源代码中,食物和流体类似,都是被单独分离成了一个特殊的概念——流体对应Fluid类,而食物对应Food类,而声明某物品是一种食物,则需要调用Item.Properties#food方法来完成。但在1.12中,食物仅仅是一种特殊的物品——ItemFood。因此,我们可以通过简单复用该类创建出许多种食物。

ItemFood类的构造器为(int amount, float saturation, boolean isWolfFood)。amount为所恢复的饥饿值,saturation为所恢复的饱食度的比例系数(而真正的饱和度值计算公式为2 * amount * saturation),而isWolfFood则用于决定该食物是否能被用于驯服狼狗。前两个参数均有对应的getter可以用,从这些getter中你可以拿到对应的ItemStack,也就是说你可以配合着meta-hack来覆写这2个getter。

此外,该类还有2个setter可以用:

  • setAlwaysEdible:用于设定:无论玩家的饥饿值是否是满的,均可以食用该食物。
  • setPotionEffect:用于设定:吃下该食物后,获得的药水效果,第一个参数要求一个PotionEffect,这个后面会讲到的,它的用法和ItemStack其实是类似的,而Potion之于PotionEffect就相当于Item之于ItemStack。第二个参数是float probability,取值范围为[0.0F, 1.0F],这个其实是表示产生预期药水效果的概率(想想看生鸡肉吧)——1.0F即代表100%,即一定会发生。

不过显然,光是一个setPotionEffect,根本没法满足大部分模组甚至于原版的需求——例如原版的金苹果就追加了不止一种PotionEffect,而该方法却只能传入一个PotionEffect。所以我们实际上可以覆写onFoodEaten这个方法。形参列表为(ItemStack stackIn, World worldIn, EntityPlayer playerIn),显然这是个很丰富的形参列表,因此,我们不妨放开点思路——我们真的只能在这里追加不止一种PotionEffect吗?实际上我们可以在这里写任何逻辑。

创建一种新食物很简单,那么新的饮料呢,比如原版的牛奶桶和药水?很遗憾,原版并没有提供专门的饮料物品类,不过也没关系,我们自己从头写就好。让我们想想看一种饮料物品应当具有怎样的行为?答案是:有饮用的时长、动画和音效。没错,就这么简单。还记得上一节的内容吗?对于设定饮用的时长,我们可以覆写getMaxItemUseDuration,单位为tick(游戏刻,原版的食物和饮料默认为32ticks),想追加饮用后的特定逻辑的话,再覆写onItemUseFinish即可。至于饮用的动画和音效,这些是由枚举对象EnumAction.DRINK来决定的。另外,由于设定上饮料一般都是由容器盛装的,因此我们通常会设定该饮料物品的containerItem,以及喝完它后返还给我们1个该containerItem[1]

import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.EnumAction;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.world.World;

public class MyCustomDrink extends Item{
   public MyCustomDrink(){
       this.setRegistryName(...);
       this.setUnlocalizedName(...);
       this.setCreativeTab(...);

       this.setMaxStackSize(1);
   }

   @Override
   public ItemStack getContainerItem(ItemStack stack){
       ...
   }

   @Override
   public int getMaxItemUseDuration(ItemStack stack){
       return 32;
   }

   @Override
   public EnumAction getItemUseAction(ItemStack stack){
       return EnumAction.DRINK;
   }

   @Override
   public ItemStack onItemUseFinish(ItemStack stack, World worldIn, EntityLivingBase entityLiving){
       ... //Do your custom game logics...

       ItemStack container = getContainerItem(stack);

       if(entityLiving instanceof EntityPlayer && !((EntityPlayer)entityLiving).capabilities.isCreativeMode){
           stack.shrink(1);
       }
       return stack.isEmpty() ? container : stack;
   }
}

就是这样,实际上该类的实现和ItemFood是大同小异的。

注释与外部链接

  1. 原版的牛奶桶并未设定其containerItem(设定上应该是桶),所以原版中有“拿牛奶桶做蛋糕,蛋糕把三个桶生吞了”这种奇葩现象。