Spaces:
Paused
Paused
| 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); |