From 26e2c519392f15d81cd20b6bfa073b2727ec781f Mon Sep 17 00:00:00 2001
From: Fellteros <144528463+Fellteros@users.noreply.github.com>
Date: Fri, 24 Jan 2025 17:06:34 +0100
Subject: [PATCH] Block Model Generation/Datagen (#268)
---
.vitepress/sidebars/develop.ts | 6 +-
develop/data-generation/block-models.md | 216 ++++++++++++++++++
.../block-model/pipe_block.png | Bin 0 -> 130 bytes
.../block-model/pipe_block_textures.zip | Bin 0 -> 731 bytes
.../block-model/pipe_block_textures_big.png | Bin 0 -> 723 bytes
.../block-model/pipe_block_top.png | Bin 0 -> 221 bytes
.../block-model/ruby_block.png | Bin 0 -> 393 bytes
.../block-model/ruby_block_big.png | Bin 0 -> 846 bytes
.../data-generation/block-model/ruby_door.png | Bin 0 -> 315 bytes
.../block-model/ruby_door_bottom.png | Bin 0 -> 388 bytes
.../block-model/ruby_door_top.png | Bin 0 -> 388 bytes
.../block-model/ruby_door_trapdoor_big.png | Bin 0 -> 1812 bytes
.../ruby_door_trapdoor_textures.zip | Bin 0 -> 2252 bytes
.../block-model/ruby_trapdoor.png | Bin 0 -> 393 bytes
.../block-model/ruby_trapdoor_big.png | Bin 0 -> 393 bytes
.../block-model/steel_block.png | Bin 0 -> 1198 bytes
.../block-model/steel_block_big.png | Bin 0 -> 1300 bytes
.../FabricDocsReferenceDataGenerator.java | 2 +
...abricDocsReferenceEnglishLangProvider.java | 10 +
.../FabricDocsReferenceModelProvider.java | 157 +++++++++++++
.../blockstates/pipe_block.json | 7 +
.../blockstates/ruby_block.json | 7 +
.../blockstates/ruby_door.json | 124 ++++++++++
.../blockstates/ruby_fence.json | 48 ++++
.../blockstates/ruby_slab.json | 13 ++
.../blockstates/ruby_stairs.json | 209 +++++++++++++++++
.../blockstates/ruby_trapdoor.json | 58 +++++
.../blockstates/steel_block.json | 7 +
.../blockstates/vertical_oak_log_slab.json | 39 ++++
.../items/pipe_block.json | 6 +
.../items/ruby_block.json | 6 +
.../items/ruby_door.json | 6 +
.../items/ruby_fence.json | 6 +
.../items/ruby_slab.json | 6 +
.../items/ruby_stairs.json | 6 +
.../items/ruby_trapdoor.json | 6 +
.../items/steel_block.json | 6 +
.../items/vertical_oak_log_slab.json | 6 +
.../fabric-docs-reference/lang/en_us.json | 9 +
.../models/block/pipe_block.json | 7 +
.../models/block/ruby_block.json | 6 +
.../models/block/ruby_door_bottom_left.json | 7 +
.../block/ruby_door_bottom_left_open.json | 7 +
.../models/block/ruby_door_bottom_right.json | 7 +
.../block/ruby_door_bottom_right_open.json | 7 +
.../models/block/ruby_door_top_left.json | 7 +
.../models/block/ruby_door_top_left_open.json | 7 +
.../models/block/ruby_door_top_right.json | 7 +
.../block/ruby_door_top_right_open.json | 7 +
.../models/block/ruby_fence_inventory.json | 6 +
.../models/block/ruby_fence_post.json | 6 +
.../models/block/ruby_fence_side.json | 6 +
.../models/block/ruby_slab.json | 8 +
.../models/block/ruby_slab_top.json | 8 +
.../models/block/ruby_stairs.json | 8 +
.../models/block/ruby_stairs_inner.json | 8 +
.../models/block/ruby_stairs_outer.json | 8 +
.../models/block/ruby_trapdoor_bottom.json | 6 +
.../models/block/ruby_trapdoor_open.json | 6 +
.../models/block/ruby_trapdoor_top.json | 6 +
.../models/block/steel_block.json | 6 +
.../models/block/vertical_oak_log_slab.json | 8 +
.../models/item/ruby_door.json | 6 +
.../com/example/docs/block/ModBlocks.java | 79 +++++++
.../docs/block/custom/VerticalSlabBlock.java | 131 +++++++++++
.../java/com/example/docs/item/ModItems.java | 1 -
.../models/block/vertical_slab.json | 174 ++++++++++++++
.../textures/block/pipe_block.png | Bin 0 -> 130 bytes
.../textures/block/pipe_block_top.png | Bin 0 -> 221 bytes
.../textures/block/ruby_block.png | Bin 0 -> 393 bytes
.../textures/block/ruby_door_bottom.png | Bin 0 -> 388 bytes
.../textures/block/ruby_door_top.png | Bin 0 -> 388 bytes
.../textures/block/ruby_trapdoor.png | Bin 0 -> 393 bytes
.../textures/block/steel_block.png | Bin 0 -> 1198 bytes
.../textures/item/ruby_door.png | Bin 0 -> 315 bytes
sidebar_translations.json | 1 +
76 files changed, 1515 insertions(+), 2 deletions(-)
create mode 100644 develop/data-generation/block-models.md
create mode 100644 public/assets/develop/data-generation/block-model/pipe_block.png
create mode 100644 public/assets/develop/data-generation/block-model/pipe_block_textures.zip
create mode 100644 public/assets/develop/data-generation/block-model/pipe_block_textures_big.png
create mode 100644 public/assets/develop/data-generation/block-model/pipe_block_top.png
create mode 100644 public/assets/develop/data-generation/block-model/ruby_block.png
create mode 100644 public/assets/develop/data-generation/block-model/ruby_block_big.png
create mode 100644 public/assets/develop/data-generation/block-model/ruby_door.png
create mode 100644 public/assets/develop/data-generation/block-model/ruby_door_bottom.png
create mode 100644 public/assets/develop/data-generation/block-model/ruby_door_top.png
create mode 100644 public/assets/develop/data-generation/block-model/ruby_door_trapdoor_big.png
create mode 100644 public/assets/develop/data-generation/block-model/ruby_door_trapdoor_textures.zip
create mode 100644 public/assets/develop/data-generation/block-model/ruby_trapdoor.png
create mode 100644 public/assets/develop/data-generation/block-model/ruby_trapdoor_big.png
create mode 100644 public/assets/develop/data-generation/block-model/steel_block.png
create mode 100644 public/assets/develop/data-generation/block-model/steel_block_big.png
create mode 100644 reference/latest/src/client/java/com/example/docs/datagen/FabricDocsReferenceModelProvider.java
create mode 100644 reference/latest/src/main/generated/assets/fabric-docs-reference/blockstates/pipe_block.json
create mode 100644 reference/latest/src/main/generated/assets/fabric-docs-reference/blockstates/ruby_block.json
create mode 100644 reference/latest/src/main/generated/assets/fabric-docs-reference/blockstates/ruby_door.json
create mode 100644 reference/latest/src/main/generated/assets/fabric-docs-reference/blockstates/ruby_fence.json
create mode 100644 reference/latest/src/main/generated/assets/fabric-docs-reference/blockstates/ruby_slab.json
create mode 100644 reference/latest/src/main/generated/assets/fabric-docs-reference/blockstates/ruby_stairs.json
create mode 100644 reference/latest/src/main/generated/assets/fabric-docs-reference/blockstates/ruby_trapdoor.json
create mode 100644 reference/latest/src/main/generated/assets/fabric-docs-reference/blockstates/steel_block.json
create mode 100644 reference/latest/src/main/generated/assets/fabric-docs-reference/blockstates/vertical_oak_log_slab.json
create mode 100644 reference/latest/src/main/generated/assets/fabric-docs-reference/items/pipe_block.json
create mode 100644 reference/latest/src/main/generated/assets/fabric-docs-reference/items/ruby_block.json
create mode 100644 reference/latest/src/main/generated/assets/fabric-docs-reference/items/ruby_door.json
create mode 100644 reference/latest/src/main/generated/assets/fabric-docs-reference/items/ruby_fence.json
create mode 100644 reference/latest/src/main/generated/assets/fabric-docs-reference/items/ruby_slab.json
create mode 100644 reference/latest/src/main/generated/assets/fabric-docs-reference/items/ruby_stairs.json
create mode 100644 reference/latest/src/main/generated/assets/fabric-docs-reference/items/ruby_trapdoor.json
create mode 100644 reference/latest/src/main/generated/assets/fabric-docs-reference/items/steel_block.json
create mode 100644 reference/latest/src/main/generated/assets/fabric-docs-reference/items/vertical_oak_log_slab.json
create mode 100644 reference/latest/src/main/generated/assets/fabric-docs-reference/models/block/pipe_block.json
create mode 100644 reference/latest/src/main/generated/assets/fabric-docs-reference/models/block/ruby_block.json
create mode 100644 reference/latest/src/main/generated/assets/fabric-docs-reference/models/block/ruby_door_bottom_left.json
create mode 100644 reference/latest/src/main/generated/assets/fabric-docs-reference/models/block/ruby_door_bottom_left_open.json
create mode 100644 reference/latest/src/main/generated/assets/fabric-docs-reference/models/block/ruby_door_bottom_right.json
create mode 100644 reference/latest/src/main/generated/assets/fabric-docs-reference/models/block/ruby_door_bottom_right_open.json
create mode 100644 reference/latest/src/main/generated/assets/fabric-docs-reference/models/block/ruby_door_top_left.json
create mode 100644 reference/latest/src/main/generated/assets/fabric-docs-reference/models/block/ruby_door_top_left_open.json
create mode 100644 reference/latest/src/main/generated/assets/fabric-docs-reference/models/block/ruby_door_top_right.json
create mode 100644 reference/latest/src/main/generated/assets/fabric-docs-reference/models/block/ruby_door_top_right_open.json
create mode 100644 reference/latest/src/main/generated/assets/fabric-docs-reference/models/block/ruby_fence_inventory.json
create mode 100644 reference/latest/src/main/generated/assets/fabric-docs-reference/models/block/ruby_fence_post.json
create mode 100644 reference/latest/src/main/generated/assets/fabric-docs-reference/models/block/ruby_fence_side.json
create mode 100644 reference/latest/src/main/generated/assets/fabric-docs-reference/models/block/ruby_slab.json
create mode 100644 reference/latest/src/main/generated/assets/fabric-docs-reference/models/block/ruby_slab_top.json
create mode 100644 reference/latest/src/main/generated/assets/fabric-docs-reference/models/block/ruby_stairs.json
create mode 100644 reference/latest/src/main/generated/assets/fabric-docs-reference/models/block/ruby_stairs_inner.json
create mode 100644 reference/latest/src/main/generated/assets/fabric-docs-reference/models/block/ruby_stairs_outer.json
create mode 100644 reference/latest/src/main/generated/assets/fabric-docs-reference/models/block/ruby_trapdoor_bottom.json
create mode 100644 reference/latest/src/main/generated/assets/fabric-docs-reference/models/block/ruby_trapdoor_open.json
create mode 100644 reference/latest/src/main/generated/assets/fabric-docs-reference/models/block/ruby_trapdoor_top.json
create mode 100644 reference/latest/src/main/generated/assets/fabric-docs-reference/models/block/steel_block.json
create mode 100644 reference/latest/src/main/generated/assets/fabric-docs-reference/models/block/vertical_oak_log_slab.json
create mode 100644 reference/latest/src/main/generated/assets/fabric-docs-reference/models/item/ruby_door.json
create mode 100644 reference/latest/src/main/java/com/example/docs/block/custom/VerticalSlabBlock.java
create mode 100644 reference/latest/src/main/resources/assets/fabric-docs-reference/models/block/vertical_slab.json
create mode 100644 reference/latest/src/main/resources/assets/fabric-docs-reference/textures/block/pipe_block.png
create mode 100644 reference/latest/src/main/resources/assets/fabric-docs-reference/textures/block/pipe_block_top.png
create mode 100644 reference/latest/src/main/resources/assets/fabric-docs-reference/textures/block/ruby_block.png
create mode 100644 reference/latest/src/main/resources/assets/fabric-docs-reference/textures/block/ruby_door_bottom.png
create mode 100644 reference/latest/src/main/resources/assets/fabric-docs-reference/textures/block/ruby_door_top.png
create mode 100644 reference/latest/src/main/resources/assets/fabric-docs-reference/textures/block/ruby_trapdoor.png
create mode 100644 reference/latest/src/main/resources/assets/fabric-docs-reference/textures/block/steel_block.png
create mode 100644 reference/latest/src/main/resources/assets/fabric-docs-reference/textures/item/ruby_door.png
diff --git a/.vitepress/sidebars/develop.ts b/.vitepress/sidebars/develop.ts
index 4a50e1c65..d9efb8e3c 100644
--- a/.vitepress/sidebars/develop.ts
+++ b/.vitepress/sidebars/develop.ts
@@ -235,7 +235,11 @@ export default [
{
text: "develop.dataGeneration.lootTables",
link: "/develop/data-generation/loot-tables"
- }
+ },
+ {
+ text: "develop.dataGeneration.blockModels",
+ link: "/develop/data-generation/block-models"
+ }
]
},
{
diff --git a/develop/data-generation/block-models.md b/develop/data-generation/block-models.md
new file mode 100644
index 000000000..cb6fe44d7
--- /dev/null
+++ b/develop/data-generation/block-models.md
@@ -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)
+
+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)
+
+Steel Block
+
+### 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)!
+:::
+
+Pipe Block
+
+### 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)
+
+Ruby Block
+
+### 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//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.
+
+Ruby Door and Trapdoor
+
+## 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.
+It's recommended to use an editor such as [Blockbench](https://www.blockbench.net/) for this, as making it manually is a really tedious process. It should look something like this:
+
+@[code lang=json](@/reference/latest/src/main/resources/assets/fabric-docs-reference/models/block/vertical_slab.json)
+
+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 generator`, the same one that got passed into `generateBlockStateModels`.
+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](https://github.com/FabricMC/fabric/blob/1.21.4/fabric-data-generation-api-v1/src/) and this documentation's [Reference Mod](https://github.com/FabricMC/fabric-docs/tree/main/reference) for more information.
+
+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.
diff --git a/public/assets/develop/data-generation/block-model/pipe_block.png b/public/assets/develop/data-generation/block-model/pipe_block.png
new file mode 100644
index 0000000000000000000000000000000000000000..12d43aaf60c28506a01e7cdb1c52441cc536b388
GIT binary patch
literal 130
zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`jKx9jP7LeL$-D$|Y&=~YLo9mV
zo-t%>VBk4&prL8TiY2Soca}2s@%Xbyv?tDnm{r-UW|@l_~@
literal 0
HcmV?d00001
diff --git a/public/assets/develop/data-generation/block-model/pipe_block_textures.zip b/public/assets/develop/data-generation/block-model/pipe_block_textures.zip
new file mode 100644
index 0000000000000000000000000000000000000000..6e3638f5cab1ced7390e7be8eaaabb3d9abd812d
GIT binary patch
literal 731
zcmWIWW@Zs#-~hr22}V&2NPv$)fuSI?AT>TICqFq`uOKhIw1S&~kp-j#OoWE;GO!=)
z>Q3MMwI^NSOHcZ1o)5*(pH6y|l#uY?>z4vfrb|o;XAZKdJhlJt&l1#g)bX7k&+Bt1
z_plV@*u=^>>r~yJXPA!<-7kt-^G*cyJgk8EZQQzoZ~Hdk{$3M^6s&JYFC!!|Gcex
z`u>J+*;hBW7A2=YKDgob?67@VbMg~%4t+>^U$5Hvq~-a!r@!yt`}^B_(e}Hcs^w?f
zMfvx9=PH?V!{mO+UaiOP|E-Vi>#W^AXSH%sDcf}>01w4~b`FKN~r
z3-unFt*ZYqBBwHV`-|jPA|HQduNK>;H$&v?>6(O_tG>+)uKcVkVg7Ym-X81IB2VJj
z{KM_1m-=z~f`ji;=MS~}z@WPe4n9UE5oScvKn_|y1__`F2-wyLq6s7vRt82;LJ9Cj
nm(0r%WME+G^>lFz
zshIQj?!nwg4iXI)?_L#i5Z>ZcnAgc?QMjDb%EKx_q*u+X=6&qkhRKJQ$Itrs*t?;9{>Jj@_G46yZOQU|5w;7tE*2bso(tF{@4HB
zb^mAoDtoY&lc5C-{gwZF;Azp%-rormb8mm!$I5qxg&~m%10AkqSlv6XJ?`(GA1^+q
z&%Z7=^Y8D3Hco~^EEs6oduEGYRyI>+GAQ_9pf?|$GhW$$zmjoH3R8mtBRbmf^fyD8
z{rmba-`OnQHz*r3I?P}|M>pQRXSMkCy#LK!{{xkbXAH2a`C`}LUoThpzLw|O&&ZQl
zy>$9K^Ni9jwJh_VKc9=kt?yYYzL)-s{3f_z5>~G+`_6b~o%8v1i`W1AclEvPhI8lV
z`7j8mVW6@fpBci|e_kJVyd8(1KGia8{$^KRpMQ=!K~)$dmVlA=b{~JjSF3NYJ~OO2
z{P`SKYqr(MA9z*#H+=KC^Xk}xu0a04w%q-N@(1{^8t{!bDPvMqeKUg~D9w7h`njxg
HN@xNAQfLf5
literal 0
HcmV?d00001
diff --git a/public/assets/develop/data-generation/block-model/pipe_block_top.png b/public/assets/develop/data-generation/block-model/pipe_block_top.png
new file mode 100644
index 0000000000000000000000000000000000000000..2c6dbf3fced778167ea558b8046ee43aea6285f8
GIT binary patch
literal 221
zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`jKx9jP7LeL$-D$|rhB?LhFJ8@
z4RqvdP~chJ#{MSMrf>P%Ez94qR~_ovwQ^%;