const mineflayer = require('mineflayer') const { pathfinder, Movements, goals } = require('mineflayer-pathfinder') const pvp = require('mineflayer-pvp').plugin let cfg = {} let bot = {} let guardPos const filterAllMobs = e => e.type === 'mob' const filterPlayers = e => e.type === 'player' const filterMods = e => e.type === 'player' && [cfg.mods].includes(e.username) // const filterPassiveMobs = e => e.kind === 'Passive mobs' const filterCreeper = e => e.mobType === 'Creeper' // const filterCreeperOrEndermen = e => ['Creeper', 'EndderMen'].includes(e.mobType) //TODO endmen hostile by default? const filterHostileMobs = e => e.kind === 'Hostile mobs' // // not needed if detecting by kind // && e.mobType !== 'Armor Stand' // Mojang classifies armor stands as mobs for some reason? // Assign the given location to be guarded function guardArea(pos) { if (pos) { cfg.guard.pos = guardPos = pos // Check for new enemies to attack // bot.off('physicTick', lookForMobs) bot.off('time', lookForMobs) bot.on('time', lookForMobs) } // We are not currently in combat, move to the guard pos if (!bot.pvp.target && guardPos) { moveToGuardPos() } } // Cancel all pathfinder and combat function stopGuarding() { guardPos = cfg.guard.pos = null bot.pvp.stop() bot.pathfinder.setGoal(null) bot.off('time', lookForMobs) // bot.off('physicTick', lookForMobs) } // Pathfinder to the guard position function moveToGuardPos() { const mcData = require('minecraft-data')(bot.version) bot.pathfinder.setMovements(new Movements(bot, mcData)) bot.pathfinder.setGoal(new goals.GoalBlock(guardPos.x, guardPos.y, guardPos.z)) } // Called when the bot has killed it's target. // () => { // if (guardPos) { // moveToGuardPos() // } // }) function lookForMobs() { if (!guardPos) return // Do nothing if bot is not guarding anything // Only look for mobs within 16 blocks const filter = e => e.position.distanceTo(bot.entity.position) < 16 && filterHostileMobs(e) const entityEnemy = bot.nearestEntity(filter) if (entityEnemy && !filterCreeper(entityEnemy)) { // if(filterCreeper(entityEnemy)) // Start attacking // bot.off('time', lookForMobs) // bot.on('physicTick', lookForMobs) bot.pvp.movements.canDig = !!cfg.move && cfg.move.canDig bot.pvp.attack(entityEnemy) } else if (entityEnemy) { bot.lookAt( entityEnemy.position ) cfg.quiet || bot.chat("AH! A creeper! They creep me out!") } } function guardSelf(entity) { if (!cfg.guard.self || entity !== bot.entity || guardPos) return // Do nothing // bot.chat("") const hurtMessages = [ "ouch!", "oww!", "help", "monster!" ] const hurtMessagesPlayer = [ "leave me alone!", "don't hurt me!", "bully!", "go away!", "stop", "no stop", "stop it", "murderer!", "what have i ever done to you? :(", ] console.info(bot.nearestEntity(filterAllMobs)) // Only look for mobs within 5 blocks // const filter = e => e.position.distanceTo(bot.entity.position) < 5 && filterHostileMobs(e) || filterPlayers(e) && !filterMods(e)//anarchy const filter = e => e.position.distanceTo(bot.entity.position) < 5 && filterHostileMobs(e) const entityEnemy = bot.nearestEntity(filter) cfg.quiet || 0.2 < Math.random() && entityEnemy && bot.chat( // TODO use fuzzy message function filterPlayers(entityEnemy) ? hurtMessagesPlayer[Math.floor(Math.random() * hurtMessagesPlayer.length)] : hurtMessages[Math.floor(Math.random() * hurtMessages.length)] ) if (entityEnemy && !filterCreeper(entityEnemy)) { // Start attacking // bot.off('time', lookForMobs) // bot.on('physicTick', lookForMobs) bot.pvp.attack(entityEnemy) bot.pvp.movements.canDig = !!cfg.move && cfg.move.canDig } } // bot.on('physicTick', lookForMobs) // Listen for player commands // bot.on('chat', (username, message) => { // // Guard the location the player is standing // if (message === 'guard') { // const player = bot.players[username] // if (!player) { // bot.chat("I can't see you.") // return // } // bot.chat('I will guard that location.') // guardArea(player.entity.position) // } // // Stop guarding // if (message === 'stop') { // bot.chat('I will no longer guard this area.') // stopGuarding() // } // }) const load = (config) => { cfg = config bot = cfg.bot cfg.guard = { pos: null, auto: true, self: true, } guardPos = cfg.guard.pos bot.loadPlugin(pathfinder) bot.loadPlugin(pvp) bot.on('stoppedAttacking', guardArea) bot.on('entityHurt', guardSelf) // bot.on("time", guardArea) } const unload = () => { stopGuarding() bot.off('time', lookForMobs) // bot.off('physicTick', lookForMobs) bot.off('stoppedAttacking', guardArea) bot.off('entityHurt', guardSelf) // bot.off("time", guardArea) } module.exports = { load, unload, guardArea, guardSelf, stopGuarding }