Skip to content

Commit 308bb12

Browse files
feat: recipe works in recipe book
1 parent b848180 commit 308bb12

21 files changed

Lines changed: 652 additions & 309 deletions

src/client/java/com/tcm/MineTale/MineTaleClient.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@
88
import net.minecraft.client.gui.screens.MenuScreens;
99

1010
public class MineTaleClient implements ClientModInitializer {
11+
12+
13+
1114
/**
1215
* Registers client-side screen factories for custom workbench menu types.
1316
*
@@ -17,6 +20,6 @@ public class MineTaleClient implements ClientModInitializer {
1720
@Override
1821
public void onInitializeClient() {
1922
MenuScreens.register(ModMenuTypes.FURNACE_WORKBENCH_MENU, FurnaceWorkbenchScreen::new);
20-
MenuScreens.register(ModMenuTypes.CAMPFIRE_WORKBENCH_MENU, CampfireWorkbenchScreen::new);
23+
MenuScreens.register(ModMenuTypes.CAMPFIRE_WORKBENCH_MENU, CampfireWorkbenchScreen::new);
2124
}
2225
}

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

Lines changed: 81 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,30 @@
11
package com.tcm.MineTale.block.workbenches.screen;
22

3+
import java.util.List;
4+
35
import com.tcm.MineTale.MineTale;
46
import com.tcm.MineTale.block.workbenches.menu.CampfireWorkbenchMenu;
7+
import com.tcm.MineTale.recipe.MineTaleRecipeBookComponent;
8+
import com.tcm.MineTale.registry.ModBlocks;
9+
import com.tcm.MineTale.registry.ModRecipeDisplay;
510

611
import net.minecraft.client.gui.GuiGraphics;
7-
import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen;
12+
import net.minecraft.client.gui.navigation.ScreenPosition;
13+
import net.minecraft.client.gui.screens.inventory.AbstractRecipeBookScreen;
14+
import net.minecraft.client.gui.screens.recipebook.RecipeBookComponent;
815
import net.minecraft.client.renderer.RenderPipelines;
916
import net.minecraft.resources.Identifier;
1017
import net.minecraft.world.entity.player.Inventory;
18+
import net.minecraft.world.item.ItemStack;
19+
import net.minecraft.world.item.crafting.RecipeBookCategories;
1120
import net.minecraft.network.chat.Component;
1221

13-
public class CampfireWorkbenchScreen extends AbstractContainerScreen<CampfireWorkbenchMenu> {
22+
// FurnaceScreen
23+
24+
public class CampfireWorkbenchScreen extends AbstractRecipeBookScreen<CampfireWorkbenchMenu> {
1425
private static final Identifier TEXTURE =
1526
Identifier.fromNamespaceAndPath(MineTale.MOD_ID, "textures/gui/container/furnace_workbench.png");
27+
1628
/**
1729
* Creates a campfire workbench screen for the provided menu, player inventory, and title.
1830
*
@@ -21,16 +33,53 @@ public class CampfireWorkbenchScreen extends AbstractContainerScreen<CampfireWor
2133
* @param title the title component shown at the top of the screen
2234
*/
2335
public CampfireWorkbenchScreen(CampfireWorkbenchMenu menu, Inventory inventory, Component title) {
24-
super(menu, inventory, title);
36+
super(menu, createRecipeBookComponent(menu), inventory, title);
37+
}
38+
39+
/**
40+
* Static helper to build the component with the custom MineTale tabs
41+
* before the super constructor is called.
42+
*/
43+
private static MineTaleRecipeBookComponent createRecipeBookComponent(CampfireWorkbenchMenu menu) {
44+
ItemStack tabIcon = new ItemStack(ModBlocks.CAMPFIRE_WORKBENCH_BLOCK.asItem());
45+
46+
// CHANGE THIS: Replace CRAFTING_MISC with your custom category
47+
List<RecipeBookComponent.TabInfo> tabs = List.of(
48+
new RecipeBookComponent.TabInfo(tabIcon.getItem(), ModRecipeDisplay.CAMPFIRE_ALLOYING_SEARCH)
49+
);
50+
51+
return new MineTaleRecipeBookComponent(menu, tabs);
2552
}
2653

2754
/**
2855
* Initializes the screen and centers the title horizontally by setting {@code titleLabelX}.
2956
*/
3057
@Override
3158
protected void init() {
59+
// Important: Set your GUI size before super.init()
60+
this.imageWidth = 176;
61+
this.imageHeight = 166;
62+
3263
super.init();
33-
this.titleLabelX = (this.imageWidth - this.font.width(this.title)) / 2;
64+
65+
// // The component is already created by the constructor, just initialize its UI state
66+
// this.recipeBookComponent.init(this.width, this.height, this.minecraft, false);
67+
// this.leftPos = this.recipeBookComponent.updateScreenPosition(this.width, this.imageWidth);
68+
69+
// // Add the toggle button
70+
// this.addRenderableWidget(new ImageButton(
71+
// this.leftPos + 5,
72+
// this.height / 2 - 49,
73+
// 20, 18,
74+
// RecipeBookComponent.RECIPE_BUTTON_SPRITES,
75+
// (button) -> {
76+
// this.recipeBookComponent.toggleVisibility();
77+
// this.leftPos = this.recipeBookComponent.updateScreenPosition(this.width, this.imageWidth);
78+
// button.setPosition(this.leftPos + 5, this.height / 2 - 49);
79+
// }
80+
// ));
81+
82+
// this.addWidget(this.recipeBookComponent);
3483
}
3584

3685
/**
@@ -57,8 +106,36 @@ protected void renderBg(GuiGraphics guiGraphics, float f, int i, int j) {
57106
*/
58107
@Override
59108
public void render(GuiGraphics graphics, int mouseX, int mouseY, float delta) {
109+
// 1. Always render the dark background tint first
60110
renderBackground(graphics, mouseX, mouseY, delta);
111+
112+
// 2. Add a null check before calling ANY methods on the component
113+
// if (this.recipeBookComponent != null) {
114+
// this.recipeBookComponent.render(graphics, mouseX, mouseY, delta);
115+
// }
116+
117+
// 3. Call super (this draws your slots and items)
61118
super.render(graphics, mouseX, mouseY, delta);
119+
120+
// 4. Ghost recipes and Tooltips also need the null check
121+
// if (this.recipeBookComponent != null) {
122+
// this.recipeBookComponent.renderGhostRecipe(graphics, true);
123+
// this.recipeBookComponent.renderTooltip(graphics, this.leftPos, this.topPos, this.hoveredSlot);
124+
// }
125+
62126
renderTooltip(graphics, mouseX, mouseY);
63127
}
128+
129+
@Override
130+
protected ScreenPosition getRecipeBookButtonPosition() {
131+
// 1. Calculate the start (left) of your workbench GUI
132+
int guiLeft = (this.width - this.imageWidth) / 2;
133+
134+
// 2. Calculate the top of your workbench GUI
135+
int guiTop = (this.height - this.imageHeight) / 2;
136+
137+
// 3. Standard Vanilla positioning:
138+
// Usually 5 pixels in from the left and 49 pixels up from the center
139+
return new ScreenPosition(guiLeft + 5, guiTop + this.imageHeight / 2 - 49);
140+
}
64141
}
Lines changed: 63 additions & 88 deletions
Original file line numberDiff line numberDiff line change
@@ -1,129 +1,104 @@
11
package com.tcm.MineTale.block.workbenches.screen;
22

