@@ -159,36 +159,34 @@ protected void renderBg(GuiGraphics guiGraphics, float f, int i, int j) {
159159 guiGraphics .blit (RenderPipelines .GUI_TEXTURED , TEXTURE , k , l , 0.0F , 0.0F , this .imageWidth , this .imageHeight , 256 , 256 );
160160 }
161161
162- @ Override
162+ @ Override
163163 public void render (GuiGraphics graphics , int mouseX , int mouseY , float delta ) {
164164 renderBackground (graphics , mouseX , mouseY , delta );
165165 super .render (graphics , mouseX , mouseY , delta );
166166
167- // 1. Get the current selection from the book
168167 RecipeDisplayId currentId = this .mineTaleRecipeBook .getSelectedRecipeId ();
169-
170- // 2. If it's NOT null, remember it!
171168 if (currentId != null ) {
172169 this .lastKnownSelectedId = currentId ;
173170 }
174171
175- // 3. Use the remembered ID to find the entry for button activation
176172 RecipeDisplayEntry selectedEntry = null ;
177173 if (this .lastKnownSelectedId != null && this .minecraft .level != null ) {
178174 ClientRecipeBook book = this .minecraft .player .getRecipeBook ();
179175 selectedEntry = ((ClientRecipeBookAccessor ) book ).getKnown ().get (this .lastKnownSelectedId );
180176 }
181177
182- // 2. Button Activation Logic
183178 if (selectedEntry != null ) {
184- // We use the entry directly. It contains the 15 ingredients needed!
179+ // Existing Button Logic
185180 boolean canCraftOne = canCraft (this .minecraft .player , selectedEntry , 1 );
186181 boolean canCraftMoreThanOne = canCraft (this .minecraft .player , selectedEntry , 2 );
187182 boolean canCraftTen = canCraft (this .minecraft .player , selectedEntry , 10 );
188183
189184 this .craftOneBtn .active = canCraftOne ;
190185 this .craftTenBtn .active = canCraftTen ;
191186 this .craftAllBtn .active = canCraftMoreThanOne ;
187+
188+ // NEW: Render the Ingredients List
189+ renderIngredientList (graphics , selectedEntry , mouseX , mouseY );
192190 } else {
193191 this .craftOneBtn .active = false ;
194192 this .craftTenBtn .active = false ;
@@ -198,6 +196,69 @@ public void render(GuiGraphics graphics, int mouseX, int mouseY, float delta) {
198196 renderTooltip (graphics , mouseX , mouseY );
199197 }
200198
199+ private void renderIngredientList (GuiGraphics graphics , RecipeDisplayEntry entry , int mouseX , int mouseY ) {
200+ Optional <List <Ingredient >> reqs = entry .craftingRequirements ();
201+ if (reqs .isEmpty ()) return ;
202+
203+ // Group requirements to avoid duplicate rows for the same item type
204+ Map <List <Holder <Item >>, Integer > aggregated = new HashMap <>();
205+ Map <List <Holder <Item >>, Ingredient > holderToIng = new HashMap <>();
206+
207+ for (Ingredient ing : reqs .get ()) {
208+ List <Holder <Item >> key = ing .items ().toList ();
209+ aggregated .put (key , aggregated .getOrDefault (key , 0 ) + 1 );
210+ holderToIng .putIfAbsent (key , ing );
211+ }
212+
213+ int startX = this .leftPos + 8 ; // Adjust to fit your texture's empty space
214+ int startY = this .topPos + 20 ;
215+ int rowHeight = 20 ;
216+ int index = 0 ;
217+
218+ for (Map .Entry <List <Holder <Item >>, Integer > reqEntry : aggregated .entrySet ()) {
219+ Ingredient ing = holderToIng .get (reqEntry .getKey ());
220+ int amountNeeded = reqEntry .getValue ();
221+ int currentY = startY + (index * rowHeight );
222+
223+ // Calculate total available (Inv + Nearby)
224+ int available = getAvailableCount (ing );
225+
226+ // Draw Item Icon
227+ ItemStack [] variants = ing .items ().toArray (ItemStack []::new );
228+ if (variants .length > 0 ) {
229+ // Cycle through variants every second
230+ ItemStack displayStack = variants [(int ) (System .currentTimeMillis () / 1000 % variants .length )];
231+ graphics .renderFakeItem (displayStack , startX , currentY );
232+
233+ // Draw Text (Red if lacking, White if okay)
234+ int color = (available < amountNeeded ) ? 0xFF5555 : 0xFFFFFF ;
235+ String progress = available + "/" + amountNeeded ;
236+ graphics .drawString (this .font , progress , startX + 20 , currentY + 4 , color , true );
237+
238+ // Tooltip logic
239+ if (mouseX >= startX && mouseX < startX + 16 && mouseY >= currentY && mouseY < currentY + 16 ) {
240+ graphics .renderTooltip (this .font , displayStack , mouseX , mouseY );
241+ }
242+ }
243+ index ++;
244+ }
245+ }
246+
247+ private int getAvailableCount (Ingredient ingredient ) {
248+ int found = 0 ;
249+ // Check Player Inventory
250+ for (ItemStack stack : this .minecraft .player .getInventory ().items ) {
251+ if (ingredient .test (stack )) found += stack .getCount ();
252+ }
253+ // Check Networked Nearby Items
254+ if (this .menu instanceof AbstractWorkbenchContainerMenu workbenchMenu ) {
255+ for (ItemStack stack : workbenchMenu .getNetworkedNearbyItems ()) {
256+ if (ingredient .test (stack )) found += stack .getCount ();
257+ }
258+ }
259+ return found ;
260+ }
261+
201262 /**
202263 * Determines whether the player has enough ingredients to craft the given recipe the specified number of times.
203264 *
@@ -297,4 +358,4 @@ protected ScreenPosition getRecipeBookButtonPosition() {
297358 // Usually 5 pixels in from the left and 49 pixels up from the center
298359 return new ScreenPosition (guiLeft + 5 , guiTop + this .imageHeight / 2 - 49 );
299360 }
300- }
361+ }
0 commit comments