115 lines
4.1 KiB
JavaScript
115 lines
4.1 KiB
JavaScript
|
// Load your dependency plugins.
|
||
|
|
||
|
const {pathfinder} = require('mineflayer-pathfinder')
|
||
|
// bot.loadPlugin(require('prismarine-viewer').mineflayer)
|
||
|
// const mineflayerViewer = require('prismarine-viewer').mineflayer
|
||
|
|
||
|
// Import required behaviors.
|
||
|
const {
|
||
|
StateTransition,
|
||
|
BotStateMachine,
|
||
|
EntityFilters,
|
||
|
BehaviorFollowEntity,
|
||
|
BehaviorLookAtEntity,
|
||
|
BehaviorGetClosestEntity,
|
||
|
NestedStateMachine,
|
||
|
BehaviorIdle,
|
||
|
StateMachineWebserver,
|
||
|
} = require("mineflayer-statemachine");
|
||
|
|
||
|
// TODO chat
|
||
|
|
||
|
|
||
|
|
||
|
// wait for our bot to login.
|
||
|
function statemachineInit() {
|
||
|
cfg.botAddress = new RegExp(`^${bot.username} (!.+)`)
|
||
|
// This targets object is used to pass data between different states. It can be left empty.
|
||
|
const targets = new Object();
|
||
|
|
||
|
// Create our states
|
||
|
const getClosestPlayer = new BehaviorGetClosestEntity(
|
||
|
bot, targets, entity => EntityFilters().PlayersOnly(entity) && bot.entity.position.distanceTo(entity.position) <= 50 ); // && a.username !== bot.username);
|
||
|
const followPlayer = new BehaviorFollowEntity(bot, targets);
|
||
|
const lookAtPlayer = new BehaviorLookAtEntity(bot, targets);
|
||
|
const stay = new BehaviorIdle();
|
||
|
|
||
|
// Create our transitions
|
||
|
const transitions = [
|
||
|
|
||
|
// We want to start following the player immediately after finding them.
|
||
|
// Since getClosestPlayer finishes instantly, shouldTransition() should always return true.
|
||
|
new StateTransition({
|
||
|
parent: getClosestPlayer,
|
||
|
child: followPlayer,
|
||
|
onTransition: (quiet) => quiet || bot.chat(`Hi ${targets.entity.username}!`),
|
||
|
shouldTransition: () => bot.entity.position.distanceTo(targets.entity.position) <= 50,
|
||
|
// shouldTransition: () => getClosestPlayer.distanceToTarget() < 100 || console.info("player too far!") && false,
|
||
|
}),
|
||
|
|
||
|
// If the distance to the player is less than two blocks, switch from the followPlayer
|
||
|
// state to the lookAtPlayer state.
|
||
|
new StateTransition({
|
||
|
parent: followPlayer,
|
||
|
child: lookAtPlayer,
|
||
|
// onTransition: () => console.log(targets),
|
||
|
shouldTransition: () => followPlayer.distanceToTarget() < 2,
|
||
|
}),
|
||
|
|
||
|
// If the distance to the player is more than two blocks, switch from the lookAtPlayer
|
||
|
// state to the followPlayer state.
|
||
|
new StateTransition({
|
||
|
parent: lookAtPlayer,
|
||
|
child: followPlayer,
|
||
|
shouldTransition: () => lookAtPlayer.distanceToTarget() >= 5,
|
||
|
}),
|
||
|
new StateTransition({
|
||
|
parent: lookAtPlayer,
|
||
|
child: stay,
|
||
|
onTransition: () => bot.chat("ok, staying"),
|
||
|
// shouldTransition: () => true,
|
||
|
}),
|
||
|
new StateTransition({
|
||
|
parent: stay,
|
||
|
child: getClosestPlayer,
|
||
|
// shouldTransition: () => Math.random() > 0.01,
|
||
|
// shouldTransition: () => Math.random() > 0.1 && getClosestPlayer.distanceToTarget() < 2,
|
||
|
}),
|
||
|
];
|
||
|
|
||
|
// Now we just wrap our transition list in a nested state machine layer. We want the bot
|
||
|
// to start on the getClosestPlayer state, so we'll specify that here.
|
||
|
const rootLayer = new NestedStateMachine(transitions, getClosestPlayer, stay);
|
||
|
|
||
|
// We can start our state machine simply by creating a new instance.
|
||
|
cfg.stateMachines.follow = new BotStateMachine(bot, rootLayer);
|
||
|
const webserver = new StateMachineWebserver(bot, cfg.stateMachines.follow);
|
||
|
webserver.startServer();
|
||
|
|
||
|
// mineflayerViewer(bot, { port: 3000 })
|
||
|
// const path = [bot.entity.position.clone()]
|
||
|
// bot.on('move', () => {
|
||
|
// if (path[path.length - 1].distanceTo(bot.entity.position) > 1) {
|
||
|
// path.push(bot.entity.position.clone())
|
||
|
// bot.viewer.drawLine('path', path)
|
||
|
// }
|
||
|
// })
|
||
|
}
|
||
|
|
||
|
const load = (config) => {
|
||
|
cfg = config
|
||
|
bot = cfg.bot
|
||
|
// cfg.inventory = {
|
||
|
// auto: true,
|
||
|
// quiet: false
|
||
|
// }
|
||
|
// bot.on('chat', inventory)
|
||
|
bot.loadPlugin(pathfinder)
|
||
|
// statemachineInit()
|
||
|
}
|
||
|
|
||
|
const unload = () => {
|
||
|
// bot.off('chat', inventory)
|
||
|
}
|
||
|
|
||
|
module.exports = { load, unload }
|