mineflayer-crafting-util
v0.5.0
Published
A plugin to simplify crafting recipes.
Maintainers
Readme
mineflayer-crafting-util
Crafting planner and execution helpers for Mineflayer bots.
The library can be used in two ways:
- As a Mineflayer plugin, which adds planning and crafting methods to
bot. - As a static planner, which builds plans from a
minecraft-dataregistry without connecting a bot.
Installation
npm i mineflayer-crafting-utilyarn add mineflayer-crafting-utilBot Usage
const mineflayer = require('mineflayer')
const { plugin: craftingUtil } = require('mineflayer-crafting-util')
const bot = mineflayer.createBot({
host: 'localhost',
port: 25565,
username: 'bot'
})
bot.loadPlugin(craftingUtil())
bot.once('spawn', async () => {
const stick = bot.registry.itemsByName.stick
const craftingTable = bot.findBlock({
matching: bot.registry.blocksByName.crafting_table.id,
maxDistance: 4
})
const plan = bot.planCraftInventory({ id: stick.id, count: 4 })
if (!plan.success) {
console.log('Missing base items:', plan.itemsRequiredBase)
return
}
await bot.craftPlan(plan, craftingTable)
})For a one-call inventory-backed craft:
const pickaxe = bot.registry.itemsByName.iron_pickaxe
const craftingTable = bot.findBlock({
matching: bot.registry.blocksByName.crafting_table.id,
maxDistance: 4
})
await bot.craftItem(pickaxe.id, 1, craftingTable)Static Usage
const mcData = require('minecraft-data')('1.21.4')
const { buildStatic } = require('mineflayer-crafting-util')
async function main () {
const { Recipe } = require('prismarine-recipe')(mcData)
const crafter = await buildStatic(Recipe)
const pickaxe = mcData.itemsByName.stone_pickaxe
const plan = crafter(
{ id: pickaxe.id, count: 1 },
{
availableItems: [
{ id: mcData.itemsByName.cobblestone.id, count: 3 },
{ id: mcData.itemsByName.oak_log.id, count: 1 }
],
multipleRecipes: true
}
)
console.log(plan.success)
console.log(plan.recipesToDo)
}
main()Exports
plugin
plugin(recipe?: Recipe): (bot: Bot, botOptions: BotOptions) => Promise<void>Mineflayer plugin factory export. Call it to create a plugin, then use with bot.loadPlugin(plugin()).
The default export is the same plugin factory:
const craftingUtil = require('mineflayer-crafting-util')
bot.loadPlugin((craftingUtil.default ?? craftingUtil.plugin)())buildStatic
buildStatic(registry: IndexedData): Promise<CraftingFunc>Builds a version-specific planner from a minecraft-data registry.
const mcData = require('minecraft-data')('1.21.4')
const { Recipe } = require('prismarine-recipe')(mcData)
const crafter = await buildStatic(Recipe)
const plan = crafter({ id: mcData.itemsByName.stick.id, count: 4 })craftPlan
craftPlan(
bot: Bot,
plan: CraftingPlan,
craftingTable: Block,
options?: CraftPlanOptions
): Promise<CraftingPlan>Executes every recipe step in an existing plan with bot.craft.
Rules:
craftingTableis required.- Throws if
plan.successis false. - Returns the same plan after crafting.
- By default, each plan step is sent to Mineflayer as one
bot.craft(recipe, recipeApplications, craftingTable)call. - With
{ strict: true }, large recipe application counts are split by the crafted item stack size.
craftItem
craftItem(
bot: Bot,
itemId: number,
count: number,
craftingTable: Block,
options?: CraftOptions,
craftOptions?: CraftPlanOptions
): Promise<CraftingPlan>Plans and executes a craft for itemId.
Defaults used by craftItem:
availableItems: current bot inventory, unless provided.careAboutExisting:false.includeRecursion:true.multipleRecipes:true.
setupActualCrafting
setupActualCrafting(bot: Bot): voidAdds bot.craftPlan and bot.craftItem to a bot. The plugin calls this automatically, so most users do not need to call it directly.
Bot Methods
Loading the plugin adds these methods to bot.
bot.planCraft
bot.planCraft(wantedItem: Item, options?: CraftOptions): CraftingPlanCreates a crafting plan for wantedItem.
Without availableItems, this answers "what would be required to craft this?" and does not validate against a specific inventory.
With availableItems, this answers "can this be crafted from these items?" and returns a concrete ordered recipe plan when possible.
bot.planCraftInventory
bot.planCraftInventory(wantedItem: Item): CraftingPlanPlans using the bot inventory as availableItems.
Internally this uses:
{
availableItems: bot inventory items,
careAboutExisting: false,
includeRecursion: true,
multipleRecipes: true
}bot.craftPlan
bot.craftPlan(
plan: CraftingPlan,
craftingTable: Block,
options?: CraftPlanOptions
): Promise<CraftingPlan>Executes an existing plan. This is the bot-bound wrapper around the exported craftPlan.
bot.craftItem
bot.craftItem(
itemId: number,
count: number,
craftingTable: Block,
options?: CraftOptions,
craftOptions?: CraftPlanOptions
): Promise<CraftingPlan>Plans from inventory and executes the result. This is the bot-bound wrapper around the exported craftItem.
Types
Item
interface Item {
id: number
count: number
}id is the numeric item id from the active Minecraft registry. count is the item count.
CraftOptions
interface CraftOptions {
availableItems?: Item[]
careAboutExisting?: boolean
includeRecursion?: boolean
multipleRecipes?: boolean
}| Option | Default | Description |
| --- | --- | --- |
| availableItems | undefined | Inventory constraints for the planner. When provided, the planner attempts to produce a craftable ordered plan from those items. |
| careAboutExisting | false | When false, matching copies of the wanted item inside availableItems are ignored so the planner crafts the requested count fresh. When true, existing wanted items can satisfy the request. |
| includeRecursion | false | Keeps recursive planning behavior enabled for inventory-backed plans. bot.planCraftInventory and craftItem enable this. |
| multipleRecipes | false | Allows the planner to try alternate recipes and recipe families when building a plan from available items. Recommended with availableItems. |
Note: availableItems may be normalized by the planner. Pass a cloned array if you need to preserve the original object identities and counts.
CraftingPlan
interface CraftingPlan {
success: boolean
itemsRequiredBase: Item[]
itemsRequiredImmediate: Item[]
itemsRemaining: Item[]
itemsCreated: Item[]
recipesToDo: RecipeInfo[]
requiresCraftingTable: boolean
}| Property | Description |
| --- | --- |
| success | Whether the planner found a valid plan. |
| itemsRequiredBase | Base items needed to complete the request, after accounting for recipesToDo. |
| itemsRequiredImmediate | Direct recipe inputs needed at the point planning stopped. |
| itemsRemaining | Requested output that is still not satisfied by the partial plan. |
| itemsCreated | Net positive items produced by recipesToDo. On partial available-item plans, this shows what can be created even when success is false. |
| recipesToDo | Ordered recipe applications to execute. |
| requiresCraftingTable | Whether any step in recipesToDo requires a crafting table. |
RecipeInfo
interface RecipeInfo {
recipe: Recipe
recipeApplications: number
}recipe is a prismarine-recipe recipe object. recipeApplications is the number of times to apply that recipe.
CraftPlanOptions
interface CraftPlanOptions {
strict?: boolean
}| Option | Default | Description |
| --- | --- | --- |
| strict | false | When true, execution splits each plan step into multiple bot.craft calls by the result item stack size. This is useful as a workaround for Mineflayer craft-count issues with non-stackable outputs. |
CraftingFunc
type CraftingFunc = (item: Item, options?: CraftOptions) => CraftingPlanReturned by buildStatic and used internally for bot.planCraft.
Working With Plans
To print recipe steps, prefer recipe.delta because some Minecraft versions expose empty recipe.ingredients arrays for shaped recipes:
function recipeInputs (recipe) {
return recipe.ingredients && recipe.ingredients.length > 0
? recipe.ingredients
: recipe.delta.filter(item => item.count < 0)
}
for (const step of plan.recipesToDo) {
const inputs = recipeInputs(step.recipe)
console.log(inputs, '=>', step.recipe.result, 'x', step.recipeApplications)
}Test And Smoke Commands
npm run build
npm test
npm run smoke:matrixManual static smoke example:
node scripts/staticPlanSmoke.js --version 1.21.4 --wanted-item stone_pickaxe --available cobblestone:3,oak_log:1