PrismarineJS/mineflayer-pathfinder

`bot.pathfinder.goto` sometimes never finish if goal is GoalNear and the block is not full height

nishio opened this issue · 12 comments

Sometimes bot.pathfinder.goto never finish. It may related floating-point calculation.

Here is my code:

const { x, y, z } = toHarvest.position;
const goal = new GoalNear(x, y, z, 2);
if (!goal.isEnd(bot.entity.position)) {
  console.log("go to ", [x, y, z], "from ", bot.entity.position);
  await bot.pathfinder.goto(goal);
  console.log("done");
}

And it stop after the following message:

go to  [ -33, 63, -214 ] from  Vec3 { x: -28.55625503370811, y: 62.875, z: -213.3506397248765 }

GoalNear.isEnd is false and bot won't walk.

Is there any workaround?

If there is an error, goto reject the promise (which throws and exception that should be catched).
Try to catch and print the error:

try {
  await bot.pathfinder.goto(goal)
} catch (e) {
  console.log(e)
}

What makes you think it is related to floating point calculation ?

I already enclosed it with try/catch and there are no error.

I'm not confident that it is related to floating point calculation. Any other suggestion?

The code is usually success, but in a small probability bot stops without any error thrown. It is reproductive. Here are some cases:

go to  [ -28, 63, -212 ] from  Vec3 { x: -30.5, y: 62.875, z: -211.68502145455264 }
go to  [ -33, 63, -213 ] from  Vec3 { x: -28.5, y: 62.875, z: -212.3358946346443 }
go to  [ -35, 63, -211 ] from  Vec3 { x: -33.4805719963985, y: 62.875, z: -213.31170003933832 }

The bot stands on a flat farm of soul sand and nether wart.

My first guess about radius boundary looks not correct. I changed the title.
Here are some other cases with distances:

go to  [ -35, 63, -210 ] from  Vec3 { x: -34.327009310748934, y: 62.875, z: -212.6377405258382 } distance: 2.7251085390251646
go to  [ -29, 63, -208 ] from  Vec3 { x: -31.623865659091162, y: 62.875, z: -206.42575916155076 } distance: 3.0624386058171473
go to  [ -28, 63, -213 ] from  Vec3 { x: -27.5, y: 62.875, z: -209.5 } distance: 3.5377429245212264

Is there any way to observe internal path-finding status? I wonder why the bot won't walk.

I added console.log in bot.pathfinder.getPathTo and found const result = astarContext.compute(); return successful result, sometimes bot won't walk and never achieve the goal.

I feel it is not related to GoalNear.

At https://github.com/PrismarineJS/mineflayer-pathfinder/blob/master/index.js#L384
nextPoint was

Move {
  x: -32.5,
  y: 62.875,
  z: -208.5,
  remainingBlocks: 0,
  cost: 1,
  toBreak: [],
  toPlace: [],
  parkour: false,
  hash: '-33,63,-209'
}

bot.entity.position was { x: -32.68931395891055, y: 62.875, z: -208.51950746279664 }

They are close. At https://github.com/PrismarineJS/mineflayer-pathfinder/blob/master/index.js#L449
dx, dy, dz are 0.18931395891055303 0 0.019507462796639174.

However, after that it repeats path.length === 0
https://github.com/PrismarineJS/mineflayer-pathfinder/blob/master/index.js#L361

It checks stateGoal.isEnd(bot.entity.position.floored()) repeatedly, and it is false.
bot.entity.position.floored() is { x: -33, y: 62, z: -209 }.

It looks the case that bot.entity.position is in the boundary of the goal, but bot.entity.position.floored() is not in it.

By changing bot.entity.position.floored() to bot.entity.position, it works well in my case. Again, I use GoalNear and it has spherical boundary. I see there are many type of goals. I'm not sure some of those goals require floored position.

There seems to be an issue with the height (y) of the block. What block is it standing on at the end ?

What block is it standing on at the end ?

Soul sand, its height is 0.875.

By changing bot.entity.position.floored() to bot.entity.position, it works well in my case.

Sorry, it decrease the frequency but not fix the problem. I recover to the original.

At this code:
https://github.com/PrismarineJS/mineflayer-pathfinder/blob/master/index.js#L361
After path.length === 0, if isEnd is false, it does not emit goal_reached nor path_update. There are nothing changes the situation, so await bot.pathfinder.goto(goal) never finish.

Changing bot.entity.position.floored() to bot.entity.position makes the X-Z boundary broaden and decrease the frequency of the problem.

Based on the knowledge above, I changed GoalNear to GoalNearXZ. It looks work well in my case. I'll fix the title of the issue.

This pr #268 should have fixed this issue. Feel free to reopen when you think there are still issues with this.