3+
import java.util.List;
4+
35
import com.tcm.MineTale.MineTale;
46
import com.tcm.MineTale.block.workbenches.menu.FurnaceWorkbenchMenu;
5-
import com.tcm.MineTale.recipe.FurnaceRecipeBookComponent;
7+
import com.tcm.MineTale.recipe.MineTaleRecipeBookComponent;
8+
import com.tcm.MineTale.registry.ModBlocks;
69

710
import net.minecraft.client.gui.GuiGraphics;
8-
import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen;
9-
import net.minecraft.client.input.KeyEvent;
11+
import net.minecraft.client.gui.navigation.ScreenPosition;
12+
import net.minecraft.client.gui.screens.inventory.AbstractRecipeBookScreen;
13+
import net.minecraft.client.gui.screens.recipebook.RecipeBookComponent;
1014
import net.minecraft.client.renderer.RenderPipelines;
1115
import net.minecraft.resources.Identifier;
1216
import net.minecraft.world.entity.player.Inventory;
17+
import net.minecraft.world.item.ItemStack;
18+
import net.minecraft.world.item.crafting.RecipeBookCategories;
1319
import net.minecraft.network.chat.Component;
1420

15-
public class FurnaceWorkbenchScreen extends AbstractContainerScreen<FurnaceWorkbenchMenu> {
21+
public class FurnaceWorkbenchScreen extends AbstractRecipeBookScreen<FurnaceWorkbenchMenu> {
1622
private static final Identifier TEXTURE =
1723
Identifier.fromNamespaceAndPath(MineTale.MOD_ID, "textures/gui/container/furnace_workbench.png");
1824

19-
private FurnaceRecipeBookComponent recipeBookComponent;
20-
2125
/**
22-
* Creates a new furnace workbench screen for the given menu, player inventory, and title.
23-
*
24-
* @param menu the container menu that provides slots and syncs state for this screen
25-
* @param inventory the player's inventory to display and interact with
26-
* @param title the title component shown at the top of the screen
26+
* Creates a new furnace workbench screen.
27+
* Note: recipeBookComponent is inherited from AbstractRecipeBookScreen.
2728
*/
2829
public FurnaceWorkbenchScreen(FurnaceWorkbenchMenu menu, Inventory inventory, Component title) {
29-
super(menu, inventory, title);
30+
super(menu, createRecipeBookComponent(menu), inventory, title);
3031
}
3132

3233
/**
33-
* Initializes the screen and centers the title horizontally by setting {@code titleLabelX}.
34+
* Static helper to build the component with the custom MineTale tabs.
35+
* This uses the FURNACE_WORKBENCH icon for this specific screen's tab.
3436
*/
37+
private static MineTaleRecipeBookComponent createRecipeBookComponent(FurnaceWorkbenchMenu menu) {
38+
ItemStack tabIcon = new ItemStack(ModBlocks.FURNACE_WORKBENCH_BLOCK_T1.asItem());
39+
40+
List<RecipeBookComponent.TabInfo> tabs = List.of(
41+
new RecipeBookComponent.TabInfo(tabIcon.getItem(), RecipeBookCategories.CRAFTING_MISC)
42+
);
43+
44+
return new MineTaleRecipeBookComponent(menu, tabs);
45+
}
46+
3547
@Override
3648
protected void init() {
49+
this.imageWidth = 176;
50+
this.imageHeight = 166;
51+
3752
super.init();
3853

39-
// 2. Initialize it here where 'this.menu' is available
40-
if (this.recipeBookComponent == null) {
41-
this.recipeBookComponent = new FurnaceRecipeBookComponent(this.menu);
42-
}
43-
44-
// Standard init and visibility logic
45-
this.recipeBookComponent.init(this.width, this.height, this.minecraft, false);
46-
if (!this.recipeBookComponent.isVisible()) {
47-
this.recipeBookComponent.toggleVisibility();
48-
}
49-
this.leftPos = this.recipeBookComponent.updateScreenPosition(this.width, this.imageWidth);
54+
// // Initialize the inherited recipeBookComponent UI state
55+
// this.recipeBookComponent.init(this.width, this.height, this.minecraft, false);
56+
// this.leftPos = this.recipeBookComponent.updateScreenPosition(this.width, this.imageWidth);
57+
58+
// // The toggle button is managed via getRecipeBookButtonPosition() in 1.21.1
59+
// // but we add the ImageButton manually to match your CampfireWorkbenchScreen logic exactly.
60+
// this.addRenderableWidget(new ImageButton(
61+
// this.leftPos + 5,
62+
// this.height / 2 - 49,
63+
// 20, 18,
64+
// RecipeBookComponent.RECIPE_BUTTON_SPRITES,
65+
// (button) -> {
66+
// this.recipeBookComponent.toggleVisibility();
67+
// this.leftPos = this.recipeBookComponent.updateScreenPosition(this.width, this.imageWidth);
68+
// button.setPosition(this.leftPos + 5, this.height / 2 - 49);
69+
// }
70+
// ));
5071
}
5172

5273
@Override
53-
public boolean keyPressed(KeyEvent keyEvent) {
54-
// 1. Let the search bar in the recipe book use the key first
55-
// If your RecipeBookComponent doesn't take KeyEvent, you'll need to map
56-
// the keyEvent.getKeyCode() to the standard int keyCode version.
57-
if (this.recipeBookComponent.keyPressed(keyEvent)) {
58-
return true;
59-
}
60-
61-
// 2. Identify the Recipe Book toggle key (Standard 'B')
62-
// We check the code to see if it matches the vanilla keybind
63-
// int keyCode = keyEvent.getKeyCode();
64-
// this.minecraft.options.ke
65-
// if (this.minecraft.options.keyRecipeBook.matches(keyCode, 0)) {
66-
// return true; // Return true to "consume" the press and do nothing
67-
// }
68-
69-
return super.keyPressed(keyEvent);
74+
protected void renderBg(GuiGraphics guiGraphics, float f, int i, int j) {
75+
int k = this.leftPos;
76+
int l = this.topPos;
77+
guiGraphics.blit(RenderPipelines.GUI_TEXTURED, TEXTURE, k, l, 0.0F, 0.0F, this.imageWidth, this.imageHeight, 256, 256);
7078
}
7179

72-
/**
73-
* Draws the furnace workbench background texture onto the screen.
74-
*
75-
* @param guiGraphics the graphics context used for drawing
76-
* @param f partial tick time used for interpolation
77-
* @param i current mouse x position
78-
* @param j current mouse y position
79-
*/
80-
protected void renderBg(GuiGraphics guiGraphics, float f, int i, int j) {
81-
int k = this.leftPos;
82-
int l = this.topPos;
83-
guiGraphics.blit(RenderPipelines.GUI_TEXTURED, TEXTURE, k, l, 0.0F, 0.0F, this.imageWidth, this.imageHeight, 256, 256);
84-
}
85-
86-
/**
87-
* Renders the furnace workbench screen, drawing its background, contents, and tooltips.
88-
*
89-
* @param graphics the graphics context used for rendering
90-
* @param mouseX the current mouse X coordinate
91-
* @param mouseY the current mouse Y coordinate
92-
* @param delta the frame time delta (partial tick) used for animated rendering
93-
*/
94-
// @Override
95-
// public void render(GuiGraphics graphics, int mouseX, int mouseY, float delta) {
96-
// // Render the dark background tint
97-
// renderBackground(graphics, mouseX, mouseY, delta);
98-
99-
// // Always render the book and the main GUI together
100-
// this.recipeBookComponent.render(graphics, mouseX, mouseY, delta);
101-
// super.render(graphics, mouseX, mouseY, delta);
102-
// this.recipeBookComponent.renderGhostRecipe(graphics, true);
103-
104-
// renderTooltip(graphics, mouseX, mouseY);
105-
// // this.recipeBookComponent.renderTooltip(graphics, this.leftPos, this.topPos, mouseX, mouseY);
106-
// }
107-
10880
@Override
10981
public void render(GuiGraphics graphics, int mouseX, int mouseY, float delta) {
110-
// 1. Always render the dark background tint first
11182
renderBackground(graphics, mouseX, mouseY, delta);
11283

113-
// 2. Add a null check before calling ANY methods on the component
114-
if (this.recipeBookComponent != null) {
115-
this.recipeBookComponent.render(graphics, mouseX, mouseY, delta);
116-
}
84+
// if (this.recipeBookComponent != null) {
85+
// this.recipeBookComponent.render(graphics, mouseX, mouseY, delta);
86+
// }
11787

118-
// 3. Call super (this draws your slots and items)
11988
super.render(graphics, mouseX, mouseY, delta);
12089

121-
// 4. Ghost recipes and Tooltips also need the null check
122-
if (this.recipeBookComponent != null) {
123-
this.recipeBookComponent.renderGhostRecipe(graphics, true);
124-
this.recipeBookComponent.renderTooltip(graphics, this.leftPos, this.topPos, this.hoveredSlot);
125-
}
90+
// if (this.recipeBookComponent != null) {
91+
// this.recipeBookComponent.renderGhostRecipe(graphics, true);
92+
// this.recipeBookComponent.renderTooltip(graphics, this.leftPos, this.topPos, this.hoveredSlot);
93+
// }
12694

12795
renderTooltip(graphics, mouseX, mouseY);
12896
}
97+
98+
@Override
99+
protected ScreenPosition getRecipeBookButtonPosition() {
100+
int guiLeft = (this.width - this.imageWidth) / 2;
101+
int guiTop = (this.height - this.imageHeight) / 2;
102+
return new ScreenPosition(guiLeft + 5, guiTop + this.imageHeight / 2 - 49);
103+
}
129104
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
package com.tcm.MineTale.mixin.client;
2+
3+
import org.spongepowered.asm.mixin.Mixin;
4+
import org.spongepowered.asm.mixin.injection.At;
5+
import org.spongepowered.asm.mixin.injection.Inject;
6+
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
7+
8+
import com.tcm.MineTale.registry.ModRecipeDisplay;
9+
import com.tcm.MineTale.registry.ModRecipes;
10+
11+
import net.minecraft.client.ClientRecipeBook;
12+
import net.minecraft.world.item.crafting.RecipeBookCategory;
13+
import net.minecraft.world.item.crafting.RecipeHolder;
14+
15+
@Mixin(ClientRecipeBook.class)
16+
public abstract class ClientRecipeBookMixin {
17+
@Inject(method = "getCategory", at = @At("HEAD"), cancellable = true)
18+
private static void minetale$addCustomCategory(RecipeHolder<?> recipe, CallbackInfoReturnable<RecipeBookCategory> cir) {
19+
if (recipe.value().getType() == ModRecipes.FURNACE_SERIALIZER) {
20+
// This tells the search engine to put your recipes into your custom tab
21+
cir.setReturnValue(ModRecipeDisplay.CAMPFIRE_ALLOYING_SEARCH);
22+
}
23+
}
24+
}

0 commit comments

Comments
 (0)