mineflayer 4.10.1 → 4.12.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.
@@ -0,0 +1,22 @@
1
+ name: Repo Commands
2
+
3
+ on:
4
+ issue_comment: # Handle comment commands
5
+ types: [created]
6
+ pull_request: # Handle renamed PRs
7
+ types: [edited]
8
+
9
+ jobs:
10
+ comment-trigger:
11
+ runs-on: ubuntu-latest
12
+ steps:
13
+ - name: Check out repository
14
+ uses: actions/checkout@v3
15
+ - name: Run command handlers
16
+ uses: PrismarineJS/prismarine-repo-actions@master
17
+ with:
18
+ # NOTE: You must specify a Personal Access Token (PAT) with repo access here. While you can use the default GITHUB_TOKEN, actions taken with it will not trigger other actions, so if you have a CI workflow, commits created by this action will not trigger it.
19
+ token: ${{ secrets.PAT_PASSWORD }}
20
+ # See `Options` section below for more info on these options
21
+ install-command: npm install
22
+ /fixlint.fix-command: npm run fix
package/docs/api.md CHANGED
@@ -187,6 +187,7 @@
187
187
  - ["entityTamed" (entity)](#entitytamed-entity)
188
188
  - ["entityShakingOffWater" (entity)](#entityshakingoffwater-entity)
189
189
  - ["entityEatingGrass" (entity)](#entityeatinggrass-entity)
190
+ - ["entityHandSwap" (entity)](#entityhandswap-entity)
190
191
  - ["entityWake" (entity)](#entitywake-entity)
191
192
  - ["entityEat" (entity)](#entityeat-entity)
192
193
  - ["entityCriticalEffect" (entity)](#entitycriticaleffect-entity)
@@ -1290,6 +1291,7 @@ Fires when an attribute of an entity changes.
1290
1291
  #### "entityTamed" (entity)
1291
1292
  #### "entityShakingOffWater" (entity)
1292
1293
  #### "entityEatingGrass" (entity)
1294
+ #### "entityHandSwap" (entity)
1293
1295
  #### "entityWake" (entity)
1294
1296
  #### "entityEat" (entity)
1295
1297
  #### "entityCriticalEffect" (entity)
@@ -17,7 +17,7 @@ Crea bots para Minecraft con una API de JavaScript potente, estable y de alto ni
17
17
 
18
18
  ## Características
19
19
 
20
- * Soporta Minecraft 1.8, 1.9, 1.10, 1.11, 1.12, 1.13, 1.14, 1.15, 1.16, 1.17, 1.18 y 1.19.
20
+ * Soporta Minecraft 1.8, 1.9, 1.10, 1.11, 1.12, 1.13, 1.14, 1.15, 1.16, 1.17, 1.18, 1.19 y 1.20.
21
21
  * Rastreo e información de entidades.
22
22
  * Información sobre bloques. Puedes solicitar información de todo lo que te rodea. Encuentra bloques en milisegundos
23
23
  * Físicas y movimientos básicos - maneja todos los cuadros de colisión
@@ -18,7 +18,7 @@ Si c'est la première fois que vous utilisez Node.js, il vaut mieux commencer av
18
18
 
19
19
  ## Caractéristiques:
20
20
 
21
- * Compatible avec Minecraft 1.8, 1.9, 1.10, 1.11, 1.12, 1.13, 1.14, 1.15 et 1.16.
21
+ * Compatible avec Minecraft 1.8, 1.9, 1.10, 1.11, 1.12, 1.13, 1.14, 1.15, 1.16, 1.17, 1.18, 1.19 et 1.20.
22
22
  * Reconnaissante et pistage des entités.
23
23
  * Identification des blocs. Vous pouvez passer en revue le monde autour de vous. Quelques millisecondes suffisent pour trouver n'importe quel bloc.
24
24
  * Information sur la physique et mouvements, données sur la taille des blocs...
package/docs/history.md CHANGED
@@ -1,3 +1,20 @@
1
+ ## 4.12.0
2
+ * [Mineflayer physics refactor (#2492)](https://github.com/PrismarineJS/mineflayer/commit/d0eb3a1afe6cda7b04ae2f88052cd868ba0c0c4f) (thanks @U5B)
3
+
4
+ ## 4.11.0
5
+ * [Import changedSlots computation from prismarine-windows (#3134)](https://github.com/PrismarineJS/mineflayer/commit/e5b5eeecf1133c1c80c0ef48d6e72fed77d84834) (thanks @kaduvert)
6
+ * [Make the place block success check ignore block updates received with no block type changes (#3090)](https://github.com/PrismarineJS/mineflayer/commit/bbdd93afe2e31d1f1e899176e7edf8e73af5d5d3) (thanks @PondWader)
7
+ * [Use node-minecraft-protocol for chat (#3110)](https://github.com/PrismarineJS/mineflayer/commit/385fba65ed6ebe632c870c7cf234666cacf5a766) (thanks @lkwilson)
8
+ * [Extended useChests.js tests (#3132)](https://github.com/PrismarineJS/mineflayer/commit/131a7ea63c9c6b2cce41ebb29a26c898f859471d) (thanks @kaduvert)
9
+ * [Allow more click modes (#3133)](https://github.com/PrismarineJS/mineflayer/commit/a315653bb94274113c9d6078d4c2ab840af0f62a) (thanks @kaduvert)
10
+ * [Add nether test (#2932)](https://github.com/PrismarineJS/mineflayer/commit/6b1d6ea15c72edc5b761b78765a53d2ab7d0d274) (thanks @frej4189)
11
+ * [Explicitly depend on pitem 1.14.0 with fix](https://github.com/PrismarineJS/mineflayer/commit/acc6ec9b5e61d566facb76e9c3ff512cc9a5137f) (thanks @rom1504)
12
+ * [Make sure we pass a string to a storagebuilder (#2645)](https://github.com/PrismarineJS/mineflayer/commit/fc95843dac69bc1101dd5ec898a2aaf4dcfbf520) (thanks @u9g)
13
+ * [extra types for enchantments (#3123)](https://github.com/PrismarineJS/mineflayer/commit/b336d2259d1ce0935bf8e10a4edb3c0a9030fb10) (thanks @zisis912)
14
+ * [Add 1.20 to supported versions in readme (#3111)](https://github.com/PrismarineJS/mineflayer/commit/d764706f53dbe7ba16cf49645d66d192a309cc5c) (thanks @litfa)
15
+ * [Handle hand swap entity status (#3097)](https://github.com/PrismarineJS/mineflayer/commit/a80d69a8f1a637ab1a0720ec776fc4f05c38afed) (thanks @PondWader)
16
+ * [Add command gh workflow allowing to use release command in comments (#3116)](https://github.com/PrismarineJS/mineflayer/commit/5a55744ee0dc670f984229ec2629239bdc3e5705) (thanks @rom1504)
17
+
1
18
  ## 4.10.1
2
19
 
3
20
  * Fix attempting to access unloaded chunks (@frej4189)
@@ -18,7 +18,7 @@
18
18
 
19
19
  ## Возможности
20
20
 
21
- * Поддержка 1.8, 1.9, 1.10, 1.11, 1.12, 1.13, 1.14, 1.15, 1.16, 1.17 и 1.18
21
+ * Поддержка 1.8, 1.9, 1.10, 1.11, 1.12, 1.13, 1.14, 1.15, 1.16, 1.17, 1.18, 1.19 и 1.20
22
22
  * Поддержка энтити и их отслеживание
23
23
  * Вы можете полностью взаимодействовать с миром. Миллисекунды на поиск любого блока
24
24
  * Физика и управление
@@ -18,7 +18,7 @@ JavaScript ile güçlü, stabil ve üst seviye Minecraft botları oluşturabilec
18
18
 
19
19
  ## Özellikler
20
20
 
21
- * Minecraft 1.8, 1.9, 1.10, 1.11, 1.12, 1.13, 1.14, 1.15 ve 1.16 sürümlerini destekler.
21
+ * Minecraft 1.8, 1.9, 1.10, 1.11, 1.12, 1.13, 1.14, 1.15, 1.16, 1.17, 1.18, 1.19 ve 1.20 sürümlerini destekler.
22
22
  * Varlık bilgisi ve takibi.
23
23
  * Blok bilgisi. Etrafını inceleyebilirsin. Bir bloğu bulmak milisaniyeler sürer.
24
24
  * Fizik ve hareket - bütün hayali kutucukları ele alabilirsin
@@ -19,7 +19,7 @@
19
19
 
20
20
  ## 特点
21
21
 
22
- * 支持版本:Minecraft 1.8, 1.9, 1.10, 1.11, 1.12, 1.13, 1.14, 1.15 1.16 1.17,1.18
22
+ * 支持版本:Minecraft 1.8, 1.9, 1.10, 1.11, 1.12, 1.13, 1.14, 1.15, 1.16, 1.17, 1.18, 1.19 和 1.20
23
23
  * 实体感知与追踪
24
24
  * 方块感知,你可以在几毫秒内查找到bot周围的任何方块
25
25
  * 物理和运动引擎 - 支持所有的碰撞箱
package/index.d.ts CHANGED
@@ -82,6 +82,7 @@ export interface BotEvents {
82
82
  entityTamed: (entity: Entity) => Promise<void> | void
83
83
  entityShakingOffWater: (entity: Entity) => Promise<void> | void
84
84
  entityEatingGrass: (entity: Entity) => Promise<void> | void
85
+ entityHandSwap: (entity: Entity) => Promise<void> | void
85
86
  entityWake: (entity: Entity) => Promise<void> | void
86
87
  entityEat: (entity: Entity) => Promise<void> | void
87
88
  entityCriticalEffect: (entity: Entity) => Promise<void> | void
@@ -729,6 +730,7 @@ export class Anvil {
729
730
 
730
731
  export interface Enchantment {
731
732
  level: number
733
+ expected: { enchant: number, level: number }
732
734
  }
733
735
 
734
736
  export class Villager extends Window<ConditionalStorageEvents> {
@@ -470,9 +470,11 @@ function inject (bot, { version, storageBuilder, hideErrors }) {
470
470
  if (bot.supportFeature('dimensionIsAnInt')) {
471
471
  return dimensionNames[dimension]
472
472
  } else if (bot.supportFeature('dimensionIsAString') || bot.supportFeature('dimensionIsAWorld')) {
473
- return dimension
473
+ return worldName
474
474
  }
475
475
  }
476
+ // only exposed for testing
477
+ bot._getDimensionName = () => worldName
476
478
 
477
479
  async function switchWorld () {
478
480
  if (bot.world) {
@@ -503,9 +505,10 @@ function inject (bot, { version, storageBuilder, hideErrors }) {
503
505
  bot._client.on('login', (packet) => {
504
506
  if (bot.supportFeature('dimensionIsAnInt')) {
505
507
  dimension = packet.dimension
508
+ worldName = dimensionToFolderName(dimension)
506
509
  } else {
507
510
  dimension = packet.dimension
508
- worldName = packet.worldName
511
+ worldName = /^minecraft:.+/.test(packet.worldName) ? packet.worldName : `minecraft:${packet.worldName}`
509
512
  }
510
513
  switchWorld()
511
514
  })
@@ -147,24 +147,10 @@ function inject (bot, options) {
147
147
  throw new Error('Incorrect type! Should be a string or number.')
148
148
  }
149
149
 
150
- if (bot.supportFeature('signedChat')) {
151
- if (message.startsWith('/')) {
152
- // We send commands as Chat Command packet in 1.19+
153
- const command = message.slice(1)
154
- const timestamp = BigInt(Date.now())
155
- bot._client.write('chat_command', {
156
- command,
157
- timestamp,
158
- salt: 0n,
159
- argumentSignatures: [],
160
- signedPreview: false,
161
- messageCount: 0,
162
- acknowledged: Buffer.alloc(3),
163
- // 1.19.2 Chat Command packet also includes an array of last seen messages
164
- previousMessages: []
165
- })
166
- return
167
- }
150
+ if (!header && message.startsWith('/')) {
151
+ // Do not try and split a command without a header
152
+ bot._client.chat(message)
153
+ return
168
154
  }
169
155
 
170
156
  const lengthLimit = CHAT_LENGTH_LIMIT - header.length
@@ -21,7 +21,8 @@ const entityStatusEvents = {
21
21
  6: 'entityTaming',
22
22
  7: 'entityTamed',
23
23
  8: 'entityShakingOffWater',
24
- 10: 'entityEatingGrass'
24
+ 10: 'entityEatingGrass',
25
+ 55: 'entityHandSwap'
25
26
  }
26
27
 
27
28
  function inject (bot) {
@@ -338,6 +339,12 @@ function inject (bot) {
338
339
  // entity status
339
340
  const entity = fetchEntity(packet.entityId)
340
341
  const eventName = entityStatusEvents[packet.entityStatus]
342
+
343
+ if (eventName === 'entityHandSwap' && entity.equipment) {
344
+ [entity.equipment[0], entity.equipment[1]] = [entity.equipment[1], entity.equipment[0]]
345
+ entity.heldItem = entity.equipment[0] // Update held item like prismarine-entity does upon equipment updates
346
+ }
347
+
341
348
  if (eventName) bot.emit(eventName, entity)
342
349
  })
343
350
 
@@ -479,6 +479,20 @@ function inject (bot, { hideErrors }) {
479
479
  }
480
480
  }
481
481
 
482
+ function getChangedSlots (oldSlots, newSlots) {
483
+ assert.equal(oldSlots.length, newSlots.length)
484
+
485
+ const changedSlots = []
486
+
487
+ for (let i = 0; i < newSlots.length; i++) {
488
+ if (!Item.equal(oldSlots[i], newSlots[i])) {
489
+ changedSlots.push(i)
490
+ }
491
+ }
492
+
493
+ return changedSlots
494
+ }
495
+
482
496
  async function clickWindow (slot, mouseButton, mode) {
483
497
  // if you click on the quick bar and have dug recently,
484
498
  // wait a bit
@@ -490,8 +504,7 @@ function inject (bot, { hideErrors }) {
490
504
  }
491
505
  const window = bot.currentWindow || bot.inventory
492
506
 
493
- assert.ok(mouseButton === 0 || mouseButton === 1)
494
- assert.strictEqual(mode, 0)
507
+ assert.ok(mode >= 0 && mode <= 4)
495
508
  const actionId = createActionNumber()
496
509
 
497
510
  const click = {
@@ -507,7 +520,33 @@ function inject (bot, { hideErrors }) {
507
520
  if (bot.supportFeature('transactionPacketExists')) {
508
521
  windowClickQueue.push(click)
509
522
  } else {
510
- changedSlots = window.acceptClick(click)
523
+ if (
524
+ // this array indicates the clicks that return changedSlots
525
+ [
526
+ 0,
527
+ // 1,
528
+ // 2,
529
+ 3,
530
+ 4
531
+ // 5,
532
+ // 6
533
+ ].includes(click.mode)) {
534
+ changedSlots = window.acceptClick(click)
535
+ } else {
536
+ // this is used as a fallback
537
+ const oldSlots = JSON.parse(JSON.stringify(window.slots))
538
+
539
+ window.acceptClick(click)
540
+
541
+ changedSlots = getChangedSlots(oldSlots, window.slots)
542
+ }
543
+
544
+ changedSlots = changedSlots.map(slot => {
545
+ return {
546
+ location: slot,
547
+ item: Item.toNotch(window.slots[slot])
548
+ }
549
+ })
511
550
  }
512
551
 
513
552
  // WHEN ADDING SUPPORT FOR OTHER CLICKS, MAKE SURE TO CHANGE changedSlots TO SUPPORT THEM
@@ -528,7 +567,8 @@ function inject (bot, { hideErrors }) {
528
567
  mouseButton,
529
568
  action: actionId,
530
569
  mode,
531
- item: Item.toNotch(click.item)
570
+ // protocol expects null even if there is an item at the slot in mode 2 and 4
571
+ item: Item.toNotch((mode === 2 || mode === 4) ? null : click.item)
532
572
  })
533
573
  } else { // 1.17
534
574
  bot._client.write('window_click', {
@@ -12,9 +12,10 @@ module.exports = inject
12
12
  const PI = Math.PI
13
13
  const PI_2 = Math.PI * 2
14
14
  const PHYSICS_INTERVAL_MS = 50
15
- const PHYSICS_TIMESTEP = PHYSICS_INTERVAL_MS / 1000
15
+ const PHYSICS_TIMESTEP = PHYSICS_INTERVAL_MS / 1000 // 0.05
16
16
 
17
- function inject (bot, { physicsEnabled }) {
17
+ function inject (bot, { physicsEnabled, maxCatchupTicks }) {
18
+ const PHYSICS_CATCHUP_TICKS = maxCatchupTicks ?? 4
18
19
  const world = { getBlock: (pos) => { return bot.blockAt(pos, false) } }
19
20
  const physics = Physics(bot.registry, world)
20
21
 
@@ -38,6 +39,7 @@ function inject (bot, { physicsEnabled }) {
38
39
  let lastPhysicsFrameTime = null
39
40
  let shouldUsePhysics = false
40
41
  bot.physicsEnabled = physicsEnabled ?? true
42
+ let deadTicks = 21
41
43
 
42
44
  const lastSent = {
43
45
  x: 0,
@@ -51,25 +53,44 @@ function inject (bot, { physicsEnabled }) {
51
53
 
52
54
  // This function should be executed each tick (every 0.05 seconds)
53
55
  // How it works: https://gafferongames.com/post/fix_your_timestep/
56
+
57
+ // WARNING: THIS IS NOT ACCURATE ON WINDOWS (15.6 Timer Resolution)
58
+ // use WSL or switch to Linux
59
+ // see: https://discord.com/channels/413438066984747026/519952494768685086/901948718255833158
54
60
  let timeAccumulator = 0
61
+ let catchupTicks = 0
55
62
  function doPhysics () {
56
63
  const now = performance.now()
57
64
  const deltaSeconds = (now - lastPhysicsFrameTime) / 1000
58
65
  lastPhysicsFrameTime = now
59
66
 
60
67
  timeAccumulator += deltaSeconds
61
-
68
+ catchupTicks = 0
62
69
  while (timeAccumulator >= PHYSICS_TIMESTEP) {
63
- if (bot.physicsEnabled && shouldUsePhysics) {
64
- physics.simulatePlayer(new PlayerState(bot, controlState), world).apply(bot)
65
- bot.emit('physicsTick')
66
- bot.emit('physicTick') // Deprecated, only exists to support old plugins. May be removed in the future
67
- }
68
- updatePosition(PHYSICS_TIMESTEP)
70
+ tickPhysics(now)
69
71
  timeAccumulator -= PHYSICS_TIMESTEP
72
+ catchupTicks++
73
+ if (catchupTicks >= PHYSICS_CATCHUP_TICKS) break
74
+ }
75
+ }
76
+
77
+ function tickPhysics (now) {
78
+ if (bot.blockAt(bot.entity.position) == null) return // check if chunk is unloaded
79
+ if (bot.physicsEnabled && shouldUsePhysics) {
80
+ physics.simulatePlayer(new PlayerState(bot, controlState), world).apply(bot)
81
+ bot.emit('physicsTick')
82
+ bot.emit('physicTick') // Deprecated, only exists to support old plugins. May be removed in the future
83
+ }
84
+ if (shouldUsePhysics) {
85
+ updatePosition(now)
70
86
  }
71
87
  }
72
88
 
89
+ // remove this when 'physicTick' is removed
90
+ bot.on('newListener', (name) => {
91
+ if (name === 'physicTick') console.warn('Mineflayer detected that you are using a deprecated event (physicTick)! Please use this event (physicsTick) instead.')
92
+ })
93
+
73
94
  function cleanup () {
74
95
  clearInterval(doPhysicsTimer)
75
96
  doPhysicsTimer = null
@@ -117,17 +138,25 @@ function inject (bot, { physicsEnabled }) {
117
138
  return dYaw
118
139
  }
119
140
 
120
- function updatePosition (dt) {
121
- // If you're dead, you're probably on the ground though ...
122
- if (!bot.isAlive) bot.entity.onGround = true
141
+ // returns false if packet should be sent, true if not
142
+ function sendPositionPacketInDeath () {
143
+ if (bot.isAlive === true) deadTicks = 0
144
+ if (bot.isAlive === false && deadTicks <= 20) deadTicks++
145
+ if (deadTicks >= 20) return true
146
+ return false
147
+ }
148
+
149
+ function updatePosition (now) {
150
+ // Only send updates for 20 ticks after death
151
+ if (sendPositionPacketInDeath()) return
123
152
 
124
153
  // Increment the yaw in baby steps so that notchian clients (not the server) can keep up.
125
154
  const dYaw = deltaYaw(bot.entity.yaw, lastSentYaw)
126
155
  const dPitch = bot.entity.pitch - (lastSentPitch || 0)
127
156
 
128
157
  // Vanilla doesn't clamp yaw, so we don't want to do it either
129
- const maxDeltaYaw = dt * physics.yawSpeed
130
- const maxDeltaPitch = dt * physics.pitchSpeed
158
+ const maxDeltaYaw = PHYSICS_TIMESTEP * physics.yawSpeed
159
+ const maxDeltaPitch = PHYSICS_TIMESTEP * physics.pitchSpeed
131
160
  lastSentYaw += math.clamp(-maxDeltaYaw, dYaw, maxDeltaYaw)
132
161
  lastSentPitch += math.clamp(-maxDeltaPitch, dPitch, maxDeltaPitch)
133
162
 
@@ -137,24 +166,28 @@ function inject (bot, { physicsEnabled }) {
137
166
  const onGround = bot.entity.onGround
138
167
 
139
168
  // Only send a position update if necessary, select the appropriate packet
140
- const positionUpdated = lastSent.x !== position.x || lastSent.y !== position.y || lastSent.z !== position.z
169
+ const positionUpdated = lastSent.x !== position.x || lastSent.y !== position.y || lastSent.z !== position.z ||
170
+ // Send a position update every second, even if no other update was made
171
+ // This function rounds to the nearest 50ms (or PHYSICS_INTERVAL_MS) and checks if a second has passed.
172
+ (Math.round((now - lastSent.time) / PHYSICS_INTERVAL_MS) * PHYSICS_INTERVAL_MS) >= 1000
141
173
  const lookUpdated = lastSent.yaw !== yaw || lastSent.pitch !== pitch
142
174
 
143
- if (positionUpdated && lookUpdated && bot.isAlive) {
175
+ if (positionUpdated && lookUpdated) {
144
176
  sendPacketPositionAndLook(position, yaw, pitch, onGround)
145
- } else if (positionUpdated && bot.isAlive) {
177
+ lastSent.time = now // only reset if positionUpdated is true
178
+ } else if (positionUpdated) {
146
179
  sendPacketPosition(position, onGround)
147
- } else if (lookUpdated && bot.isAlive) {
180
+ lastSent.time = now // only reset if positionUpdated is true
181
+ } else if (lookUpdated) {
148
182
  sendPacketLook(yaw, pitch, onGround)
149
- } else if (performance.now() - lastSent.time >= 1000) {
150
- // Send a position packet every second, even if no update was made
151
- sendPacketPosition(position, onGround)
152
- lastSent.time = performance.now()
153
- } else if (positionUpdateSentEveryTick && bot.isAlive) {
183
+ } else if (positionUpdateSentEveryTick || onGround !== lastSent.onGround) {
154
184
  // For versions < 1.12, one player packet should be sent every tick
155
185
  // for the server to update health correctly
186
+ // For versions >= 1.12, onGround !== lastSent.onGround should be used, but it doesn't ever trigger outside of login
156
187
  bot._client.write('flying', { onGround: bot.entity.onGround })
157
188
  }
189
+
190
+ lastSent.onGround = bot.entity.onGround // onGround is always set
158
191
  }
159
192
 
160
193
  bot.physics = physics
@@ -262,7 +295,14 @@ function inject (bot, { physicsEnabled }) {
262
295
  // player position and look (clientbound)
263
296
  bot._client.on('position', (packet) => {
264
297
  bot.entity.height = 1.62
265
- bot.entity.velocity.set(0, 0, 0)
298
+
299
+ // Velocity is only set to 0 if the flag is not set, otherwise keep current velocity
300
+ const vel = bot.entity.velocity
301
+ vel.set(
302
+ packet.flags & 1 ? vel.x : 0,
303
+ packet.flags & 2 ? vel.y : 0,
304
+ packet.flags & 4 ? vel.z : 0
305
+ )
266
306
 
267
307
  // If flag is set, then the corresponding value is relative, else it is absolute
268
308
  const pos = bot.entity.position
@@ -280,19 +320,14 @@ function inject (bot, { physicsEnabled }) {
280
320
 
281
321
  if (bot.supportFeature('teleportUsesOwnPacket')) {
282
322
  bot._client.write('teleport_confirm', { teleportId: packet.teleportId })
283
- // Force send an extra packet to be like vanilla client
284
- sendPacketPositionAndLook(pos, newYaw, newPitch, bot.entity.onGround)
285
323
  }
286
324
  sendPacketPositionAndLook(pos, newYaw, newPitch, bot.entity.onGround)
287
325
 
288
326
  shouldUsePhysics = true
289
- bot.entity.timeSinceOnGround = 0
327
+ bot.jumpTicks = 0
290
328
  lastSentYaw = bot.entity.yaw
329
+ lastSentPitch = bot.entity.pitch
291
330
 
292
- if (doPhysicsTimer === null) {
293
- lastPhysicsFrameTime = performance.now()
294
- doPhysicsTimer = setInterval(doPhysics, PHYSICS_INTERVAL_MS)
295
- }
296
331
  bot.emit('forcedMove')
297
332
  })
298
333
 
@@ -313,5 +348,12 @@ function inject (bot, { physicsEnabled }) {
313
348
 
314
349
  bot.on('mount', () => { shouldUsePhysics = false })
315
350
  bot.on('respawn', () => { shouldUsePhysics = false })
351
+ bot.on('login', () => {
352
+ shouldUsePhysics = false
353
+ if (doPhysicsTimer === null) {
354
+ lastPhysicsFrameTime = performance.now()
355
+ doPhysicsTimer = setInterval(doPhysics, PHYSICS_INTERVAL_MS)
356
+ }
357
+ })
316
358
  bot.on('end', cleanup)
317
359
  }
@@ -10,7 +10,12 @@ function inject (bot) {
10
10
 
11
11
  let newBlock = bot.blockAt(dest)
12
12
  if (oldBlock.type === newBlock.type) {
13
- [oldBlock, newBlock] = await onceWithCleanup(bot, `blockUpdate:${dest}`, { timeout: 5000 })
13
+ [oldBlock, newBlock] = await onceWithCleanup(bot, `blockUpdate:${dest}`, {
14
+ timeout: 5000,
15
+ // Condition to wait to receive block update actually changing the block type, in case the bot receives block updates with no changes
16
+ // oldBlock and newBlock will both be null when the world unloads
17
+ checkCondition: (oldBlock, newBlock) => !oldBlock || !newBlock || oldBlock.type !== newBlock.type
18
+ })
14
19
  }
15
20
 
16
21
  // blockUpdate emits (null, null) when the world unloads
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mineflayer",
3
- "version": "4.10.1",
3
+ "version": "4.12.0",
4
4
  "description": "create minecraft bots with a stable, high level API",
5
5
  "main": "index.js",
6
6
  "types": "index.d.ts",
@@ -22,18 +22,18 @@
22
22
  "license": "MIT",
23
23
  "dependencies": {
24
24
  "minecraft-data": "^3.37.0",
25
- "minecraft-protocol": "^1.43.1",
25
+ "minecraft-protocol": "^1.44.0",
26
26
  "prismarine-biome": "^1.1.1",
27
27
  "prismarine-block": "^1.17.0",
28
28
  "prismarine-chat": "^1.7.1",
29
29
  "prismarine-chunk": "^1.34.0",
30
30
  "prismarine-entity": "^2.2.0",
31
- "prismarine-item": "^1.12.1",
31
+ "prismarine-item": "^1.14.0",
32
32
  "prismarine-nbt": "^2.0.0",
33
33
  "prismarine-physics": "^1.7.0",
34
34
  "prismarine-recipe": "^1.3.0",
35
35
  "prismarine-registry": "^1.5.0",
36
- "prismarine-windows": "^2.5.0",
36
+ "prismarine-windows": "^2.8.0",
37
37
  "prismarine-world": "^3.6.0",
38
38
  "protodef": "^1.14.0",
39
39
  "typed-emitter": "^1.0.0",