Closed LQR471814 closed 3 years ago
Expected behavior, not ideal but blockAtCursor only returns solid blocks
alright, rip
If anyone is looking for a workaround to this, here's my re-implementation of the logic of blockAtCursor
with a bit of math and the bot.blockAt
method.
//? typescript by the way, you can just remove the special syntax for vanilla JS though
const raytrace = (bot: Bot, filter: string, radius: number, steps: number) => {
const positionInDirection = (position: Vec3, distance: number, yaw: number) => { //? Position should be in format (x, z)
return new Vec3(
position.x - Math.sin(yaw) * distance,
position.y,
position.z - Math.cos(yaw) * distance,
)
}
const position = bot.entity.position.offset(0, bot.entity.height, 0)
const blocks = []
let lastBlock = {
position: new Vec3(NaN, NaN, NaN)
}
for (let r = 0; r < radius; r += radius / steps) {
const block = bot.blockAt(positionInDirection(
position, r,
bot.entity.yaw
))
if (
block &&
block.name === filter &&
!block.position.equals(lastBlock.position)
) {
blocks.push(block)
lastBlock = block
}
}
return blocks
}
One thing to keep in mind is that the function returns an array of blocks, it doesn't stop at the first one found. The array goes from closest first, furthest last.
The parameter filter
is used to filter for blocks of a specific name (like oak_wood
or anything on the Block.name
property)
Parameter radius
is the distance that you want the bot to raytrace to.
Parameter steps
is the amount of times you want the bot to poll through the line. You can imagine a series of dots in a line coming out of the bot's head towards the direction it's looking at. If a block is intersecting one of these dots, it will be picked up. Increasing steps
will consume more compute power but will pick up blocks that aren't "solid" (they don't occupy the full space of the block, like sugarcane or a fence) more easily.
If anyone is looking for a workaround to this, here's my re-implementation of the logic of
blockAtCursor
with a bit of math and thebot.blockAt
method.//? typescript by the way, you can just remove the special syntax for vanilla JS though const raytrace = (bot: Bot, filter: string, radius: number, steps: number) => { const positionInDirection = (position: Vec3, distance: number, yaw: number) => { //? Position should be in format (x, z) return new Vec3( position.x - Math.sin(yaw) * distance, position.y, position.z - Math.cos(yaw) * distance, ) } const position = bot.entity.position.offset(0, bot.entity.height, 0) const blocks = [] let lastBlock = { position: new Vec3(NaN, NaN, NaN) } for (let r = 0; r < radius; r += radius / steps) { const block = bot.blockAt(positionInDirection( position, r, bot.entity.yaw )) if ( block && block.name === filter && !block.position.equals(lastBlock.position) ) { blocks.push(block) lastBlock = block } } return blocks }
One thing to keep in mind is that the function returns an array of blocks, it doesn't stop at the first one found. The array goes from closest first, furthest last.
The parameter
filter
is used to filter for blocks of a specific name (likeoak_wood
or anything on theBlock.name
property) Parameterradius
is the distance that you want the bot to raytrace to. Parametersteps
is the amount of times you want the bot to poll through the line. You can imagine a series of dots in a line coming out of the bot's head towards the direction it's looking at. If a block is intersecting one of these dots, it will be picked up. Increasingsteps
will consume more compute power but will pick up blocks that aren't "solid" (they don't occupy the full space of the block, like sugarcane or a fence) more easily.
How would I implement this? I'm trying to make my bot basically hold left click while moving right, but blockAtCursor doesn't work with nether wart.
async function dig() {
if (bot.blockAtCursor().name !== 'air' && bot.blockAtCursor().name !== null) await bot.dig(bot.blockAtCursor(), false);
dig()
}
setTimeout(async () => {
bot.chat('/play sb')
}, 3000);
setTimeout(async () => {
bot.chat('/is')
}, 4000);
setTimeout(async () => {
dig();
}, 5000);
Versions
Detailed description of a problem
I am building a bot that farms sugarcane in rows 2 blocks wide.
What did you try yet?
The way you would usually operate this kind of farm is by holding down "a" and "forward" and hold left click while looking diagonally to get all the sugarcane.
While it is possible to poll the bot many times per second checking for a sugarcane block in front of the block and having the bot dig the block and the block adjacent to it, this is highly inefficient since the
dig
function has to move the camera very frequently screwing with momentum and all those things.To try an replicate the behavior of regular farming, I wanted to use the
blockAtCursor
method however it returned null when I aimed at the sugarcane. When I aiming at a different angle towards a wall beyond the sugarcane it returned the block of the wall rather than the sugarcane right in front of it. This occurs no matter where the bot is in relation to the sugarcane, inside, outside, in front of it etc...Your current code
Expected behavior
blockAtCursor
should return the sugarcane block in which I can calldig
on.Additional context
I can vouch that the sugarcane does exist, I can find it with
findBlock
and I can also mine it.