Difference between revisions of "Item Properties"

From Forge Community Wiki
m (ChampionAsh5357 moved page Item Overrides to Item Properties without leaving a redirect: ItemOverrides is a superset of item properties to which this is)
(Update to 1.17)
Line 4: Line 4:
  
 
== Adding Properties to Items  ==
 
== Adding Properties to Items  ==
<code><nowiki>ItemModelsProperties::registerProperty</nowiki></code> is used to add a property to a specific item. The <code>ResourceLocation</code> parameter is the name given to the property (e.g. <code><nowiki>new ResourceLocation("pull")</nowiki></code>). The <code>IItemPropertyGetter</code> is a function that takes the <code>ItemStack</code>, the <code>ClientWorld</code> it’s in, and the <code>LivingEntity</code> that holds it, returning the <code>float</code> value for the property. Some examples are the <code><nowiki>pulling</nowiki></code> and <code><nowiki>pull</nowiki></code> properties for <code>Items#BOW</code>, and the several default ones in <code>ItemModelProperties</code>. For modded item properties, it is recommended that the modid of the mod is used as the namespace (e.g. <code><nowiki>examplemod:property</nowiki></code> and not just <code>property</code>, as that really means <code><nowiki>minecraft:property</nowiki></code>).
+
<code><nowiki>ItemProperties::register</nowiki></code> is used to add a property to a specific item. The <code>ResourceLocation</code> parameter is the name given to the property (e.g. <code><nowiki>new ResourceLocation("pull")</nowiki></code>). The <code>ItemPropertyFunction</code> is a function that takes the <code>ItemStack</code>, the <code>ClientLevel</code> it’s in, the <code>LivingEntity</code> that holds it, and the <code>int</code> containing the id of the holding entity or '''0''', returning the <code>float</code> value for the property. Some examples are the <code><nowiki>pulling</nowiki></code> and <code><nowiki>pull</nowiki></code> properties for <code>Items#BOW</code>, and the several default ones in <code>ItemProperties</code>. For modded item properties, it is recommended that the modid of the mod is used as the namespace (e.g. <code><nowiki>examplemod:property</nowiki></code> and not just <code>property</code>, as that really means <code><nowiki>minecraft:property</nowiki></code>). There's also another private method <code>ItemProperties::registerGeneric</code> that is used to add properties to all items, and it does not take <code>Item</code> as its parameter since all items will apply this property.
 +
 
 +
{{Tip/Important|Use <code>FMLClientSetupEvent#enqueueWork</code> to proceed with the tasks, since the data structures in <code>ItemProperties</code> are not thread-safe.}}
 +
 
 +
{{Tip|<code>ItemPropertyFunction</code> is deprecated by Mojang in favor of using the subinterface <code>ClampedItemPropertyFunction</code> which clamps the result between '''0''' and '''1'''.}}
  
 
== Using Overrides ==
 
== Using Overrides ==
 
A good example can be found in <code><nowiki>model/item/bow.json</nowiki></code>. For reference, here is a hypothetical example of an item with an <code><nowiki>examplemod:power</nowiki></code> property. If the values have no match, the default is the current model.
 
A good example can be found in <code><nowiki>model/item/bow.json</nowiki></code>. For reference, here is a hypothetical example of an item with an <code><nowiki>examplemod:power</nowiki></code> property. If the values have no match, the default is the current model.
<block important>A predicate applies to all values greater than or equal to the given value.</block>
+
 
 +
{{Tip/Important|A predicate applies to all values greater than or equal to the given value.}}
 +
 
 
<syntaxhighlight lang="json">
 
<syntaxhighlight lang="json">
 
{
 
{
Line 14: Line 20:
 
   "textures": {
 
   "textures": {
 
     "__comment": "Default",
 
     "__comment": "Default",
     "layer0": "examplemod:items/examplePartial"
+
     "layer0": "examplemod:items/example_partial"
 
   },
 
   },
 
   "overrides": [
 
   "overrides": [
Line 22: Line 28:
 
         "examplemod:power": 0.75
 
         "examplemod:power": 0.75
 
       },
 
       },
       "model": "examplemod:item/examplePowered"
+
       "model": "examplemod:item/example_powered"
 
     }
 
     }
 
   ]
 
   ]
 
}
 
}
 
