Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion lib/plugins/ray_trace.js
Original file line number Diff line number Diff line change
Expand Up @@ -55,8 +55,11 @@ module.exports = (bot) => {
}

bot.blockAtEntityCursor = (entity = bot.entity, maxDistance = 256, matcher = null) => {
if (!entity.position || !entity.height || !entity.pitch || !entity.yaw) return null
if (!entity.position) return null
const { position, height, pitch, yaw } = entity
// Number.isFinite (rather than truthiness) so a legitimate 0 yaw or pitch
// is not mistaken for a missing value. See issue #3935.
if (!Number.isFinite(height) || !Number.isFinite(pitch) || !Number.isFinite(yaw)) return null

const eyePosition = position.offset(0, height, 0)
const viewDirection = getViewDirection(pitch, yaw)
Expand Down
30 changes: 30 additions & 0 deletions test/externalTests/rayTrace.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,34 @@ module.exports = () => async (bot) => {
block = bot.blockInSight()
assert.deepStrictEqual(block.position, relBlock.position)
assert.deepStrictEqual(block.face, relBlock.face)

// Regression for #3935: a yaw or pitch of exactly 0 is a valid orientation
// and must not be rejected by the validation in blockAtEntityCursor.
// yaw=0, pitch=0 looks straight ahead along -Z. Build a small stone wall a
// couple of blocks ahead at eye level (3 wide, to stay robust to the bot's
// exact sub-block position), clear the path in front of it, then assert the
// ray trace finds the wall instead of returning null.
const pos = bot.entity.position
const bx = Math.floor(pos.x)
const bz = Math.floor(pos.z)
const eyeY = Math.floor(pos.y + bot.entity.height)
// clear the eye-level path in front of the bot (2 deep, 3 wide)
for (const dz of [0, -1]) {
for (const dx of [-1, 0, 1]) {
await bot.test.setBlock({ x: bx + dx, y: eyeY, z: bz + dz, blockName: 'air' })
}
}
// stone wall 2 blocks ahead
for (const dx of [-1, 0, 1]) {
await bot.test.setBlock({ x: bx + dx, y: eyeY, z: bz - 2, blockName: 'stone' })
}
bot.entity.yaw = 0
bot.entity.pitch = 0
const zeroBlock = bot.blockAtEntityCursor(bot.entity, 16)
assert.ok(zeroBlock, 'blockAtEntityCursor returned null for zero yaw/pitch (#3935)')
assert.strictEqual(zeroBlock.name, 'stone')
// tidy up the wall
for (const dx of [-1, 0, 1]) {
await bot.test.setBlock({ x: bx + dx, y: eyeY, z: bz - 2, blockName: 'air' })
}
}
Loading