Skip to content

Commit cab93b0

Browse files
Merge pull request #14 from CodeMonkeysMods/feat/add-furnace-block-basics
initial files for furnace block
2 parents bcb4d84 + 9d46031 commit cab93b0

15 files changed

Lines changed: 1142 additions & 26 deletions

build.gradle

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ dependencies {
3737
modImplementation "net.fabricmc:fabric-loader:${project.loader_version}"
3838

3939
// Fabric API. This is technically optional, but you probably want it anyway.
40-
modImplementation "net.fabricmc.fabric-api:fabric-api:${project.fabric_version}"
40+
modImplementation "net.fabricmc.fabric-api:fabric-api:${project.fabric_api_version}"
4141

4242
}
4343

gradle.properties

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
# Done to increase the memory available to gradle.
2-
org.gradle.jvmargs=-Xmx1G
2+
org.gradle.jvmargs=-Xmx4G
33
org.gradle.parallel=true
44

55
# IntelliJ IDEA is not yet fully compatible with configuration cache, see: https://github.com/FabricMC/fabric-loom/issues/1349
@@ -8,13 +8,13 @@ org.gradle.configuration-cache=false
88
# Fabric Properties
99
# check these on https://fabricmc.net/develop
1010
minecraft_version=1.21.11
11-
loader_version=0.18.2
12-
loom_version=1.14-SNAPSHOT
11+
loader_version=0.18.4
12+
loom_version=1.15-SNAPSHOT
13+
14+
# Fabric API
15+
fabric_api_version=0.141.2+1.21.11
1316

1417
# Mod Properties
1518
mod_version=1.0.0
1619
maven_group=com.tcm
17-
archives_base_name=MineTale
18-
19-
# Dependencies
20-
fabric_version=0.139.4+1.21.11
20+
archives_base_name=MineTale
Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,17 @@
11
package com.tcm.MineTale;
22

3+
import com.tcm.MineTale.block.workbenches.screen.FurnaceWorkbenchScreen;
4+
import com.tcm.MineTale.registry.ModMenuTypes;
5+
36
import net.fabricmc.api.ClientModInitializer;
7+
import net.minecraft.client.gui.screens.MenuScreens;
48

59
public class MineTaleClient implements ClientModInitializer {
10+
/**
11+
* Registers the screen factory for the furnace workbench menu so the client can create FurnaceWorkbenchScreen instances for that menu type.
12+
*/
613
@Override
714
public void onInitializeClient() {
8-
// This entrypoint is suitable for setting up client-specific logic, such as rendering.
15+
MenuScreens.register(ModMenuTypes.FURNACE_WORKBENCH_MENU, FurnaceWorkbenchScreen::new);
916
}
1017
}
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
package com.tcm.MineTale.block.workbenches.screen;
2+
3+
import com.tcm.MineTale.block.workbenches.menu.FurnaceWorkbenchMenu;
4+
5+
import net.minecraft.client.gui.GuiGraphics;
6+
import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen;
7+
import net.minecraft.client.renderer.RenderPipelines;
8+
import net.minecraft.resources.Identifier;
9+
import net.minecraft.world.entity.player.Inventory;
10+
import net.minecraft.network.chat.Component;
11+
12+
public class FurnaceWorkbenchScreen extends AbstractContainerScreen<FurnaceWorkbenchMenu> {
13+
private static final Identifier TEXTURE =
14+
// Identifier.fromNamespaceAndPath(MineTale.MOD_ID, "textures/gui/container/furnace_workbench.png");
15+
Identifier.withDefaultNamespace("textures/gui/container/furnace.png");
16+
17+
/**
18+
* Creates a new furnace workbench screen for the given menu, player inventory, and title.
19+
*
20+
* @param menu the container menu that provides slots and syncs state for this screen
21+
* @param inventory the player's inventory to display and interact with
22+
* @param title the title component shown at the top of the screen
23+
*/
24+
public FurnaceWorkbenchScreen(FurnaceWorkbenchMenu menu, Inventory inventory, Component title) {
25+
super(menu, inventory, title);
26+
}
27+
28+
/**
29+
* Initializes the screen and centers the title horizontally by setting {@code titleLabelX}.
30+
*/
31+
@Override
32+
protected void init() {
33+
super.init();
34+
this.titleLabelX = (this.imageWidth - this.font.width(this.title)) / 2;
35+
}
36+
37+
/**
38+
* Draws the furnace workbench background texture onto the screen.
39+
*
40+
* @param guiGraphics the graphics context used for drawing
41+
* @param f partial tick time used for interpolation
42+
* @param i current mouse x position
43+
* @param j current mouse y position
44+
*/
45+
protected void renderBg(GuiGraphics guiGraphics, float f, int i, int j) {
46+
int k = this.leftPos;
47+
int l = this.topPos;
48+
guiGraphics.blit(RenderPipelines.GUI_TEXTURED, TEXTURE, k, l, 0.0F, 0.0F, this.imageWidth, this.imageHeight, 256, 256);
49+
}
50+
51+
/**
52+
* Renders the furnace workbench screen, drawing its background, contents, and tooltips.
53+
*
54+
* @param graphics the graphics context used for rendering
55+
* @param mouseX the current mouse X coordinate
56+
* @param mouseY the current mouse Y coordinate
57+
* @param delta the frame time delta (partial tick) used for animated rendering
58+
*/
59+
@Override
60+
public void render(GuiGraphics graphics, int mouseX, int mouseY, float delta) {
61+
renderBackground(graphics, mouseX, mouseY, delta);
62+
super.render(graphics, mouseX, mouseY, delta);
63+
renderTooltip(graphics, mouseX, mouseY);
64+
}
65+
}

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

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
import com.tcm.MineTale.registry.ModEntities;
1111
import com.tcm.MineTale.registry.ModEntityDataSerializers;
1212
import com.tcm.MineTale.registry.ModItems;
13+
import com.tcm.MineTale.registry.ModMenuTypes;
1314

