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.
- package/.github/workflows/commands.yml +22 -0
- package/docs/api.md +2 -0
- package/docs/es/README_ES.md +1 -1
- package/docs/fr/README_FR.md +1 -1
- package/docs/history.md +17 -0
- package/docs/ru/README_RU.md +1 -1
- package/docs/tr/README_TR.md +1 -1
- package/docs/zh/README_ZH_CN.md +1 -1
- package/index.d.ts +2 -0
- package/lib/plugins/blocks.js +5 -2
- package/lib/plugins/chat.js +4 -18
- package/lib/plugins/entities.js +8 -1
- package/lib/plugins/inventory.js +44 -4
- package/lib/plugins/physics.js +73 -31
- package/lib/plugins/place_block.js +6 -1
- package/package.json +4 -4
|
@@ -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)
|
package/docs/es/README_ES.md
CHANGED
|
@@ -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.
|
|
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
|
package/docs/fr/README_FR.md
CHANGED
|
@@ -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.
|
|
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)
|
package/docs/ru/README_RU.md
CHANGED
|
@@ -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.
|
|
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
|
* Физика и управление
|
package/docs/tr/README_TR.md
CHANGED
|
@@ -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.
|
|
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
|
package/docs/zh/README_ZH_CN.md
CHANGED
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> {
|
package/lib/plugins/blocks.js
CHANGED
|
@@ -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
|
|
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
|
})
|
package/lib/plugins/chat.js
CHANGED
|
@@ -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 (
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
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
|
package/lib/plugins/entities.js
CHANGED
|
@@ -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
|
|
package/lib/plugins/inventory.js
CHANGED
|
@@ -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(
|
|
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
|
-
|
|
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
|
|
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', {
|
package/lib/plugins/physics.js
CHANGED
|
@@ -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
|
-
|
|
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
|
-
|
|
121
|
-
|
|
122
|
-
if (
|
|
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 =
|
|
130
|
-
const maxDeltaPitch =
|
|
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
|
|
175
|
+
if (positionUpdated && lookUpdated) {
|
|
144
176
|
sendPacketPositionAndLook(position, yaw, pitch, onGround)
|
|
145
|
-
|
|
177
|
+
lastSent.time = now // only reset if positionUpdated is true
|
|
178
|
+
} else if (positionUpdated) {
|
|
146
179
|
sendPacketPosition(position, onGround)
|
|
147
|
-
|
|
180
|
+
lastSent.time = now // only reset if positionUpdated is true
|
|
181
|
+
} else if (lookUpdated) {
|
|
148
182
|
sendPacketLook(yaw, pitch, onGround)
|
|
149
|
-
} else if (
|
|
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
|
-
|
|
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.
|
|
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}`, {
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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",
|