diff --git a/src/agent/library/skills.js b/src/agent/library/skills.js index bbe8acf..9d62ef1 100644 --- a/src/agent/library/skills.js +++ b/src/agent/library/skills.js @@ -4,7 +4,7 @@ import pf from 'mineflayer-pathfinder'; import Vec3 from 'vec3'; import settings from "../../../settings.js"; -const blockPlaceDelay = settings.block_place_delay || 10; +const blockPlaceDelay = settings.block_place_delay == null ? 0 : settings.block_place_delay; const useDelay = blockPlaceDelay > 0; export function log(bot, message) { @@ -506,7 +506,7 @@ export async function pickupNearbyItems(bot) { let pickedUp = 0; while (nearestItem) { bot.pathfinder.setMovements(new pf.Movements(bot)); - await bot.pathfinder.goto(new pf.goals.GoalFollow(nearestItem, 0.8), true); + await goToGoal(bot, new pf.goals.GoalFollow(nearestItem, 0.8)); await new Promise(resolve => setTimeout(resolve, 200)); let prev = nearestItem; nearestItem = getNearestItem(bot); @@ -549,7 +549,7 @@ export async function breakBlockAt(bot, x, y, z) { movements.canPlaceOn = false; movements.allow1by1towers = false; bot.pathfinder.setMovements(movements); - await bot.pathfinder.goto(new pf.goals.GoalNear(pos.x, pos.y, pos.z, 4)); + await goToGoal(bot, new pf.goals.GoalNear(pos.x, pos.y, pos.z, 4)); } if (bot.game.gameMode !== 'creative') { await bot.tool.equipForBlock(block); @@ -727,7 +727,7 @@ export async function placeBlock(bot, blockType, x, y, z, placeOn='bottom', dont let pos = targetBlock.position; let movements = new pf.Movements(bot); bot.pathfinder.setMovements(movements); - await bot.pathfinder.goto(new pf.goals.GoalNear(pos.x, pos.y, pos.z, 4)); + await goToGoal(bot, new pf.goals.GoalNear(pos.x, pos.y, pos.z, 4)); } await bot.equip(block, 'hand'); @@ -952,6 +952,10 @@ export async function giveToPlayer(bot, itemType, username, num=1) { * @example * await skills.giveToPlayer(bot, "oak_log", "player1"); **/ + if (bot.username === username) { + log(bot, `You cannot give items to yourself.`); + return false; + } let player = bot.players[username].entity if (!player) { log(bot, `Could not find ${username}.`); @@ -1011,7 +1015,7 @@ export async function giveToPlayer(bot, itemType, username, num=1) { export async function goToGoal(bot, goal) { /** - * Navigate to the given goal, attempting minimally destructive movements. + * Navigate to the given goal. Use doors and attempt minimally destructive movements. * @param {MinecraftBot} bot, reference to the minecraft bot. * @param {pf.goals.Goal} goal, the goal to navigate to. **/ @@ -1025,30 +1029,18 @@ export async function goToGoal(bot, goal) { const destructiveMovements = new pf.Movements(bot); - let final_movements = null; - let movements = [ - {name: 'nonDestructive', movements: nonDestructiveMovements}, - {name: 'destructive', movements: destructiveMovements} - ]; + let final_movements = destructiveMovements; const pathfind_timeout = 1000; - try { - for (let i = 0; i < movements.length; i++) { - const movement = movements[i].movements; - const path = await bot.pathfinder.getPathTo(movement, goal, pathfind_timeout); - if (path && path.path && path.path.length > 0 && path.status !== 'noPath') { - final_movements = movement; - log(bot, `Using ${movements[i].name} movements.`); - break; - } - } - if (!final_movements) { - log(bot, `Could not find a path to ${username}.`); - return false; - } - } catch (err) { - log(bot, `Could not find a path: ${err.message}.`); - return false; + if (await bot.pathfinder.getPathTo(nonDestructiveMovements, goal, pathfind_timeout).status === 'success') { + final_movements = nonDestructiveMovements; + log(bot, `Found non-destructive path.`); + } + else if (await bot.pathfinder.getPathTo(destructiveMovements, goal, pathfind_timeout).status === 'success') { + log(bot, `Found destructive path.`); + } + else { + log(bot, `Could not find a path to goal, attempting to navigate anyway using destructive movements.`); } const doorCheckInterval = startDoorInterval(bot); @@ -1059,9 +1051,9 @@ export async function goToGoal(bot, goal) { clearInterval(doorCheckInterval); return true; } catch (err) { - log(bot, `Could not find a path: ${err.message}.`); clearInterval(doorCheckInterval); - return false; + // we need to catch so we can clean up the door check interval, then rethrow the error + throw err; } } @@ -1168,9 +1160,16 @@ export async function goToPosition(bot, x, y, z, min_distance=2) { try { await goToGoal(bot, new pf.goals.GoalNear(x, y, z, min_distance)); - log(bot, `You have reached at ${x}, ${y}, ${z}.`); clearInterval(progressInterval); - return true; + const distance = bot.entity.position.distanceTo(new Vec3(x, y, z)); + if (distance <= min_distance+1) { + log(bot, `You have reached at ${x}, ${y}, ${z}.`); + return true; + } + else { + log(bot, `Unable to reach ${x}, ${y}, ${z}, you are ${Math.round(distance)} blocks away.`); + return false; + } } catch (err) { log(bot, `Pathfinding stopped: ${err.message}.`); clearInterval(progressInterval); @@ -1235,7 +1234,10 @@ export async function goToPlayer(bot, username, distance=3) { * @example * await skills.goToPlayer(bot, "player"); **/ - + if (bot.username === username) { + log(bot, `You are already at ${username}.`); + return true; + } if (bot.modes.isOn('cheat')) { bot.chat('/tp @s ' + username); log(bot, `Teleported to ${username}.`); @@ -1287,7 +1289,7 @@ export async function followPlayer(bot, username, distance=4) { if (bot.modes.isOn('cheat') && bot.entity.position.distanceTo(player.position) > 100 && player.isOnGround) { await goToPlayer(bot, username); } - const is_nearby = bot.entity.position.distanceTo(player.position) <= distance + 1; + const is_nearby = bot.entity.position.distanceTo(player.position) <= distance + 2; if (is_nearby) { clearInterval(doorCheckInterval); doorCheckInterval = null; @@ -1334,7 +1336,7 @@ export async function moveAway(bot, distance) { } } - await bot.pathfinder.goto(inverted_goal); + await goToGoal(bot, inverted_goal); let new_pos = bot.entity.position; log(bot, `Moved away from nearest entity to ${new_pos}.`); return true; @@ -1528,7 +1530,7 @@ export async function tillAndSow(bot, x, y, z, seedType=null) { if (bot.entity.position.distanceTo(block.position) > 4.5) { let pos = block.position; bot.pathfinder.setMovements(new pf.Movements(bot)); - await bot.pathfinder.goto(new pf.goals.GoalNear(pos.x, pos.y, pos.z, 4)); + await goToGoal(bot, new pf.goals.GoalNear(pos.x, pos.y, pos.z, 4)); } if (block.name !== 'farmland') { let hoe = bot.inventory.items().find(item => item.name.includes('hoe')); @@ -1574,7 +1576,7 @@ export async function activateNearestBlock(bot, type) { if (bot.entity.position.distanceTo(block.position) > 4.5) { let pos = block.position; bot.pathfinder.setMovements(new pf.Movements(bot)); - await bot.pathfinder.goto(new pf.goals.GoalNear(pos.x, pos.y, pos.z, 4)); + await goToGoal(bot, new pf.goals.GoalNear(pos.x, pos.y, pos.z, 4)); } await bot.activateBlock(block); log(bot, `Activated ${type} at x:${block.position.x.toFixed(1)}, y:${block.position.y.toFixed(1)}, z:${block.position.z.toFixed(1)}.`); diff --git a/src/agent/library/world.js b/src/agent/library/world.js index 0253b41..ae97d2d 100644 --- a/src/agent/library/world.js +++ b/src/agent/library/world.js @@ -354,6 +354,7 @@ export async function isClearPath(bot, target) { let movements = new pf.Movements(bot) movements.canDig = false; movements.canPlaceOn = false; + movements.canOpenDoors = false; let goal = new pf.goals.GoalNear(target.position.x, target.position.y, target.position.z, 1); let path = await bot.pathfinder.getPathTo(movements, goal, 100); return path.status === 'success';