mineflayer 4.20.0 → 4.20.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/docs/history.md CHANGED
@@ -1,3 +1,10 @@
1
+ ## 4.20.1
2
+ * [Add bossBarCreated event in index.d.ts (#3340)](https://github.com/PrismarineJS/mineflayer/commit/8299288526cd7ff24bcd87511814221f8ad62507) (thanks @gguio)
3
+ * [Update scoreboard.js (#3318)](https://github.com/PrismarineJS/mineflayer/commit/195b3cbd70a110080af9b77a4659991c5d9e484a) (thanks @vicdum)
4
+ * [Fix hardcoded diggingface for cancel digging (#3322)](https://github.com/PrismarineJS/mineflayer/commit/ab78bf855929a476386b5eb6efcf3b271d02455e) (thanks @Vinciepincie)
5
+ * [Fix 1.20.4 server resource pack error (#3320)](https://github.com/PrismarineJS/mineflayer/commit/7c01eeb970647ed2933c10cb2b94fd7b44c777f5) (thanks @TerminalCalamitas)
6
+ * [Fix scoreboard delete handler not first checking if scoreboard exists (#3324)](https://github.com/PrismarineJS/mineflayer/commit/d9e9e15aeb646d81da2a3e2987566de47e3bae04) (thanks @Ynfuien)
7
+
1
8
  ## 4.20.0
2
9
  * [Update api.md - addChatPattern[Set] link to example of usage (#3304)](https://github.com/PrismarineJS/mineflayer/commit/bb3e5877b7b3b8ab063b39a5b47d103b819da1c2) (thanks @boly38)
3
10
  * [Fixed deleted scoreboards not being removed from ScoreBoard.positions (#3306)](https://github.com/PrismarineJS/mineflayer/commit/643023df91bf428d3e7d30e8f2eab97e3238b0b2) (thanks @Ynfuien)
package/index.d.ts CHANGED
@@ -158,9 +158,10 @@ export interface BotEvents {
158
158
  teamUpdated: (team: Team) => Promise<void> | void
159
159
  teamMemberAdded: (team: Team) => Promise<void> | void
160
160
  teamMemberRemoved: (team: Team) => Promise<void> | void
161
+ bossBarCreated: (bossBar: BossBar) => Promise<void> | void
161
162
  bossBarDeleted: (bossBar: BossBar) => Promise<void> | void
162
163
  bossBarUpdated: (bossBar: BossBar) => Promise<void> | void
163
- resourcePack: (url: string, hash: string) => Promise<void> | void
164
+ resourcePack: (url: string, hash?: string, uuid?: string) => Promise<void> | void
164
165
  particle: (particle: Particle) => Promise<void> | void
165
166
  }
166
167
 
@@ -12,29 +12,29 @@ function inject (bot) {
12
12
  let diggingTask = createDoneTask()
13
13
 
14
14
  bot.targetDigBlock = null
15
+ bot.targetDigFace = null
15
16
  bot.lastDigTime = null
16
17
 
17
18
  async function dig (block, forceLook, digFace) {
18
19
  if (block === null || block === undefined) {
19
20
  throw new Error('dig was called with an undefined or null block')
20
21
  }
22
+
21
23
  if (!digFace || typeof digFace === 'function') {
22
24
  digFace = 'auto'
23
25
  }
24
26
 
25
- if (bot.targetDigBlock) bot.stopDigging()
26
-
27
- let diggingFace = 1 // Default (top)
27
+ bot.targetDigFace = 1 // Default (top)
28
28
 
29
29
  if (forceLook !== 'ignore') {
30
30
  if (digFace?.x || digFace?.y || digFace?.z) {
31
31
  // Determine the block face the bot should mine
32
32
  if (digFace.x) {
33
- diggingFace = digFace.x > 0 ? BlockFaces.EAST : BlockFaces.WEST
33
+ bot.targetDigFace = digFace.x > 0 ? BlockFaces.EAST : BlockFaces.WEST
34
34
  } else if (digFace.y) {
35
- diggingFace = digFace.y > 0 ? BlockFaces.TOP : BlockFaces.BOTTOM
35
+ bot.targetDigFace = digFace.y > 0 ? BlockFaces.TOP : BlockFaces.BOTTOM
36
36
  } else if (digFace.z) {
37
- diggingFace = digFace.z > 0 ? BlockFaces.SOUTH : BlockFaces.NORTH
37
+ bot.targetDigFace = digFace.z > 0 ? BlockFaces.SOUTH : BlockFaces.NORTH
38
38
  }
39
39
  await bot.lookAt(
40
40
  block.position.offset(0.5, 0.5, 0.5).offset(digFace.x * 0.5, digFace.y * 0.5, digFace.z * 0.5),
@@ -76,8 +76,8 @@ function inject (bot) {
76
76
  const rayPos = rayBlock.position
77
77
  if (
78
78
  rayPos.x === block.position.x &&
79
- rayPos.y === block.position.y &&
80
- rayPos.z === block.position.z
79
+ rayPos.y === block.position.y &&
80
+ rayPos.z === block.position.z
81
81
  ) {
82
82
  validFaces.push({
83
83
  face: rayBlock.face,
@@ -86,6 +86,7 @@ function inject (bot) {
86
86
  }
87
87
  }
88
88
  }
89
+
89
90
  if (validFaces.length > 0) {
90
91
  // Chose closest valid face
91
92
  let closest
@@ -101,11 +102,11 @@ function inject (bot) {
101
102
  }
102
103
  }
103
104
  await bot.lookAt(closest.targetPos, forceLook)
104
- diggingFace = closest.face
105
+ bot.targetDigFace = closest.face
105
106
  } else if (closerBlocks.length === 0 && block.shapes.length === 0) {
106
107
  // no other blocks were detected and the block has no shapes.
107
108
  // The block in question is replaceable (like tall grass) so we can just dig it
108
- // TODO: do AABB + ray intercept check to this position for diggingFace.
109
+ // TODO: do AABB + ray intercept check to this position for digFace.
109
110
  await bot.lookAt(block.position.offset(0.5, 0.5, 0.5), forceLook)
110
111
  } else {
111
112
  // Block is obstructed return error?
@@ -116,11 +117,15 @@ function inject (bot) {
116
117
  }
117
118
  }
118
119
 
120
+ // In vanilla the client will cancel digging the current block once the other block is at the crosshair.
121
+ // Todo: don't wait until lookAt is at middle of the block, but at the edge of it.
122
+ if (bot.targetDigBlock) bot.stopDigging()
123
+
119
124
  diggingTask = createTask()
120
125
  bot._client.write('block_dig', {
121
126
  status: 0, // start digging
122
127
  location: block.position,
123
- face: diggingFace // default face is 1 (top)
128
+ face: bot.targetDigFace // default face is 1 (top)
124
129
  })
125
130
  const waitTime = bot.digTime(block)
126
131
  waitTimeout = setTimeout(finishDigging, waitTime)
@@ -140,10 +145,11 @@ function inject (bot) {
140
145
  bot._client.write('block_dig', {
141
146
  status: 2, // finish digging
142
147
  location: bot.targetDigBlock.position,
143
- face: diggingFace // hard coded to always dig from the top
148
+ face: bot.targetDigFace // always the same as the start face
144
149
  })
145
150
  }
146
151
  bot.targetDigBlock = null
152
+ bot.targetDigFace = null
147
153
  bot.lastDigTime = performance.now()
148
154
  bot._updateBlockState(block.position, 0)
149
155
  }
@@ -151,8 +157,15 @@ function inject (bot) {
151
157
  const eventName = `blockUpdate:${block.position}`
152
158
  bot.on(eventName, onBlockUpdate)
153
159
 
160
+ const currentBlock = block
154
161
  bot.stopDigging = () => {
155
162
  if (!bot.targetDigBlock) return
163
+
164
+ // Replicate the odd vanilla cancellation face value.
165
+ // When the cancellation is because of a new dig request on another block it's the same as the new dig start face. In all other cases it's 0.
166
+ const stoppedBecauseOfNewDigRequest = !currentBlock.position.equals(bot.targetDigBlock.position)
167
+ const cancellationDiggingFace = !stoppedBecauseOfNewDigRequest ? bot.targetDigFace : 0
168
+
156
169
  bot.removeListener(eventName, onBlockUpdate)
157
170
  clearInterval(swingInterval)
158
171
  clearTimeout(waitTimeout)
@@ -161,10 +174,11 @@ function inject (bot) {
161
174
  bot._client.write('block_dig', {
162
175
  status: 1, // cancel digging
163
176
  location: bot.targetDigBlock.position,
164
- face: 1 // hard coded to always dig from the top
177
+ face: cancellationDiggingFace
165
178
  })
166
179
  const block = bot.targetDigBlock
167
180
  bot.targetDigBlock = null
181
+ bot.targetDigFace = null
168
182
  bot.lastDigTime = performance.now()
169
183
  bot.emit('diggingAborted', block)
170
184
  bot.stopDigging = noop
@@ -182,6 +196,7 @@ function inject (bot) {
182
196
  swingInterval = null
183
197
  waitTimeout = null
184
198
  bot.targetDigBlock = null
199
+ bot.targetDigFace = null
185
200
  bot.lastDigTime = performance.now()
186
201
  bot.emit('diggingCompleted', newBlock)
187
202
  diggingTask.finish()
@@ -199,8 +214,8 @@ function inject (bot) {
199
214
  function canDigBlock (block) {
200
215
  return (
201
216
  block &&
202
- block.diggable &&
203
- block.position.offset(0.5, 0.5, 0.5).distanceTo(bot.entity.position.offset(0, 1.65, 0)) <= 5.1
217
+ block.diggable &&
218
+ block.position.offset(0.5, 0.5, 0.5).distanceTo(bot.entity.position.offset(0, 1.65, 0)) <= 5.1
204
219
  )
205
220
  }
206
221
 
@@ -1,7 +1,12 @@
1
+ const UUID = require('uuid-1345')
2
+
1
3
  module.exports = inject
2
4
 
3
5
  function inject (bot) {
6
+ let uuid
4
7
  let latestHash
8
+ let latestUUID
9
+ let activeResourcePacks = {}
5
10
  const TEXTURE_PACK_RESULTS = {
6
11
  SUCCESSFULLY_LOADED: 0,
7
12
  DECLINED: 1,
@@ -9,9 +14,38 @@ function inject (bot) {
9
14
  ACCEPTED: 3
10
15
  }
11
16
 
17
+ bot._client.on('add_resource_pack', (data) => { // Emits the same as resource_pack_send but sends uuid rather than hash because that's how active packs are tracked
18
+ const uuid = new UUID(data.uuid)
19
+ // Adding the pack to a set by uuid
20
+ latestUUID = uuid
21
+ activeResourcePacks[uuid] = data.url
22
+
23
+ bot.emit('resourcePack', data.url, uuid)
24
+ })
25
+
26
+ bot._client.on('remove_resource_pack', (data) => { // Doesn't emit anything because it is removing rather than adding
27
+ // if uuid isn't provided remove all packs
28
+ if (data.uuid === undefined) {
29
+ activeResourcePacks = {}
30
+ } else {
31
+ // Try to remove uuid from set
32
+ try {
33
+ delete activeResourcePacks[new UUID(data.uuid)]
34
+ } catch (error) {
35
+ console.error('Tried to remove UUID but it was not in the active list.')
36
+ }
37
+ }
38
+ })
39
+
12
40
  bot._client.on('resource_pack_send', (data) => {
13
- bot.emit('resourcePack', data.url, data.hash)
14
- latestHash = data.hash
41
+ if (bot.supportFeature('resourcePackUsesUUID')) {
42
+ uuid = new UUID(data.uuid)
43
+ bot.emit('resourcePack', uuid, data.url)
44
+ latestUUID = uuid
45
+ } else {
46
+ bot.emit('resourcePack', data.url, data.hash)
47
+ latestHash = data.hash
48
+ }
15
49
  })
16
50
 
17
51
  function acceptResourcePack () {
@@ -24,6 +58,15 @@ function inject (bot) {
24
58
  result: TEXTURE_PACK_RESULTS.SUCCESSFULLY_LOADED,
25
59
  hash: latestHash
26
60
  })
61
+ } else if (bot.supportFeature('resourcePackUsesUUID')) {
62
+ bot._client.write('resource_pack_receive', {
63
+ uuid: latestUUID,
64
+ result: TEXTURE_PACK_RESULTS.ACCEPTED
65
+ })
66
+ bot._client.write('resource_pack_receive', {
67
+ uuid: latestUUID,
68
+ result: TEXTURE_PACK_RESULTS.SUCCESSFULLY_LOADED
69
+ })
27
70
  } else {
28
71
  bot._client.write('resource_pack_receive', {
29
72
  result: TEXTURE_PACK_RESULTS.ACCEPTED
@@ -35,6 +78,12 @@ function inject (bot) {
35
78
  }
36
79
 
37
80
  function denyResourcePack () {
81
+ if (bot.supportFeature('resourcePackUsesUUID')) {
82
+ bot._client.write('resource_pack_receive', {
83
+ uuid: latestUUID,
84
+ result: TEXTURE_PACK_RESULTS.DECLINED
85
+ })
86
+ }
38
87
  bot._client.write('resource_pack_receive', {
39
88
  result: TEXTURE_PACK_RESULTS.DECLINED
40
89
  })
@@ -18,8 +18,10 @@ function inject (bot) {
18
18
  delete scoreboards[packet.name]
19
19
 
20
20
  for (const position in ScoreBoard.positions) {
21
+ if (!ScoreBoard.positions[position]) continue
21
22
  const scoreboard = ScoreBoard.positions[position]
22
- if (scoreboard.name === packet.name) {
23
+
24
+ if (scoreboard && scoreboard.name === packet.name) {
23
25
  delete ScoreBoard.positions[position]
24
26
  break
25
27
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mineflayer",
3
- "version": "4.20.0",
3
+ "version": "4.20.1",
4
4
  "description": "create minecraft bots with a stable, high level API",
5
5
  "main": "index.js",
6
6
  "types": "index.d.ts",