mineflayer 4.17.0 → 4.18.0

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/README.md CHANGED
@@ -17,7 +17,7 @@ First time using Node.js? You may want to start with the [tutorial](tutorial.md)
17
17
 
18
18
  ## Features
19
19
 
20
- * Supports Minecraft 1.8 to 1.20.1 (1.8, 1.9, 1.10, 1.11, 1.12, 1.13, 1.14, 1.15, 1.16, 1.17, 1.18, 1.19 and 1.20)
20
+ * Supports Minecraft 1.8 to 1.20.2 (1.8, 1.9, 1.10, 1.11, 1.12, 1.13, 1.14, 1.15, 1.16, 1.17, 1.18, 1.19 and 1.20)
21
21
  * Entity knowledge and tracking.
22
22
  * Block knowledge. You can query the world around you. Milliseconds to find any block.
23
23
  * Physics and movement - handle all bounding boxes
@@ -35,7 +35,7 @@ First time using Node.js? You may want to start with the [tutorial](tutorial.md)
35
35
 
36
36
  ## Installation
37
37
 
38
- First install Node.js >= 14 from [nodejs.org](https://nodejs.org/) then:
38
+ First install Node.js >= 18 from [nodejs.org](https://nodejs.org/) then:
39
39
 
40
40
  `npm install mineflayer`
41
41
 
package/docs/README.md CHANGED
@@ -17,7 +17,7 @@ First time using Node.js? You may want to start with the [tutorial](tutorial.md)
17
17
 
18
18
  ## Features
19
19
 
20
- * Supports Minecraft 1.8 to 1.20.1 (1.8, 1.9, 1.10, 1.11, 1.12, 1.13, 1.14, 1.15, 1.16, 1.17, 1.18, 1.19 and 1.20)
20
+ * Supports Minecraft 1.8 to 1.20.2 (1.8, 1.9, 1.10, 1.11, 1.12, 1.13, 1.14, 1.15, 1.16, 1.17, 1.18, 1.19 and 1.20)
21
21
  * Entity knowledge and tracking.
22
22
  * Block knowledge. You can query the world around you. Milliseconds to find any block.
23
23
  * Physics and movement - handle all bounding boxes
@@ -35,7 +35,7 @@ First time using Node.js? You may want to start with the [tutorial](tutorial.md)
35
35
 
36
36
  ## Installation
37
37
 
38
- First install Node.js >= 14 from [nodejs.org](https://nodejs.org/) then:
38
+ First install Node.js >= 18 from [nodejs.org](https://nodejs.org/) then:
39
39
 
40
40
  `npm install mineflayer`
41
41
 
package/docs/api.md CHANGED
@@ -225,7 +225,7 @@
225
225
  - ["blockBreakProgressEnd" (block, entity)](#blockbreakprogressend-block-entity)
226
226
  - ["diggingCompleted" (block)](#diggingcompleted-block)
227
227
  - ["diggingAborted" (block)](#diggingaborted-block)
228
- - ["usedFirework"](#usedfirework)
228
+ - ["usedfirework"](#usedfirework)
229
229
  - ["move"](#move)
230
230
  - ["forcedMove"](#forcedmove)
231
231
  - ["mount"](#mount)
@@ -291,7 +291,7 @@
291
291
  - [bot.getExplosionDamages(entity, position, radius, [rawDamages])](#botgetexplosiondamagesentity-position-radius-rawdamages)
292
292
  - [bot.lookAt(point, [force])](#botlookatpoint-force)
293
293
  - [bot.look(yaw, pitch, [force])](#botlookyaw-pitch-force)
294
- - [bot.updateSign(block, text)](#botupdatesignblock-text)
294
+ - [bot.updateSign(block, text, back = false)](#botupdatesignblock-text-back--false)
295
295
  - [bot.equip(item, destination)](#botequipitem-destination)
296
296
  - [bot.unequip(destination)](#botunequipdestination)
297
297
  - [bot.tossStack(item)](#bottossstackitem)
@@ -331,6 +331,7 @@
331
331
  - [bot.setCommandBlock(pos, command, [options])](#botsetcommandblockpos-command-options)
332
332
  - [bot.supportFeature(name)](#botsupportfeaturename)
333
333
  - [bot.waitForTicks(ticks)](#botwaitforticksticks)
334
+ - [bot.respawn()](#botrespawn)
334
335
  - [Lower level inventory methods](#lower-level-inventory-methods)
335
336
  - [bot.clickWindow(slot, mouseButton, mode)](#botclickwindowslot-mousebutton-mode)
336
337
  - [bot.putSelectedItemRange(start, end, window, slot)](#botputselecteditemrangestart-end-window-slot)
@@ -2103,6 +2104,10 @@ The list of available features can be found inside the [./lib/features.json](htt
2103
2104
 
2104
2105
  This is a promise-based function that waits for a given number of in-game ticks to pass before continuing. This is useful for quick timers that need to function with specific timing, regardless of the given physics tick speed of the bot. This is similar to the standard Javascript setTimeout function, but runs on the physics timer of the bot specifically.
2105
2106
 
2107
+ #### bot.respawn()
2108
+
2109
+ When `respawn` option is disabled, you can call this method manually to respawn.
2110
+
2106
2111
  ### Lower level inventory methods
2107
2112
 
2108
2113
  These are lower level methods for the inventory, they can be useful sometimes but prefer the inventory methods presented above if you can.
@@ -33,7 +33,7 @@ Primeira vez usando o Node.js? Você pode querer começar com o tutorial [tutori
33
33
  - Dê uma olhada em nossos [projetos atuais](https://github.com/PrismarineJS/mineflayer/wiki/Big-Prismarine-projects)
34
34
 
35
35
  ## Instalação
36
- - Primeiro, instale o Node.js >= 14 a partir do [nodejs.org](https://nodejs.org/)
36
+ - Primeiro, instale o Node.js >= 18 a partir do [nodejs.org](https://nodejs.org/)
37
37
 
38
38
  `npm install mineflayer`
39
39
 
@@ -34,7 +34,7 @@ Crea bots para Minecraft con una API de JavaScript potente, estable y de alto ni
34
34
  Echa un vistazo a nuestros [proyectos actuales](https://github.com/PrismarineJS/mineflayer/wiki/Big-Prismarine-projects)
35
35
 
36
36
  ## Instalación
37
- Primero instala Node.js >= 14 desde [nodejs.org](https://nodejs.org/)
37
+ Primero instala Node.js >= 18 desde [nodejs.org](https://nodejs.org/)
38
38
 
39
39
  `npm install mineflayer`
40
40
 
package/docs/history.md CHANGED
@@ -1,3 +1,10 @@
1
+ ## 4.18.0
2
+ * [Minecraft 1.20.2 support (#3262)](https://github.com/PrismarineJS/mineflayer/commit/2ff9919760d714be57dcb678f8ab5ecff69f5fee) (thanks @rom1504)
3
+ * [Update recommended Node.js version (#3279)](https://github.com/PrismarineJS/mineflayer/commit/5c71edf48bb2f2dfa16cddb9af5baa0c4d55cf0d) (thanks @Nyaasu66)
4
+ * [feat: bot.respawn, fix respawn with flying squid (#3206)](https://github.com/PrismarineJS/mineflayer/commit/3a6ce543b4ba8a3d0f55777670d142968af14571) (thanks @zardoy)
5
+ * [Add `maxCatchupTicks`, improve `supportFeature` typing (#3277)](https://github.com/PrismarineJS/mineflayer/commit/91108d392c4c5800204dd4674ce9247495ac98e0) (thanks @zardoy)
6
+ * [Fixed typo of "fromt" to "from" (#3273)](https://github.com/PrismarineJS/mineflayer/commit/216cab742db1cd053d9fa23bd7293b770239085b) (thanks @BorretSquared)
7
+
1
8
  ## 4.17.0
2
9
  * [Exclude browser from node version check (#3268)](https://github.com/PrismarineJS/mineflayer/commit/c466d327227796865c53bfd24e66668911be4af5) (thanks @rom1504)
3
10
  * [Fix for a possible error in lib/plugins/entities.js file (#3254)](https://github.com/PrismarineJS/mineflayer/commit/15cfeb4fa59edfcddf7a0b70a966294b24d798ed) (thanks @Mykola1453)
@@ -368,7 +368,7 @@
368
368
  "mcData = require('minecraft-data')(bot.version)\n",
369
369
  "# Create a new movements class\n",
370
370
  "movements = pathfinder.Movements(bot, mcData)\n",
371
- "# How far to be fromt the goal\n",
371
+ "# How far to be from the goal\n",
372
372
  "RANGE_GOAL = 1"
373
373
  ],
374
374
  "execution_count": null,
@@ -531,4 +531,4 @@
531
531
  ]
532
532
  }
533
533
  ]
534
- }
534
+ }
@@ -35,7 +35,7 @@
35
35
 
36
36
  ## Установка
37
37
 
38
- Сначала установите Node.js >= 14 из [nodejs.org](https://nodejs.org/), затем выполните:
38
+ Сначала установите Node.js >= 18 из [nodejs.org](https://nodejs.org/), затем выполните:
39
39
 
40
40
  `npm install mineflayer`
41
41
 
@@ -36,7 +36,7 @@
36
36
 
37
37
  ## 安装
38
38
 
39
- 首先,从 [nodejs.org](https://nodejs.org/) 安装 nodejs(版本要求 >= 14),
39
+ 首先,从 [nodejs.org](https://nodejs.org/) 安装 nodejs(版本要求 >= 18),
40
40
 
41
41
  然后在你创建的bot项目目录中,使用命令行运行:
42
42
 
@@ -3,7 +3,7 @@
3
3
  "version": "0.0.0",
4
4
  "private": true,
5
5
  "dependencies": {
6
- "mineflayer-pathfinder": "^1.6.1",
6
+ "mineflayer-pathfinder": "^2.4.5",
7
7
  "mineflayer": "file:../../"
8
8
  },
9
9
  "description": "A mineflayer example"
package/index.d.ts CHANGED
@@ -10,6 +10,7 @@ import { Entity } from 'prismarine-entity'
10
10
  import { ChatMessage } from 'prismarine-chat'
11
11
  import { world } from 'prismarine-world'
12
12
  import { Registry } from 'prismarine-registry'
13
+ import { IndexedData } from 'minecraft-data'
13
14
 
14
15
  export function createBot (options: { client: Client } & Partial<BotOptions>): Bot
15
16
  export function createBot (options: BotOptions): Bot
@@ -26,6 +27,8 @@ export interface BotOptions extends ClientOptions {
26
27
  difficulty?: number
27
28
  chatLengthLimit?: number
28
29
  physicsEnabled?: boolean
30
+ /** @default 4 */
31
+ maxCatchupTicks?: number
29
32
  client?: Client
30
33
  brand?: string
31
34
  defaultChatPatterns?: boolean
@@ -64,6 +67,7 @@ export interface BotEvents {
64
67
  unmatchedMessage: (stringMsg: string, jsonMsg: ChatMessage) => Promise<void> | void
65
68
  inject_allowed: () => Promise<void> | void
66
69
  login: () => Promise<void> | void
70
+ /** When `respawn` option is disabled, you can call this method manually to respawn. */
67
71
  spawn: () => Promise<void> | void
68
72
  respawn: () => Promise<void> | void
69
73
  game: () => Promise<void> | void
@@ -204,7 +208,7 @@ export interface Bot extends TypedEmitter<BotEvents> {
204
208
 
205
209
  connect: (options: BotOptions) => void
206
210
 
207
- supportFeature: (feature: string) => boolean
211
+ supportFeature: IndexedData['supportFeature']
208
212
 
209
213
  end: (reason?: string) => void
210
214
 
@@ -424,6 +428,8 @@ export interface Bot extends TypedEmitter<BotEvents> {
424
428
  acceptResourcePack: () => void
425
429
 
426
430
  denyResourcePack: () => void
431
+
432
+ respawn: () => void
427
433
  }
428
434
 
429
435
  export interface simpleClick {
@@ -268,6 +268,30 @@ function inject (bot, { version, storageBuilder, hideErrors }) {
268
268
  }
269
269
  })
270
270
 
271
+ // Chunk batches are used by the server to throttle the chunks per tick for players based on their connection speed.
272
+ let chunkBatchStartTime = 0
273
+ // The Vanilla client uses nano seconds with its weighted average starting at 2000000 converted to milliseconds that is 2
274
+ let weightedAverage = 2
275
+ // This is used for keeping track of the weight of the old average when updating it.
276
+ let oldSampleWeight = 1
277
+
278
+ bot._client.on('chunk_batch_start', (packet) => {
279
+ // Get the time the chunk batch is starting.
280
+ chunkBatchStartTime = Date.now()
281
+ })
282
+
283
+ bot._client.on('chunk_batch_finished', (packet) => {
284
+ const milliPerChunk = (Date.now() - chunkBatchStartTime) / packet.batchSize
285
+ // Prevents the MilliPerChunk from being hugely different then the average, Vanilla uses 3 as a constant here.
286
+ const clampedMilliPerChunk = Math.min(Math.max(milliPerChunk, weightedAverage / 3.0), weightedAverage * 3.0)
287
+ weightedAverage = ((weightedAverage * oldSampleWeight) + clampedMilliPerChunk) / (oldSampleWeight + 1)
288
+ // 49 is used in Vanilla client to limit it to 50 samples
289
+ oldSampleWeight = Math.min(49, oldSampleWeight + 1)
290
+ bot._client.write('chunk_batch_received', {
291
+ // Vanilla uses 7000000 as a constant here, since we are using milliseconds that is now 7. Not sure why they pick this constant to convert from nano seconds per chunk to chunks per tick.
292
+ chunksPerTick: 7 / weightedAverage
293
+ })
294
+ })
271
295
  bot._client.on('map_chunk', (packet) => {
272
296
  addColumn({
273
297
  x: packet.x,
@@ -26,7 +26,7 @@ const entityStatusEvents = {
26
26
  }
27
27
 
28
28
  function inject (bot) {
29
- const { mobs, entitiesArray } = bot.registry
29
+ const { mobs } = bot.registry
30
30
  const Entity = require('prismarine-entity')(bot.version)
31
31
  const Item = require('prismarine-item')(bot.version)
32
32
  const ChatMessage = require('prismarine-chat')(bot.registry)
@@ -129,33 +129,6 @@ function inject (bot) {
129
129
  if (eventName) bot.emit(eventName, entity)
130
130
  })
131
131
 
132
- bot._client.on('named_entity_spawn', (packet) => {
133
- // in case player_info packet was not sent before named_entity_spawn : ignore named_entity_spawn (see #213)
134
- if (packet.playerUUID in bot.uuidToUsername) {
135
- // spawn named entity
136
- const entity = fetchEntity(packet.entityId)
137
- entity.type = 'player'
138
- entity.name = 'player'
139
- entity.username = bot.uuidToUsername[packet.playerUUID]
140
- entity.uuid = packet.playerUUID
141
- entity.dataBlobs = packet.data
142
- if (bot.supportFeature('fixedPointPosition')) {
143
- entity.position.set(packet.x / 32, packet.y / 32, packet.z / 32)
144
- } else if (bot.supportFeature('doublePosition')) {
145
- entity.position.set(packet.x, packet.y, packet.z)
146
- }
147
- entity.yaw = conv.fromNotchianYawByte(packet.yaw)
148
- entity.pitch = conv.fromNotchianPitchByte(packet.pitch)
149
- entity.height = NAMED_ENTITY_HEIGHT
150
- entity.width = NAMED_ENTITY_WIDTH
151
- entity.metadata = parseMetadata(packet.metadata, entity.metadata)
152
- if (bot.players[entity.username] !== undefined && !bot.players[entity.username].entity) {
153
- bot.players[entity.username].entity = entity
154
- }
155
- bot.emit('entitySpawn', entity)
156
- }
157
- })
158
-
159
132
  bot.on('entityCrouch', (entity) => {
160
133
  entity.height = CROUCH_HEIGHT
161
134
  })
@@ -171,10 +144,11 @@ function inject (bot) {
171
144
  bot.emit('playerCollect', collector, collected)
172
145
  })
173
146
 
147
+ // What is internalId?
148
+ const entityDataByInternalId = Object.fromEntries(bot.registry.entitiesArray.map((e) => [e.internalId, e]))
149
+
174
150
  function setEntityData (entity, type, entityData) {
175
- if (entityData === undefined) {
176
- entityData = entitiesArray.find(entity => entity.internalId === type)
177
- }
151
+ entityData ??= entityDataByInternalId[type]
178
152
  if (entityData) {
179
153
  entity.type = entityData.type || 'object'
180
154
  entity.displayName = entityData.displayName
@@ -193,24 +167,57 @@ function inject (bot) {
193
167
  }
194
168
  }
195
169
 
196
- // spawn object/vehicle on versions < 1.19, on versions > 1.19 handles all non-player entities
197
- bot._client.on('spawn_entity', (packet) => {
198
- const entity = fetchEntity(packet.entityId)
199
- const entityData = bot.registry.entities[packet.type]
200
- setEntityData(entity, packet.type, entityData)
201
-
170
+ function updateEntityPos (entity, pos) {
202
171
  if (bot.supportFeature('fixedPointPosition')) {
203
- entity.position.set(packet.x / 32, packet.y / 32, packet.z / 32)
172
+ entity.position.set(pos.x / 32, pos.y / 32, pos.z / 32)
204
173
  } else if (bot.supportFeature('doublePosition')) {
205
- entity.position.set(packet.x, packet.y, packet.z)
206
- } else if (bot.supportFeature('consolidatedEntitySpawnPacket')) {
207
- entity.headPitch = conv.fromNotchianPitchByte(packet.headPitch)
174
+ entity.position.set(pos.x, pos.y, pos.z)
208
175
  }
176
+ entity.yaw = conv.fromNotchianYawByte(pos.yaw)
177
+ entity.pitch = conv.fromNotchianPitchByte(pos.pitch)
178
+ }
209
179
 
210
- entity.uuid = packet.objectUUID
211
- entity.yaw = conv.fromNotchianYawByte(packet.yaw)
212
- entity.pitch = conv.fromNotchianPitchByte(packet.pitch)
213
- entity.objectData = packet.objectData
180
+ function addNewPlayer (entityId, uuid, pos) {
181
+ const entity = fetchEntity(entityId)
182
+ entity.type = 'player'
183
+ entity.name = 'player'
184
+ entity.username = bot.uuidToUsername[uuid]
185
+ entity.uuid = uuid
186
+ updateEntityPos(entity, pos)
187
+ entity.height = NAMED_ENTITY_HEIGHT
188
+ entity.width = NAMED_ENTITY_WIDTH
189
+ if (bot.players[entity.username] !== undefined && !bot.players[entity.username].entity) {
190
+ bot.players[entity.username].entity = entity
191
+ }
192
+ return entity
193
+ }
194
+
195
+ function addNewNonPlayer (entityId, uuid, entityType, pos) {
196
+ const entity = fetchEntity(entityId)
197
+ const entityData = bot.registry.entities[entityType]
198
+ setEntityData(entity, entityType, entityData)
199
+ updateEntityPos(entity, pos)
200
+ return entity
201
+ }
202
+
203
+ bot._client.on('named_entity_spawn', (packet) => {
204
+ // in case player_info packet was not sent before named_entity_spawn : ignore named_entity_spawn (see #213)
205
+ if (packet.playerUUID in bot.uuidToUsername) {
206
+ // spawn named entity
207
+ const entity = addNewPlayer(packet.entityId, packet.playerUUID, packet, packet.metadata)
208
+ entity.dataBlobs = packet.data // this field doesn't appear to be listed on any version
209
+ entity.metadata = parseMetadata(packet.metadata, entity.metadata) // 1.8
210
+ bot.emit('entitySpawn', entity)
211
+ }
212
+ })
213
+
214
+ // spawn object/vehicle on versions < 1.19, on versions > 1.19 handles all non-player entities
215
+ // on versions >= 1.20.2, this also handles player entities
216
+ bot._client.on('spawn_entity', (packet) => {
217
+ const entityData = entityDataByInternalId[packet.type]
218
+ const entity = entityData?.type === 'player'
219
+ ? addNewPlayer(packet.entityId, packet.objectUUID, packet)
220
+ : addNewNonPlayer(packet.entityId, packet.objectUUID, packet.type, packet)
214
221
  bot.emit('entitySpawn', entity)
215
222
  })
216
223
 
@@ -71,6 +71,11 @@ function inject (bot, options) {
71
71
  const brandChannel = getBrandCustomChannelName()
72
72
  bot._client.registerChannel(brandChannel, ['string', []])
73
73
 
74
+ // 1.20.2
75
+ bot._client.on('registry_data', (packet) => {
76
+ bot.registry.loadDimensionCodec(packet.codec)
77
+ })
78
+
74
79
  bot._client.on('login', (packet) => {
75
80
  handleRespawnPacketData(packet)
76
81
 
@@ -25,10 +25,17 @@ function inject (bot, options) {
25
25
  bot.emit('death')
26
26
  }
27
27
  if (!options.respawn) return
28
- bot._client.write('client_command', { payload: 0 })
28
+ bot.respawn()
29
29
  } else if (bot.health > 0 && !bot.isAlive) {
30
30
  bot.isAlive = true
31
31
  bot.emit('spawn')
32
32
  }
33
33
  })
34
+
35
+ const respawn = () => {
36
+ if (bot.isAlive) return
37
+ bot._client.write('client_command', bot.supportFeature('respawnIsPayload') ? { payload: 0 } : { actionId: 0 })
38
+ }
39
+
40
+ bot.respawn = respawn
34
41
  }
package/lib/version.js CHANGED
@@ -1,6 +1,8 @@
1
- const testedVersions = ['1.8.8', '1.9.4', '1.10.2', '1.11.2', '1.12.2', '1.13.2', '1.14.4', '1.15.2', '1.16.5', '1.17.1', '1.18.2', '1.19', '1.19.2', '1.19.3', '1.19.4', '1.20.1']
1
+ const testedVersions = ['1.8.8', '1.9.4', '1.10.2', '1.11.2', '1.12.2', '1.13.2', '1.14.4', '1.15.2', '1.16.5', '1.17.1', '1.18.2', '1.19', '1.19.2', '1.19.3', '1.19.4', '1.20.1', '1.20.2']
2
2
  module.exports = {
3
+
3
4
  testedVersions,
4
5
  latestSupportedVersion: testedVersions[testedVersions.length - 1],
5
6
  oldestSupportedVersion: testedVersions[0]
7
+
6
8
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mineflayer",
3
- "version": "4.17.0",
3
+ "version": "4.18.0",
4
4
  "description": "create minecraft bots with a stable, high level API",
5
5
  "main": "index.js",
6
6
  "types": "index.d.ts",
@@ -17,11 +17,11 @@
17
17
  "url": "git://github.com/PrismarineJS/mineflayer.git"
18
18
  },
19
19
  "engines": {
20
- "node": ">=14"
20
+ "node": ">=18"
21
21
  },
22
22
  "license": "MIT",
23
23
  "dependencies": {
24
- "minecraft-data": "^3.44.0",
24
+ "minecraft-data": "^3.56.0",
25
25
  "minecraft-protocol": "^1.44.0",
26
26
  "prismarine-biome": "^1.1.1",
27
27
  "prismarine-block": "^1.17.0",