tutorial:datagen_model
Differences
This shows you the differences between two versions of the page.
Both sides previous revisionPrevious revisionNext revision | Previous revision | ||
tutorial:datagen_model [2025/04/18 13:17] – [Adding Item Models] solidblock | tutorial:datagen_model [2025/04/18 14:59] (current) – [Model Generation] solidblock | ||
---|---|---|---|
Line 1: | Line 1: | ||
====== Model Generation ====== | ====== Model Generation ====== | ||
- | We know that almost every item needs a corresponding **item baked model** (or //item model// for short), and an **item models definition** since 1.21.4. Each block needs a **block baked model** (or //block model// for short) and a **block states definition**, | + | :!: The page is translated from [[zh_cn: |
+ | |||
+ | We know that almost every item needs a corresponding **item baked model** (or //item model// for short), and an **item models definition** since 1.21.4. Each block needs a **block baked model** (or //block model// for short) and a **block states definition**, | ||
In data generator, models and definitions are generated together. Usually, when generation a model, a model id is returned, which will be used in the block states definition or item models definition. We will go into that from simple ones to details. | In data generator, models and definitions are generated together. Usually, when generation a model, a model id is returned, which will be used in the block states definition or item models definition. We will go into that from simple ones to details. | ||
Line 85: | Line 87: | ||
</ | </ | ||
- | ==== Addin Data Generation For a Directional Block ==== | ||
- | **QUICK WARNING**: This is very complicated as heck!!! | ||
- | In this, example, we will generate directional blockstates | + | ===== Common vanilla block models (taking stairs and slabs for example) ===== |
- | Firstly, we add the block itself and register | + | Sometimes a block model is not so simple, because |
- | <code java> | + | |
- | // In the Tutorial class (or your mod initializer class) | + | |
- | public static final Block MACHINE_BLOCK = new Block(FabricBlockSettings.copy(Blocks.BLAST_FURNACE)); | + | |
- | @Override | + | For versions after 1.21.2: |
- | public | + | <code java TutorialBlocks.json> |
- | | + | |
- | } | + | settings -> new StairsBlock(Blocks.DIAMOND_BLOCK.getDefaultState(), settings), |
+ | | ||
+ | public static final Block DIAMOND_SLAB = register("diamond_slab", | ||
+ | SlabBlock:: | ||
+ | AbstractBlock.Settings.copy(Blocks.DIORITE_SLAB)); | ||
</ | </ | ||
- | Now that we have successfully registered our block, let's get to the good stuff! | ||
- | <code java> | + | For versions before 1.21.2: |
- | private | + | <code java TutorialBlocks.json> |
- | private MyModelGenerator(FabricDataOutput generator) { | + | |
- | super(generator); | + | new StairsBlock(Blocks.DIAMOND_BLOCK.getDefaultState(), |
- | } | + | |
- | + | | |
- | @Override | + | new SlabBlock(AbstractBlock.Settings.copy(Blocks.DIORITE_SLAB))); |
- | public void generateBlockStateModels(BlockStateModelGenerator blockStateModelGenerator) | + | </ |
- | // ... | + | |
- | blockStateModelGenerator.blockStateCollector.accept(MultipartBlockStateSupplier.create(Tutorial.MACHINE_BLOCK) | + | And then we create regular stairs model, inner corner stairs model, outer corner stairs model, bottom slab model and top slab model. For double slab model we directly use vanilla diamond block model. When creating models for these blocks, the id of the models will be returned, and we create block states definitions with the utility methods in '' |
- | .with(When.create().set(Properties.HORIZONTAL_FACING, Direction.NORTH), | + | |
- | | + | <code java TutorialModelGenerator.json> |
- | } | + | final TextureMap diamondTexture = TextureMap.all(Identifier.ofVanilla(" |
- | + | ||
- | @Override | + | final Identifier stairsModelId = Models.STAIRS.upload(TutorialBlocks.DIAMOND_STAIRS, |
- | public void generateItemModels(ItemModelGenerator itemModelGenerator) { | + | final Identifier innerStairsModelId = Models.INNER_STAIRS.upload(TutorialBlocks.DIAMOND_STAIRS, |
- | // ... | + | final Identifier outerStairsModelId = Models.OUTER_STAIRS.upload(TutorialBlocks.DIAMOND_STAIRS, |
- | } | + | |
+ | BlockStateModelGenerator.createStairsBlockState(TutorialBlocks.DIAMOND_STAIRS, | ||
+ | BlockStateModelGenerator.createWeightedVariant(innerStairsModelId), | ||
+ | | ||
+ | BlockStateModelGenerator.createWeightedVariant(outerStairsModelId))); | ||
+ | blockStateModelGenerator.registerParentedItemModel(TutorialBlocks.DIAMOND_STAIRS, stairsModelId); | ||
+ | |||
+ | final Identifier slabBottomModelId = Models.SLAB.upload(TutorialBlocks.DIAMOND_SLAB, diamondTexture, | ||
+ | final Identifier slabTopModelId = Models.SLAB_TOP.upload(TutorialBlocks.DIAMOND_SLAB, | ||
+ | blockStateModelGenerator.blockStateCollector.accept( | ||
+ | BlockStateModelGenerator.createSlabBlockState(TutorialBlocks.DIAMOND_SLAB, | ||
+ | BlockStateModelGenerator.createWeightedVariant(slabBottomModelId), | ||
+ | BlockStateModelGenerator.createWeightedVariant(slabTopModelId), | ||
+ | BlockStateModelGenerator.createWeightedVariant(Identifier.ofVanilla(" | ||
+ | | ||
+ | | ||
+ | </ | ||
+ | |||
+ | > In versions before 1.21.4, we do not need to call '' | ||
+ | |||
+ | Well done! We successfully added all models, block states definitions and item models definitions needed with several lines of code. | ||
+ | |||
+ | ===== Directional blocks | ||
+ | |||
+ | A directional block usually uses one block model, but in the block states definition, different model variants will be mapped into, such as different x-rotation, y-rotation and uvlock. (These words seem similar when we used to manually write block states definitions JSONs?) | ||
+ | |||
+ | Taking a vertical slab block we created in the [[directionalblock]] tutorial as an example, we generate models and block states definitions with data generator. | ||
+ | |||
+ | ==== Custom model ==== | ||
+ | |||
+ | We have created a '' | ||
+ | |||
+ | To inherit this template model in the data generator, we create a '' | ||
+ | |||
+ | <code java TutorialModelGenerator.java> | ||
+ | public class TutorialModelGenerator extends FabricModelProvider { | ||
+ | public static final Model VERTICAL_SLAB = new Model( | ||
+ | Optional.of(Identifier.of(" | ||
+ | Optional.empty(), | ||
+ | TextureKey.BOTTOM, | ||
+ | |||
+ | // ... | ||
} | } | ||
</ | </ | ||
+ | |||
+ | Then we call the '' | ||
+ | <code java TutorialModelGenerator.java> | ||
+ | @Override | ||
+ | public void generateBlockStateModels(BlockStateModelGenerator blockStateModelGenerator) { | ||
+ | // ... | ||
+ | | ||
+ | final Identifier verticalSlabModelId = VERTICAL_SLAB.upload(TutorialBlocks.POLISHED_ANDESITE_VERTICAL_SLAB, | ||
+ | blockStateModelGenerator.registerParentedItemModel(TutorialBlocks.POLISHED_ANDESITE_VERTICAL_SLAB, | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | ==== Custom block states definition (since 1.21.5) ==== | ||
+ | It's now an important part — now we create a block states definition for a vertical slab block. Actually it's not so complicated, | ||
+ | |||
+ | In 1.21.5, a block states definition is '' | ||
+ | * '' | ||
+ | * '' | ||
+ | |||
+ | For '' | ||
+ | * **Method one**: Specify one model variant, and modify the variant according to block states, such as modifying x-rotation, y-rotation and uvlock. All block states use the same model id, with only possible different variants. | ||
+ | * **Method two**: Allocating model variants for different block states directly, and then you can also continue to modify variants. In this case, the block states may use different model ids. | ||
+ | |||
+ | Our vertical slab has two block state properties: '' | ||
+ | <code java TutorialModelGenerator.java> | ||
+ | @Override | ||
+ | public void generateBlockStateModels(BlockStateModelGenerator blockStateModelGenerator) { | ||
+ | // ... | ||
+ | | ||
+ | blockStateModelGenerator.blockStateCollector.accept( | ||
+ | VariantsBlockModelDefinitionCreator.of(TutorialBlocks.POLISHED_ANDESITE_VERTICAL_SLAB, | ||
+ | BlockStateModelGenerator.createWeightedVariant(verticalSlabModelId)) | ||
+ | .apply(BlockStateModelGenerator.UV_LOCK) | ||
+ | .coordinate(BlockStateVariantMap.operations(VerticalSlabBlock.FACING) | ||
+ | .register(Direction.NORTH, | ||
+ | .register(Direction.EAST, | ||
+ | .register(Direction.SOUTH, | ||
+ | .register(Direction.WEST, | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | The '' | ||
+ | |||
+ | > Can we use method two? Of course yes! The code is the following: | ||
+ | > <code java TutorialModelGenerator.java> | ||
+ | blockStateModelGenerator.blockStateCollector.accept( | ||
+ | VariantsBlockModelDefinitionCreator.of( | ||
+ | TutorialBlocks.POLISHED_ANDESITE_VERTICAL_SLAB) | ||
+ | .with(BlockStateVariantMap.models(VerticalSlabBlock.FACING) | ||
+ | .register(Direction.NORTH, | ||
+ | .register(Direction.EAST, | ||
+ | .register(Direction.SOUTH, | ||
+ | .register(Direction.WEST, | ||
+ | ) | ||
+ | .apply(BlockStateModelGenerator.UV_LOCK) | ||
+ | ); | ||
+ | </ | ||
+ | > We find that in method two, when calling '' | ||
+ | |||
+ | In the method one and method two described above, apart from registering model operations or model variants one by one with the '' | ||
+ | |||
+ | If a block state has multiple properties that affect model variants, you can provide multiple properties in '' |
tutorial/datagen_model.1744982256.txt.gz · Last modified: 2025/04/18 13:17 by solidblock