Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PrismarineJS
GitHub Repository: PrismarineJS/mineflayer
Path: blob/master/lib/plugins/place_entity.js
1467 views
1
const assert = require('assert')
2
3
module.exports = inject
4
5
function inject (bot) {
6
const Item = require('prismarine-item')(bot.registry)
7
8
/**
9
*
10
* @param {import('prismarine-block').Block} referenceBlock
11
* @param {import('vec3').Vec3} faceVector
12
* @param {{forceLook?: boolean | 'ignore', offhand?: boolean, swingArm?: 'right' | 'left', showHand?: boolean}} options
13
*/
14
async function placeEntityWithOptions (referenceBlock, faceVector, options) {
15
if (!bot.heldItem) throw new Error('must be holding an item to place an entity')
16
17
const type = bot.heldItem.name // used for assert
18
.replace(/.+_boat/, 'boat')
19
.replace(/.+_spawn_egg/, 'spawn_egg')
20
assert(['end_crystal', 'boat', 'spawn_egg', 'armor_stand'].includes(type), 'Unimplemented')
21
22
let name = bot.heldItem.name // used for finding entity after spawn
23
.replace(/.+_boat/, 'boat')
24
25
if (name.endsWith('spawn_egg')) {
26
name = bot.heldItem.spawnEggMobName
27
}
28
29
if (type === 'spawn_egg') {
30
options.showHand = false
31
}
32
33
if (!options.swingArm) options.swingArm = options.offhand ? 'left' : 'right'
34
35
const pos = await bot._genericPlace(referenceBlock, faceVector, options)
36
37
if (type === 'boat') {
38
if (bot.supportFeature('useItemWithOwnPacket')) {
39
bot._client.write('use_item', {
40
hand: options.offhand ? 1 : 0
41
})
42
} else {
43
bot._client.write('block_place', {
44
location: { x: -1, y: -1, z: -1 },
45
direction: -1,
46
heldItem: Item.toNotch(bot.heldItem),
47
cursorX: 0,
48
cursorY: 0,
49
cursorZ: 0
50
})
51
}
52
}
53
54
const dest = pos.plus(faceVector)
55
const entity = await waitForEntitySpawn(name, dest)
56
bot.emit('entityPlaced', entity)
57
return entity
58
}
59
60
async function placeEntity (referenceBlock, faceVector) {
61
return await placeEntityWithOptions(referenceBlock, faceVector, {})
62
}
63
64
function waitForEntitySpawn (name, placePosition) {
65
const maxDistance = name === 'bat' ? 4 : name === 'boat' ? 3 : 2
66
let mobName = name
67
if (name === 'end_crystal') {
68
if (bot.supportFeature('enderCrystalNameEndsInErNoCaps')) {
69
mobName = 'ender_crystal'
70
} else if (bot.supportFeature('entityNameLowerCaseNoUnderscore')) {
71
mobName = 'endercrystal'
72
} else if (bot.supportFeature('enderCrystalNameNoCapsWithUnderscore')) {
73
mobName = 'end_crystal'
74
} else {
75
mobName = 'EnderCrystal'
76
}
77
} else if (name === 'boat') {
78
mobName = bot.supportFeature('entityNameUpperCaseNoUnderscore') ? 'Boat' : 'boat'
79
} else if (name === 'armor_stand') {
80
if (bot.supportFeature('entityNameUpperCaseNoUnderscore')) {
81
mobName = 'ArmorStand'
82
} else if (bot.supportFeature('entityNameLowerCaseNoUnderscore')) {
83
mobName = 'armorstand'
84
} else {
85
mobName = 'armor_stand'
86
}
87
}
88
89
return new Promise((resolve, reject) => {
90
function listener (entity) {
91
const dist = entity.position.distanceTo(placePosition)
92
if (entity.name === mobName && dist < maxDistance) {
93
resolve(entity)
94
}
95
bot.off('entitySpawn', listener)
96
}
97
98
setTimeout(() => {
99
bot.off('entitySpawn', listener)
100
reject(new Error('Failed to place entity'))
101
}, 5000) // reject after 5s
102
103
bot.on('entitySpawn', listener)
104
})
105
}
106
107
bot.placeEntity = placeEntity
108
bot._placeEntityWithOptions = placeEntityWithOptions
109
}
110
111