Skip to content

Latest commit

 

History

History
142 lines (118 loc) · 9.51 KB

goalsExplained.md

File metadata and controls

142 lines (118 loc) · 9.51 KB

Mineflayer-Pathfinder: Goals

A (more) detailed explanation by Jovan04

This page is an explanation about goals in mineflayer-pathfinder. A Goal is an instance of a class that allows the user to specify a location that they want a mineflayer bot to go to. Goals are the backbone of mineflayer because they provide an easy way to control your mineflayer bot with mineflayer-pathfinder.

General Goals

It's useful to think about goals in pathfinder as conditions that need to be fulfilled. For example, one of the most common goals is GoalBlock. As the documentation for the GoalBlock goal says:

One specific block that the player should stand inside at foot level

Thus, we have our condition. In order to complete the GoalBlock goal, our bot needs to get its feet inside the specified block. Simple as that.
That's great and all, but how do we use it?
Here's a quick example. Let's walk through everything it does.

First, we need to import mineflayer, as well as pathfinder and things related to it:

const mineflayer = require('mineflayer')
const { pathfinder, Movements, goals:{ GoalBlock } } = require('mineflayer-pathfinder')

Here, we import a few things from pathfinder:

  • the pathfinder plugin itself
  • the Movements() class, which defines how our bot is allowed to move
  • the goals object, and from it the GoalBlock goal

Next, we'll create our bot. This is just like creating any other Mineflayer bot:

const bot = mineflayer.createBot({
  host: 'localhost',
  port: 25565,
  username: 'Pathfinder',
  auth: 'offline'
})

We'll also add a spawn event listener to load the pathfinder plugin and create the bot's Movements class:

bot.once('spawn', () => {
  bot.loadPlugin(pathfinder) // load pathfinder plugin into the bot
  const defaultMovements = new Movements(bot) // create a new instance of the `Movements` class
  bot.pathfinder.setMovements(defaultMovements) // set the bot's movements to the `Movements` we just created
})

The Movements class essentially tells the bot what moves it's allowed to make. This includes, but isn't limited to: What blocks (if any) it can place/break, whether it can pillar straight up, and how far it's allowed to fall.
What we've done so far is mostly boilerplate; you'll probably use it every time you use pathfinder.

Now, we'll create a chat listener that we'll use to make pathfinder move:

bot.on('chat', async (username, message) => {
  if (username === bot.username) return // make bot ignore its own messages

  if (message === 'go') { // this is our trigger message (only works on servers with vanilla chat)
    // our pathfinder code goes here!
  }
})

Now, let's go back to the GoalBlock goal. If we look at the documentation again, we can see that the GoalBlock takes three arguments: an x coordinate, a y coordinate, and a z coordinate, all integers. In order to use the GoalBlock goal, we would need to create a new instance of the GoalBlock class with those coordinates. If we wanted our bot to pathfind to the coordinates 15, 3, 75, we could do that like this:

const myGoal = new GoalBlock(15, 3, 75)

Now that we have our goal, how do we use it? Simple! Pathfinder has a method for traveling to a goal, goto. We can access it through bot.pathfinder.goto(goal), and we'll use the await Javascript keyword to make our code wait for the bot to finish walking to the goal beore continuing:

await bot.pathfinder.goto(myGoal)

We can also use bot.chat to have the bot tell us when it starts and finishes going to the goal. If we add that to the lines we just wrote, it can look something like this:

bot.chat('Going to my goal!')
const myGoal = new GoalBlock(15, 3, 75)
await bot.pathfinder.goto(myGoal)
bot.chat('Arrived at my goal!')

Let's put those four lines inside our chat listener, likeso:

bot.on('chat', async (username, message) => {
  if (username === bot.username) return // make bot ignore its own messages

  if (message === 'go') { // this is our trigger message (only works on servers with vanilla chat)
    bot.chat('Going to my goal!')
    const myGoal = new GoalBlock(15, 3, 75)
    await bot.pathfinder.goto(myGoal)
    bot.chat('Arrived at my goal!')
  }
})

And now we're done! We can type go in chat, and the bot will walk to the coordinates we specified. Remember that GoalBlock makes the bot put its feet in the block we specified. You can view and download the full example script here.

