-
Notifications
You must be signed in to change notification settings - Fork 180
Block Model Generation/Datagen #268
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from 44 commits
Commits
Show all changes
48 commits
Select commit
Hold shift + click to select a range
cc75667
Created example ModelProvider
Fellteros dbd321c
Registered ModelProvider
Fellteros 0215b1c
Added an example block
Fellteros f9bfaee
Revert since I created the files in the wrong version. srry bout that
Fellteros f63d2bf
Added the example ModelProvider and registered it
Fellteros a044921
created the actual page and added it to the sidebar
Fellteros eaadf7c
Added Simple Cube All, Singletons and Block Texture Pool chapters
Fellteros caa5ce7
Added the Model Generation translation
Fellteros 8e33244
Added textures to Ruby Block, Door, Trapdoor and Steel Block
Fellteros 9954500
Added textures to Ruby Door and Pipe Block
Fellteros 2e71383
Added page for item model generation. Feel free to complete it, I won't.
Fellteros e1dd6e1
Added the Item Model Generation Page, renamed models.md to block-mode…
Fellteros 40f0bb0
Added translations for all blocks from Model Generation tutorial.
Fellteros 521d207
Added needed methods
Fellteros 58fe6b9
Added a new helper method for easier addition of Items
Fellteros c485173
Added example blocks and a new helper method for Model Generation
Fellteros deeef7c
Put all textures into one atlas
Fellteros 4574ef3
Completed the tutorial, added links and sources
Fellteros 9e08adb
Added translations for all blocks from Block Model Generation
Fellteros 2af0474
Added translations for block-models.md and item-models.md
Fellteros abb2c06
Created an example block for the custom datagen method implementation
Fellteros 3748daa
blockstates, block models and item models of all blocks from Block Mo…
Fellteros 1b9928f
blockstates, block models and item models of all blocks from Block Mo…
Fellteros db83bf0
Merge remote-tracking branch 'origin/main'
Fellteros 1c4ffe1
Deleted item-models.md as it is redundant.
Fellteros 6c740c5
Removed item-models.md page, as it is redundant
Fellteros c49b770
Removed the getStateForNeighborUpdate method as it is redundant.
Fellteros 79e6751
Removed the helper methods as they are redundant.
Fellteros 2ef8bdf
Optimized imports
Fellteros 48a7e5e
renamed Identifiers for better understanding
Fellteros c52d367
Made changes according to natri0's suggestions (thx a lot)
Fellteros bf251a2
Made changes according to IMB11's requests
Fellteros 066f319
Reformatted the RUBY_FAMILY
Fellteros 8bbf9cc
Deleted as it isn't used anymore
Fellteros e26528e
Added previews and files for download into the assets folder
Fellteros 1458660
Fixed a few typos
Fellteros 109dafd
(Hopefully) fixed all markdown-lint issues in block-models.md
Fellteros fdce0da
Fixed a few typos and optimized imports
Fellteros 68b5276
Merge remote-tracking branch 'origin/main'
Fellteros f291c76
Checkstyle fixes
Fellteros bea15b9
Added item texture for Ruby Door, added it to the textures .zip folde…
Fellteros 55684d1
Changed according to its-miroma's suggestions
Fellteros 69c26df
Capitalized the PREREQUISITES title in block-models.md
Fellteros b4ddb7a
Merge branch 'main' into main
Fellteros 36434ce
Changed according to IMB11's requests
Fellteros 0e4881d
Excluded imports
Fellteros 01501f6
formatted the JSON properly
Fellteros 41b2563
Merge remote-tracking branch 'origin/main'
Fellteros File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,216 @@ | ||
--- | ||
title: Block Model Generation | ||
description: A guide to generating block models and blockstates via datagen. | ||
authors: | ||
- Fellteros | ||
- natri0 | ||
- IMB11 | ||
- its-miroma | ||
--- | ||
|
||
# Block Model Generation {#block-model-generation} | ||
|
||
::: info PREREQUISITES | ||
Make sure you've completed the [datagen setup](./setup) process first. | ||
::: | ||
|
||
## 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) | ||
its-miroma marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
Register this class in your `DataGeneratorEntrypoint` within the `onInitializeDataGenerator` method. | ||
|
||
## Blockstates and Block Models {#blockstates-and-block-models} | ||
|
||
```java | ||
@Override | ||
public void generateBlockStateModels(BlockStateModelGenerator blockStateModelGenerator) { | ||
} | ||
``` | ||
|
||
For block models, we will primarily be focusing on the `generateBlockStateModels` method. Notice the parameter `BlockStateModelGenerator blockStateModelGenerator` - this object will be responsible for generating all the JSON files. | ||
Here are some handy examples you can use to generate your desired models: | ||
|
||
### Simple Cube All {#simple-cube-all} | ||
|
||
@[code lang=java transcludeWith=:::datagen-model:cube-all](@/reference/latest/src/client/java/com/example/docs/datagen/FabricDocsReferenceModelProvider.java) | ||
|
||
This is the most commonly used function. It generates a JSON model file for a normal `cube_all` block model. One texture is used for all six sides, in this case we use `steel_block`. | ||
|
||
@[code](@/reference/latest/src/main/generated/assets/fabric-docs-reference/models/block/steel_block.json) | ||
|
||
It also generates a blockstate JSON file. Since we have no blockstate properties (e.g. Axis, Facing, ...), one variant is sufficient, and is used every time the block is placed. | ||
|
||
@[code](@/reference/latest/src/main/generated/assets/fabric-docs-reference/blockstates/steel_block.json) | ||
|
||
<DownloadEntry visualURL="/assets/develop/data-generation/block-model/steel_block_big.png" downloadURL="/assets/develop/data-generation/block-model/steel_block.png">Steel Block</DownloadEntry> | ||
|
||
### Singletons {#singletons} | ||
|
||
The `registerSingleton` method provides JSON model files based on the `TexturedModel` you pass in and a single blockstate variant. | ||
|
||
@[code lang=java transcludeWith=:::datagen-model:cube-top-for-ends](@/reference/latest/src/client/java/com/example/docs/datagen/FabricDocsReferenceModelProvider.java) | ||
|
||
This method will generate models for a normal cube, that uses the texture file `pipe_block` for the sides and the texture file `pipe_block_top` for the top and bottom sides. | ||
|
||
@[code](@/reference/latest/src/main/generated/assets/fabric-docs-reference/models/block/pipe_block.json) | ||
|
||
:::tip | ||
If you're stuck choosing which `TextureModel` you should use, open the `TexturedModel` class and look at the [`TextureMaps`](#using-texture-map)! | ||
::: | ||
|
||
<DownloadEntry visualURL="/assets/develop/data-generation/block-model/pipe_block_textures_big.png" downloadURL="/assets/develop/data-generation/block-model/pipe_block_textures.zip">Pipe Block</DownloadEntry> | ||
|
||
### Block Texture Pool {#block-texture-pool} | ||
|
||
@[code lang=java transcludeWith=:::datagen-model:block-texture-pool-normal](@/reference/latest/src/client/java/com/example/docs/datagen/FabricDocsReferenceModelProvider.java) | ||
|
||
Another useful method is `registerCubeAllModelTexturePool`: define the textures by passing in the "base block", and then append the "children", which will have the same textures. | ||
In this case, we passed in the `RUBY_BLOCK`, so the stairs, slab and fence will use the `RUBY_BLOCK` texture. | ||
|
||
::: warning | ||
It will also generate a [simple cube all JSON model](#simple-cube-all) for the "base block" to ensure that it has a block model. | ||
|
||
Be aware of this, if you're changing block model of this particular block, as it will result in en error. | ||
::: | ||
|
||
You can also append a `BlockFamily`, which will generate models for all of its "children". | ||
|
||
@[code lang=java transcludeWith=:::datagen-model:family-declaration](@/reference/latest/src/main/java/com/example/docs/block/ModBlocks.java) | ||
|
||
@[code lang=java transcludeWith=:::datagen-model:block-texture-pool-family](@/reference/latest/src/client/java/com/example/docs/datagen/FabricDocsReferenceModelProvider.java) | ||
|
||
<DownloadEntry visualURL="/assets/develop/data-generation/block-model/ruby_block_big.png" downloadURL="/assets/develop/data-generation/block-model/ruby_block.png">Ruby Block</DownloadEntry> | ||
|
||
### Doors and Trapdoors {#doors-and-trapdoors} | ||
|
||
@[code lang=java transcludeWith=:::datagen-model:door-and-trapdoor](@/reference/latest/src/client/java/com/example/docs/datagen/FabricDocsReferenceModelProvider.java) | ||
|
||
Doors and trapdoors are a little different. Here, you have to make three new textures - two for the door, and one for the trapdoor. | ||
|
||
1. The door: | ||
- It has two parts - the upper half and the lower half. **Each needs its own texture:** in this case `ruby_door_top` for the upper half and `ruby_door_bottom` for the lower. | ||
- The `registerDoor()` method will create models for all orientations of the door, both open and closed. | ||
- **You also need an item texture!** Put it in `assets/<mod_id>/textures/item/` folder. | ||
2. The trapdoor: | ||
- Here, you need only one texture, in this case named `ruby_trapdoor`. It will be used for all sides. | ||
- Since `TrapdoorBlock` has a `FACING` property, you can use the commented out method to generate model files with rotated textures = the trapdoor will be "orientable". Otherwise, it will look the same no matter the direction it's facing. | ||
|
||
<DownloadEntry visualURL="/assets/develop/data-generation/block-model/ruby_door_trapdoor_big.png" downloadURL="/assets/develop/data-generation/block-model/ruby_door_trapdoor_textures.zip">Ruby Door and Trapdoor</DownloadEntry> | ||
|
||
## Custom Block Models {#custom-block-models} | ||
|
||
In this section, we'll create the models for a Vertical Oak Log Slab, with Oak Log textures. | ||
|
||
_Points 2. - 6. are declared in an inner static helper class called `CustomBlockStateModelGenerator`._ | ||
|
||
### Custom Block Class {#custom-block-class} | ||
|
||
Create a `VerticalSlab` block with a `FACING` property and a `SINGLE` boolean property, like in the [Block States](../blocks/blockstates) tutorial. `SINGLE` will indicate if there are both slabs. | ||
Then you should override `getOutlineShape` and `getCollisionShape`, so that the outline is rendered correctly, and the block has the correct collision shape. | ||
|
||
@[code lang=java transcludeWith=:::datagen-model-custom:voxels](@/reference/latest/src/main/java/com/example/docs/block/custom/VerticalSlabBlock.java) | ||
|
||
@[code lang=java transcludeWith=:::datagen-model-custom:collision](@/reference/latest/src/main/java/com/example/docs/block/custom/VerticalSlabBlock.java) | ||
|
||
Also override the `canReplace()` method, otherwise you couldn't make the slab a full block. | ||
|
||
@[code lang=java transcludeWith=:::datagen-model-custom:replace](@/reference/latest/src/main/java/com/example/docs/block/custom/VerticalSlabBlock.java) | ||
|
||
And you're done! You can now test the block out and place it in game. | ||
|
||
### Parent Block Model {#parent-block-model} | ||
|
||
Now, let's create a parent block model. It will determine the size, position in hand or other slots and the `x` and `y` coordinates of the texture. | ||
I highly recommend using [Blockbench](https://www.blockbench.net/) for this, as making it manually is a really tedious process. It should look something like this: | ||
its-miroma marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
@[code lang=json](@/reference/latest/src/main/resources/assets/fabric-docs-reference/models/block/vertical_slab.json) | ||
its-miroma marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
See [how blockstates are formatted](https://minecraft.wiki/w/Blockstates_definition_format) for more information. | ||
Notice the `#bottom`, `#top`, `#side` keywords. They act as variables that can be set by models that have this one as a parent: | ||
|
||
```json | ||
{ | ||
"parent": "minecraft:block/cube_bottom_top", | ||
"textures": { | ||
"bottom": "minecraft:block/sandstone_bottom", | ||
"side": "minecraft:block/sandstone", | ||
"top": "minecraft:block/sandstone_top" | ||
} | ||
} | ||
``` | ||
|
||
The `bottom` value will replace the `#bottom` placeholder and so on. **Put it in the `resources/assets/mod_id/models/block/` folder.** | ||
|
||
### Custom Model {#custom-model} | ||
|
||
Another thing we will need is an instance of the `Model` class. It will represent the actual [parent block model](#parent-block-model) inside our mod. | ||
|
||
@[code lang=java transcludeWith=:::datagen-model-custom:model](@/reference/latest/src/client/java/com/example/docs/datagen/FabricDocsReferenceModelProvider.java) | ||
|
||
The `block()` method creates a new `Model`, pointing to the `vertical_slab.json` file inside the `resources/assets/mod_id/models/block/` folder. | ||
The `TextureKey`s represent the "placeholders" (`#bottom`, `#top`, ...) as an Object. | ||
|
||
### Using Texture Map {#using-texture-map} | ||
|
||
What does `TextureMap` do? It actually provides the Identifiers that point to the textures. It technically behaves like a normal map - you associate a `TextureKey` (Key) with an `Identifier` (Value). | ||
|
||
You can either use the vanilla ones, like `TextureMap.all()`(which associates all TextureKeys with the same Identifier), or create a new one, by creating a new instance and then using `.put()` to associate keys with values. | ||
|
||
::: tip | ||
`TextureMap.all()` associates all TextureKeys with the same Identifier, no matter how many of them there are! | ||
::: | ||
|
||
Since we want to use the Oak Log textures, but have the ``BOTTOM``, ``TOP`` and ``SIDE`` ``TextureKey``s, we need to create a new one. | ||
|
||
@[code lang=java transcludeWith=:::datagen-model-custom:texture-map](@/reference/latest/src/client/java/com/example/docs/datagen/FabricDocsReferenceModelProvider.java) | ||
|
||
The ``bottom`` and ``top`` faces will use `oak_log_top.png`, the sides will use `oak_log.png`. | ||
|
||
::: warning | ||
All `TextureKey`s in the TextureMap **have to** match all `TextureKey`s in your parent block model! | ||
::: | ||
|
||
### Custom `BlockStateSupplier` Method {#custom-supplier-method} | ||
|
||
The `BlockStateSupplier` contains all blockstate variants, their rotation, and other options like uvlock. | ||
|
||
@[code lang=java transcludeWith=:::datagen-model-custom:supplier](@/reference/latest/src/client/java/com/example/docs/datagen/FabricDocsReferenceModelProvider.java) | ||
|
||
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()`. | ||
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. | ||
|
||
### Custom Datagen Method {#custom-datagen-method} | ||
|
||
The last step - creating an actual method you can call and that will generate the JSONs. | ||
But what are the parameters for? | ||
|
||
1. `BlockStateModelGenerator bsmg`, the same one that got passed into `generateBlockStateModels`. | ||
its-miroma marked this conversation as resolved.
Show resolved
Hide resolved
|
||
2. `Block vertSlabBlock` is the block to which we will generate the JSONs. | ||
3. `Block fullBlock` - is the model used when the `SINGLE` property is false = the slab block looks like a full block. | ||
4. `TextureMap textures` defines the actual textures the model uses. See the [Using Texture Map](#using-texture-map) chapter. | ||
|
||
@[code lang=java transcludeWith=:::datagen-model-custom:gen](@/reference/latest/src/client/java/com/example/docs/datagen/FabricDocsReferenceModelProvider.java) | ||
|
||
First, we get the `Identifier` of the single slab model with `VERTICAL_SLAB.upload()`. Then we get the `Identifier` of the full block model with `ModelIds.getBlockModelId()`, and pass those two models into `createVerticalSlabBlockStates`. | ||
The `BlockStateSupplier` gets passed into the `blockStateCollector`, so that the JSON files are actually generated. | ||
Also, we create a model for the vertical slab item with `BlockStateModelGenerator.registerParentedItemModel()`. | ||
|
||
And that is all! Now all that's left to do is to call our method in our `ModelProvider`: | ||
|
||
@[code lang=java transcludeWith=:::datagen-model-custom:method-call](@/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 and the Fabric docs reference mod for more information. | ||
its-miroma marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
You can also find more examples of using custom datagen methods by browsing mods' open-source code, for example [Vanilla+ Blocks](https://github.com/Fellteros/vanillablocksplus) and [Vanilla+ Verticals](https://github.com/Fellteros/vanillavsplus) by Fellteros. |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added
BIN
+731 Bytes
public/assets/develop/data-generation/block-model/pipe_block_textures.zip
Binary file not shown.
Binary file added
BIN
+723 Bytes
public/assets/develop/data-generation/block-model/pipe_block_textures_big.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added
BIN
+221 Bytes
public/assets/develop/data-generation/block-model/pipe_block_top.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added
BIN
+846 Bytes
public/assets/develop/data-generation/block-model/ruby_block_big.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added
BIN
+388 Bytes
public/assets/develop/data-generation/block-model/ruby_door_bottom.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added
BIN
+388 Bytes
public/assets/develop/data-generation/block-model/ruby_door_top.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added
BIN
+1.77 KB
public/assets/develop/data-generation/block-model/ruby_door_trapdoor_big.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added
BIN
+2.2 KB
public/assets/develop/data-generation/block-model/ruby_door_trapdoor_textures.zip
Binary file not shown.
Binary file added
BIN
+393 Bytes
public/assets/develop/data-generation/block-model/ruby_trapdoor.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added
BIN
+393 Bytes
public/assets/develop/data-generation/block-model/ruby_trapdoor_big.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added
BIN
+1.27 KB
public/assets/develop/data-generation/block-model/steel_block_big.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.