107 lines
3.1 KiB
JavaScript
107 lines
3.1 KiB
JavaScript
const assert = require('assert')
|
|
module.exports = inject
|
|
|
|
function inject (bot) {
|
|
const Item = require('prismarine-item')(bot.registry)
|
|
/**
|
|
*
|
|
* @param {import('prismarine-block').Block} referenceBlock
|
|
* @param {import('vec3').Vec3} faceVector
|
|
* @param {{half?: 'top'|'bottom', delta?: import('vec3').Vec3, forceLook?: boolean | 'ignore', offhand?: boolean, swingArm?: 'right' | 'left', showHand?: boolean}} options
|
|
*/
|
|
async function _genericPlace (referenceBlock, faceVector, options) {
|
|
let handToPlaceWith = 0
|
|
if (options.offhand) {
|
|
if (!bot.inventory.slots[45]) {
|
|
throw new Error('must be holding an item in the off-hand to place')
|
|
}
|
|
handToPlaceWith = 1
|
|
} else if (!bot.heldItem) {
|
|
throw new Error('must be holding an item to place')
|
|
}
|
|
|
|
// Look at the center of the face
|
|
let dx = 0.5 + faceVector.x * 0.5
|
|
let dy = 0.5 + faceVector.y * 0.5
|
|
let dz = 0.5 + faceVector.z * 0.5
|
|
if (dy === 0.5) {
|
|
if (options.half === 'top') dy += 0.25
|
|
else if (options.half === 'bottom') dy -= 0.25
|
|
}
|
|
if (options.delta) {
|
|
dx = options.delta.x
|
|
dy = options.delta.y
|
|
dz = options.delta.z
|
|
}
|
|
if (options.forceLook !== 'ignore') {
|
|
await bot.lookAt(referenceBlock.position.offset(dx, dy, dz), options.forceLook)
|
|
}
|
|
// TODO: tell the server that we are sneaking while doing this
|
|
const pos = referenceBlock.position
|
|
|
|
if (options.swingArm) {
|
|
bot.swingArm(options.swingArm, options.showHand)
|
|
}
|
|
|
|
if (bot.supportFeature('blockPlaceHasHeldItem')) {
|
|
const packet = {
|
|
location: pos,
|
|
direction: vectorToDirection(faceVector),
|
|
heldItem: Item.toNotch(bot.heldItem),
|
|
cursorX: Math.floor(dx * 16),
|
|
cursorY: Math.floor(dy * 16),
|
|
cursorZ: Math.floor(dz * 16)
|
|
}
|
|
bot._client.write('block_place', packet)
|
|
} else if (bot.supportFeature('blockPlaceHasHandAndIntCursor')) {
|
|
bot._client.write('block_place', {
|
|
location: pos,
|
|
direction: vectorToDirection(faceVector),
|
|
hand: handToPlaceWith,
|
|
cursorX: Math.floor(dx * 16),
|
|
cursorY: Math.floor(dy * 16),
|
|
cursorZ: Math.floor(dz * 16)
|
|
})
|
|
} else if (bot.supportFeature('blockPlaceHasHandAndFloatCursor')) {
|
|
bot._client.write('block_place', {
|
|
location: pos,
|
|
direction: vectorToDirection(faceVector),
|
|
hand: handToPlaceWith,
|
|
cursorX: dx,
|
|
cursorY: dy,
|
|
cursorZ: dz
|
|
})
|
|
} else if (bot.supportFeature('blockPlaceHasInsideBlock')) {
|
|
bot._client.write('block_place', {
|
|
location: pos,
|
|
direction: vectorToDirection(faceVector),
|
|
hand: handToPlaceWith,
|
|
cursorX: dx,
|
|
cursorY: dy,
|
|
cursorZ: dz,
|
|
insideBlock: false
|
|
})
|
|
}
|
|
|
|
return pos
|
|
}
|
|
bot._genericPlace = _genericPlace
|
|
}
|
|
|
|
function vectorToDirection (v) {
|
|
if (v.y < 0) {
|
|
return 0
|
|
} else if (v.y > 0) {
|
|
return 1
|
|
} else if (v.z < 0) {
|
|
return 2
|
|
} else if (v.z > 0) {
|
|
return 3
|
|
} else if (v.x < 0) {
|
|
return 4
|
|
} else if (v.x > 0) {
|
|
return 5
|
|
}
|
|
assert.ok(false, `invalid direction vector ${v}`)
|
|
}
|