@@ -7,6 +7,7 @@ import type { Mineflayer } from '../libs/mineflayer'
77import { ActionError } from '../utils/errors'
88import { useLogger } from '../utils/logger'
99import { McData } from '../utils/mcdata'
10+ import { planRecipe } from '../utils/recipe-planner'
1011import { ensureCraftingTable } from './actions/ensure'
1112import { collectBlock , placeBlock } from './blocks'
1213import { goToNearestBlock , goToPosition , moveAway } from './movement'
@@ -40,8 +41,7 @@ export async function craftRecipe(
4041 try {
4142 await mineflayer . bot . craft ( recipe , num , craftingTable ?? undefined )
4243 logger . log (
43- `Successfully crafted ${ num } ${ itemName } ${
44- craftingTable ? ' using crafting table' : ''
44+ `Successfully crafted ${ num } ${ itemName } ${ craftingTable ? ' using crafting table' : ''
4545 } .`,
4646 )
4747 return true
@@ -78,8 +78,7 @@ export async function craftRecipe(
7878 }
7979 catch ( err ) {
8080 logger . log (
81- `Attempt ${ attempts + 1 } to move to crafting table failed: ${
82- ( err as Error ) . message
81+ `Attempt ${ attempts + 1 } to move to crafting table failed: ${ ( err as Error ) . message
8382 } `,
8483 )
8584 if ( err instanceof ActionError )
@@ -137,12 +136,56 @@ export async function craftRecipe(
137136 }
138137 }
139138
140- // RECURSION GUARD:
139+ // RECURSION GUARD + AUTO-CRAFT INTERMEDIATE MATERIALS :
141140 // If we failed to craft basic items (planks, sticks) without a table,
142- // do NOT try to find a table. These items do not need a table.
143- // Seeking a table often triggers "ensureCraftingTable" -> "ensurePlanks" -> infinite loop.
141+ // check if we can craft from raw materials using the recipe planner.
144142 if ( itemName . includes ( 'planks' ) || itemName === 'stick' || itemName === 'crafting_table' ) {
145- logger . log ( `Recursion Guard: Skipping crafting table search for basic item: ${ itemName } ` )
143+ logger . log ( `Recursion Guard: Checking if we can craft ${ itemName } from raw materials` )
144+
145+ // Use the recipe planner to see if we can craft this item
146+ const plan = planRecipe ( mineflayer . bot , itemName , num )
147+
148+ if ( plan . status === 'unknown_item' ) {
149+ throw new ActionError ( 'UNKNOWN' , `Unknown item: ${ itemName } ` )
150+ }
151+
152+ // If we can craft now (have all materials including intermediates), do it
153+ if ( plan . canCraftNow && plan . steps . length > 0 ) {
154+ logger . log ( `Recipe planner found craftable path with ${ plan . steps . length } steps` )
155+
156+ // Craft all intermediate steps first (in reverse order = base materials first)
157+ for ( const step of [ ...plan . steps ] . reverse ( ) ) {
158+ if ( step . action === 'craft' ) {
159+ logger . log ( `Auto-crafting intermediate: ${ step . amount } x ${ step . item } ` )
160+ // Use direct bot.craft for intermediates to avoid infinite recursion
161+ const stepItemId = mcData . getItemId ( step . item )
162+ if ( ! stepItemId ) {
163+ throw new ActionError ( 'UNKNOWN' , `Unknown intermediate item: ${ step . item } ` )
164+ }
165+ const stepRecipes = mineflayer . bot . recipesFor ( stepItemId , null , 1 , null )
166+ if ( stepRecipes && stepRecipes . length > 0 ) {
167+ const outputPerCraft = stepRecipes [ 0 ] . result ?. count ?? 1
168+ const craftCount = Math . ceil ( step . amount / outputPerCraft )
169+ await mineflayer . bot . craft ( stepRecipes [ 0 ] , craftCount )
170+ logger . log ( `Successfully crafted ${ craftCount } x ${ step . item } ` )
171+ }
172+ }
173+ }
174+
175+ return true
176+ }
177+
178+ // Can't craft - provide helpful error message
179+ if ( Object . keys ( plan . missing ) . length > 0 ) {
180+ const missingList = Object . entries ( plan . missing )
181+ . map ( ( [ item , count ] ) => `${ count } x ${ item } ` )
182+ . join ( ', ' )
183+ throw new ActionError ( 'RESOURCE_MISSING' , `Cannot craft ${ itemName } - missing: ${ missingList } ` , {
184+ item : itemName ,
185+ missing : plan . missing ,
186+ } )
187+ }
188+
146189 throw new ActionError ( 'RESOURCE_MISSING' , `Cannot craft ${ itemName } - missing ingredients` , { item : itemName } )
147190 }
148191
0 commit comments