mineflayer 3.10.0 → 3.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/FUNDING.yml +0 -2
- package/.github/workflows/ci.yml +20 -16
- package/README.md +16 -15
- package/docs/README.md +16 -15
- package/docs/api.md +50 -27
- package/docs/es/README_ES.md +1 -1
- package/docs/es/api_es.md +34 -18
- package/docs/fr/README_FR.md +1 -1
- package/docs/history.md +28 -0
- package/docs/ru/README_RU.md +1 -1
- package/docs/ru/api_ru.md +1 -1
- package/docs/tr/README_TR.md +1 -1
- package/docs/zh/README_ZH_CN.md +1 -1
- package/examples/chatterbox.js +1 -1
- package/examples/discord.js +15 -5
- package/examples/plugins/afk.js +50 -37
- package/examples/python/basic.py +2 -2
- package/examples/python/chatterbox.py +1 -1
- package/examples/screenshot-with-node-canvas-webgl/screenshot.js +2 -2
- package/index.d.ts +108 -134
- package/lib/conversions.js +1 -1
- package/lib/features.json +57 -27
- package/lib/loader.js +5 -4
- package/lib/plugins/bed.js +1 -1
- package/lib/plugins/block_actions.js +19 -7
- package/lib/plugins/blocks.js +17 -4
- package/lib/plugins/chat.js +5 -6
- package/lib/plugins/command_block.js +1 -1
- package/lib/plugins/craft.js +10 -18
- package/lib/plugins/creative.js +2 -2
- package/lib/plugins/digging.js +15 -6
- package/lib/plugins/enchantment_table.js +4 -2
- package/lib/plugins/entities.js +13 -8
- package/lib/plugins/explosion.js +3 -1
- package/lib/plugins/fishing.js +2 -2
- package/lib/plugins/game.js +55 -50
- package/lib/plugins/inventory.js +164 -40
- package/lib/plugins/physics.js +16 -5
- package/lib/plugins/place_block.js +7 -6
- package/lib/plugins/ray_trace.js +10 -0
- package/lib/plugins/simple_inventory.js +1 -1
- package/lib/plugins/sound.js +1 -1
- package/lib/plugins/spawn_point.js +1 -1
- package/lib/plugins/villager.js +57 -42
- package/lib/version.js +3 -3
- package/package.json +23 -22
package/lib/plugins/inventory.js
CHANGED
|
@@ -13,6 +13,13 @@ const DIG_CLICK_TIMEOUT = 500
|
|
|
13
13
|
// The eat time comes from https://minecraft.fandom.com/wiki/Food#Usage
|
|
14
14
|
const CONSUME_TIMEOUT = 2500
|
|
15
15
|
|
|
16
|
+
const ALWAYS_CONSUMABLES = [
|
|
17
|
+
'potion',
|
|
18
|
+
'milk_bucket',
|
|
19
|
+
'enchanted_golden_apple',
|
|
20
|
+
'golden_apple'
|
|
21
|
+
]
|
|
22
|
+
|
|
16
23
|
function inject (bot, { version, hideErrors }) {
|
|
17
24
|
const Item = require('prismarine-item')(version)
|
|
18
25
|
const windows = require('prismarine-windows')(version)
|
|
@@ -20,7 +27,13 @@ function inject (bot, { version, hideErrors }) {
|
|
|
20
27
|
|
|
21
28
|
let eatingTask = createDoneTask()
|
|
22
29
|
|
|
23
|
-
let nextActionNumber = 0
|
|
30
|
+
let nextActionNumber = 0 // < 1.17
|
|
31
|
+
let stateId = -1
|
|
32
|
+
if (bot.supportFeature('stateIdUsed')) {
|
|
33
|
+
const listener = packet => { stateId = packet.stateId }
|
|
34
|
+
bot._client.on('window_items', listener)
|
|
35
|
+
bot._client.on('set_slot', listener)
|
|
36
|
+
}
|
|
24
37
|
const windowClickQueue = []
|
|
25
38
|
let windowItems
|
|
26
39
|
|
|
@@ -30,11 +43,36 @@ function inject (bot, { version, hideErrors }) {
|
|
|
30
43
|
bot.inventory = windows.createWindow(0, 'minecraft:inventory', 'Inventory')
|
|
31
44
|
bot.currentWindow = null
|
|
32
45
|
bot.heldItem = null
|
|
46
|
+
bot.usingHeldItem = false
|
|
33
47
|
|
|
34
48
|
bot._client.on('entity_status', (packet) => {
|
|
35
49
|
if (packet.entityId === bot.entity.id && packet.entityStatus === 9 && !eatingTask.done) {
|
|
36
50
|
eatingTask.finish()
|
|
37
51
|
}
|
|
52
|
+
bot.usingHeldItem = false
|
|
53
|
+
})
|
|
54
|
+
|
|
55
|
+
let previousHeldItem = null
|
|
56
|
+
bot.on('heldItemChanged', (heldItem) => {
|
|
57
|
+
// we only disable the item if the item type or count changes
|
|
58
|
+
if (
|
|
59
|
+
heldItem?.type === previousHeldItem?.type && heldItem?.count === previousHeldItem?.count
|
|
60
|
+
) {
|
|
61
|
+
previousHeldItem = heldItem
|
|
62
|
+
return
|
|
63
|
+
}
|
|
64
|
+
if (!eatingTask.done) {
|
|
65
|
+
eatingTask.finish()
|
|
66
|
+
}
|
|
67
|
+
bot.usingHeldItem = false
|
|
68
|
+
})
|
|
69
|
+
|
|
70
|
+
bot._client.on('set_cooldown', (packet) => {
|
|
71
|
+
if (bot.heldItem && bot.heldItem.type !== packet.itemID) return
|
|
72
|
+
if (!eatingTask.done) {
|
|
73
|
+
eatingTask.finish()
|
|
74
|
+
}
|
|
75
|
+
bot.usingHeldItem = false
|
|
38
76
|
})
|
|
39
77
|
|
|
40
78
|
async function consume () {
|
|
@@ -42,7 +80,7 @@ function inject (bot, { version, hideErrors }) {
|
|
|
42
80
|
eatingTask.cancel(new Error('Consuming cancelled due to calling bot.consume() again'))
|
|
43
81
|
}
|
|
44
82
|
|
|
45
|
-
if (bot.food === 20) {
|
|
83
|
+
if (bot.game.gameMode !== 'creative' && !ALWAYS_CONSUMABLES.includes(bot.heldItem.name) && bot.food === 20) {
|
|
46
84
|
throw new Error('Food is full')
|
|
47
85
|
}
|
|
48
86
|
|
|
@@ -54,6 +92,7 @@ function inject (bot, { version, hideErrors }) {
|
|
|
54
92
|
}
|
|
55
93
|
|
|
56
94
|
function activateItem (offHand = false) {
|
|
95
|
+
bot.usingHeldItem = true
|
|
57
96
|
if (bot.supportFeature('useItemWithBlockPlace')) {
|
|
58
97
|
bot._client.write('block_place', {
|
|
59
98
|
location: new Vec3(-1, 255, -1),
|
|
@@ -76,9 +115,10 @@ function inject (bot, { version, hideErrors }) {
|
|
|
76
115
|
location: new Vec3(0, 0, 0),
|
|
77
116
|
face: 5
|
|
78
117
|
})
|
|
118
|
+
bot.usingHeldItem = false
|
|
79
119
|
}
|
|
80
120
|
|
|
81
|
-
async function putSelectedItemRange (start, end, window, slot
|
|
121
|
+
async function putSelectedItemRange (start, end, window, slot) {
|
|
82
122
|
// put the selected item back indow the slot range in window
|
|
83
123
|
|
|
84
124
|
// try to put it in an item that already exists and just increase
|
|
@@ -88,11 +128,7 @@ function inject (bot, { version, hideErrors }) {
|
|
|
88
128
|
const item = window.findItemRange(start, end, window.selectedItem.type, window.selectedItem.metadata, true, window.selectedItem.nbt)
|
|
89
129
|
|
|
90
130
|
if (item && item.stackSize !== item.count) { // something to join with
|
|
91
|
-
|
|
92
|
-
await clickWindow(item.slot, 0, 0)
|
|
93
|
-
} else {
|
|
94
|
-
await Promise.all([clickWindow(item.slot, 0, 0), once(window, `updateSlot:${item.slot}`)])
|
|
95
|
-
}
|
|
131
|
+
await clickWindow(item.slot, 0, 0)
|
|
96
132
|
} else { // nothing to join with
|
|
97
133
|
const emptySlot = window.firstEmptySlotRange(start, end)
|
|
98
134
|
if (emptySlot === null) { // no room left
|
|
@@ -103,11 +139,7 @@ function inject (bot, { version, hideErrors }) {
|
|
|
103
139
|
await tossLeftover()
|
|
104
140
|
}
|
|
105
141
|
} else {
|
|
106
|
-
|
|
107
|
-
await Promise.all([clickWindow(emptySlot, 0, 0), once(window, `updateSlot:${emptySlot}`)])
|
|
108
|
-
} else {
|
|
109
|
-
await clickWindow(emptySlot, 0, 0)
|
|
110
|
-
}
|
|
142
|
+
await clickWindow(emptySlot, 0, 0)
|
|
111
143
|
}
|
|
112
144
|
}
|
|
113
145
|
}
|
|
@@ -171,8 +203,9 @@ function inject (bot, { version, hideErrors }) {
|
|
|
171
203
|
await bot.lookAt(entity.position.offset(0, 1, 0), false)
|
|
172
204
|
bot._client.write('use_entity', {
|
|
173
205
|
target: entity.id,
|
|
174
|
-
mouse: 0,
|
|
175
|
-
sneaking: false
|
|
206
|
+
mouse: 0, // interact with entity
|
|
207
|
+
sneaking: false,
|
|
208
|
+
hand: 0 // interact with the main hand
|
|
176
209
|
})
|
|
177
210
|
}
|
|
178
211
|
|
|
@@ -181,8 +214,9 @@ function inject (bot, { version, hideErrors }) {
|
|
|
181
214
|
await bot.lookAt(position, false)
|
|
182
215
|
bot._client.write('use_entity', {
|
|
183
216
|
target: entity.id,
|
|
184
|
-
mouse: 2,
|
|
217
|
+
mouse: 2, // interact with entity at
|
|
185
218
|
sneaking: false,
|
|
219
|
+
hand: 0, // interact with the main hand
|
|
186
220
|
x: position.x - entity.position.x,
|
|
187
221
|
y: position.y - entity.position.y,
|
|
188
222
|
z: position.z - entity.position.z
|
|
@@ -333,20 +367,84 @@ function inject (bot, { version, hideErrors }) {
|
|
|
333
367
|
bot._client.write('close_window', {
|
|
334
368
|
windowId: window.id
|
|
335
369
|
})
|
|
370
|
+
copyInventory(window)
|
|
336
371
|
bot.currentWindow = null
|
|
337
372
|
bot.emit('windowClose', window)
|
|
338
373
|
}
|
|
339
374
|
|
|
375
|
+
function copyInventory (window) {
|
|
376
|
+
const slotOffset = window.inventoryStart - bot.inventory.inventoryStart
|
|
377
|
+
for (let i = window.inventoryStart; i < window.inventoryEnd; i++) {
|
|
378
|
+
const item = window.slots[i]
|
|
379
|
+
const slot = i - slotOffset
|
|
380
|
+
if (item) {
|
|
381
|
+
item.slot = slot
|
|
382
|
+
}
|
|
383
|
+
bot.inventory.slots[slot] = item
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
function tradeMatch (limitItem, targetItem) {
|
|
388
|
+
return targetItem.type === limitItem.type && targetItem.count >= limitItem.count
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
function expectTradeUpdate (window) {
|
|
392
|
+
const trade = window.selectedTrade
|
|
393
|
+
const hasItem = !!window.slots[2]
|
|
394
|
+
|
|
395
|
+
if (hasItem !== tradeMatch(trade.inputItem1, window.slots[0])) {
|
|
396
|
+
if (trade.hasItems2) {
|
|
397
|
+
return hasItem !== tradeMatch(trade.inputItem2, window.slots[1])
|
|
398
|
+
}
|
|
399
|
+
return true
|
|
400
|
+
}
|
|
401
|
+
return false
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
async function waitForWindowUpdate (window, slot) {
|
|
405
|
+
if (window.type === 'minecraft:inventory') {
|
|
406
|
+
if (slot >= 1 && slot <= 4) {
|
|
407
|
+
await once(bot.inventory, 'updateSlot:0')
|
|
408
|
+
}
|
|
409
|
+
} else if (window.type === 'minecraft:crafting') {
|
|
410
|
+
if (slot >= 1 && slot <= 9) {
|
|
411
|
+
await once(bot.currentWindow, 'updateSlot:0')
|
|
412
|
+
}
|
|
413
|
+
} else if (window.type === 'minecraft:merchant') {
|
|
414
|
+
const toUpdate = []
|
|
415
|
+
if (slot <= 2 && !window.selectedTrade.tradeDisabled && expectTradeUpdate(window)) {
|
|
416
|
+
toUpdate.push(once(bot.currentWindow, 'updateSlot:2'))
|
|
417
|
+
}
|
|
418
|
+
if (slot === 2) {
|
|
419
|
+
for (const item of bot.currentWindow.containerItems()) {
|
|
420
|
+
toUpdate.push(once(bot.currentWindow, `updateSlot:${item.slot}`))
|
|
421
|
+
}
|
|
422
|
+
}
|
|
423
|
+
await Promise.all(toUpdate)
|
|
424
|
+
}
|
|
425
|
+
}
|
|
426
|
+
|
|
340
427
|
function confirmTransaction (windowId, actionId, accepted) {
|
|
341
428
|
// drop the queue entries for all the clicks that the server did not send
|
|
342
429
|
// transaction packets for.
|
|
343
|
-
|
|
344
|
-
|
|
430
|
+
// Also reject transactions that aren't sent from mineflayer
|
|
431
|
+
let click = windowClickQueue[0]
|
|
432
|
+
if (click === undefined || !windowClickQueue.some(clicks => clicks.id === actionId)) {
|
|
433
|
+
// mimic vanilla client and send a rejection for faulty transaction packets
|
|
434
|
+
bot._client.write('transaction', {
|
|
435
|
+
windowId: windowId,
|
|
436
|
+
action: actionId,
|
|
437
|
+
accepted: true
|
|
438
|
+
// bot.emit(`confirmTransaction${click.id}`, false)
|
|
439
|
+
})
|
|
345
440
|
if (!hideErrors) {
|
|
346
441
|
console.log(`WARNING : unknown transaction confirmation for window ${windowId}, action ${actionId} and accepted ${accepted}`)
|
|
347
442
|
}
|
|
348
443
|
return
|
|
349
444
|
}
|
|
445
|
+
// shift it later if packets are sent out of order
|
|
446
|
+
click = windowClickQueue.shift()
|
|
447
|
+
|
|
350
448
|
assert.ok(click.id <= actionId)
|
|
351
449
|
while (actionId > click.id) {
|
|
352
450
|
onAccepted()
|
|
@@ -401,37 +499,66 @@ function inject (bot, { version, hideErrors }) {
|
|
|
401
499
|
windowId: window.id,
|
|
402
500
|
item: slot === -999 ? null : window.slots[slot]
|
|
403
501
|
}
|
|
404
|
-
windowClickQueue.push(click)
|
|
405
|
-
bot._client.write('window_click', {
|
|
406
|
-
windowId: window.id,
|
|
407
|
-
slot,
|
|
408
|
-
mouseButton,
|
|
409
|
-
action: actionId,
|
|
410
|
-
mode,
|
|
411
|
-
item: Item.toNotch(click.item)
|
|
412
|
-
})
|
|
413
502
|
|
|
414
|
-
|
|
503
|
+
let changedSlots
|
|
504
|
+
if (bot.supportFeature('transactionPacketExists')) {
|
|
505
|
+
windowClickQueue.push(click)
|
|
506
|
+
} else {
|
|
507
|
+
changedSlots = window.acceptClick(click)
|
|
508
|
+
}
|
|
415
509
|
|
|
416
|
-
//
|
|
417
|
-
if (
|
|
418
|
-
|
|
419
|
-
|
|
510
|
+
// WHEN ADDING SUPPORT FOR OTHER CLICKS, MAKE SURE TO CHANGE changedSlots TO SUPPORT THEM
|
|
511
|
+
if (bot.supportFeature('stateIdUsed')) { // 1.17.1 +
|
|
512
|
+
bot._client.write('window_click', {
|
|
513
|
+
windowId: window.id,
|
|
514
|
+
stateId,
|
|
515
|
+
slot,
|
|
516
|
+
mouseButton,
|
|
517
|
+
mode,
|
|
518
|
+
changedSlots: changedSlots,
|
|
519
|
+
cursorItem: Item.toNotch(window.selectedItem)
|
|
520
|
+
})
|
|
521
|
+
} else if (bot.supportFeature('actionIdUsed')) { // <= 1.16.5
|
|
522
|
+
bot._client.write('window_click', {
|
|
523
|
+
windowId: window.id,
|
|
524
|
+
slot,
|
|
525
|
+
mouseButton,
|
|
526
|
+
action: actionId,
|
|
527
|
+
mode,
|
|
528
|
+
item: Item.toNotch(click.item)
|
|
529
|
+
})
|
|
530
|
+
} else { // 1.17
|
|
531
|
+
bot._client.write('window_click', {
|
|
532
|
+
windowId: window.id,
|
|
533
|
+
slot,
|
|
534
|
+
mouseButton,
|
|
535
|
+
mode,
|
|
536
|
+
changedSlots: changedSlots,
|
|
537
|
+
cursorItem: Item.toNotch(window.selectedItem)
|
|
538
|
+
})
|
|
420
539
|
}
|
|
421
540
|
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
541
|
+
if (bot.supportFeature('transactionPacketExists')) {
|
|
542
|
+
const response = once(bot, `confirmTransaction${actionId}`)
|
|
543
|
+
if (!window.transactionRequiresConfirmation(click)) {
|
|
544
|
+
confirmTransaction(window.id, actionId, true)
|
|
545
|
+
}
|
|
546
|
+
const [success] = await response
|
|
547
|
+
if (!success) {
|
|
548
|
+
throw new Error(`Server rejected transaction for clicking on slot ${slot}, on window with id ${window?.id}.`)
|
|
549
|
+
}
|
|
550
|
+
} else {
|
|
551
|
+
await waitForWindowUpdate(window, slot)
|
|
425
552
|
}
|
|
426
553
|
}
|
|
427
554
|
|
|
428
|
-
async function putAway (slot
|
|
555
|
+
async function putAway (slot) {
|
|
429
556
|
const window = bot.currentWindow || bot.inventory
|
|
430
557
|
const promisePutAway = once(window, `updateSlot:${slot}`)
|
|
431
558
|
await clickWindow(slot, 0, 0)
|
|
432
559
|
const start = window.inventoryStart
|
|
433
560
|
const end = window.inventoryEnd
|
|
434
|
-
await putSelectedItemRange(start, end, window, null
|
|
561
|
+
await putSelectedItemRange(start, end, window, null)
|
|
435
562
|
await promisePutAway
|
|
436
563
|
}
|
|
437
564
|
|
|
@@ -448,9 +575,6 @@ function inject (bot, { version, hideErrors }) {
|
|
|
448
575
|
|
|
449
576
|
bot._client.on('transaction', (packet) => {
|
|
450
577
|
// confirm transaction
|
|
451
|
-
if (packet.action < 0) {
|
|
452
|
-
return
|
|
453
|
-
}
|
|
454
578
|
confirmTransaction(packet.windowId, packet.action, packet.accepted)
|
|
455
579
|
})
|
|
456
580
|
|
package/lib/plugins/physics.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
const Vec3 = require('vec3')
|
|
1
|
+
const { Vec3 } = require('vec3')
|
|
2
2
|
const assert = require('assert')
|
|
3
3
|
const math = require('../math')
|
|
4
4
|
const conv = require('../conversions')
|
|
@@ -33,6 +33,7 @@ function inject (bot, { physicsEnabled }) {
|
|
|
33
33
|
sneak: false
|
|
34
34
|
}
|
|
35
35
|
let lastSentYaw = null
|
|
36
|
+
let lastSentPitch = null
|
|
36
37
|
let doPhysicsTimer = null
|
|
37
38
|
let lastPhysicsFrameTime = null
|
|
38
39
|
let shouldUsePhysics = false
|
|
@@ -122,13 +123,16 @@ function inject (bot, { physicsEnabled }) {
|
|
|
122
123
|
|
|
123
124
|
// Increment the yaw in baby steps so that notchian clients (not the server) can keep up.
|
|
124
125
|
const dYaw = deltaYaw(bot.entity.yaw, lastSentYaw)
|
|
126
|
+
const dPitch = bot.entity.pitch - (lastSentPitch || 0)
|
|
125
127
|
|
|
126
128
|
// Vanilla doesn't clamp yaw, so we don't want to do it either
|
|
127
129
|
const maxDeltaYaw = dt * physics.yawSpeed
|
|
130
|
+
const maxDeltaPitch = dt * physics.pitchSpeed
|
|
128
131
|
lastSentYaw += math.clamp(-maxDeltaYaw, dYaw, maxDeltaYaw)
|
|
132
|
+
lastSentPitch += math.clamp(-maxDeltaPitch, dPitch, maxDeltaPitch)
|
|
129
133
|
|
|
130
|
-
const yaw = conv.toNotchianYaw(lastSentYaw)
|
|
131
|
-
const pitch = conv.toNotchianPitch(
|
|
134
|
+
const yaw = Math.fround(conv.toNotchianYaw(lastSentYaw))
|
|
135
|
+
const pitch = Math.fround(conv.toNotchianPitch(lastSentPitch))
|
|
132
136
|
const position = bot.entity.position
|
|
133
137
|
const onGround = bot.entity.onGround
|
|
134
138
|
|
|
@@ -225,8 +229,15 @@ function inject (bot, { physicsEnabled }) {
|
|
|
225
229
|
}
|
|
226
230
|
lookingTask = createTask()
|
|
227
231
|
|
|
228
|
-
|
|
229
|
-
|
|
232
|
+
// this is done to bypass certain anticheat checks that detect the player's sensitivity
|
|
233
|
+
// by calculating the gcd of how much they move the mouse each tick
|
|
234
|
+
const sensitivity = conv.fromNotchianPitch(0.15) // this is equal to 100% sensitivity in vanilla
|
|
235
|
+
const yawChange = Math.round((yaw - bot.entity.yaw) / sensitivity) * sensitivity
|
|
236
|
+
const pitchChange = Math.round((pitch - bot.entity.pitch) / sensitivity) * sensitivity
|
|
237
|
+
|
|
238
|
+
bot.entity.yaw += yawChange
|
|
239
|
+
bot.entity.pitch += pitchChange
|
|
240
|
+
|
|
230
241
|
if (force) {
|
|
231
242
|
lastSentYaw = yaw
|
|
232
243
|
return
|
|
@@ -4,13 +4,14 @@ module.exports = inject
|
|
|
4
4
|
|
|
5
5
|
function inject (bot) {
|
|
6
6
|
async function placeBlockWithOptions (referenceBlock, faceVector, options) {
|
|
7
|
-
|
|
8
|
-
|
|
7
|
+
const dest = referenceBlock.position.plus(faceVector)
|
|
8
|
+
let oldBlock = bot.blockAt(dest)
|
|
9
|
+
await bot._genericPlace(referenceBlock, faceVector, options)
|
|
9
10
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
11
|
+
let newBlock = bot.blockAt(dest)
|
|
12
|
+
if (oldBlock.type === newBlock.type) {
|
|
13
|
+
[oldBlock, newBlock] = await onceWithCleanup(bot, `blockUpdate:${dest}`, { timeout: 5000 })
|
|
14
|
+
}
|
|
14
15
|
|
|
15
16
|
if (oldBlock.type === newBlock.type) {
|
|
16
17
|
throw new Error(`No block has been placed : the block is still ${oldBlock.name}`)
|
package/lib/plugins/ray_trace.js
CHANGED
|
@@ -23,4 +23,14 @@ module.exports = (bot) => {
|
|
|
23
23
|
|
|
24
24
|
return bot.world.raycast(eyePosition, viewDirection, maxDistance, matcher)
|
|
25
25
|
}
|
|
26
|
+
|
|
27
|
+
bot.blockAtEntityCursor = (entity = bot.entity, maxDistance = 256, matcher = null) => {
|
|
28
|
+
if (!entity.position || !entity.height || !entity.pitch || !entity.yaw) return null
|
|
29
|
+
const { position, height, pitch, yaw } = entity
|
|
30
|
+
|
|
31
|
+
const eyePosition = position.offset(0, height, 0)
|
|
32
|
+
const viewDirection = getViewDirection(pitch, yaw)
|
|
33
|
+
|
|
34
|
+
return bot.world.raycast(eyePosition, viewDirection, maxDistance, matcher)
|
|
35
|
+
}
|
|
26
36
|
}
|
|
@@ -91,7 +91,7 @@ function inject (bot) {
|
|
|
91
91
|
item = bot.inventory.findInventoryItem(item)
|
|
92
92
|
}
|
|
93
93
|
if (item == null || typeof item !== 'object') {
|
|
94
|
-
throw new Error('Invalid item object in equip')
|
|
94
|
+
throw new Error('Invalid item object in equip (item is null or typeof item is not object)')
|
|
95
95
|
}
|
|
96
96
|
if (!destination || destination === null) {
|
|
97
97
|
destination = 'hand'
|
package/lib/plugins/sound.js
CHANGED
package/lib/plugins/villager.js
CHANGED
|
@@ -83,6 +83,7 @@ function inject (bot, { version }) {
|
|
|
83
83
|
}
|
|
84
84
|
|
|
85
85
|
villager.trades = null
|
|
86
|
+
villager.selectedTrade = null
|
|
86
87
|
|
|
87
88
|
villager.once('close', () => {
|
|
88
89
|
bot._client.removeListener(tradeListPacket, gotTrades)
|
|
@@ -117,7 +118,6 @@ function inject (bot, { version }) {
|
|
|
117
118
|
if (!ready) {
|
|
118
119
|
ready = true
|
|
119
120
|
villager.emit('ready')
|
|
120
|
-
console.log('emit ready')
|
|
121
121
|
}
|
|
122
122
|
}
|
|
123
123
|
}
|
|
@@ -127,6 +127,7 @@ function inject (bot, { version }) {
|
|
|
127
127
|
assert.notStrictEqual(villager.trades, null)
|
|
128
128
|
assert.notStrictEqual(villager.trades[choice], null)
|
|
129
129
|
const Trade = villager.trades[choice]
|
|
130
|
+
villager.selectedTrade = Trade
|
|
130
131
|
count = count || Trade.maximumNbTradeUses - Trade.nbTradeUses
|
|
131
132
|
assert.ok(Trade.maximumNbTradeUses - Trade.nbTradeUses > 0, 'trade blocked')
|
|
132
133
|
assert.ok(Trade.maximumNbTradeUses - Trade.nbTradeUses >= count)
|
|
@@ -134,8 +135,9 @@ function inject (bot, { version }) {
|
|
|
134
135
|
const itemCount1 = villager.count(Trade.inputItem1.type, Trade.inputItem1.metadata)
|
|
135
136
|
const hasEnoughItem1 = itemCount1 >= Trade.realPrice * count
|
|
136
137
|
let hasEnoughItem2 = true
|
|
138
|
+
let itemCount2 = 0
|
|
137
139
|
if (Trade.hasItem2) {
|
|
138
|
-
|
|
140
|
+
itemCount2 = villager.count(Trade.inputItem2.type, Trade.inputItem2.metadata)
|
|
139
141
|
hasEnoughItem2 = itemCount2 >= Trade.inputItem2.count * count
|
|
140
142
|
}
|
|
141
143
|
if (!hasEnoughItem1 || !hasEnoughItem2) {
|
|
@@ -143,60 +145,73 @@ function inject (bot, { version }) {
|
|
|
143
145
|
}
|
|
144
146
|
|
|
145
147
|
selectTrade(choice)
|
|
146
|
-
|
|
147
148
|
if (bot.supportFeature('selectingTradeMovesItems')) { // 1.14+ the server moves items around by itself after selecting a trade
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
149
|
+
const proms = []
|
|
150
|
+
proms.push(once(villager, 'updateSlot:0'))
|
|
151
|
+
if (Trade.hasItem2) proms.push(once(villager, 'updateSlot:1'))
|
|
152
|
+
if (bot.supportFeature('setSlotAsTransaction')) {
|
|
153
|
+
proms.push(once(villager, 'updateSlot:2'))
|
|
154
|
+
await new Promise((resolve, reject) => {
|
|
155
|
+
let countOfItemOneLeftToTake = itemCount1 > 64 ? 64 : itemCount1
|
|
156
|
+
let countOfItemTwoLeftToTake = 0
|
|
157
|
+
if (Trade.hasItem2) {
|
|
158
|
+
countOfItemTwoLeftToTake = itemCount2 > 64 ? 64 : itemCount2
|
|
156
159
|
}
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
160
|
+
const listener = (slot, oldItem, newItem) => {
|
|
161
|
+
if (!(slot >= villager.inventoryStart && slot <= villager.inventoryEnd)) return
|
|
162
|
+
if (newItem === null) {
|
|
163
|
+
if (oldItem.type === Trade.inputItem1.type) countOfItemOneLeftToTake -= oldItem.count
|
|
164
|
+
else if (Trade.hasItem2 && oldItem.type === Trade.inputItem2.type) countOfItemTwoLeftToTake -= oldItem.count
|
|
165
|
+
}
|
|
166
|
+
if (countOfItemOneLeftToTake === 0 && countOfItemTwoLeftToTake === 0) {
|
|
167
|
+
villager.off('updateSlot', listener)
|
|
168
|
+
resolve()
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
villager.on('updateSlot', listener)
|
|
172
|
+
})
|
|
173
|
+
}
|
|
174
|
+
await Promise.all(proms)
|
|
165
175
|
}
|
|
176
|
+
|
|
166
177
|
for (let i = 0; i < count; i++) {
|
|
167
178
|
await putRequirements(villager, Trade, count)
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
assert.strictEqual(slot1.type, Trade.inputItem1.type)
|
|
173
|
-
const updatedCount1 = slot1.count - Trade.realPrice
|
|
174
|
-
const updatedSlot1 = updatedCount1 <= 0
|
|
175
|
-
? null
|
|
176
|
-
: { ...slot1, count: updatedCount1 }
|
|
177
|
-
villager.updateSlot(0, updatedSlot1)
|
|
179
|
+
// ToDo: See if this does anything kappa
|
|
180
|
+
Trade.nbTradeUses++
|
|
181
|
+
if (Trade.maximumNbTradeUses - Trade.nbTradeUses === 0) {
|
|
182
|
+
Trade.tradeDisabled = true
|
|
178
183
|
}
|
|
184
|
+
if (!bot.supportFeature('setSlotAsTransaction')) {
|
|
185
|
+
villager.updateSlot(2, Object.assign({}, Trade.outputItem))
|
|
186
|
+
|
|
187
|
+
const [slot1, slot2] = villager.slots
|
|
188
|
+
if (slot1) {
|
|
189
|
+
assert.strictEqual(slot1.type, Trade.inputItem1.type)
|
|
190
|
+
const updatedCount1 = slot1.count - Trade.realPrice
|
|
191
|
+
const updatedSlot1 = updatedCount1 <= 0
|
|
192
|
+
? null
|
|
193
|
+
: { ...slot1, count: updatedCount1 }
|
|
194
|
+
villager.updateSlot(0, updatedSlot1)
|
|
195
|
+
}
|
|
179
196
|
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
197
|
+
if (slot2) {
|
|
198
|
+
assert.strictEqual(slot2.type, Trade.inputItem2.type)
|
|
199
|
+
const updatedCount2 = slot2.count - Trade.inputItem2.count
|
|
200
|
+
const updatedSlot2 = updatedCount2 <= 0
|
|
201
|
+
? null
|
|
202
|
+
: { ...slot2, count: updatedCount2 }
|
|
203
|
+
villager.updateSlot(1, updatedSlot2)
|
|
204
|
+
}
|
|
187
205
|
}
|
|
188
|
-
|
|
206
|
+
|
|
207
|
+
await bot.putAway(2)
|
|
189
208
|
}
|
|
190
209
|
|
|
191
210
|
for (const i of [0, 1]) {
|
|
192
211
|
if (villager.slots[i]) {
|
|
193
|
-
await bot.putAway(i
|
|
212
|
+
await bot.putAway(i) // 1.14+ whole stacks of items will automatically be placed , so there might be some left over
|
|
194
213
|
}
|
|
195
214
|
}
|
|
196
|
-
|
|
197
|
-
if (Trade.maximumNbTradeUses - Trade.nbTradeUses === 0) {
|
|
198
|
-
Trade.tradeDisabled = true
|
|
199
|
-
}
|
|
200
215
|
}
|
|
201
216
|
|
|
202
217
|
async function putRequirements (window, Trade, count) {
|
package/lib/version.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
module.exports = {
|
|
2
|
-
supportedVersions: ['1.8', '1.9', '1.10', '1.11', '1.12', '1.13', '1.14', '1.15', '1.16'],
|
|
3
|
-
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']
|
|
4
|
-
}
|
|
2
|
+
supportedVersions: ['1.8', '1.9', '1.10', '1.11', '1.12', '1.13', '1.14', '1.15', '1.16', '1.17'],
|
|
3
|
+
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']
|
|
4
|
+
} // when updating testedVersions, make sure to update CI.yml
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "mineflayer",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.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",
|
|
@@ -21,31 +21,32 @@
|
|
|
21
21
|
},
|
|
22
22
|
"license": "MIT",
|
|
23
23
|
"dependencies": {
|
|
24
|
-
"minecraft-data": "^2.
|
|
25
|
-
"minecraft-protocol": "^1.
|
|
26
|
-
"prismarine-biome": "^1.1.
|
|
27
|
-
"prismarine-block": "^1.
|
|
28
|
-
"prismarine-chat": "^1.
|
|
29
|
-
"prismarine-chunk": "^1.
|
|
30
|
-
"prismarine-entity": "^1.
|
|
31
|
-
"prismarine-item": "^1.
|
|
32
|
-
"prismarine-
|
|
24
|
+
"minecraft-data": "^2.95.0",
|
|
25
|
+
"minecraft-protocol": "^1.26.5",
|
|
26
|
+
"prismarine-biome": "^1.1.1",
|
|
27
|
+
"prismarine-block": "^1.10.3",
|
|
28
|
+
"prismarine-chat": "^1.3.3",
|
|
29
|
+
"prismarine-chunk": "^1.26.0",
|
|
30
|
+
"prismarine-entity": "^1.2.0",
|
|
31
|
+
"prismarine-item": "^1.11.0",
|
|
32
|
+
"prismarine-nbt": "^2.0.0",
|
|
33
|
+
"prismarine-physics": "^1.3.1",
|
|
33
34
|
"prismarine-recipe": "^1.1.0",
|
|
34
|
-
"prismarine-windows": "^2.2
|
|
35
|
+
"prismarine-windows": "^2.4.2",
|
|
35
36
|
"prismarine-world": "^3.6.0",
|
|
36
|
-
"protodef": "^1.
|
|
37
|
-
"typed-emitter": "^1.
|
|
38
|
-
"vec3": "^0.1.
|
|
37
|
+
"protodef": "^1.14.0",
|
|
38
|
+
"typed-emitter": "^1.3.1",
|
|
39
|
+
"vec3": "^0.1.7"
|
|
39
40
|
},
|
|
40
41
|
"devDependencies": {
|
|
41
|
-
"@types/node": "^
|
|
42
|
-
"doctoc": "^2.0.
|
|
43
|
-
"minecraft-wrap": "^1.
|
|
42
|
+
"@types/node": "^17.0.0",
|
|
43
|
+
"doctoc": "^2.0.1",
|
|
44
|
+
"minecraft-wrap": "^1.3.0",
|
|
44
45
|
"mineflayer": "file:.",
|
|
45
|
-
"mocha": "^9.
|
|
46
|
-
"standard": "^16.0.
|
|
47
|
-
"
|
|
48
|
-
"
|
|
49
|
-
"
|
|
46
|
+
"mocha": "^9.1.2",
|
|
47
|
+
"standard": "^16.0.4",
|
|
48
|
+
"standard-markdown": "^7.1.0",
|
|
49
|
+
"ts-standard": "^11.0.0",
|
|
50
|
+
"typescript": "^4.4.3"
|
|
50
51
|
}
|
|
51
52
|
}
|