This is an old revision of the document!
Table of Contents
模型生成
我们知道,几乎每个物品都需要对应的物品烘焙模型(item baked model,以下简称物品模型),从 1.21.4 开始还需要物品模型映射(item models definition)。每个方块都需要方块烘焙模型(block baked model,以下简称方块模型)和方块状态映射(block states definition),还需要对应的物品烘焙模型或者物品模型映射。一个方块就有这么多大大小小复杂的 JSON 要文件。显然,一个个去制作太费神了。因此,我们使用数据生成器为方块和物品生成模型。
在数据生成器中,模型和映射通常是一起生成的,通常来说,生成模型时返回一个模型 id,然后利用这个模型 id 去生成方块状态映射或物品模型映射。我们将从简单到复杂逐个开始。
注意:我们在之前的教程中,在
resources
文件夹内可能已经手动创建了一些 JSON 文件。当数据生成器生成同名的 JSON 文件时,会与我们已经手动创建的 JSON 冲突,因此在运行数据生成前,请删除它们。
先从最简单的开始
首先,先创建一个类,继承 FabricModelProvider
,并在数据生成的入口点注册它:
- TutorialModelGenerator.java
public static class TutorialModelGenerator extends FabricModelProvider { public TutorialModelGenerator(FabricDataOutput output) { super(output); } @Override public void generateBlockStateModels(BlockStateModelGenerator blockStateModelGenerator) { // ... } @Override public void generateItemModels(ItemModelGenerator itemModelGenerator) { // ... } }
- ExampleModDataGenerator.java
public class ExampleModDataGenerator implements DataGeneratorEntrypoint { @Override public void onInitializeDataGenerator(FabricDataGenerator generator) { // ... pack.addProvider(TutorialModelGenerator::new); } }
简单的方块模型
我们在 blocks 的教程中创建过一个示例方块。那么在这里,我们使用短短几行代码,为它创建方块状态映射和方块模型:
- TutorialModelGenerator.java
@Override public void generateBlockStateModels(BlockStateModelGenerator blockStateModelGenerator) { blockStateModelGenerator.registerSimpleCubeAll(TutorialBlocks.EXAMPLE_BLOCK); }
这行代码会创建一个最简单的方块模型,该模型是一个完整的方块,各面都使用与其 id 一致的纹理:tutorial:block/example_block
。注意,纹理是图片,一般不会使用数据生成器生成。同时还会创建一个最简单的方块状态映射,直接使用其方块模型。
或者也可以这样(下面的代码仍是在 generateBlockStateModels
方法中的),这种方法就可以指定不同的方块模型类型,第一行返回的是模型 id,而在生成方块状态映射时会使用此模型 id:
final Identifier exampleBlockModelId = TexturedModel.CUBE_ALL.upload(TutorialBlocks.EXAMPLE_BLOCK, blockStateModelGenerator.modelCollector); blockStateModelGenerator.registerParentedItemModel(TutorialBlocks.EXAMPLE_BLOCK, exampleBlockModelId);
如果需要指定不同的纹理,可以手动创建方块模型(例如六面都使用红树原木的顶部纹理):
final Identifier exampleBlockModelId = Models.CUBE_ALL.upload(TutorialBlocks.EXAMPLE_BLOCK, TextureMap.all(Identifier.ofVanilla("block/mangrove_log_top")), blockStateModelGenerator.modelCollector); blockStateModelGenerator.registerParentedItemModel(TutorialBlocks.EXAMPLE_BLOCK, exampleBlockModelId);
简单的物品模型(1.21.4 之后)
生成物品模型也很简单:
- TutorialModelGenerator.java
@Override public void generateItemModels(ItemModelGenerator itemModelGenerator) { itemModelGenerator.register(TutorialItems.CUSTOM_ITEM, Models.GENERATED); }
这个物品模型将使用最基本的物品模型映射,物品模型为 item/generated
,并使用与其 id 一致的纹理(tutorial:item/custom_item
)。当然,你也可以根据需要,将 Models.GENERATED
修改成其他的值。
如果itemModelGenerator.register
没有指定第二个参数,那么就只会生成物品模型映射,不会生成物品模型。
如果想要指定不同的纹理(例如在这个例子中,直接使用原版的白色羊毛纹理),那么也可以手动创建模型和模型映射(下面的代码仍是在 generateItemModels
方法中的)。
- TutorialModelGenerator.java
itemModelGenerator.register(TutorialItems.CUSTOM_ITEM, Models.GENERATED); final Identifier modelId = Models.GENERATED.upload(TutorialItems.CUSTOM_ITEM, TextureMap.layer0(Identifier.of("block/white_wool")), itemModelGenerator.modelCollector); itemModelGenerator.output.accept(TutorialItems.CUSTOM_ITEM, ItemModels.basic(modelId));
添加方块模型
BlockStateModelGenerator
类包含了很多创建方块模型的方法。在本例中,我们将会创建一个每个面都相同的方块,也就是 JSON 中的 minecraft:block/cube_all
。
public static Block SIMPLE_BLOCK = Registry.register(Registries.BLOCK, new Identifier("tutorial", "simple_block"), new Block(...)); public static BlockItem SIMPLE_BLOCK_ITEM = Registry.register(Registries.ITEM, ..., new BlockItem(SIMPLE_BLOCK, ...)); // ... @Override public void generateBlockStateModels(BlockStateModelGenerator blockStateModelGenerator) { blockStateModelGenerator.registerSimpleCubeAll(SIMPLE_BLOCK); }
因为 SIMPLE_BLOCK
的 BlockItem
已经存在并且已经注册,所以会自动生成一个物品模型,该物品模型直接继承方块模型。这可以在 generateItemModels
方法中重写。
严格验证
默认情况下,如果运行过程中,没有为所有属于被处理的模组的方块生成方块模型,数据生成将报错。Fabric API 允许禁用该功能。为此,请编辑你的 build.gradle
文件,删除 loom {}
块中的 VM 参数 -Dfabric-api.datagen.strict-validation
。
添加物品模型
ItemModelGenerator
包含了其他的多种创建物品模型的方法。
在这个例子中,我们重写上一个例子中的 SIMPLE_BLOCK
方块模型生成的物品模型。我们将从 SIMPLE_BLOCK_ITEM
生成一个物品模型。
public static Block SIMPLE_BLOCK = Registry.register(Registries.BLOCK, new Identifier("tutorial", "simple_block"), new Block(...)); public static BlockItem SIMPLE_BLOCK_ITEM = Registry.register(Registries.ITEM, ..., new BlockItem(SIMPLE_BLOCK, ...)); // ... @Override public void generateItemModels(ItemModelGenerator itemModelGenerator) { itemModelGenerator.register(SIMPLE_BLOCK_ITEM, Models.GENERATED); }
正在施工中
为带有朝向的方块添加数据生成
警告:这将非常复杂!!!
在本例中,我们将为 MACHINE_BLOCK
生成带有朝向的方块模型。
首先,添加方块自身并且注册它。
// 在 Tutorial 类(或者你自己的模组的初始化类中) public static final Block MACHINE_BLOCK = new Block(FabricBlockSettings.copy(Blocks.BLAST_FURNACE)); @Override public void onInitialize() { Registry.register(Registries.BLOCK, new Identifier("tutorial", "machine"), MACHINE_BLOCK); }
现在我们成功地注册好了方块,让我们向好的方向发展!
private static class MyModelGenerator extends FabricModelProvider { private MyModelGenerator(FabricDataGenerator generator) { super(generator); } @Override public void generateBlockStateModels(BlockStateModelGenerator blockStateModelGenerator) { // ... blockStateModelGenerator.blockStateCollector.accept(MultipartBlockStateSupplier.create(Tutorial.MACHINE_BLOCK) .with(When.create().set(Properties.HORIZONTAL_FACING, Direction.NORTH), BlockStateVariant.create().put(VariantSettings.X, VariantSettings.Rotation.X))); } @Override public void generateItemModels(ItemModelGenerator itemModelGenerator) { // ... } }