const mineflayer = require('mineflayer'); const express = require('express'); const http = require('http'); const socketIo = require('socket.io'); const { pathfinder, Movements, goals: { GoalBlock, GoalFollow } } = require('mineflayer-pathfinder'); const Vec3 = require('vec3').Vec3; const app = express(); const server = http.createServer(app); const io = socketIo(server); let bot = null; let states = { afkWalk: false, dirtLoop: false, follow: false, manualDisconnect: false, timerId: null, resourcePackAccepted: false // Track resource pack acceptance }; function spawnBot() { if (states.manualDisconnect) return; bot = mineflayer.createBot({ host: 'mcgalaxy.space', port: 25580, username: 'drdalta', auth: 'microsoft', version: '1.21.4' }); bot.loadPlugin(pathfinder); bot.once('spawn', () => { console.log('Bot has spawned'); const mcData = require('minecraft-data')(bot.version); const mov = new Movements(bot, mcData); bot.pathfinder.setMovements(mov); // Handle resource pack prompt with improved logging bot.on('resource_pack_send', (url, hash) => { console.log('Received resource pack URL:', url, 'Hash:', hash); bot.acceptResourcePack(); console.log('Resource pack accepted'); states.resourcePackAccepted = true; // Mark as accepted }); // Detect if resource pack fails to load bot.on('resource_pack_deny', () => { console.log('Resource pack was denied or failed to load. Attempting to reconnect...'); states.manualDisconnect = false; bot.quit(); setTimeout(spawnBot, 5000); // Retry after 5 seconds }); // Log server messages to debug further prompts or issues bot.on('message', (message) => { const msg = message.toString(); console.log('Server message:', msg); if (msg.includes('resource pack') && !states.resourcePackAccepted) { console.log('Resource pack prompt detected, re-attempting acceptance...'); bot.acceptResourcePack(); } }); // Afk walk loop setInterval(() => { if (states.afkWalk && !states.follow && bot.entity) { const { x, y, z } = bot.entity.position; const tx = x + (Math.random() - 0.5) * 4; const tz = z + (Math.random() - 0.5) * 4; bot.pathfinder.setGoal(new GoalBlock(Math.floor(tx), Math.floor(y), Math.floor(tz))); } }, 10000); // Dirt loop setInterval(async () => { if (!states.dirtLoop || states.follow || !bot.entity) return; try { const basePos = bot.entity.position.offset(0, -1, 2); const frontPos = bot.entity.position.offset(0, 0, 2); const base = bot.blockAt(basePos); const front = bot.blockAt(frontPos); const dirt = bot.inventory.items().find(i => i.name.includes('dirt')); if (!base || !dirt) return; await bot.equip(dirt, 'hand'); if (front && front.name !== 'air') { await bot.dig(front); await new Promise(res => setTimeout(res, 2001)); } await bot.placeBlock(base, new Vec3(0, 1, 0)); await new Promise(res => setTimeout(res, 500)); } catch (err) { console.log('DirtLoop error:', err.message); } }, 2500); }); bot.on('end', reason => { console.log('Disconnected:', reason); states.resourcePackAccepted = false; // Reset on disconnect if (!states.manualDisconnect) { setTimeout(spawnBot, 5000); } }); bot.on('error', e => console.log('Error:', e.message)); } spawnBot(); io.on('connection', socket => { console.log('Client connected'); socket.on('command', msg => { if (!bot || !bot.entity) return; const [cmd, param] = msg.split(':'); switch (cmd) { case 'toggle_afk': states.afkWalk = !states.afkWalk; break; case 'toggle_dirt': states.dirtLoop = !states.dirtLoop; break; case 'toggle_follow': states.follow = !states.follow; if (states.follow) { const target = bot.players['DrTurjo']?.entity; if (target) { bot.pathfinder.setGoal(new GoalFollow(target, 1), true); } else states.follow = false; } else bot.pathfinder.stop(); break; case 'move': bot.setControlState(param, true); break; case 'stop': bot.clearControlStates(); break; case 'click_left': { const ent = bot.nearestEntity(); if (ent) bot.attack(ent); break; } case 'click_right': bot.activateItem(); break; case 'slot': { const s = parseInt(param, 10) - 1; if (s >= 0 && s <= 8) bot.setQuickBarSlot(s); break; } case 'timer': { if (states.timerId) clearTimeout(states.timerId); const mins = parseInt(param, 10); if (isNaN(mins) || mins <= 0) return; states.timerId = setTimeout(() => { states.manualDisconnect = true; bot.quit(); }, mins * 60 * 1000); break; } case 'disconnect': states.manualDisconnect = true; bot.quit(); break; case 'reconnect': states.manualDisconnect = false; bot.quit(); setTimeout(spawnBot, 1000); break; case 'chat': bot.chat(param); break; } }); socket.on('get_inv', () => { if (!bot) return; const inv = bot.inventory.items().map(i => ({ slot: i.slot, name: i.name, count: i.count })); socket.emit('inventory', inv); }); }); app.use(express.static(__dirname)); app.get('/', (req, res) => res.sendFile(__dirname + '/index.html')); server.listen(process.env.PORT || 7860);