const EventEmitter = require("events"); const mineflayer = require('mineflayer'); const { pathfinder, Movements, goals } = require('mineflayer-pathfinder'); const { GoalBlock } = goals; const pvp = require('mineflayer-pvp').plugin; const net = require('net'); const prefix = "[BattlegroundBot] "; class CommandServer extends EventEmitter { sockets = []; server; launch() { var server = net.createServer(); server.on('connection', (socket) => { this.sockets.push(socket); // Обработка входящей даты (по сути команды) socket.on('data', async (data) => { try { var obj = JSON.parse(data); this.emit(obj.command.toLowerCase(), socket, obj.data.split(" ")); } catch (err) { console.log(prefix + "Ошибка во время парсинга команды: " + err); } }); socket.on('close', () => { console.log(prefix + "Покдлючение разорвано."); }); socket.on('error', (error) => { console.log(prefix + "Покдлючение разорвано. (" + error + ")."); }); }); server.on('listening', () => { console.log(prefix + "Комманд сервер запущен на порту 40525."); }); server.listen(40525); } } class BattlegroundBot extends EventEmitter { bot; socket; set socket(x) { this.socket = x; } /* .start() запускает бота и прослушивает spawn. Когда бот спавнится, вызывается 'establish'. Наступает этап авторизации. */ async start(nickname) { const options = { host: 'localhost', port: 25669, username: nickname } this.bot = mineflayer.createBot(options); this.bot.loadPlugin(pathfinder); this.bot.loadPlugin(pvp); console.log(prefix + "Minecraft-сервер найден. Ожидаем стабилизации подключения и спавна."); this.bot.once('spawn', () => { const moves = new Movements(this.bot); moves.scafoldingBlocks.push(this.bot.registry.itemsByName['green_concrete'].id) moves.maxDropDown = 5; moves.placeCost = 0; moves.liquidCost = 2; moves.dontMineUnderFallingBlock = false; this.bot.pathfinder.setMovements(moves); this.bot.pvp.movements = moves; this.emit('establish', this.bot, this.socket); }); this.bot.on('death', () => { this.emit('killed', this.socket); }); this.bot.once('end', (reason) => { this.emit('disconnected', reason); }); this.bot.on('goal_reached', () => { this.emit('done', this.socket); }); this.bot.on('path_stop', (reason) => { this.emit('done', this.socket); }); this.bot.on('error', (reason) => { this.emit('done', this.socket); }); this.bot.on('stoppedAttacking', () => { this.emit('done', this.socket); }); } moveTo(destination) { this.bot.pathfinder.setGoal(null); this.bot.pathfinder.setGoal(destination); } fight(username) { const player = this.bot.players[username]; if (!player) { return; } this.bot.pvp.attack(player.entity); return true; } } let bots = []; let server = new CommandServer(); server.launch(); server.on('connect', (socket, nickname) => { let battlebot = new BattlegroundBot(); battlebot.socket = socket; battlebot.start(nickname[0]); // На этом этапе мы можем сообщить серверу, что мы бот, а не человек. // Сервер пометит нас соответствующим тэгом (или хуй пойми чем) и перенесёт на арену. battlebot.on('establish', (bot, socket) => { console.log(prefix + "Подключение к Minecraft-серверу успешно. Бот заспавнился и готов принимать команды."); socket.write("AUTH " + bot.username + "\r\n"); battlebot.on('disconnected', (reason) => { console.log(prefix + "Подключение с Minecraft-сервером разорвано, причина: " + reason + "."); }); battlebot.on('done', (socket) => { socket.write("DONE\r\n"); }); server.on('goto', (socket, destination) => { battlebot.moveTo(new GoalBlock(destination[0], destination[1], destination[2])); }); server.on('fight', (socket, data) => { battlebot.fight(data[0]); }); server.on('death', (socket) => { battlebot.bot.pathfinder.setGoal(null); battlebot.bot.pvp.stop(); }); }); });