</syntaxhighlight>
 
</syntaxhighlight>
And here’s a hypothetical snippet from the supporting code. (This does not have to be client-only; it will work on a server too. In vanilla, properties are registered in the item’s constructor.)
+
 
 +
And here’s a hypothetical snippet from the supporting code. Unlike the older versions (lower than 1.16.x), this needs to be done on client side only because <code>ItemProperties</code> does not exist on server.
 +
 
 
<syntaxhighlight lang="java">
 
<syntaxhighlight lang="java">
 
public void clientSetup(final FMLCLientSetupEvent event) {
 
public void clientSetup(final FMLCLientSetupEvent event) {
   ItemModelProperties.registerProperty(item, new ResourceLocation("examplemod:power"), new IItemPropertyGetter() {
+
   event.enqueueWork(() ->
    @Override
+
  {
    public float call(ItemStack stack, @Nullable ClientWorld world, @Nullable LivingEntity entity) {
+
    ItemProperties.register(ExampleItems.APPLE,  
      return (float)getPowerLevel(stack) / (float)getMaxPower(stack); // Some external methods
+
      new ResourceLocation(ExampleMod.MODID, "pulling"), (stack, level, living, id) -> {
    }
+
        return living != null && living.isUsingItem() && living.getUseItem() == stack ? 1.0F : 0.0F;
   }
+
      });
 +
   });
 
}
 
}
 
</syntaxhighlight>
 
</syntaxhighlight>

Revision as of 18:02, 2 August 2021

Item properties are a way for the "properties" of items to be exposed to the model system. An example is the bow, where the most important property is how far the bow has been pulled. This information is then used to choose a model for the bow, creating an animation for pulling it.

An item property assigns a certain float value to every ItemStack it is registered for, and vanilla item model definitions can use these values to define “overrides”, where an item defaults to a certain model, but if an override matches, it overrides the model and uses another. They are useful mainly because of the fact that they are continuous. For example, bows use item properties to define their pull animation. Since the value of the property is a float, it increases continuously from 0 to 1. This allows resource packs to add as many models as they want for the bow pulling animation along that spectrum, instead of being stuck with four “slots” for their models in the animation. The same is true of the compass and clock.

Adding Properties to Items

ItemProperties::register is used to add a property to a specific item. The ResourceLocation parameter is the name given to the property (e.g. new ResourceLocation("pull")). The ItemPropertyFunction is a function that takes the ItemStack, the ClientLevel it’s in, the LivingEntity that holds it, and the int containing the id of the holding entity or 0, returning the float value for the property. Some examples are the pulling and pull properties for Items#BOW, and the several default ones in ItemProperties. For modded item properties, it is recommended that the modid of the mod is used as the namespace (e.g. examplemod:property and not just property, as that really means minecraft:property). There's also another private method ItemProperties::registerGeneric that is used to add properties to all items, and it does not take Item as its parameter since all items will apply this property.

Important

Use FMLClientSetupEvent#enqueueWork to proceed with the tasks, since the data structures in ItemProperties are not thread-safe.
ItemPropertyFunction is deprecated by Mojang in favor of using the subinterface ClampedItemPropertyFunction which clamps the result between 0 and 1.

Using Overrides

A good example can be found in model/item/bow.json. For reference, here is a hypothetical example of an item with an examplemod:power property. If the values have no match, the default is the current model.

Important

A predicate applies to all values greater than or equal to the given value.
{
  "parent": "item/generated",
  "textures": {
    "__comment": "Default",
    "layer0": "examplemod:items/example_partial"
  },
  "overrides": [
    {
      "__comment": "power >= .75",
      "predicate": {
        "examplemod:power": 0.75
      },
      "model": "examplemod:item/example_powered"
    }
  ]
}

And here’s a hypothetical snippet from the supporting code. Unlike the older versions (lower than 1.16.x), this needs to be done on client side only because ItemProperties does not exist on server.

public void clientSetup(final FMLCLientSetupEvent event) {
  event.enqueueWork(() ->
  {
    ItemProperties.register(ExampleItems.APPLE, 
      new ResourceLocation(ExampleMod.MODID, "pulling"), (stack, level, living, id) -> {
        return living != null && living.isUsingItem() && living.getUseItem() == stack ? 1.0F : 0.0F;
      });
  });
}