And, there you have it. That's how you use the GoalBlock goal! Most of the other goals are used in a similar way, but with different arguments. You can look at the documentation for those. However, there are a few goals that are a little confusing.

Composite Goals

The Composite goals, GoalCompositeAny and GoalCompositeAll, are both quite different from most other goals. Instead of being standalone goals themselves, they allow you to combine other goals in interesting ways. They're called composite goals because they're composed of (or made up of) other goals. But before we can talk about the composite goals in more detail, we should talk about the GoalNear goal. The composite goals are made up of other goals, and GoalNear is a good example.

GoalNear is almost the same as GoalBlock, but with one extra argument. Where GoalBlock only has x, y, z, GoalNear has x, y, z, range. The additional argument, range, specifies how far away from the target block the bot can be in order to still satisfy the goal. For example, the goal GoalNear(15, 3, 75, 5) would be satisfied once the bot is within 5 blocks of 15, 3, 75.

Now, let's set up our program to use composite goals.

In the composite goal example, we make three goals: LapisGoal, GoldGoal, and DiamondGoal. They correspond to standing within 5 blocks of a Lapis block, a Gold block, and a Diamond block, respectively (see picture below):

  const LapisGoal = new GoalNear(0, 1, 3, 5) // our bot needs to stand within 5 blocks of the point (0, 1, 3) in order to satisfy this goal (blue circle below)
  const GoldGoal = new GoalNear(3, 1, -2, 5) // our bot needs to stand within 5 blocks of the point (3, 1, -2) in order to satisfy this goal (yellow circle below)
  const DiamondGoal = new GoalNear(-3, 1, -2, 5) // our bot needs to stand within 5 blocks of the point (-3, 1, -2) in order to satisfy this goal (white circle below)

Diagram of the three goals

GoalCompositeAny

The first type of composite goal is called GoalCompositeAny. Being a composite goal, GoalCompositeAny is a goal made up of other goals. In order for your bot to complete GoalCompositeAny, it needs to satisfy any one of the contained goals. Above, we made three goals (LapisGoal, GoldGoal, and DiamondGoal).
Let's put them into an array:

const goalsArray = [LapisGoal, GoldGoal, DiamondGoal] // array containing all three of our goals; we'll use this array in our `GoalCompositeAny` goal

And create a new GoalCompositeAny with that array:

const goalAny = new GoalCompositeAny(goalsArray)

Now, just like any other goal, we can tell pathfinder to goto our new GoalCompositeAny:

await bot.pathfinder.goto(goalAny)

The GoalCompositeAny is completed when the bot completes any one of the goals it was created with. For our example above, goalAny will be completed when the bot completes any one of LapisGoal, GoldGoal, or DiamondGoal. In other words, goalAny will be completed when the bot's location is inside the blue circle or the yellow circle or the white circle (see image above).

GoalCompositeAll

The other type of composite goal is called GoalCompositeAll. Being a composite goal, GoalCompositeAll is a goal made up of other goals. In order for your bot to complete GoalCompositeAll, it needs to satisfy all of the contained goals. Above, we made three goals (LapisGoal, GoldGoal, and DiamondGoal).
Let's put them into an array:

const goalsArray = [LapisGoal, GoldGoal, DiamondGoal] // array containing all three of our goals; we'll use this array in our `GoalCompositeAll` goal

And create a new GoalCompositeAll with that array:

const goalAll = new GoalCompositeAll(goalsArray)

Now, just like any other goal, we can tell pathfinder to goto our new GoalCompositeAll:

await bot.pathfinder.goto(goalAll)

The GoalCompositeAll is completed when the bot completes all of the goals it was created with. For our example above, goalAll will be completed when the bot completes all of LapisGoal, GoldGoal, or DiamondGoal. In other words, goalAll will be completed when the bot's location is inside the blue circle and the yellow circle and the white circle (see image above). It's important to clarify that the bot needs to be in all three circles at the same time. Going from one circle to another to the last is not a valid path to complete the goal.

And there you have it! That's a basic introduction to using goals in mineflayer-pathfinder. If any of this was confusing, or you'd like help with something more complicated, feel free to join the PrismarineJS Discord server. We're always happy to provide help for mineflayer and other PrismarineJS libraries.