Skip to content

Commit bf2c444

Browse files
fix: custom furnace block model, not currently aligned
1 parent dfa2baa commit bf2c444

10 files changed

Lines changed: 408 additions & 8 deletions

File tree

src/client/java/com/tcm/MineTale/block/workbenches/screen/WorkbenchWorkbenchScreen.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@
1717
import net.minecraft.client.gui.navigation.ScreenPosition;
1818
import net.minecraft.client.gui.screens.inventory.AbstractRecipeBookScreen;
1919
import net.minecraft.client.gui.screens.recipebook.RecipeBookComponent;
20-
import net.minecraft.client.gui.screens.recipebook.RecipeBookPage;
2120
import net.minecraft.client.gui.screens.recipebook.RecipeCollection;
2221
import net.minecraft.client.renderer.RenderPipelines;
2322
import net.minecraft.resources.Identifier;

src/client/java/com/tcm/MineTale/datagen/ModModelProvider.java

Lines changed: 58 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,39 @@
11
package com.tcm.MineTale.datagen;
22

3+
import com.tcm.MineTale.MineTale;
34
import com.tcm.MineTale.registry.ModBlocks;
45
import net.fabricmc.fabric.api.client.datagen.v1.provider.FabricModelProvider;
56
import net.fabricmc.fabric.api.datagen.v1.FabricDataOutput;
67
import net.minecraft.client.data.models.BlockModelGenerators;
78
import net.minecraft.client.data.models.ItemModelGenerators;
9+
import net.minecraft.client.data.models.blockstates.MultiVariantGenerator;
10+
import net.minecraft.client.data.models.blockstates.PropertyDispatch;
11+
import net.minecraft.client.data.models.model.ModelLocationUtils;
12+
import net.minecraft.client.data.models.model.ModelTemplates;
13+
import net.minecraft.client.data.models.model.TextureMapping;
14+
import net.minecraft.client.data.models.model.TextureSlot;
15+
import net.minecraft.client.renderer.block.model.VariantMutator;
16+
import net.minecraft.core.Direction;
17+
import net.minecraft.resources.Identifier;
18+
import net.minecraft.world.level.block.Block;
19+
import net.minecraft.world.level.block.state.properties.BlockStateProperties;
20+
import net.minecraft.world.level.block.state.properties.ChestType;
21+
import net.minecraft.world.level.block.state.properties.DoubleBlockHalf;
822

