Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 9 additions & 1 deletion .vitepress/sidebars/develop.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Fabric } from "../types";
import {Fabric} from "../types";

export default [
{
Expand Down Expand Up @@ -92,6 +92,10 @@ export default [
text: "develop.items.potions",
link: "/develop/items/potions",
},
{
text: "develop.items.spawn-egg",
link: "/develop/items/spawn-egg",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perhaps the page should go under "entities?" That's where I'd look for it first.

}
],
},
{
Expand Down Expand Up @@ -240,6 +244,10 @@ export default [
text: "develop.dataGeneration.blockModels",
link: "/develop/data-generation/block-models",
},
{
text: "develop.dataGeneration.itemModels",
link: "/develop/data-generation/item-models",
},
],
},
{
Expand Down
8 changes: 4 additions & 4 deletions develop/data-generation/block-models.md
Original file line number Diff line number Diff line change
Expand Up @@ -180,12 +180,12 @@ The `BlockStateSupplier` contains all blockstate variants, their rotation, and o

First, we create a new `VariantsBlockStateSupplier` using `VariantsBlockStateSupplier.create()`.
Then we create a new `BlockStateVariantMap` that contains parameters for all variants of the block, in this case `FACING` and `SINGLE`, and pass it into the `VariantsBlockStateSupplier`.
Specify which model and which transformations (uvlock, rotation) is used when using `.register()`.
Specify which model and which transformations (uvlock, rotation) are used when using `.register()`.
For example:

- On the first line, the block is facing north, and is single => we use the model with no rotation.
- On the fourth line, the block is facing west, and is single => we rotate the model on the Y axis by 270°.
- On the sixth line, the block is facing east, but isn't single => it looks like a normal oak log => we don't have to rotate it.
- On the first line, the block is facing north, and is single we use the model with no rotation.
- On the fourth line, the block is facing west, and is single we rotate the model on the Y axis by 270°.
- On the sixth line, the block is facing east, but it isn't single it looks like a normal oak log we don't have to rotate it.

### Custom Datagen Method {#custom-datagen-method}

Expand Down
252 changes: 252 additions & 0 deletions develop/data-generation/item-models.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,252 @@
---
title: Item Model Generation
description: A guide to generating item models via datagen.
authors:
- Fellteros
- VatinMc
- skycatminepokie
---

:::info PREREQUISITES
Make sure you've completed the [datagen setup](./setup) and created your [first item](../items/first-item).
:::

## Setup {#setup}

First, we will need to create our ModelProvider. Create a class that `extends FabricModelProvider`. Implement both abstract methods: `generateBlockStateModels` and `generateItemModels`.
Lastly, create a constructor matching super.

@[code lang=java transcludeWith=:::datagen-model:provider](@/reference/latest/src/client/java/com/example/docs/datagen/FabricDocsReferenceModelProvider.java)

Register this class in your `DataGeneratorEntrypoint` within the `onInitializeDataGenerator` method.

## Generated Files {#generated-files}

Generating item models results in creating two separate JSON files:

1. **Item model**. File responsible for defining the textures, rotation and overall looks of the item. It's generated in the `generated/assets/modid/models/item` directory.
2. **Item model definition**. File defining which model should be used depending on various criteria such as components, interactions and more. It's generated in the `generated/assets/modid/items` directory.

## Item Models {#item-models}

This section covers the most used and basic methods used for generating item models.

```java
@Override
public void generateItemModels(ItemModelGenerator itemModelGenerator) {
}
```

For item models, we will be using the `generateItemModels` method. Its parameter `ItemModelGenerator itemModelGenerator` is responsible for generating the item models and also contains methods for doing so.

### Simple Item Models {#simple-item-models}

@[code lang=java transcludeWith=:::datagen-model:generated](@/reference/latest/src/client/java/com/example/docs/datagen/FabricDocsReferenceModelProvider.java)

Simple item models are the default ones, which most Minecraft items use. Their parent model is the `GENERATED` Model. They use their 2D texture, which is then rendered as 3D in-game. An example would be boats, candles or dyes.

_**assets/modid/models/item/ruby.json**_

@[code](@/reference/latest/src/main/generated/assets/fabric-docs-reference/models/item/ruby.json)

Since we're using only one variant no matter the circumstances, we reference only the `ruby.json` item model file.

_**assets/modid/items/ruby.json**_

@[code](@/reference/latest/src/main/generated/assets/fabric-docs-reference/items/ruby.json)

:::tip
Search for `generated.json` file to see the exact rotation, scaling and positioning of the model.
:::

<DownloadEntry visualURL="/assets/develop/data-generation/item-model/ruby_big.png" downloadURL="/assets/develop/data-generation/item-model/ruby.png">Ruby</DownloadEntry>

### Handheld Item Models {#handheld-item-models}

@[code lang=java transcludeWith=:::datagen-model:handheld](@/reference/latest/src/client/java/com/example/docs/datagen/FabricDocsReferenceModelProvider.java)

This type of item model is generally used by tools and weapons (axes, swords, trident). They are rotated and positioned a little differently from the simple models to look more natural in hand. Other than that, they look exactly the same as the simple ones.

_**assets/modid/models/item/guidite_axe.json**_

@[code](@/reference/latest/src/main/generated/assets/fabric-docs-reference/models/item/guidite_axe.json)

<DownloadEntry visualURL="/assets/develop/data-generation/item-model/guidite_axe_big.png" downloadURL="/assets/develop/data-generation/item-model/guidite_axe.png">Guidite Axe</DownloadEntry>

### Spawn Eggs {#spawn-eggs}

@[code lang=java transcludeWith=:::datagen-model:spawn-egg](@/reference/latest/src/client/java/com/example/docs/datagen/FabricDocsReferenceModelProvider.java)

Since spawn eggs use a template model, we can use the `registerSpawnEgg()` method of the `ItemModelGenerator` instance, to assign the colors and link the model to the `SpawnEggItem`. After running datagen, it should look like this:

@[code](@/reference/latest/src/main/generated/assets/fabric-docs-reference/items/custom_spawn_egg.json)

::: info
Minecraft uses signed 32-bit Integers to store ARGB color values. Java is able to convert RGB hexadecimal color values like shown above.

If you don't want to worry about the conversion, you can use tools like [Spawn Egg Color Picker](https://vatinmc.github.io/spawn-egg-color-picker/).
:::

### Dyeable Items {#dyeable-items}

@[code lang=java transcludeWith=:::datagen-model:dyeable](@/reference/latest/src/client/java/com/example/docs/datagen/FabricDocsReferenceModelProvider.java)

The `ItemModelGenerator` also provides a method for generating models for dyeable items. Here you have to pass in a default decimal color value the item uses when it isn't dyed. (default value for leather is `-6265536`)
It generates a simple item model JSON and an item model definition file specifying the tint color.

![Dyeing leather gloves](/assets/develop/data-generation/item-model/leather_gloves_dyeing.png)

_**assets/modid/items/leather_gloves.json**_

@[code](@/reference/latest/src/main/generated/assets/fabric-docs-reference/items/leather_gloves.json)

:::warning IMPORTANT
You have to add your item to the `ItemTags.DYEABLE` Tag so you can dye it in your inventory!
:::

<DownloadEntry visualURL="/assets/develop/data-generation/item-model/leather_gloves_big.png" downloadURL="/assets/develop/data-generation/item-model/leather_gloves.png">Leather Gloves</DownloadEntry>

### Conditional Item Models {#conditional-item-models}

@[code lang=java transcludeWith=:::datagen-model:condition](@/reference/latest/src/client/java/com/example/docs/datagen/FabricDocsReferenceModelProvider.java)

Next, we'll look into generating item models that change their visual based when a specific boolean is true; in this case, the second parameter `BooleanProperty`. Here are some of them:

| Property | Description |
|------------------------|--------------------------------------------------------------------------------|
| `KeybindDownProperty` | True when a specified key is pressed. |
| `UsingItemProperty` | True when the item is being used (e.g. when blocking with a shield). |
| `BrokenProperty` | True when the item has 0 durability (e.g. elytra changes texture when broken). |
| `HasComponentProperty` | True when the item has a certain component. |

Of course, this isn't all of them. There is plenty more that will almost certainly cover your needs.

The third and fourth parameters are the models used when the property is true or false respectively.

<VideoPlayer src="/assets/develop/data-generation/item-model/flashlight_turning_on.webm">Flashlight turning on and off</VideoPlayer>

_**assets/modid/items/flashlight.json**_

@[code](@/reference/latest/src/main/generated/assets/fabric-docs-reference/items/flashlight.json)

<DownloadEntry visualURL="/assets/develop/data-generation/item-model/flashlight_textures_big.png" downloadURL="/assets/develop/data-generation/item-model/flashlight_textures.zip">Flashlight</DownloadEntry>

:::warning IMPORTANT
When obtaining `Identifier`s for the `ItemModels.basic()`, always use `itemModelGenerator.upload()` or any other method using it, otherwise your item model files won't generate, only item model definitions!
:::

### Composite Item Models {#composite-item-models}

@[code lang=java transcludeWith=:::datagen-model:composite](@/reference/latest/src/client/java/com/example/docs/datagen/FabricDocsReferenceModelProvider.java)

These item models are composed of one or more textures layered on top of each other. There aren't any vanilla methods for this, you have to use `ItemModelGenerator`'s `output` field and then `accept()` for it to work.
Here's the item model definition JSON:

_**assets/modid/items/enhanced_hoe.json**_

@[code](@/reference/latest/src/main/generated/assets/fabric-docs-reference/items/enhanced_hoe.json)

<DownloadEntry visualURL="/assets/develop/data-generation/item-model/enhanced_hoe_textures_big.png" downloadURL="/assets/develop/data-generation/item-model/enhanced_hoe_textures.zip">Enhanced Hoe</DownloadEntry>

### Select Item Models {#select-item-models}

@[code lang=java transcludeWith=:::datagen-model:select](@/reference/latest/src/client/java/com/example/docs/datagen/FabricDocsReferenceModelProvider.java)

Renders an item model based on the value of a specific property. These are some of them:

| Property | Description |
|-----------------------------|----------------------------------------------------------------------------------------------------|
| `ContextDimensionProperty` | Renders an item model based on the dimension in which the player is (Overworld, Nether, End). |
| `MainHandProperty` | Renders an item model when the item is equipped in player's main hand. |
| `DisplayContextProperty` | Renders an item model based on the position in which the item is (`ground`, `fixed`, `head`, ...). |
| `ContextEntityTypeProperty` | Renders an item model based on the entity holding the item. |

In this example, the item changes texture when traveling between dimensions; green in Overworld, red in the Nether and black in the End.

![Dimensional crystal changing texture based on dimension](/assets/develop/data-generation/item-model/crystal.png)

_**assets/modid/items/dimensional_crystal.json**_

@[code](@/reference/latest/src/main/generated/assets/fabric-docs-reference/items/dimensional_crystal.json)

<DownloadEntry visualURL="/assets/develop/data-generation/item-model/dimensional_crystal_textures_big.png" downloadURL="/assets/develop/data-generation/item-model/dimensional_crystal_textures.zip">Dimensional Crystal</DownloadEntry>

### Range Dispatch Item Models {#range-dispatch-item-models}

@[code lang=java transcludeWith=:::datagen-model:range-dispatch](@/reference/latest/src/client/java/com/example/docs/datagen/FabricDocsReferenceModelProvider.java)

Renders an item model based on the value of a numeric property. Take in an item and list of variants paired with a value. There are quite a few, here are some examples:

| Property | Description |
|-----------------------|------------------------------------------------------------------------------|
| `CooldownProperty` | Renders an item model based on item's remaining cooldown. |
| `CountPropery` | Renders an item model based on stack size. |
| `UseDurationProperty` | Renders an item model based on how long the item is being used. |
| `DamageProperty` | Renders an item model based on attack damage (`minecraft:damage` component). |

This example uses the `CountProperty`, changing the texture from one knife up to three based on the stack size.

:::tip
Some other examples of range dispatch item models are the compass, bow or brush.
:::

![Throwing knives changing texture based on count](/assets/develop/data-generation/item-model/throwing_knives_example.png)

_**assets/modid/items/throwing_knives.json**_

@[code](@/reference/latest/src/main/generated/assets/fabric-docs-reference/items/throwing_knives.json)

<DownloadEntry visualURL="/assets/develop/data-generation/item-model/throwing_knives_textures_big.png" downloadURL="/assets/develop/data-generation/item-model/throwing_knives_textures.zip">Throwing Knives</DownloadEntry>

## Custom Item Models {#custom-item-models}

:::info
All fields and methods for this part of the tutorial are declared in a static inner class called `CustomItemModelGenerator`.
:::

Generating item models isn't limited to only vanilla methods; you can, of course, create your own. In this section, we will be creating a custom model for a balloon item.

### Parent Item Model {#parent-item-model}

First, let's create a parent item model that defines how does the item look in-game. We want the balloon to look the same as simple item models, but scaled up. That's pretty straight-forward; we set the parent to be the `item/generated` model, and then override the scaling.
Put this JSON file in the `resources/assets/mod_id/models/item` folder.

**_models/item/scaled2x.json_**

@[code](@/reference/latest/src/main/resources/assets/fabric-docs-reference/models/item/scaled2x.json)

This will make the model twice as big as the normal ones. Feel free to experiment with the values until you get the desired output.

<DownloadEntry visualURL="/assets/develop/data-generation/item-model/balloon_big.png" downloadURL="/assets/develop/data-generation/item-model/balloon.png">Balloon</DownloadEntry>

### Custom Model {#custom-model}

Next, we need to create an instance of the `Model` class. It will represent the actual [parent item model](#parent-item-model) inside our mod.

@[code lang=java transcludeWith=:::datagen-model-custom:item-model](@/reference/latest/src/client/java/com/example/docs/datagen/FabricDocsReferenceModelProvider.java)

The `item()` method creates a new `Model` instance, pointing to the `scaled2x.json` file inside the `resources/assets/mod_id/models/item` folder.

TextureKey `LAYER0` represents the `#layer0` texture variable, which will then be replaced by an identifier pointing to a texture.

### Custom Datagen Method {#custom-datagen-method}

The last step is creating a custom method, which will be called in the `generateItemModels()` method and will be responsible for generating our item models.

@[code lang=java transcludeWith=:::datagen-model-custom:item-datagen-method](@/reference/latest/src/client/java/com/example/docs/datagen/FabricDocsReferenceModelProvider.java)

Let's go over what the parameters are for:

1. `Item item`: The item, for which we are generating the models (in this case `ModItems.BALLOON`).
2. `ItemModelGenerator generator`: the same that get passed into the `generateItemModels()` method. Used for its fields.

First, we get the `Identifier` of the item with `BALLOON.upload()`, passing in a `TextureMap` and the `modelCollector` from our `generator` parameter.
Then, we'll use another of its fields, the `output` (which essentially works as a consumer), and use the `accept()` method, so that the models are actually generated.

And that's all! Now, we only need to call our method in the `generateItemModels()` method.

@[code lang=java transcludeWith=:::datagen-model-custom:balloon](@/reference/latest/src/client/java/com/example/docs/datagen/FabricDocsReferenceModelProvider.java)

## Sources and Links {#sources-and-links}

You can view the example tests in [Fabric API](https://github.com/FabricMC/fabric/blob/1.21.4/fabric-data-generation-api-v1/src/), this documentation's [Reference Mod](https://github.com/FabricMC/fabric-docs/tree/main/reference) and the [Minecraft Wiki](https://minecraft.wiki/) for more information.
1 change: 1 addition & 0 deletions develop/data-generation/setup.md
Original file line number Diff line number Diff line change
Expand Up @@ -84,3 +84,4 @@ Now that datagen is set up, we need to add **providers**. These are what generat
- [Recipes](./recipes)
- [Tags](./tags)
- [Translations](./translations)
- [Item Models](./item-models.md)
Loading