PrismarineJS / mineflayer

Create Minecraft bots with a powerful, stable, and high level JavaScript API.
https://prismarinejs.github.io/mineflayer/
MIT License
4.96k stars 904 forks source link

Add function findChest #2171

Closed sefirosweb closed 1 year ago

sefirosweb commented 3 years ago

Is your feature request related to a problem? Please describe.

When you want to find the chests you have an issue with the findblock function this duplicate the blocks when is double chest

Describe the solution you'd like

I made some code for to do that, but i'm not sure if that have sense to add into mineflayer, What you think?

The code:

const findChests = (options) => {
    options = options || {}
    const matching = options.matching || ['chest', 'ender_chest', 'trapped_chest'].map(name => mcData.blocksByName[name].id)
    const point = (options.point || bot.entity.position).floored()
    const maxDistance = options.maxDistance || 16
    const count = options.count || 1
    const useExtraInfo = options.useExtraInfo || false

    const blocksFound = bot.findBlocks({
      matching,
      maxDistance,
      point,
      count: count * 2,
      useExtraInfo
    }).map(chest => bot.blockAt(chest))

    const chests = []
    let block, secondBlock, secondBlockIndex, props
    while (blocksFound.length > 0) {
      if (chests.length >= count) {
        break
      }

      block = blocksFound.shift()
      props = block.getProperties()

      if (props.type === 'single') {
        chests.push(block)
        continue
      }

      if (props.facing === 'south' && props.type === 'right') {
        secondBlock = block.position.offset(1, 0, 0)
      }

      if (props.facing === 'south' && props.type === 'left') {
        secondBlock = block.position.offset(-1, 0, 0)
      }

      if (props.facing === 'north' && props.type === 'left') {
        secondBlock = block.position.offset(1, 0, 0)
      }

      if (props.facing === 'north' && props.type === 'right') {
        secondBlock = block.position.offset(-1, 0, 0)
      }

      if (props.facing === 'east' && props.type === 'right') {
        secondBlock = block.position.offset(0, 0, -1)
      }

      if (props.facing === 'east' && props.type === 'left') {
        secondBlock = block.position.offset(0, 0, 1)
      }

      if (props.facing === 'west' && props.type === 'left') {
        secondBlock = block.position.offset(0, 0, -1)
      }

      if (props.facing === 'west' && props.type === 'right') {
        secondBlock = block.position.offset(0, 0, 1)
      }

      secondBlockIndex = blocksFound.findIndex(chest => chest.position.equals(secondBlock))
      if (secondBlockIndex >= 0) {
        blocksFound.splice(secondBlockIndex, 1)
      }

      block.secondBlock = bot.blockAt(secondBlock)

      chests.push(block)
    }

    return chests
  }
extremeheat commented 3 years ago

Yeah, this is very inefficient, there needs to be a better algorithm to do this. Reminder this algorithm would also need to work with 1.12 and below which do not have this extra state data you’re using.

extremeheat commented 3 years ago

A good starting point would be the getChestType function here:

https://github.com/PrismarineJS/mineflayer/blob/master/lib/plugins/block_actions.js#L37

sefirosweb commented 3 years ago

How can I make it compatible with old versions if I don't have all the information (is looking at)

extremeheat commented 3 years ago

Same way the client does. Block actions plugin is a good start.

sefirosweb commented 1 year ago

Fixed by imharvol