148 lines
4.7 KiB
JavaScript
148 lines
4.7 KiB
JavaScript
/* Pathfinder Chaining Goals example
|
|
|
|
This example shows how to chain goals together.
|
|
Run this example with:
|
|
|
|
node examples/chaining-goals.js [host] [port] [mail/username] [is online `true`]
|
|
|
|
If you want to connect to an offline server use a username instead of an email
|
|
and no password. If you want to join a online server use your email and follow
|
|
the instructions in the command line to authenticated with microsoft auth.
|
|
|
|
In Game Chat commands:
|
|
come
|
|
- Path finds to the chatting player's position when in render distance.
|
|
|
|
follow
|
|
- Follows the chatting player's entity until `stop` is chatted
|
|
|
|
stop
|
|
- Stops the bot from following or path finding
|
|
|
|
point
|
|
- Set a checkpoint at the chatting player's position
|
|
|
|
walk
|
|
- Walk to all set checkpoints
|
|
*/
|
|
|
|
// Import all the modules we need
|
|
const mineflayer = require('mineflayer')
|
|
const { pathfinder, Movements } = require('mineflayer-pathfinder')
|
|
const {
|
|
GoalNear, GoalBlock, GoalFollow
|
|
} = require('mineflayer-pathfinder').goals
|
|
|
|
if (process.argv.length > 6) {
|
|
console.log('Usage : node chaining-goals.js [<host>] [<port>] ' +
|
|
'[<microsoft email/name>] [<is online `true`>]')
|
|
process.exit(1)
|
|
}
|
|
|
|
// Create the bot
|
|
const bot = mineflayer.createBot({
|
|
host: process.argv[2] || 'localhost',
|
|
port: parseInt(process.argv[3]) || 25565,
|
|
username: process.argv[4] || 'checkpointBot',
|
|
// to join offline servers auth type has to be 'mojang' (???)
|
|
auth: process.argv[5] === 'true' ? 'microsoft' : 'mojang',
|
|
// Skip validation when joining a offline server
|
|
skipValidation: process.argv[5] !== 'true'
|
|
})
|
|
|
|
// Load the pathfinder plugin
|
|
bot.loadPlugin(pathfinder)
|
|
|
|
// Wait for the bot to spawn in the world
|
|
bot.once('spawn', () => {
|
|
// We create different movement generators for different type of activity
|
|
const defaultMove = new Movements(bot)
|
|
bot.pathfinder.setMovements(defaultMove)
|
|
|
|
// Print debug messages when the path changes
|
|
bot.on('path_update', (r) => {
|
|
const nodesPerTick = (r.visitedNodes * 50 / r.time).toFixed(2)
|
|
console.log(`I can get there in ${r.path.length} moves. ` +
|
|
`Computation took ${r.time.toFixed(2)} ms (${r.visitedNodes} nodes` +
|
|
`, ${nodesPerTick} nodes/tick)`)
|
|
})
|
|
|
|
bot.on('goal_reached', (goal) => {
|
|
console.log('Here I am !')
|
|
})
|
|
|
|
bot.on('path_reset', (reason) => {
|
|
console.log(`Path was reset for reason: ${reason}`)
|
|
})
|
|
|
|
let checkpoints = []
|
|
|
|
// Make pathfinder walk to all checkpoints in order
|
|
async function walkCheckpoints () {
|
|
if (checkpoints.length === 0) {
|
|
bot.chat('There are no checkpoints')
|
|
return
|
|
}
|
|
|
|
// Remove all checkpoints when starting to walking
|
|
const checkPointCopy = [...checkpoints]
|
|
checkpoints = []
|
|
for (const checkpoint of checkPointCopy) {
|
|
// Make a new goal to goto. GoalBlock will make the bot walk to the
|
|
// block position off checkpoint.
|
|
const goal = new GoalBlock(checkpoint.x, checkpoint.y, checkpoint.z)
|
|
try {
|
|
// Use await to make sure the bot is at the checkpoint before moving on
|
|
await bot.pathfinder.goto(goal)
|
|
} catch (error) {
|
|
console.log('Got error from goto', error.message)
|
|
// If we get an error we quit the loop
|
|
return
|
|
}
|
|
}
|
|
}
|
|
|
|
// Listen for chat messages chatted by other players
|
|
// Note: This may not work on every server as mineflayer uses regex to match
|
|
// chat messages. Some servers may use chat messages that do not match the
|
|
// regex.
|
|
bot.on('chat', (username, message) => {
|
|
if (username === bot.username) return // Ignore our own messages
|
|
|
|
// Get the player entity from the username.
|
|
// Note: This might not work on some servers where the players nametag name
|
|
// dose not match the chat message name.
|
|
const target = bot.players[username] ? bot.players[username].entity : null
|
|
if (message === 'come') {
|
|
if (!target) {
|
|
bot.chat('I don\'t see you !')
|
|
return
|
|
}
|
|
const p = target.position
|
|
|
|
bot.pathfinder.setGoal(new GoalNear(p.x, p.y, p.z, 1))
|
|
} else if (message === 'follow') {
|
|
bot.pathfinder.setGoal(new GoalFollow(target, 3), true)
|
|
// follow is a dynamic goal: setGoal(goal, dynamic=true)
|
|
// when reached, the goal will stay active and will not
|
|
// emit an event
|
|
} else if (message === 'stop') {
|
|
bot.pathfinder.stop() // Also resets the current goal
|
|
} else if (message === 'point') {
|
|
if (!target) {
|
|
bot.chat('I don\'t see you !')
|
|
return
|
|
}
|
|
const pos = target.position.floored()
|
|
checkpoints.push(pos)
|
|
bot.chat(`Checkpoint ${pos} set`)
|
|
} else if (message === 'walk') {
|
|
walkCheckpoints()
|
|
.then(() => {
|
|
bot.chat('Done')
|
|
})
|
|
.catch(console.error)
|
|
}
|
|
})
|
|
})
|