923
public class ModModelProvider extends FabricModelProvider {
1024
/**
11-
* Creates a ModModelProvider using the given Fabric data output.
12-
*
13-
* @param output the FabricDataOutput used to write generated model and blockstate data
14-
*/
15-
public ModModelProvider(FabricDataOutput output) { super(output); }
25+
* Creates a ModModelProvider using the given Fabric data output.
26+
*
27+
* @param output the FabricDataOutput used to write generated model and blockstate data
28+
*/
29+
public ModModelProvider(FabricDataOutput output) { super(output); }
30+
31+
// Recreate the rotation logic locally since the base one is private
32+
private static final PropertyDispatch<VariantMutator> WORKBENCH_ROTATION = PropertyDispatch.modify(BlockStateProperties.HORIZONTAL_FACING)
33+
.select(Direction.NORTH, BlockModelGenerators.NOP)
34+
.select(Direction.EAST, BlockModelGenerators.Y_ROT_90)
35+
.select(Direction.SOUTH, BlockModelGenerators.Y_ROT_180)
36+
.select(Direction.WEST, BlockModelGenerators.Y_ROT_270);
1637

1738
/**
1839
* Registers block state and model definitions for the mod's log blocks.
@@ -54,6 +75,38 @@ public void generateBlockStateModels(BlockModelGenerators blockStateModelGenerat
5475
blockStateModelGenerator.woodProvider(ModBlocks.STRIPPED_LOG).logWithHorizontal(ModBlocks.STRIPPED_LOG);
5576
blockStateModelGenerator.woodProvider(ModBlocks.WINDWILLOW_LOG).logWithHorizontal(ModBlocks.WINDWILLOW_LOG);
5677
blockStateModelGenerator.woodProvider(ModBlocks.WILD_WISTERIA_LOG).logWithHorizontal(ModBlocks.WILD_WISTERIA_LOG).wood(ModBlocks.WILD_WISTERIA_WOOD);
78+
79+
registerLargeWorkbench(blockStateModelGenerator, ModBlocks.FURNACE_WORKBENCH_BLOCK_T1);
80+
}
81+
82+
private void registerLargeWorkbench(BlockModelGenerators generator, Block block) {
83+
// 1. Get the base identifier (e.g., minetale:block/furnace_workbench_block_t1)
84+
Identifier blockId = ModelLocationUtils.getModelLocation(block);
85+
86+
// 2. Build the references to your manual JSON files
87+
// .withSuffix() creates: minetale:block/furnace_workbench_block_t1_bottom_left, etc.
88+
Identifier bottomLeft = blockId.withSuffix("_bottom_left");
89+
Identifier bottomRight = blockId.withSuffix("_bottom_right");
90+
Identifier topLeft = blockId.withSuffix("_top_left");
91+
Identifier topRight = blockId.withSuffix("_top_right");
92+
Identifier inventory = blockId.withSuffix("_inventory");
93+
94+
// 3. Dispatch to Blockstate (Tells the game which model to show for each state)
95+
generator.blockStateOutput.accept(MultiVariantGenerator.dispatch(block)
96+
.with(PropertyDispatch.initial(BlockStateProperties.DOUBLE_BLOCK_HALF, BlockStateProperties.CHEST_TYPE)
97+
.select(DoubleBlockHalf.LOWER, ChestType.LEFT, BlockModelGenerators.plainVariant(bottomLeft))
98+
.select(DoubleBlockHalf.LOWER, ChestType.RIGHT, BlockModelGenerators.plainVariant(bottomRight))
99+
.select(DoubleBlockHalf.UPPER, ChestType.LEFT, BlockModelGenerators.plainVariant(topLeft))
100+
.select(DoubleBlockHalf.UPPER, ChestType.RIGHT, BlockModelGenerators.plainVariant(topRight))
101+
// Support the 'SINGLE' state as a fallback
102+
.select(DoubleBlockHalf.LOWER, ChestType.SINGLE, BlockModelGenerators.plainVariant(bottomLeft))
103+
.select(DoubleBlockHalf.UPPER, ChestType.SINGLE, BlockModelGenerators.plainVariant(topLeft))
104+
)
105+
.with(WORKBENCH_ROTATION)
106+
);
107+
108+
// 4. Map the Item in your hand to the inventory JSON
109+
generator.registerSimpleItemModel(block, inventory);
57110
}
58111

59112
/**

src/client/java/com/tcm/MineTale/recipe/MineTaleRecipeBookComponent.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66

77
import com.tcm.MineTale.mixin.client.RecipeBookComponentAccessor;
88
import com.tcm.MineTale.registry.ModRecipeDisplay;
9-
import com.tcm.MineTale.registry.ModRecipes;
109
import com.tcm.MineTale.util.Constants;
1110

1211
import net.minecraft.client.gui.components.WidgetSprites;

src/main/java/com/tcm/MineTale/block/workbenches/FurnaceWorkbench.java

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,20 @@
1010
import com.tcm.MineTale.registry.ModTiers.FurnaceTier;
1111

1212
import net.minecraft.core.BlockPos;
13+
import net.minecraft.core.Direction;
14+
import net.minecraft.world.level.BlockGetter;
1315
import net.minecraft.world.level.Level;
16+
import net.minecraft.world.level.block.Block;
1417
import net.minecraft.world.level.block.RenderShape;
1518
import net.minecraft.world.level.block.entity.BlockEntity;
1619
import net.minecraft.world.level.block.entity.BlockEntityTicker;
1720
import net.minecraft.world.level.block.entity.BlockEntityType;
1821
import net.minecraft.world.level.block.state.BlockState;
22+
import net.minecraft.world.level.block.state.properties.ChestType;
23+
import net.minecraft.world.level.block.state.properties.DoubleBlockHalf;
24+
import net.minecraft.world.phys.shapes.CollisionContext;
25+
import net.minecraft.world.phys.shapes.Shapes;
26+
import net.minecraft.world.phys.shapes.VoxelShape;
1927

2028
public class FurnaceWorkbench extends AbstractWorkbench<FurnaceWorkbenchEntity> {
2129
// Setting these to true creates the 2x2 multi-block footprint
@@ -86,4 +94,42 @@ public RenderShape getRenderShape(BlockState state) {
8694
// Essential so that the 2x2 model is visible
8795
return RenderShape.MODEL;
8896
}
97+
98+
protected static final VoxelShape LOWER_LEFT_SHAPE = Shapes.or(
99+
Block.box(0.0, 0.0, 0.0, 16.0, 8.0, 16.0), // Base
100+
Block.box(2.0, 8.0, 2.0, 16.0, 16.0, 14.0) // Mid-section
101+
);
102+
103+
protected static final VoxelShape LOWER_RIGHT_SHAPE = Shapes.or(
104+
Block.box(0.0, 0.0, 0.0, 16.0, 8.0, 16.0), // Base
105+
Block.box(0.0, 8.0, 2.0, 13.0, 16.0, 14.0) // Mid-section (Shifted X: 29-16=13)
106+
);
107+
108+
protected static final VoxelShape UPPER_LEFT_SHAPE = Shapes.or(
109+
Block.box(1.0, 0.0, 1.0, 16.0, 5.0, 14.0), // Tabletop (flush right)
110+
Block.box(8.0, 5.0, 4.0, 16.0, 9.0, 12.0), // Shelf (flush right)
111+
Block.box(6.0, 9.0, 3.0, 16.0, 12.0, 13.0) // Top Cap (flush right)
112+
);
113+
114+
115+
protected static final VoxelShape UPPER_RIGHT_SHAPE = Shapes.or(
116+
Block.box(0.0, 0.0, 1.0, 15.0, 5.0, 14.0), // Tabletop (Shifted X: 31-16=15)
117+
Block.box(0.0, 5.0, 4.0, 8.0, 9.0, 12.0), // Shelf (Shifted X: 24-16=8)
118+
Block.box(0.0, 9.0, 3.0, 10.0, 12.0, 13.0) // Top Cap (Shifted X: 26-16=10)
119+
);
120+
121+
@Override
122+
public VoxelShape getShape(BlockState state, BlockGetter level, BlockPos pos, CollisionContext context) {
123+
DoubleBlockHalf half = state.getValue(HALF);
124+
ChestType type = state.getValue(TYPE);
125+
126+
// We select the correct pre-defined VoxelShape based on position
127+
if (half == DoubleBlockHalf.LOWER) {
128+
return (type == ChestType.LEFT || type == ChestType.SINGLE)
129+
? LOWER_LEFT_SHAPE : LOWER_RIGHT_SHAPE;
130+
} else {
131+
return (type == ChestType.LEFT || type == ChestType.SINGLE)
132+
? UPPER_LEFT_SHAPE : UPPER_RIGHT_SHAPE;
133+
}
134+
}
89135
}

src/main/java/com/tcm/MineTale/recipe/WorkbenchRecipe.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
import java.util.List;
44

55
import com.mojang.serialization.Codec;
6-
import com.mojang.serialization.DataResult;
76
import com.mojang.serialization.MapCodec;
87
import com.mojang.serialization.codecs.RecordCodecBuilder;
98
import com.tcm.MineTale.registry.ModRecipeDisplay;
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
{
2+
"format_version": "1.21.11",
3+
"credit": "Made with Blockbench",
4+
"texture_size": [128, 128],
5+
"textures": {
6+
"0": "minetale:block/furnace_workbench",
7+
"particle": "minetale:block/furnace_workbench"
8+
},
9+
"elements": [
10+
{
11+
"from": [0, 0, 0],
12+
"to": [32, 8, 16],
13+
"rotation": {"angle": 0, "axis": "y", "origin": [3, 0, 1]},
14+
"faces": {
15+
"north": {"uv": [2, 2, 6, 3], "texture": "#0"},
16+
"east": {"uv": [0, 2, 2, 3], "texture": "#0"},
17+
"south": {"uv": [8, 2, 12, 3], "texture": "#0"},
18+
"west": {"uv": [6, 2, 8, 3], "texture": "#0"},
19+
"up": {"uv": [6, 2, 2, 0], "texture": "#0"},
20+
"down": {"uv": [10, 0, 6, 2], "texture": "#0"}
21+
}
22+
},
23+
{
24+
"from": [2, 8, 2],
25+
"to": [29, 16, 14],
26+
"rotation": {"angle": 0, "axis": "y", "origin": [5, 8, 3]},
27+
"faces": {
28+
"north": {"uv": [1.5, 6.875, 4.875, 7.875], "texture": "#0"},
29+
"east": {"uv": [0, 6.875, 1.5, 7.875], "texture": "#0"},
30+
"south": {"uv": [6.375, 6.875, 9.75, 7.875], "texture": "#0"},
31+
"west": {"uv": [4.875, 6.875, 6.375, 7.875], "texture": "#0"},
32+
"up": {"uv": [4.875, 6.875, 1.5, 5.375], "texture": "#0"},
33+
"down": {"uv": [8.25, 5.375, 4.875, 6.875], "texture": "#0"}
34+
}
35+
},
36+
{
37+
"from": [1, 16, 1],
38+
"to": [31, 21, 15],
39+
"rotation": {"angle": 0, "axis": "y", "origin": [2, 16, 2]},
40+
"faces": {
41+
"north": {"uv": [1.75, 4.75, 5.5, 5.375], "texture": "#0"},
42+
"east": {"uv": [0, 4.75, 1.75, 5.375], "texture": "#0"},
43+
"south": {"uv": [7.25, 4.75, 11, 5.375], "texture": "#0"},
44+
"west": {"uv": [5.5, 4.75, 7.25, 5.375], "texture": "#0"},
45+
"up": {"uv": [5.5, 4.75, 1.75, 3], "texture": "#0"},
46+
"down": {"uv": [9.25, 3, 5.5, 4.75], "texture": "#0"}
47+
}
48+
},
49+
{
50+
"from": [8, 21, 4],
51+
"to": [24, 25, 12],
52+
"rotation": {"angle": 0, "axis": "y", "origin": [9, 21, 5]},
53+
"faces": {
54+
"north": {"uv": [8.5, 8.875, 10.5, 9.375], "texture": "#0"},
55+
"east": {"uv": [7.5, 8.875, 8.5, 9.375], "texture": "#0"},
56+
"south": {"uv": [11.5, 8.875, 13.5, 9.375], "texture": "#0"},
57+
"west": {"uv": [10.5, 8.875, 11.5, 9.375], "texture": "#0"},
58+
"up": {"uv": [10.5, 8.875, 8.5, 7.875], "texture": "#0"},
59+
"down": {"uv": [12.5, 7.875, 10.5, 8.875], "texture": "#0"}
60+
}
61+
},
62+
{
63+
"from": [6, 25, 3],
64+
"to": [26, 28, 13],
65+
"rotation": {"angle": 0, "axis": "y", "origin": [7, 25, 4]},
66+
"faces": {
67+
"north": {"uv": [1.25, 9.125, 3.75, 9.5], "texture": "#0"},
68+
"east": {"uv": [0, 9.125, 1.25, 9.5], "texture": "#0"},
69+
"south": {"uv": [5, 9.125, 7.5, 9.5], "texture": "#0"},
70+
"west": {"uv": [3.75, 9.125, 5, 9.5], "texture": "#0"},
71+
"up": {"uv": [3.75, 9.125, 1.25, 7.875], "texture": "#0"},
72+
"down": {"uv": [6.25, 7.875, 3.75, 9.125], "texture": "#0"}
73+
}
74+
}
75+
]
76+
}
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
{
2+
"format_version": "1.21.11",
3+
"credit": "Made with Blockbench",
4+
"texture_size": [128, 128],
5+
"textures": {
6+
"0": "minetale:block/furnace_workbench",
7+
"particle": "minetale:block/furnace_workbench"
8+
},
9+
"elements": [
10+
{
11+
"from": [-16, 0, 0],
12+
"to": [16, 8, 16],
13+
"rotation": {"angle": 0, "axis": "y", "origin": [-13, 0, 1]},
14+
"faces": {
15+
"north": {"uv": [2, 2, 6, 3], "texture": "#0"},
16+
"east": {"uv": [0, 2, 2, 3], "texture": "#0"},
17+
"south": {"uv": [8, 2, 12, 3], "texture": "#0"},
18+
"west": {"uv": [6, 2, 8, 3], "texture": "#0"},
19+
"up": {"uv": [6, 2, 2, 0], "texture": "#0"},
20+
"down": {"uv": [10, 0, 6, 2], "texture": "#0"}
21+
}
22+
},
23+
{
24+
"from": [-14, 8, 2],
25+
"to": [13, 16, 14],
26+
"rotation": {"angle": 0, "axis": "y", "origin": [-11, 8, 3]},
27+
"faces": {
28+
"north": {"uv": [1.5, 6.875, 4.875, 7.875], "texture": "#0"},
29+
"east": {"uv": [0, 6.875, 1.5, 7.875], "texture": "#0"},
30+
"south": {"uv": [6.375, 6.875, 9.75, 7.875], "texture": "#0"},
31+
"west": {"uv": [4.875, 6.875, 6.375, 7.875], "texture": "#0"},
32+
"up": {"uv": [4.875, 6.875, 1.5, 5.375], "texture": "#0"},
33+
"down": {"uv": [8.25, 5.375, 4.875, 6.875], "texture": "#0"}
34+
}
35+
},
36+
{
37+
"from": [-15, 16, 1],
38+
"to": [15, 21, 15],
39+
"rotation": {"angle": 0, "axis": "y", "origin": [-14, 16, 2]},
40+
"faces": {
41+
"north": {"uv": [1.75, 4.75, 5.5, 5.375], "texture": "#0"},
42+
"east": {"uv": [0, 4.75, 1.75, 5.375], "texture": "#0"},
43+
"south": {"uv": [7.25, 4.75, 11, 5.375], "texture": "#0"},
44+
"west": {"uv": [5.5, 4.75, 7.25, 5.375], "texture": "#0"},
45+
"up": {"uv": [5.5, 4.75, 1.75, 3], "texture": "#0"},
46+
"down": {"uv": [9.25, 3, 5.5, 4.75], "texture": "#0"}
47+
}
48+
},
49+
{
50+
"from": [-8, 21, 4],
51+
"to": [8, 25, 12],
52+
"rotation": {"angle": 0, "axis": "y", "origin": [-7, 21, 5]},
53+
"faces": {
54+
"north": {"uv": [8.5, 8.875, 10.5, 9.375], "texture": "#0"},
55+
"east": {"uv": [7.5, 8.875, 8.5, 9.375], "texture": "#0"},
56+
"south": {"uv": [11.5, 8.875, 13.5, 9.375], "texture": "#0"},
57+
"west": {"uv": [10.5, 8.875, 11.5, 9.375], "texture": "#0"},
58+
"up": {"uv": [10.5, 8.875, 8.5, 7.875], "texture": "#0"},
59+
"down": {"uv": [12.5, 7.875, 10.5, 8.875], "texture": "#0"}
60+
}
61+
},
62+
{
63+
"from": [-10, 25, 3],
64+
"to": [10, 28, 13],
65+
"rotation": {"angle": 0, "axis": "y", "origin": [-9, 25, 4]},
66+
"faces": {
67+
"north": {"uv": [1.25, 9.125, 3.75, 9.5], "texture": "#0"},
68+
"east": {"uv": [0, 9.125, 1.25, 9.5], "texture": "#0"},
69+
"south": {"uv": [5, 9.125, 7.5, 9.5], "texture": "#0"},
70+
"west": {"uv": [3.75, 9.125, 5, 9.5], "texture": "#0"},
71+
"up": {"uv": [3.75, 9.125, 1.25, 7.875], "texture": "#0"},
72+
"down": {"uv": [6.25, 7.875, 3.75, 9.125], "texture": "#0"}
73+
}
74+
}
75+
]
76+
}

0 commit comments

Comments
 (0)