PrismarineJS / mineflayer

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

Fix villager suppot #955

Closed imharvol closed 4 years ago

imharvol commented 4 years ago

Versions

Detailed description of a problem

At first when I try to use bot.openVillager(villagerEntity) I get this error:

(node:10190) UnhandledPromiseRejectionWarning: AssertionError [ERR_ASSERTION]: Expected values to be strictly equal:
120 !== undefined
at Bot.openVillager (/dir/node_modules/mineflayer/lib/plugins/villager.js:56:12)

Which is easy to solve (villager in 1.8 has a capital letter), but lets just comment that assert for simplicity. The problem comes when I try to run the code without that assert and I get this error:

/dir/node_modules/minecraft-protocol/src/transforms/framing.js:67
          } else { throw e }
                   ^

Error: Read error for trades.3.firstInput.unknown.true.nbtData.type : 18 is not in the mappings value
    at ProtoDef.readMapper (/dir/node_modules/protodef/src/datatypes/utils.js:30:34)
    at ProtoDef.read (/dir/node_modules/protodef/src/protodef.js:36:25)
    at ProtoDef.read (/dir/node_modules/protodef/src/protodef.js:110:29)
    at /dir/node_modules/protodef/src/datatypes/structures.js:45:32
    at tryCatch (/dir/node_modules/protodef/src/utils.js:50:16)
    at tryDoc (/dir/node_modules/protodef/src/utils.js:54:10)
    at /dir/node_modules/protodef/src/datatypes/structures.js:44:5
    at Array.forEach (<anonymous>)
    at ProtoDef.readContainer (/dir/node_modules/protodef/src/datatypes/structures.js:43:12)
    at ProtoDef.read (/dir/node_modules/protodef/src/protodef.js:36:25) {
  field: 'trades.3.firstInput.unknown.true.nbtData.type'
}

I guess some changes broke backwards compatibility with 1.8 villagers.

Current code

let villager = bot.openVillager(villagerEntity)

Expected behavior

Shouldn't throw error

plexigras commented 4 years ago

what is the villagerEntity you are passing to bot.openVillager?

imharvol commented 4 years ago

Its an Object of Entity:

Entity {
  _events: [Object: null prototype] {},
  _eventsCount: 0,
  _maxListeners: undefined,
  id: 69,
  type: 'mob',
  position: Vec3 { x: -542.5, y: 14, z: 1596.5 },
  velocity: Vec3 { x: 0, y: -1.8369140625, z: 0 },
  yaw: 3.3624858870453256,
  pitch: 0.024543692606170175,
  onGround: true,
  height: 0,
  effects: {},
  equipment: [ <5 empty items> ],
  heldItem: undefined,
  isValid: true,
  metadata: [
    0,               300,
    '',              0,
    0,               <1 empty item>,
    20,              0,
    0,               0,
    <2 empty items>, 0,
    <2 empty items>, 0,
    0
  ],
  uuid: undefined,
  mobType: 'Villager',
  displayName: 'Villager',
  entityType: 120,
  name: 'Villager',
  kind: 'NPCs',
  headPitch: -3.141592653589793
}

JSON.stringify:

{"_events":{},"_eventsCount":0,"id":69,"type":"mob","position":{"x":-542.5,"y":14,"z":1596.5},"velocity":{"x":0,"y":-1.8369140625,"z":0},"yaw":3.3624858870453256,"pitch":0.024543692606170175,"onGround":true,"height":0,"effects":{},"equipment":[null,null,null,null,null],"isValid":true,"metadata":[0,300,"",0,0,null,20,0,0,0,null,null,0,null,null,0,0],"mobType":"Villager","displayName":"Villager","entityType":120,"name":"Villager","kind":"NPCs","headPitch":-3.141592653589793}
imharvol commented 4 years ago

Just tried on 1.12.2 and throws the same errors.

plexigras commented 4 years ago

i can't figure out how this ever worked in the first place but it definitely did.

Karang commented 4 years ago

fixed in https://github.com/PrismarineJS/mineflayer/pull/968

imharvol commented 4 years ago

Not sure if this should be closed, I'm still getting an error (at least) in 1.8.8

Code:

const mineflayer = require('mineflayer')

function sleep (ms) {
    return new Promise(resolve => {
        setTimeout(resolve, ms)
    })
}

const bot = mineflayer.createBot({
  host: 'localhost',
  port: 38293,
  username: 'Player',
  version: '1.8.8'
})

bot.on('spawn', async function (username, message) {
  await sleep(1000)

  const villagerEntityID = Object.keys(bot.entities).find(entity => {
    entity = bot.entities[entity]
    return entity.mobType === 'Villager'
  })

  const villagerEntity = bot.entities[villagerEntityID]
  const villager = bot.openVillager(villagerEntity)
})

Error: error.log

rom1504 commented 4 years ago

I don't think that await sleep(1000) is enough

imharvol commented 4 years ago

It still happens even waiting 10s

rom1504 commented 4 years ago

what's the full error ? can you print villagerEntityID and villagerEntity ?

imharvol commented 4 years ago

Sure, there you go: error.log

rom1504 commented 4 years ago

I don't understand, I don't see the error. you only got

/node_modules/minecraft-protocol/src/transforms/framing.js:67
          } else { throw e }

nothing else ???

rom1504 commented 4 years ago

and why is village instance printed, is that related ?

rom1504 commented 4 years ago

ok got it,the openVillager callback was called wrong, fixed and released as 2.14.1