VORAUSSETZUNGEN
Stelle sicher, dass du den Prozess der Einrichtung des Datengenerators zuerst abgeschlossen hast.
Einrichtung
Zuerst müssen wir unseren ModelProvider erstellen. Erstelle eine Klasse, welche von FabricModelProvider erbt. Implementiere beide abstrakten Methoden: generateBlockStateModels und generateItemModels. Zum Schluss, erstelle einen Konstruktor, der zu super passt.
java
public class ExampleModModelProvider extends FabricModelProvider {
public ExampleModModelProvider(FabricDataOutput output) {
super(output);
}
@Override
public void generateBlockStateModels(BlockModelGenerators blockStateModelGenerator) {
}
@Override
public void generateItemModels(ItemModelGenerators itemModelGenerator) {
}
@Override
public String getName() {
return "ExampleModModelProvider";
}
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
Registriere diese Klasse in deinem DataGeneratorEntrypoint innerhalb der Methode onInitializeDataGenerator.
java
pack.addProvider(ExampleModModelProvider::new);1
Blockzustände und Blockmodelle
java
@Override
public void generateBlockStateModels(BlockStateModelGenerator blockStateModelGenerator) {
}1
2
3
2
3
Für Blockmodelle werden wir uns hauptsächlich auf die generateBlockStateModels-Methode fokusieren. Beachte den Parameter BlockStateModelGenerator blockStateModelGenerator - dieses Objekt wird für die Generierung aller JSON-Dateien verantwortlich sein. Hier sind einige praktische Beispiele, die du zur Generierung deiner gewünschten Modelle verwenden kannst:
Einfacher Cube All
java
blockStateModelGenerator.createTrivialCube(ModBlocks.STEEL_BLOCK);1
Dies ist die am häufigsten verwendete Funktion. Sie generiert eine JSON-Modell-Datei für ein normales cube_all Blockmodell. Eine Textur wird für alle sechs Seiten genutzt, in diesem Fall nutzen wir steel_block.
json
{
"parent": "minecraft:block/cube_all",
"textures": {
"all": "example-mod:block/steel_block"
}
}1
2
3
4
5
6
2
3
4
5
6
Sie generiert auch eine Blockzustand-JSON-Datei. Da wir keine Blockzustand-Eigenschaften (z. B. Achsen, Ausrichtung, ...) haben, ist eine Variante ausreichend und wird jedes Mal verwendet, wenn der Block platziert wird.
json
{
"variants": {
"": {
"model": "example-mod:block/steel_block"
}
}
}1
2
3
4
5
6
7
2
3
4
5
6
7
Singletons
Die registerSingleton-Methode liefert JSON-Modelldateien basierend auf dem übergebenen TexturedModel und einer einzelnen Blockzustand-Variante.
java
blockStateModelGenerator.createTrivialBlock(ModBlocks.PIPE_BLOCK, TexturedModel.COLUMN_ALT);1
Diese Methode wird Modelle für einen normalen Würfel generieren, der die Texturdatei pipe_block für die Seiten und die Texturdatei pipe_block_top für die obere und untere Seite nutzt.
json
{
"parent": "minecraft:block/cube_column",
"textures": {
"end": "example-mod:block/pipe_block_top",
"side": "example-mod:block/pipe_block"
}
}1
2
3
4
5
6
7
2
3
4
5
6
7
TIP
Wenn du dich nicht entscheiden kannst, welches TextureModel du verwenden sollst, öffne die Klasse TexturedModel und sieh dir die TextureMaps an!
Block-Textur-Pool
java
blockStateModelGenerator.family(ModBlocks.RUBY_BLOCK)
.stairs(ModBlocks.RUBY_STAIRS)
.slab(ModBlocks.RUBY_SLAB)
.fence(ModBlocks.RUBY_FENCE);1
2
3
4
2
3
4
Eine andere nützliche Methode ist registerCubeAllModelTexturePool: Definiere die Texturen, indem du den "Basisblock" übergibst, und füge dann die "Kinder" hinzu, die die gleichen Texturen haben. In diesem Fall haben wir den RUBY_BLOCK übergeben, so dass die Treppe, die Stufe und der Zaun die Textur RUBY_BLOCK verwenden werden.
WARNING
Sie wird auch ein einfaches Cube All JSON-Modell für den "Basisblock" generieren, um sicherzustellen, dass er ein Blockmodell hat.
Sei dir dessen bewusst, wenn du das Blockmodell dieses bestimmten Blocks änderst, da dies zu einem Fehler führen wird.
Du kannst auch eine BlockFamily anhängen, die Modelle für alle ihre "Kinder" generieren wird.
java
public static final BlockFamily RUBY_FAMILY =
new BlockFamily.Builder(ModBlocks.RUBY_BLOCK)
.stairs(ModBlocks.RUBY_STAIRS)
.slab(ModBlocks.RUBY_SLAB)
.fence(ModBlocks.RUBY_FENCE)
.getFamily();1
2
3
4
5
6
2
3
4
5
6
java
blockStateModelGenerator.family(ModBlocks.RUBY_BLOCK).generateFor(ModBlocks.RUBY_FAMILY);1
Türen und Falltüren
java
blockStateModelGenerator.createDoor(ModBlocks.RUBY_DOOR);
blockStateModelGenerator.createTrapdoor(ModBlocks.RUBY_TRAPDOOR);
// blockStateModelGenerator.registerOrientableTrapdoor(ModBlocks.RUBY_TRAPDOOR);1
2
3
2
3
Türen und Falltüren sein ein wenig anders. Hier musst du drei neue Texturen erstellen - zwei für die Türe, und eine für die Falltüre.
- Die Tür:
- Sie hat zwei Teile - die obere und die untere Hälfte. Jede benötigt ihre eigene Textur: In diesem Fall
ruby_door_topfür die obere undruby_door_bottomfür die untere Hälfte. - Die Methode
registerDoor()wird Modelle für alle Ausrichtungen der Tür, sowohl offen als auch geschlossen erstellen. - Du benötigst auch eine Itemtextur! Lege sie in dem Ordner
assets/example-mod/textures/item/ab.
- Sie hat zwei Teile - die obere und die untere Hälfte. Jede benötigt ihre eigene Textur: In diesem Fall
- Die Falltür:
- Hier benötigst du nur eine Textur, die in diesem Fall
ruby_trapdoorheißt. Diese wird für alle Seiten genutzt. - Da
TrapdoorBlockeine EigenschaftFACINGhat, kannst du die auskommentierte Methode verwenden, um Modell-Dateien mit rotierten Texturen zu generieren = Die Falltüre wird "orientierbar" sein. Andernfalls sieht sie immer gleich aus, egal in welche Richtung sie gerichtet ist.
- Hier benötigst du nur eine Textur, die in diesem Fall
Benutzerdefinierte Blockmodelle
In diesem Abschnitt werden wir die Modelle für eine vertikale Eichenstammstufe, mit einer Eichenstamm-Textur, erstellen.
Alle Felder und Methoden für diesen Teil des Tutorials werden in einer statischen inneren Klasse mit dem Namen CustomBlockStateModelGenerator deklariert.
Zeige CustomBlockStateModelGenerator
java
public static class CustomBlockStateModelGenerator {
// :::custom-model
public static final ModelTemplate VERTICAL_SLAB = block("vertical_slab", TextureSlot.BOTTOM, TextureSlot.TOP, TextureSlot.SIDE);
//helper method for creating Models
private static ModelTemplate block(String parent, TextureSlot... requiredTextureKeys) {
return new ModelTemplate(Optional.of(Identifier.fromNamespaceAndPath(ExampleMod.MOD_ID, "block/" + parent)), Optional.empty(), requiredTextureKeys);
}
//helper method for creating Models with variants
private static ModelTemplate block(String parent, String variant, TextureSlot... requiredTextureKeys) {
return new ModelTemplate(Optional.of(Identifier.fromNamespaceAndPath(ExampleMod.MOD_ID, "block/" + parent)), Optional.of(variant), requiredTextureKeys);
}
// :::custom-model
// :::custom-texture-map
public static TextureMapping blockAndTopForEnds(Block block) {
return new TextureMapping()
.put(TextureSlot.TOP, ModelLocationUtils.getModelLocation(block, "_top"))
.put(TextureSlot.BOTTOM, ModelLocationUtils.getModelLocation(block, "_top"))
.put(TextureSlot.SIDE, ModelLocationUtils.getModelLocation(block));
}
// :::custom-texture-map
// :::custom-supplier
private static BlockModelDefinitionGenerator createVerticalSlabBlockStates(Block vertSlabBlock, Identifier vertSlabId, Identifier fullBlockId) {
MultiVariant vertSlabModel = BlockModelGenerators.plainVariant(vertSlabId);
MultiVariant fullBlockModel = BlockModelGenerators.plainVariant(fullBlockId);
return MultiVariantGenerator.dispatch(vertSlabBlock)
.with(PropertyDispatch.initial(VerticalSlabBlock.FACING, VerticalSlabBlock.SINGLE)
.select(Direction.NORTH, true, vertSlabModel.with(BlockModelGenerators.UV_LOCK))
.select(Direction.EAST, true, vertSlabModel.with(BlockModelGenerators.UV_LOCK).with(BlockModelGenerators.Y_ROT_90))
.select(Direction.SOUTH, true, vertSlabModel.with(BlockModelGenerators.UV_LOCK).with(BlockModelGenerators.Y_ROT_180))
.select(Direction.WEST, true, vertSlabModel.with(BlockModelGenerators.UV_LOCK).with(BlockModelGenerators.Y_ROT_270))
.select(Direction.NORTH, false, fullBlockModel.with(BlockModelGenerators.UV_LOCK))
.select(Direction.EAST, false, fullBlockModel.with(BlockModelGenerators.UV_LOCK))
.select(Direction.SOUTH, false, fullBlockModel.with(BlockModelGenerators.UV_LOCK))
.select(Direction.WEST, false, fullBlockModel.with(BlockModelGenerators.UV_LOCK))
);
}
// :::custom-supplier
// :::custom-gen
public static void registerVerticalSlab(BlockModelGenerators generator, Block vertSlabBlock, Block fullBlock, TextureMapping textures) {
Identifier slabModel = VERTICAL_SLAB.create(vertSlabBlock, textures, generator.modelOutput);
Identifier fullBlockModel = ModelLocationUtils.getModelLocation(fullBlock);
generator.blockStateOutput.accept(createVerticalSlabBlockStates(vertSlabBlock, slabModel, fullBlockModel));
generator.registerSimpleItemModel(vertSlabBlock, slabModel);
}
// :::custom-gen
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
Benutzerdefinierte Blockklasse
Erstelle einen Block VerticalSlab mit einer Eigenschaft FACING und einer boolean-Eigenschaft SINGLE, wie in dem Tutorial Blockzustände beschrieben. SINGLE zeigt an, ob beide Stufen sind. Dann solltest du getOutlineShape und getCollisionShape überschreiben, so dass die Umrandung korrekt gerendert wird und der Block die richtige Kollisionsform hat.
java
public static final VoxelShape NORTH_SHAPE = Block.box(0.0, 0.0, 0.0, 16.0, 16.0, 8.0);
public static final VoxelShape SOUTH_SHAPE = Block.box(0.0, 0.0, 8.0, 16.0, 16.0, 16.0);
public static final VoxelShape WEST_SHAPE = Block.box(0.0, 0.0, 0.0, 8.0, 16.0, 16.0);
public static final VoxelShape EAST_SHAPE = Block.box(8.0, 0.0, 0.0, 16.0, 16.0, 16.0);1
2
3
4
2
3
4
java
@Override
protected VoxelShape getBlockSupportShape(BlockState state, BlockGetter level, BlockPos pos) {
boolean type = state.getValue(SINGLE);
Direction direction = state.getValue(FACING);
VoxelShape voxelShape;
if (type) {
switch (direction) {
case WEST -> voxelShape = WEST_SHAPE.singleEncompassing();
case EAST -> voxelShape = EAST_SHAPE.singleEncompassing();
case SOUTH -> voxelShape = SOUTH_SHAPE.singleEncompassing();
case NORTH -> voxelShape = NORTH_SHAPE.singleEncompassing();
default -> throw new MatchException(null, null);
}
return voxelShape;
} else {
return Shapes.block();
}
}
@Override
protected VoxelShape getShape(BlockState state, BlockGetter level, BlockPos pos, CollisionContext context) {
return this.getBlockSupportShape(state, level, pos);
}
@Override
protected VoxelShape getCollisionShape(BlockState state, BlockGetter level, BlockPos pos, CollisionContext context) {
return this.getBlockSupportShape(state, level, pos);
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
Überschreibe auch die Methode canReplace(), sonst kannst du die Stufe nicht zu einem vollen Block machen.
java
@Override
protected boolean canBeReplaced(BlockState state, BlockPlaceContext context) {
Direction direction = state.getValue(FACING);
if (context.getItemInHand().is(this.asItem()) && state.getValue(SINGLE)) {
if (context.replacingClickedOnBlock()) {
return context.getClickedFace().getOpposite() == direction;
}
}
return false;
}1
2
3
4
5
6
7
8
9
10
11
12
13
2
3
4
5
6
7
8
9
10
11
12
13
Und du bist fertig! Du kannst jetzt den Block testen und im Spiel platzieren.
Übergeordnetes Blockmodell
Lasst und jetzt ein übergeordnetes Blockmodell erstellen. Es bestimmt die Größe, Position in der Hand oder in anderen Slots und die x und y Koordinaten der Textur. Es wird empfohlen für dies einen Editor, wie Blockbench zu verwenden, da die manuelle Erstellung ein wirklich mühsamer Prozess ist. Es sollte wie folgt aussehen:
json
{
"parent": "minecraft:block/block",
"textures": {
"particle": "#side"
},
"display": {
"gui": {
"rotation": [30, -135, 0],
"translation": [-1.5, 0.75, 0],
"scale": [0.625, 0.625, 0.625]
},
"firstperson_righthand": {
"rotation": [0, -45, 0],
"translation": [0, 2, 0],
"scale": [0.375, 0.375, 0.375]
},
"firstperson_lefthand": {
"rotation": [0, 315, 0],
"translation": [0, 2, 0],
"scale": [0.375, 0.375, 0.375]
},
"thirdperson_righthand": {
"rotation": [75, -45, 0],
"translation": [0, 0, 2],
"scale": [0.375, 0.375, 0.375]
},
"thirdperson_lefthand": {
"rotation": [75, 315, 0],
"translation": [0, 0, 2],
"scale": [0.375, 0.375, 0.375]
}
},
"elements": [
{
"from": [0, 0, 0],
"to": [16, 16, 8],
"faces": {
"down": {
"uv": [0, 8, 16, 16],
"texture": "#bottom",
"cullface": "down",
"tintindex": 0
},
"up": {
"uv": [0, 0, 16, 8],
"texture": "#top",
"cullface": "up",
"tintindex": 0
},
"north": {
"uv": [0, 0, 16, 16],
"texture": "#side",
"cullface": "north",
"tintindex": 0
},
"south": {
"uv": [0, 0, 16, 16],
"texture": "#side",
"tintindex": 0
},
"west": {
"uv": [0, 0, 8, 16],
"texture": "#side",
"cullface": "west",
"tintindex": 0
},
"east": {
"uv": [8, 0, 16, 16],
"texture": "#side",
"cullface": "east",
"tintindex": 0
}
}
}
]
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
Für weitere Informationen, siehe dir an wie Blockzustände formatiert sind. Beachte die Schlüsselwörter #bottom, #top, #side. Sie dienen als Variablen, die von Modellen gesetzt werden können, die dieses Modell als übergeordnetes Modell haben:
json
{
"parent": "minecraft:block/cube_bottom_top",
"textures": {
"bottom": "minecraft:block/sandstone_bottom",
"side": "minecraft:block/sandstone",
"top": "minecraft:block/sandstone_top"
}
}1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
Der Wert bottom wird den Platzhalter #bottom ersetzen und so weiter. Füge es in den Ordner resources/assets/example-mod/models/block/ ein.
Benutzerdefinierte Modelle
Eine weitere Sache, die wir benötigen, ist eine Instanz der Klasse Model. Sie wird das tatsächliche übergeordnete Blockmodell in unserem Mod repräsentieren.
java
public static final ModelTemplate VERTICAL_SLAB = block("vertical_slab", TextureSlot.BOTTOM, TextureSlot.TOP, TextureSlot.SIDE);
//helper method for creating Models
private static ModelTemplate block(String parent, TextureSlot... requiredTextureKeys) {
return new ModelTemplate(Optional.of(Identifier.fromNamespaceAndPath(ExampleMod.MOD_ID, "block/" + parent)), Optional.empty(), requiredTextureKeys);
}
//helper method for creating Models with variants
private static ModelTemplate block(String parent, String variant, TextureSlot... requiredTextureKeys) {
return new ModelTemplate(Optional.of(Identifier.fromNamespaceAndPath(ExampleMod.MOD_ID, "block/" + parent)), Optional.of(variant), requiredTextureKeys);
}1
2
3
4
5
6
7
8
9
10
11
12
2
3
4
5
6
7
8
9
10
11
12
Die Methode block() erstellt ein neues Model, das auf die Datei vertical_slab.json in unserem Ordner resources/assets/example-mod/models/block/ verweist. Die TextureSlots repräsentieren die "Platzhalter" (#bottom, #top, ...) als ein Objekt.
Die Textur Map verwenden
Was macht dasTextureMapping? Sie liefert die Identifikatoren, die auf die Textur verweisen. Technisch gesehen verhält sie sich wie eine normale Map - man verbindet einen TextureSlot (Schlüssel) mit einem Identifier (Wert).
Du kannst entweder die von Vanilla verwenden, wie TextureMapping.cube() (die alle TextureKeys mit dem selben Identifier verknüpft), oder eine Neue erstellen, indem du eine neue Instanz erstellst und dann .put() aufrufst, um Schlüssel mit Werten zu verknüpfen.
TIP
TextureMapping.cube() verknüpft alle TextureSlots mit dem selben Identifier, egal wie viele es davon gibt!
Da wir die Eichenstammtexturen nutzen wollen, aber die BOTTOM, TOP und SIDE TextureSlots haben, müssen wir eine neue erstellen.
java
public static TextureMapping blockAndTopForEnds(Block block) {
return new TextureMapping()
.put(TextureSlot.TOP, ModelLocationUtils.getModelLocation(block, "_top"))
.put(TextureSlot.BOTTOM, ModelLocationUtils.getModelLocation(block, "_top"))
.put(TextureSlot.SIDE, ModelLocationUtils.getModelLocation(block));
}1
2
3
4
5
6
7
2
3
4
5
6
7
Die bottom und top Flächen werden oak_log_top.png verwenden, die Seiten werden oak_log.png verwenden.
WARNING
Alle TextureSlots in deiner TextureMap müssen mit den TextureSlots in deinem übergeordneten Blockmodell übereinstimmen!
Benutzerdefinierte BlockModelDefinitionGenerator-Methode
Der BlockModelDefinitionGenerator beinhaltet alle Varianten an Blockzuständen, deren Rotation und anderen Optionen, wie die UV-Sperre.
java
private static BlockModelDefinitionGenerator createVerticalSlabBlockStates(Block vertSlabBlock, Identifier vertSlabId, Identifier fullBlockId) {
MultiVariant vertSlabModel = BlockModelGenerators.plainVariant(vertSlabId);
MultiVariant fullBlockModel = BlockModelGenerators.plainVariant(fullBlockId);
return MultiVariantGenerator.dispatch(vertSlabBlock)
.with(PropertyDispatch.initial(VerticalSlabBlock.FACING, VerticalSlabBlock.SINGLE)
.select(Direction.NORTH, true, vertSlabModel.with(BlockModelGenerators.UV_LOCK))
.select(Direction.EAST, true, vertSlabModel.with(BlockModelGenerators.UV_LOCK).with(BlockModelGenerators.Y_ROT_90))
.select(Direction.SOUTH, true, vertSlabModel.with(BlockModelGenerators.UV_LOCK).with(BlockModelGenerators.Y_ROT_180))
.select(Direction.WEST, true, vertSlabModel.with(BlockModelGenerators.UV_LOCK).with(BlockModelGenerators.Y_ROT_270))
.select(Direction.NORTH, false, fullBlockModel.with(BlockModelGenerators.UV_LOCK))
.select(Direction.EAST, false, fullBlockModel.with(BlockModelGenerators.UV_LOCK))
.select(Direction.SOUTH, false, fullBlockModel.with(BlockModelGenerators.UV_LOCK))
.select(Direction.WEST, false, fullBlockModel.with(BlockModelGenerators.UV_LOCK))
);
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
Zuerst erstellen wir einen neuen BlockModelDefinitionGenerator unter Verwendung von MultiVariantGenerator.dispatch(). Dann erstellen wir einen neuen PropertyDispatch, der Parameter für alle Varianten des Blocks beinhaltet, in diesem Fall FACING und SINGLE und übergeben diesen in den MultiVariantGenerator. Gebe an, welches Modell und welche Transformation (uvlock, rotation) bei der Verwendung von .register() genutzt werden sollen. Zum Beispiel:
- Zeile 6: Einzelne Stufe nach Norden ausgerichtet, daher verwenden wir das Modell ohne Rotation
- Zeile 9: einzelne Stufe nach Westen ausgerichtet, daher rotieren wir das Modell um 270° um die Y-Achse
- Zeilen 10-13: Nicht-Einzelne Stufe, die wie ein voller Block aussieht und nicht rotiert werden muss
Benutzerdefinierte Methode für den Datengenerator
Der letzte Schritt - die Erstellung der tatsächlichen Methode, die du aufrufen kannst und die die JSONs generieren wird. Aber für was sind die Parameter?
BlockModelGenerators generator, das gleiche, dass wir angenerateBlockStateModelsübergeben haben.Block vertSlabBlockist der Block, zu dem wir die JSONs generieren werden.Block fullBlock- ist das Modell, dass genutzt wird, wenn die EigenschaftSINGLEfalse ist = der Stufenblock sieht wie ein voller Block aus.TextureMapping texturesdefiniert die tatsächlichen Texturen, die das Modell nutzt. Siehe das Kapitel die Texture Map verwenden.
java
public static void registerVerticalSlab(BlockModelGenerators generator, Block vertSlabBlock, Block fullBlock, TextureMapping textures) {
Identifier slabModel = VERTICAL_SLAB.create(vertSlabBlock, textures, generator.modelOutput);
Identifier fullBlockModel = ModelLocationUtils.getModelLocation(fullBlock);
generator.blockStateOutput.accept(createVerticalSlabBlockStates(vertSlabBlock, slabModel, fullBlockModel));
generator.registerSimpleItemModel(vertSlabBlock, slabModel);
}1
2
3
4
5
6
7
2
3
4
5
6
7
Zuerst erhalten wir den Identifier des einzelnen Stufenmodell mit VERTICAL_SLAB.create(). Dann erhalten wir den Identifier des vollen Blockmodell mit ModelLocationUtils.getModelLocation().
Wir können dann diese zwei Modelle an createVerticalSlabBlockStates übergeben, welches selbst in den Consumer blockStateOutput übergeben wird, welcher die JSON-Dateien für die Modelle generiert.
Schließlich erstellen wir ein Modell für das Item der vertikalen Stufe mit BlockModelGenerators.registerSimpleItemModel().
Und das ist alles! Jetzt müssen wir nur noch unsere Methode in unserem ModelProvider aufrufen:
java
CustomBlockStateModelGenerator.registerVerticalSlab(
blockStateModelGenerator,
ModBlocks.VERTICAL_OAK_LOG_SLAB,
Blocks.OAK_LOG,
CustomBlockStateModelGenerator.blockAndTopForEnds(Blocks.OAK_LOG)
);1
2
3
4
5
6
2
3
4
5
6
Quellen und Links
Du kannst für weitere Informationen die Beispieltests der Fabric API und die im Beispiel-Mod dieser Dokumentation ansehen.
Du kannst auch weitere Beispiele für die Verwendung von benutzerdefinierten Methoden für den Datengenerator finden, indem du den Opens Source-Code von Mods durchsuchst, zum Beispiel Vanilla+ Blocks und Vanilla+ Verticals von Fellteros.









