| | |
| | const express = require('express'); |
| | const http = require('http'); |
| | const socketIo = require('socket.io'); |
| | const mineflayer = require('mineflayer'); |
| | const path = require('path'); |
| |
|
| | const app = express(); |
| | const server = http.createServer(app); |
| | const io = socketIo(server); |
| |
|
| | |
| | const SERVER_HOST = 'dm.progamer.me'; |
| | const SERVER_PORT = 40675; |
| | const SERVER_VERSION = '1.21.8'; |
| | const BOT_NAMES = ['Alfha_lag', 'Bigboybloom', 'Kitcat']; |
| | const ROTATION_DURATION = 3600; |
| |
|
| | |
| | let currentBotIndex = 0; |
| | let rotationStartTime = null; |
| | let activeBot = null; |
| | let serverStatus = { online: false, players: '0/0', latency: 0 }; |
| | const botStats = {}; |
| |
|
| | |
| | BOT_NAMES.forEach(name => { |
| | botStats[name] = { |
| | name, |
| | status: 'offline', |
| | deaths: 0, |
| | reconnects: 0, |
| | uptime: 0, |
| | position: { x: 0, y: 0, z: 0 }, |
| | health: 20, |
| | food: 20, |
| | isActive: false |
| | }; |
| | }); |
| |
|
| | |
| | function createBot(botName) { |
| | console.log(`๐ Starting ${botName}...`); |
| | |
| | const bot = mineflayer.createBot({ |
| | host: SERVER_HOST, |
| | port: SERVER_PORT, |
| | username: botName, |
| | auth: 'offline', |
| | version: SERVER_VERSION, |
| | hideErrors: false, |
| | checkTimeoutInterval: 30000, |
| | keepAlive: true |
| | }); |
| |
|
| | let circleInterval = null; |
| | let centerPos = null; |
| | let angle = 0; |
| |
|
| | bot.once('spawn', () => { |
| | console.log(`โ
${botName} connected`); |
| | botStats[botName].status = 'online'; |
| | botStats[botName].uptime = Date.now(); |
| | |
| | |
| | setTimeout(() => { |
| | if (!bot.entity) return; |
| | |
| | centerPos = bot.entity.position.clone(); |
| | |
| | circleInterval = setInterval(() => { |
| | if (!bot.entity) return; |
| | |
| | try { |
| | const radius = 4; |
| | angle += 0.03; |
| | |
| | const targetX = centerPos.x + Math.cos(angle) * radius; |
| | const targetZ = centerPos.z + Math.sin(angle) * radius; |
| | |
| | const dx = targetX - bot.entity.position.x; |
| | const dz = targetZ - bot.entity.position.z; |
| | const yaw = Math.atan2(-dx, -dz); |
| | |
| | bot.look(yaw, 0, true); |
| | bot.setControlState('forward', true); |
| | |
| | |
| | botStats[botName].position = { |
| | x: Math.floor(bot.entity.position.x), |
| | y: Math.floor(bot.entity.position.y), |
| | z: Math.floor(bot.entity.position.z) |
| | }; |
| | botStats[botName].health = bot.health || 20; |
| | botStats[botName].food = bot.food || 20; |
| | } catch (err) { |
| | console.error(`Movement error for ${botName}:`, err.message); |
| | } |
| | }, 100); |
| | }, 2000); |
| | }); |
| |
|
| | bot.on('death', () => { |
| | console.log(`๐ ${botName} died`); |
| | botStats[botName].deaths++; |
| | if (circleInterval) clearInterval(circleInterval); |
| | centerPos = null; |
| | }); |
| |
|
| | bot.on('respawn', () => { |
| | console.log(`๐ ${botName} respawned`); |
| | if (circleInterval) clearInterval(circleInterval); |
| | centerPos = null; |
| | angle = 0; |
| | }); |
| |
|
| | bot.on('kicked', (reason) => { |
| | console.log(`โ ${botName} kicked: ${reason}`); |
| | botStats[botName].status = 'offline'; |
| | if (circleInterval) clearInterval(circleInterval); |
| | }); |
| |
|
| | bot.on('error', (err) => { |
| | console.error(`โ ${botName} error:`, err.message); |
| | }); |
| |
|
| | bot.on('end', () => { |
| | console.log(`๐ ${botName} disconnected`); |
| | botStats[botName].status = 'offline'; |
| | if (circleInterval) clearInterval(circleInterval); |
| | |
| | |
| | setTimeout(() => { |
| | if (activeBot && activeBot.username === botName) { |
| | console.log(`๐ Reconnecting ${botName}...`); |
| | botStats[botName].reconnects++; |
| | activeBot = createBot(botName); |
| | } |
| | }, 5000); |
| | }); |
| |
|
| | return bot; |
| | } |
| |
|
| | |
| | function stopBot(bot) { |
| | if (!bot) return; |
| | |
| | try { |
| | bot.quit(); |
| | console.log(`โน๏ธ Stopped ${bot.username}`); |
| | } catch (err) { |
| | console.error('Error stopping bot:', err.message); |
| | } |
| | } |
| |
|
| | |
| | function rotationManager() { |
| | setInterval(() => { |
| | const currentBot = BOT_NAMES[currentBotIndex]; |
| | const now = Date.now(); |
| | |
| | if (!rotationStartTime || (now - rotationStartTime) >= (ROTATION_DURATION * 1000)) { |
| | |
| | if (activeBot) { |
| | stopBot(activeBot); |
| | botStats[activeBot.username].isActive = false; |
| | } |
| | |
| | |
| | setTimeout(() => { |
| | activeBot = createBot(currentBot); |
| | botStats[currentBot].isActive = true; |
| | rotationStartTime = Date.now(); |
| | |
| | console.log(`๐ Rotation: ${currentBot} is now active`); |
| | |
| | |
| | currentBotIndex = (currentBotIndex + 1) % BOT_NAMES.length; |
| | }, 2000); |
| | } |
| | }, 5000); |
| | } |
| |
|
| | |
| | async function checkServerStatus() { |
| | try { |
| | const net = require('net'); |
| | const client = new net.Socket(); |
| | const startTime = Date.now(); |
| | |
| | client.setTimeout(5000); |
| | |
| | client.connect(SERVER_PORT, SERVER_HOST, () => { |
| | const latency = Date.now() - startTime; |
| | serverStatus = { |
| | online: true, |
| | latency, |
| | players: '?/?' |
| | }; |
| | client.destroy(); |
| | }); |
| | |
| | client.on('error', () => { |
| | serverStatus = { online: false, latency: 0, players: '0/0' }; |
| | client.destroy(); |
| | }); |
| | |
| | client.on('timeout', () => { |
| | serverStatus = { online: false, latency: 0, players: '0/0' }; |
| | client.destroy(); |
| | }); |
| | } catch (err) { |
| | serverStatus = { online: false, latency: 0, players: '0/0' }; |
| | } |
| | } |
| |
|
| | |
| | io.on('connection', (socket) => { |
| | console.log('๐ฑ Client connected'); |
| | |
| | const sendUpdate = () => { |
| | const currentBot = BOT_NAMES[(currentBotIndex - 1 + BOT_NAMES.length) % BOT_NAMES.length]; |
| | const nextBot = BOT_NAMES[currentBotIndex]; |
| | const elapsed = rotationStartTime ? Math.floor((Date.now() - rotationStartTime) / 1000) : 0; |
| | const remaining = Math.max(0, ROTATION_DURATION - elapsed); |
| | |
| | |
| | Object.keys(botStats).forEach(name => { |
| | if (botStats[name].status === 'online' && botStats[name].uptime) { |
| | botStats[name].uptimeSeconds = Math.floor((Date.now() - botStats[name].uptime) / 1000); |
| | } else { |
| | botStats[name].uptimeSeconds = 0; |
| | } |
| | }); |
| | |
| | socket.emit('update', { |
| | server: { |
| | host: SERVER_HOST, |
| | port: SERVER_PORT, |
| | version: SERVER_VERSION, |
| | status: serverStatus |
| | }, |
| | rotation: { |
| | current: currentBot, |
| | next: nextBot, |
| | elapsed, |
| | remaining, |
| | queue: BOT_NAMES |
| | }, |
| | bots: Object.values(botStats) |
| | }); |
| | }; |
| | |
| | const interval = setInterval(sendUpdate, 1000); |
| | sendUpdate(); |
| | |
| | socket.on('forceRotation', () => { |
| | rotationStartTime = 0; |
| | socket.emit('rotationForced', true); |
| | }); |
| | |
| | socket.on('disconnect', () => { |
| | clearInterval(interval); |
| | console.log('๐ด Client disconnected'); |
| | }); |
| | }); |
| |
|
| | |
| | app.use(express.static(__dirname)); |
| | app.get('/', (req, res) => { |
| | res.sendFile(path.join(__dirname, 'index.html')); |
| | }); |
| |
|
| | |
| | const PORT = process.env.PORT || 7860; |
| | server.listen(PORT, () => { |
| | console.log('โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ'); |
| | console.log('๐ฎ MINECRAFT BOT MANAGER'); |
| | console.log('โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ'); |
| | console.log(`๐ก Server: ${SERVER_HOST}:${SERVER_PORT}`); |
| | console.log(`๐ค Bots: ${BOT_NAMES.join(', ')}`); |
| | console.log(`โฑ๏ธ Rotation: ${ROTATION_DURATION / 60} minutes`); |
| | console.log(`๐ Dashboard: http://localhost:${PORT}`); |
| | console.log('โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ'); |
| | }); |
| |
|
| | |
| | rotationManager(); |
| | setInterval(checkServerStatus, 1000); |
| | checkServerStatus(); |