diff --git a/lib/plugins/digging.js b/lib/plugins/digging.js index 1c6bf3b4e..ea2763b05 100644 --- a/lib/plugins/digging.js +++ b/lib/plugins/digging.js @@ -12,29 +12,29 @@ function inject (bot) { let diggingTask = createDoneTask() bot.targetDigBlock = null + bot.targetDigFace = null bot.lastDigTime = null async function dig (block, forceLook, digFace) { if (block === null || block === undefined) { throw new Error('dig was called with an undefined or null block') } + if (!digFace || typeof digFace === 'function') { digFace = 'auto' } - if (bot.targetDigBlock) bot.stopDigging() - - let diggingFace = 1 // Default (top) + bot.targetDigFace = 1 // Default (top) if (forceLook !== 'ignore') { if (digFace?.x || digFace?.y || digFace?.z) { // Determine the block face the bot should mine if (digFace.x) { - diggingFace = digFace.x > 0 ? BlockFaces.EAST : BlockFaces.WEST + bot.targetDigFace = digFace.x > 0 ? BlockFaces.EAST : BlockFaces.WEST } else if (digFace.y) { - diggingFace = digFace.y > 0 ? BlockFaces.TOP : BlockFaces.BOTTOM + bot.targetDigFace = digFace.y > 0 ? BlockFaces.TOP : BlockFaces.BOTTOM } else if (digFace.z) { - diggingFace = digFace.z > 0 ? BlockFaces.SOUTH : BlockFaces.NORTH + bot.targetDigFace = digFace.z > 0 ? BlockFaces.SOUTH : BlockFaces.NORTH } await bot.lookAt( block.position.offset(0.5, 0.5, 0.5).offset(digFace.x * 0.5, digFace.y * 0.5, digFace.z * 0.5), @@ -76,8 +76,8 @@ function inject (bot) { const rayPos = rayBlock.position if ( rayPos.x === block.position.x && - rayPos.y === block.position.y && - rayPos.z === block.position.z + rayPos.y === block.position.y && + rayPos.z === block.position.z ) { validFaces.push({ face: rayBlock.face, @@ -86,6 +86,7 @@ function inject (bot) { } } } + if (validFaces.length > 0) { // Chose closest valid face let closest @@ -101,11 +102,11 @@ function inject (bot) { } } await bot.lookAt(closest.targetPos, forceLook) - diggingFace = closest.face + bot.targetDigFace = closest.face } else if (closerBlocks.length === 0 && block.shapes.length === 0) { // no other blocks were detected and the block has no shapes. // The block in question is replaceable (like tall grass) so we can just dig it - // TODO: do AABB + ray intercept check to this position for diggingFace. + // TODO: do AABB + ray intercept check to this position for digFace. await bot.lookAt(block.position.offset(0.5, 0.5, 0.5), forceLook) } else { // Block is obstructed return error? @@ -116,11 +117,15 @@ function inject (bot) { } } + // In vanilla the client will cancel digging the current block once the other block is at the crosshair. + // Todo: don't wait until lookAt is at middle of the block, but at the edge of it. + if (bot.targetDigBlock) bot.stopDigging() + diggingTask = createTask() bot._client.write('block_dig', { status: 0, // start digging location: block.position, - face: diggingFace // default face is 1 (top) + face: bot.targetDigFace // default face is 1 (top) }) const waitTime = bot.digTime(block) waitTimeout = setTimeout(finishDigging, waitTime) @@ -140,10 +145,11 @@ function inject (bot) { bot._client.write('block_dig', { status: 2, // finish digging location: bot.targetDigBlock.position, - face: diggingFace // hard coded to always dig from the top + face: bot.targetDigFace // always the same as the start face }) } bot.targetDigBlock = null + bot.targetDigFace = null bot.lastDigTime = performance.now() bot._updateBlockState(block.position, 0) } @@ -151,8 +157,15 @@ function inject (bot) { const eventName = `blockUpdate:${block.position}` bot.on(eventName, onBlockUpdate) + const currentBlock = block bot.stopDigging = () => { if (!bot.targetDigBlock) return + + // Replicate the odd vanilla cancellation face value. + // When the cancellation is because of a new dig request on another block it's the same as the new dig start face. In all other cases it's 0. + const stoppedBecauseOfNewDigRequest = !currentBlock.position.equals(bot.targetDigBlock.position) + const cancellationDiggingFace = !stoppedBecauseOfNewDigRequest ? bot.targetDigFace : 0 + bot.removeListener(eventName, onBlockUpdate) clearInterval(swingInterval) clearTimeout(waitTimeout) @@ -161,10 +174,11 @@ function inject (bot) { bot._client.write('block_dig', { status: 1, // cancel digging location: bot.targetDigBlock.position, - face: 1 // hard coded to always dig from the top + face: cancellationDiggingFace }) const block = bot.targetDigBlock bot.targetDigBlock = null + bot.targetDigFace = null bot.lastDigTime = performance.now() bot.emit('diggingAborted', block) bot.stopDigging = noop @@ -182,6 +196,7 @@ function inject (bot) { swingInterval = null waitTimeout = null bot.targetDigBlock = null + bot.targetDigFace = null bot.lastDigTime = performance.now() bot.emit('diggingCompleted', newBlock) diggingTask.finish() @@ -199,8 +214,8 @@ function inject (bot) { function canDigBlock (block) { return ( block && - block.diggable && - block.position.offset(0.5, 0.5, 0.5).distanceTo(bot.entity.position.offset(0, 1.65, 0)) <= 5.1 + block.diggable && + block.position.offset(0.5, 0.5, 0.5).distanceTo(bot.entity.position.offset(0, 1.65, 0)) <= 5.1 ) }