1415
public class MineTale implements ModInitializer {
1516
public static final String MOD_ID = "minetale";
@@ -19,10 +20,17 @@ public class MineTale implements ModInitializer {
1920
// That way, it's clear which mod wrote info, warnings, and errors.
2021
public static final Logger LOGGER = LoggerFactory.getLogger(MOD_ID);
2122

23+
/**
24+
* Initializes and registers the mod's game content and subsystems during Fabric startup.
25+
*
26+
* <p>Triggers initialization for blocks, block entities, menu types, entities, items, and entity
27+
* data serializers so they are registered with the game before gameplay begins.</p>
28+
*/
2229
@Override
2330
public void onInitialize() {
2431
ModBlocks.initialize();
2532
ModBlockEntities.initialize();
33+
ModMenuTypes.initialize();
2634
ModEntities.initialize();
2735
ModItems.initialize();
2836

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

Lines changed: 98 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,10 @@
33
import net.minecraft.core.BlockPos;
44
import net.minecraft.core.Direction;
55
import net.minecraft.util.RandomSource;
6+
import net.minecraft.world.InteractionResult;
7+
import net.minecraft.world.MenuProvider;
68
import net.minecraft.world.entity.LivingEntity;
9+
import net.minecraft.world.entity.player.Player;
710
import net.minecraft.world.item.ItemStack;
811
import net.minecraft.world.item.context.BlockPlaceContext;
912
import net.minecraft.world.level.Level;
@@ -18,11 +21,15 @@
1821
import net.minecraft.world.level.block.state.BlockState;
1922
import net.minecraft.world.level.block.state.StateDefinition;
2023
import net.minecraft.world.level.block.state.properties.*;
24+
import net.minecraft.world.phys.BlockHitResult;
25+
2126
import org.jetbrains.annotations.Nullable;
2227

28+
import com.tcm.MineTale.block.workbenches.entity.AbstractWorkbenchEntity;
29+
2330
import java.util.function.Supplier;
2431

25-
public abstract class AbstractWorkbench<E extends BlockEntity> extends BaseEntityBlock {
32+
public abstract class AbstractWorkbench<E extends AbstractWorkbenchEntity> extends BaseEntityBlock {
2633
public static final EnumProperty<Direction> FACING = HorizontalDirectionalBlock.FACING;
2734
public static final EnumProperty<DoubleBlockHalf> HALF = BlockStateProperties.DOUBLE_BLOCK_HALF;
2835
public static final EnumProperty<ChestType> TYPE = BlockStateProperties.CHEST_TYPE;
@@ -127,8 +134,98 @@ private boolean isCompatiblePart(BlockState current, BlockState neighbor) {
127134
return true;
128135
}
129136

137+
/**
138+
* Registers the block state properties used by this block.
139+
*
140+
* @param builder the state builder to populate with this block's properties (`FACING`, `HALF`, `TYPE`)
141+
*/
130142
@Override
131143
protected void createBlockStateDefinition(StateDefinition.Builder<Block, BlockState> builder) {
132144
builder.add(FACING, HALF, TYPE);
133145
}
146+
147+
/**
148+
* Create the block entity for the primary anchor of a multipart workbench.
149+
*
150+
* @param pos the position where the block entity would be created
151+
* @param state the block state at the position
152+
* @return the new block entity when this block is the primary anchor (lower half with TYPE `LEFT` or `SINGLE`), or `null` if this block is a secondary part
153+
*/
154+
@Nullable
155+
@Override
156+
public BlockEntity newBlockEntity(BlockPos pos, BlockState state) {
157+
// We only want a Block Entity at the 'primary' anchor point of the structure.
158+
// For 1x1: HALF=LOWER, TYPE=SINGLE
159+
// For 2x1: HALF=LOWER, TYPE=LEFT
160+
// For 2x2: HALF=LOWER, TYPE=LEFT
161+
162+
boolean isLower = state.getValue(HALF) == DoubleBlockHalf.LOWER;
163+
ChestType type = state.getValue(TYPE);
164+
165+
// If it's the RIGHT side of a wide block, or the UPPER half of a tall block, return null.
166+
if (isLower && (type == ChestType.LEFT || type == ChestType.SINGLE)) {
167+
return this.blockEntityType.get().create(pos, state);
168+
}
169+
170+
return null;
171+
}
172+
173+
/**
174+
* Open the workbench menu for the block's master part when a player interacts without an item.
175+
*
176+
* @param state the block state at the clicked position
177+
* @param level the level in which the interaction occurs
178+
* @param pos the position of the block that was interacted with
179+
* @param player the player performing the interaction
180+
* @param hitResult details about the hit (hit position and face)
181+
* @return {@code InteractionResult.CONSUME} if a menu was opened on the server, {@code InteractionResult.SUCCESS} on the client, {@code InteractionResult.PASS} otherwise
182+
*/
183+
@Override
184+
protected InteractionResult useWithoutItem(BlockState state, Level level, BlockPos pos, Player player, BlockHitResult hitResult) {
185+
if (level.isClientSide()) {
186+
return InteractionResult.SUCCESS;
187+
}
188+
189+
// 1. Find the Master Position (Bottom-Left)
190+
BlockPos masterPos = getMasterPos(state, pos);
191+
BlockEntity blockEntity = level.getBlockEntity(masterPos);
192+
193+
// 2. Check if the Master block has the MenuProvider trait
194+
if (blockEntity instanceof MenuProvider menuProvider) {
195+
// 3. Open the Screen (this triggers the ScreenHandler/Menu)
196+
player.openMenu(menuProvider);
197+
return InteractionResult.CONSUME;
198+
}
199+
200+
return InteractionResult.PASS;
201+
}
202+
203+
/**
204+
* Compute the master (bottom-left) anchor position for this workbench block.
205+
*
206+
* The master is the block that serves as the primary anchor for multi-block
207+
* behavior and block-entity placement: if this block is the upper half the
208+
* master is one block below; if this block is the right-side part the master
209+
* is one block to the left relative to the block's facing.
210+
*
211+
* @param state the block state used to determine HALF, TYPE, and FACING
212+
* @param pos the current block position
213+
* @return the position of the master (bottom-left) block for this workbench
214+
*/
215+
public BlockPos getMasterPos(BlockState state, BlockPos pos) {
216+
BlockPos master = pos;
217+
Direction facing = state.getValue(FACING);
218+
219+
// Move down if we are the upper half
220+
if (state.getValue(HALF) == DoubleBlockHalf.UPPER) {
221+
master = master.below();
222+
}
223+
224+
// Move left if we are the right side (relative to facing)
225+
if (state.getValue(TYPE) == ChestType.RIGHT) {
226+
master = master.relative(facing.getCounterClockWise());
227+
}
228+
229+
return master;
230+
}
134231
}

0 commit comments

Comments
 (0)