Skip to content

Commit 2e1d965

Browse files
Merge pull request #59 from CodeMonkeysMods/Andy/test-inventory-display-items
Implement ingredient list rendering in workbench screen
2 parents 9df4330 + 61fa10b commit 2e1d965

File tree

7 files changed

+118
-16
lines changed

7 files changed

+118
-16
lines changed

.github/workflows/build.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
# against bad commits.
55

66
name: build
7-
on: [pull_request, push]
7+
on: [push]
88

99
jobs:
1010
build:

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

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@
3535
import net.minecraft.world.item.crafting.display.SlotDisplayContext;
3636
import net.minecraft.network.chat.Component;
3737

38-
public class ArmorersWorkbenchScreen extends AbstractRecipeBookScreen<ArmorersWorkbenchMenu> {
38+
public class ArmorersWorkbenchScreen extends ModAbstractContainerScreen<ArmorersWorkbenchMenu> {
3939
private static final Identifier TEXTURE =
4040
Identifier.fromNamespaceAndPath(MineTale.MOD_ID, "textures/gui/container/workbench_workbench.png");
4141

@@ -190,6 +190,9 @@ public void render(GuiGraphics graphics, int mouseX, int mouseY, float delta) {
190190
this.craftOneBtn.active = canCraftOne;
191191
this.craftTenBtn.active = canCraftTen;
192192
this.craftAllBtn.active = canCraftMoreThanOne;
193+
194+
// NEW: Render the Ingredients List
195+
this.renderIngredientList(graphics, selectedEntry, mouseX, mouseY);
193196
} else {
194197
this.craftOneBtn.active = false;
195198
this.craftTenBtn.active = false;

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

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@
2020
import net.minecraft.client.gui.GuiGraphics;
2121
import net.minecraft.client.gui.components.Button;
2222
import net.minecraft.client.gui.navigation.ScreenPosition;
23-
import net.minecraft.client.gui.screens.inventory.AbstractRecipeBookScreen;
2423
import net.minecraft.client.gui.screens.recipebook.RecipeBookComponent;
2524
import net.minecraft.client.renderer.RenderPipelines;
2625
import net.minecraft.core.Holder;
@@ -34,8 +33,9 @@
3433
import net.minecraft.world.item.crafting.display.RecipeDisplayId;
3534
import net.minecraft.world.item.crafting.display.SlotDisplayContext;
3635
import net.minecraft.network.chat.Component;
36+
import org.jspecify.annotations.NonNull;
3737

38-
public class BuildersWorkbenchScreen extends AbstractRecipeBookScreen<BuildersWorkbenchMenu> {
38+
public class BuildersWorkbenchScreen extends ModAbstractContainerScreen<BuildersWorkbenchMenu> {
3939
private static final Identifier TEXTURE =
4040
Identifier.fromNamespaceAndPath(MineTale.MOD_ID, "textures/gui/container/workbench_workbench.png");
4141

@@ -159,35 +159,33 @@ protected void renderBg(GuiGraphics guiGraphics, float f, int i, int j) {
159159
}
160160

161161
@Override
162-
public void render(GuiGraphics graphics, int mouseX, int mouseY, float delta) {
162+
public void render(@NonNull GuiGraphics graphics, int mouseX, int mouseY, float delta) {
163163
renderBackground(graphics, mouseX, mouseY, delta);
164164
super.render(graphics, mouseX, mouseY, delta);
165165

166-
// 1. Get the current selection from the book
167166
RecipeDisplayId currentId = this.mineTaleRecipeBook.getSelectedRecipeId();
168-
169-
// 2. If it's NOT null, remember it!
170167
if (currentId != null) {
171168
this.lastKnownSelectedId = currentId;
172169
}
173170

174-
// 3. Use the remembered ID to find the entry for button activation
175171
RecipeDisplayEntry selectedEntry = null;
176172
if (this.lastKnownSelectedId != null && this.minecraft.level != null) {
177173
ClientRecipeBook book = this.minecraft.player.getRecipeBook();
178174
selectedEntry = ((ClientRecipeBookAccessor) book).getKnown().get(this.lastKnownSelectedId);
179175
}
180176

181-
// 2. Button Activation Logic
182177
if (selectedEntry != null) {
183-
// We use the entry directly. It contains the 15 ingredients needed!
178+
// Existing Button Logic
184179
boolean canCraftOne = canCraft(this.minecraft.player, selectedEntry, 1);
185180
boolean canCraftMoreThanOne = canCraft(this.minecraft.player, selectedEntry, 2);
186181
boolean canCraftTen = canCraft(this.minecraft.player, selectedEntry, 10);
187182

188183
this.craftOneBtn.active = canCraftOne;
189184
this.craftTenBtn.active = canCraftTen;
190185
this.craftAllBtn.active = canCraftMoreThanOne;
186+
187+
// NEW: Render the Ingredients List
188+
this.renderIngredientList(graphics, selectedEntry, mouseX, mouseY);
191189
} else {
192190
this.craftOneBtn.active = false;
193191
this.craftTenBtn.active = false;
@@ -296,4 +294,4 @@ protected ScreenPosition getRecipeBookButtonPosition() {
296294
// Usually 5 pixels in from the left and 49 pixels up from the center
297295
return new ScreenPosition(guiLeft + 5, guiTop + this.imageHeight / 2 - 49);
298296
}
299-
}
297+
}

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

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@
3535
import net.minecraft.world.item.crafting.display.SlotDisplayContext;
3636
import net.minecraft.network.chat.Component;
3737

38-
public class FarmersWorkbenchScreen extends AbstractRecipeBookScreen<FarmersWorkbenchMenu> {
38+
public class FarmersWorkbenchScreen extends ModAbstractContainerScreen<FarmersWorkbenchMenu> {
3939
private static final Identifier TEXTURE =
4040
Identifier.fromNamespaceAndPath(MineTale.MOD_ID, "textures/gui/container/workbench_workbench.png");
4141

@@ -198,6 +198,9 @@ public void render(GuiGraphics graphics, int mouseX, int mouseY, float delta) {
198198
this.craftOneBtn.active = canCraftOne;
199199
this.craftTenBtn.active = canCraftTen;
200200
this.craftAllBtn.active = canCraftMoreThanOne;
201+
202+
// NEW: Render the Ingredients List
203+
this.renderIngredientList(graphics, selectedEntry, mouseX, mouseY);
201204
} else {
202205
this.craftOneBtn.active = false;
203206
this.craftTenBtn.active = false;
Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
package com.tcm.MineTale.block.workbenches.screen;
2+
3+
import com.tcm.MineTale.block.workbenches.menu.AbstractWorkbenchContainerMenu;
4+
5+
import net.minecraft.client.gui.GuiGraphics;
6+
import net.minecraft.client.gui.screens.inventory.AbstractRecipeBookScreen;
7+
import net.minecraft.client.gui.screens.recipebook.RecipeBookComponent;
8+
import net.minecraft.core.Holder;
9+
import net.minecraft.network.chat.Component;
10+
import net.minecraft.world.entity.player.Inventory;
11+
import net.minecraft.world.item.Item;
12+
import net.minecraft.world.item.ItemStack;
13+
import net.minecraft.world.item.crafting.Ingredient;
14+
import net.minecraft.world.item.crafting.display.RecipeDisplayEntry;
15+
16+
import java.util.HashMap;
17+
import java.util.List;
18+
import java.util.Map;
19+
import java.util.Optional;
20+
21+
22+
public abstract class ModAbstractContainerScreen<T extends AbstractWorkbenchContainerMenu> extends AbstractRecipeBookScreen<T> {
23+
24+
public ModAbstractContainerScreen(T recipeBookMenu, RecipeBookComponent<?> recipeBookComponent, Inventory inventory, Component component) {
25+
super(recipeBookMenu, recipeBookComponent, inventory, component);
26+
}
27+
28+
protected void renderIngredientList(GuiGraphics graphics, RecipeDisplayEntry entry, int mouseX, int mouseY) {
29+
Optional<List<Ingredient>> reqs = entry.craftingRequirements();
30+
if (reqs.isEmpty()) return;
31+
32+
// Group requirements to avoid duplicate rows for the same item type
33+
Map<List<Holder<Item>>, Integer> aggregated = new HashMap<>();
34+
Map<List<Holder<Item>>, Ingredient> holderToIng = new HashMap<>();
35+
36+
for (Ingredient ing : reqs.get()) {
37+
List<Holder<Item>> key = ing.items().toList();
38+
aggregated.put(key, aggregated.getOrDefault(key, 0) + 1);
39+
holderToIng.putIfAbsent(key, ing);
40+
}
41+
42+
int startX = this.leftPos + 8; // Adjust to fit your texture's empty space
43+
int startY = this.topPos + 20;
44+
int rowHeight = 20;
45+
int index = 0;
46+
47+
for (Map.Entry<List<Holder<Item>>, Integer> reqEntry : aggregated.entrySet()) {
48+
Ingredient ing = holderToIng.get(reqEntry.getKey());
49+
int amountNeeded = reqEntry.getValue();
50+
int currentY = startY + (index * rowHeight);
51+
52+
// Calculate total available (Inv + Nearby)
53+
int available = getAvailableCount(ing);
54+
55+
// Draw Item Icon
56+
// Inside your loop
57+
ItemStack[] variants = ing.items().map(ItemStack::new).toArray(ItemStack[]::new);
58+
if (variants.length > 0) {
59+
long time = System.currentTimeMillis() / 1000;
60+
ItemStack displayStack = variants[(int) (time % variants.length)];
61+
62+
graphics.renderFakeItem(displayStack, startX, currentY);
63+
64+
int color = (available < amountNeeded) ? 0xFFFF5555 : 0xFFFFFFFF; // Added alpha channel
65+
String progress = available + "/" + amountNeeded;
66+
graphics.drawString(this.font, progress, startX + 22, currentY + 4, color);
67+
68+
if (mouseX >= startX && mouseX <= startX + 16 && mouseY >= currentY && mouseY <= currentY + 16) {
69+
graphics.setTooltipForNextFrame(this.font, displayStack, mouseX, mouseY);
70+
}
71+
}
72+
index++;
73+
}
74+
}
75+
76+
private int getAvailableCount(Ingredient ingredient) {
77+
int found = 0;
78+
// Check Player Inventory
79+
// Use getContainerSize() and getItem(i) for safe access
80+
Inventory inv = this.minecraft.player.getInventory();
81+
for (int i = 0; i < inv.getContainerSize(); i++) {
82+
ItemStack stack = inv.getItem(i);
83+
if (ingredient.test(stack)) {
84+
found += stack.getCount();
85+
}
86+
}
87+
88+
// Check Networked Nearby Items
89+
if (this.menu instanceof AbstractWorkbenchContainerMenu workbenchMenu) {
90+
for (ItemStack stack : workbenchMenu.getNetworkedNearbyItems()) {
91+
if (ingredient.test(stack)) found += stack.getCount();
92+
}
93+
}
94+
return found;
95+
}
96+
}

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

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@
3535
import net.minecraft.world.item.crafting.display.SlotDisplayContext;
3636
import net.minecraft.network.chat.Component;
3737

38-
public class WorkbenchWorkbenchScreen extends AbstractRecipeBookScreen<WorkbenchWorkbenchMenu> {
38+
public class WorkbenchWorkbenchScreen extends ModAbstractContainerScreen<WorkbenchWorkbenchMenu> {
3939
private static final Identifier TEXTURE =
4040
Identifier.fromNamespaceAndPath(MineTale.MOD_ID, "textures/gui/container/workbench_workbench.png");
4141

@@ -197,6 +197,9 @@ public void render(GuiGraphics graphics, int mouseX, int mouseY, float delta) {
197197
this.craftOneBtn.active = canCraftOne;
198198
this.craftTenBtn.active = canCraftTen;
199199
this.craftAllBtn.active = canCraftMoreThanOne;
200+
201+
// NEW: Render the Ingredients List
202+
this.renderIngredientList(graphics, selectedEntry, mouseX, mouseY);
200203
} else {
201204
this.craftOneBtn.active = false;
202205
this.craftTenBtn.active = false;

src/main/java/com/tcm/MineTale/block/workbenches/menu/AbstractWorkbenchContainerMenu.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
package com.tcm.MineTale.block.workbenches.menu;
22

3-
import java.util.ArrayList;
4-
import java.util.List;
3+
import java.util.*;
54

65
import org.jspecify.annotations.Nullable;
76

0 commit comments

Comments
 (0)