mcbot / index.js
srinetwork's picture
Upload 3 files
eb5d055 verified
Raw History Blame Contribute Delete
9.14 kB
const express = require('express');
const http = require('http');
const { Server } = require('socket.io');
const mineflayer = require('mineflayer');
const path = require('path');
const app = express();
const server = http.createServer(app);
const io = new Server(server, {
cors: {
origin: "*",
methods: ["GET", "POST"]
}
});
const PORT = process.env.PORT || 7860;
// Store active bots
const activeBots = new Map();
// Middleware
app.use(express.json());
app.use(express.static('public'));
// Health check endpoint
app.get('/health', (req, res) => {
res.json({ status: true, uptime: process.uptime(), bots: activeBots.size });
});
// API Routes
app.get('/api/bots', (req, res) => {
const bots = Array.from(activeBots.entries()).map(([id, data]) => ({
id,
username: data.bot.username,
host: data.host,
port: data.port,
connected: data.connected,
players: data.players || []
}));
res.json(bots);
});
// Socket.IO Connection
io.on('connection', (socket) => {
console.log('Client connected:', socket.id);
let currentBot = null;
let botId = null;
// Connect bot to Minecraft server
socket.on('connect-bot', (config) => {
const { username, host, port = 25565, version } = config;
if (!username || !host) {
socket.emit('error', { message: 'Username and host are required' });
return;
}
// Disconnect existing bot for this socket
if (currentBot) {
currentBot.quit();
activeBots.delete(botId);
}
botId = `${socket.id}_${Date.now()}`;
try {
const bot = mineflayer.createBot({
host: host,
port: parseInt(port),
username: username,
version: version || false,
auth: 'offline',
hideErrors: true
});
currentBot = bot;
const botData = {
bot: bot,
socket: socket,
host: host,
port: port,
connected: false,
players: [],
chatHistory: []
};
activeBots.set(botId, botData);
// Bot Events
bot.on('login', () => {
botData.connected = true;
socket.emit('bot-status', {
status: 'online',
username: bot.username,
host: host,
port: port
});
console.log(`Bot ${username} connected to ${host}:${port}`);
});
bot.on('spawn', () => {
socket.emit('bot-spawned', {
position: bot.entity?.position,
health: bot.health,
food: bot.food
});
updatePlayersList(bot, socket);
});
bot.on('chat', (username, message) => {
if (username === bot.username) return;
const chatData = {
username: username,
message: message,
timestamp: new Date().toISOString(),
type: 'chat'
};
botData.chatHistory.push(chatData);
socket.emit('chat-message', chatData);
});
bot.on('message', (jsonMsg) => {
const text = jsonMsg.toString();
if (text && !text.includes(bot.username)) {
socket.emit('system-message', {
message: text,
timestamp: new Date().toISOString()
});
}
});
bot.on('playerJoined', (player) => {
socket.emit('player-joined', {
username: player.username,
timestamp: new Date().toISOString()
});
updatePlayersList(bot, socket);
});
bot.on('playerLeft', (player) => {
socket.emit('player-left', {
username: player.username,
timestamp: new Date().toISOString()
});
updatePlayersList(bot, socket);
});
bot.on('health', () => {
socket.emit('bot-health', {
health: bot.health,
food: bot.food
});
});
bot.on('death', () => {
socket.emit('bot-death', {
message: 'Bot died!',
timestamp: new Date().toISOString()
});
});
bot.on('kicked', (reason) => {
socket.emit('bot-kicked', {
reason: reason.toString(),
timestamp: new Date().toISOString()
});
cleanupBot(botId);
});
bot.on('error', (err) => {
console.error('Bot error:', err.message);
socket.emit('bot-error', {
message: err.message,
timestamp: new Date().toISOString()
});
});
bot.on('end', (reason) => {
socket.emit('bot-disconnected', {
reason: reason || 'Connection closed',
timestamp: new Date().toISOString()
});
cleanupBot(botId);
});
} catch (error) {
socket.emit('error', { message: error.message });
}
});
// Send chat message
socket.on('send-chat', (message) => {
if (currentBot && currentBot.chat) {
currentBot.chat(message);
socket.emit('chat-sent', {
username: currentBot.username,
message: message,
timestamp: new Date().toISOString()
});
}
});
// Send command
socket.on('send-command', (command) => {
if (currentBot && currentBot.chat) {
currentBot.chat(command);
}
});
// Bot actions
socket.on('bot-action', (action) => {
if (!currentBot) return;
switch(action.type) {
case 'jump':
currentBot.setControlState('jump', true);
setTimeout(() => currentBot.setControlState('jump', false), 500);
break;
case 'sneak':
currentBot.setControlState('sneak', true);
setTimeout(() => currentBot.setControlState('sneak', false), 1000);
break;
case 'look':
if (action.x !== undefined && action.y !== undefined && action.z !== undefined) {
const Vec3 = require('vec3');
currentBot.lookAt(new Vec3(action.x, action.y, action.z));
}
break;
case 'move':
if (action.direction) {
currentBot.setControlState(action.direction, true);
setTimeout(() => currentBot.setControlState(action.direction, false), 500);
}
break;
}
});
// Disconnect bot
socket.on('disconnect-bot', () => {
if (currentBot) {
currentBot.quit();
cleanupBot(botId);
currentBot = null;
botId = null;
}
});
// Get players list
socket.on('get-players', () => {
if (currentBot) {
updatePlayersList(currentBot, socket);
}
});
// Disconnect handler
socket.on('disconnect', () => {
console.log('Client disconnected:', socket.id);
if (currentBot) {
currentBot.quit();
cleanupBot(botId);
}
});
});
function updatePlayersList(bot, socket) {
if (!bot.players) return;
const players = Object.values(bot.players).map(p => ({
username: p.username,
ping: p.ping,
uuid: p.uuid
}));
socket.emit('players-list', players);
}
function cleanupBot(id) {
if (activeBots.has(id)) {
const data = activeBots.get(id);
if (data.bot) {
try {
data.bot.quit();
data.bot.removeAllListeners();
} catch (e) {}
}
activeBots.delete(id);
}
}
// Start server
server.listen(PORT, () => {
console.log(`🎮 Minecraft Bot Controller running on port ${PORT}`);
console.log(`🌐 Access the web interface at http://localhost:${PORT}`);
});
// Graceful shutdown
process.on('SIGTERM', () => {
console.log('SIGTERM received, shutting down gracefully');
activeBots.forEach((data, id) => {
cleanupBot(id);
});
server.close(() => {
process.exit(0);
});
});
process.on('SIGINT', () => {
console.log('SIGINT received, shutting down gracefully');
activeBots.forEach((data, id) => {
cleanupBot(id);
});
server.close(() => {
process.exit(0);
});
});