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

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

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

MCBBS Wiki GitHub群组已上线!

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

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

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

用户:MashKJo/1.12.2模组开发教程/16.高级物品(四) - 高级物品模型

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

物品模型在不同场合下的渲染变换

这里的“各种场合”包括:GUI内、被玩家以不同视角拿在手上时、在物品展示框中时等情况。这属于原版的内容,参见:模型#渲染变换 - 中文 Minecraft Wiki

小提示:直接手写这些渲染变换的参数很不直观,推荐读者使用Blockbench进行这些参数的可视化调控。

物品属性覆盖(Item Property Override)

这是一个允许我们根据当前的ItemStack所持有的信息来指定不同的物品模型的机制。

首先我们需要一个IItemPropertyGetter:

public static final IItemPropertyGetter MY_ITEM_PROPERTY_GETTER = new IItemPropertyGetter(){
   @SideOnly(Side.CLIENT)
   @Override
   public float apply(ItemStack stack, @Nullable World world, @Nullable EntityLivingBase entityLiving){
       ...
   }
}

这里用的是匿名内部类而非lambda——因为内部那个方法需要用@SideOnly(Side.CLIENT)修饰。apply方法的形参列表很丰富,你大可以好好利用这些形参,最后输出一个float值。

紧接着你就需要告知:你的某一物品有这一IItemPropertyGetter,一般是在该物品类的构造器中这样写:

this.addPropertyOverride(new ResourceLocation(...), MY_ITEM_PROPERTY_GETTER);

然后我们就可以把这个IItemPropertyGetter体现在该物品的模型json文件中了:

{
   ...
   "overrides": [
       {
           "predicate": {
               <your property getter's resource location name>: <a float value>
           },
           "model": "..."
       },
       ...
       ]
}

这样,当该Property等于特定的值时,物品模型会被替换为overrides中的相应的model的。注意:这个数值是精确匹配的。

原版内建了4种IItemPropertyGetter:DAMAGED_GETTER(ItemStack是否受到损害)、DAMAGE_GETTER(ItemStack当前的损害程度)、LEFTHANDED_GETTER(持有该ItemStack的生物实体的主手是否为左手)、COOLDOWN_GETTER(该ItemStack对应的Item的冷却进度),且Item类的构造方法中,addPropertyOverride了后两种IItemPropertyGetter,也就是说理论上所有物品都有这两种IItemPropertyGetter。

ItemMeshDefinition

Property Override并不是所有时候都好用的——有些时候它甚至有些画蛇添足,硬是要把条件分支转化为不同的float值,太过麻烦。如果在你的需求中,物品模型的变化并不依赖于当前的World和持有该ItemStack的生物实体,我们就可以考虑使用ItemMeshDefinition。它是一个原版的函数式接口,唯一的方法为:ModelResourceLocation getModelLocation(ItemStack stack)。ItemMeshDefinition相比Property Override,更加直观好用——直接根据当前的ItemStack的信息指定ModelResourceLocation,而省去了Property Override的转化数据、写overrides json的过程。

Forge提供了一个方法来设置我们自己的ItemMeshDefinition:

ModelLoader.setCustomMeshDefinition(item, stack -> { ... } );

但注意,ItemMeshDefinition并不能用于动态地生成模型。通过它所指定的模型仍然需要通过常规的声明模型的方式声明,一定能被穷尽,且Minecraft必须提前知道所有的可能的模型:

ModelBakery.registerItemVariants(item, resourceLocation1, resourceLocation2...);