MCBBS Wiki欢迎您共同参与编辑!在参与编辑之前请先阅读Wiki方针。
如果在编辑的过程中遇到了什么问题,可以去讨论板提问。
为了您能够无阻碍地参与编辑 未验证/绑定过邮箱的用户,请尽快绑定/验证。
MCBBS Wiki GitHub群组已上线!
您可以在回声洞中发表吐槽!
服务器状态监控。点击进入
本站由MCBBS用户自行搭建,与MCBBS及东银河系漫游指南(北京)科技有限公司没有从属关系。点此了解 MCBBS Wiki 不是什么>>
用户:MashKJo/1.12.2模组开发教程/16.高级物品(四) - 高级物品模型
物品模型在不同场合下的渲染变换
这里的“各种场合”包括: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...);