@baipiaodajun/mcbots
Version:
Minecraft bot and status dashboard for multi-server management
1,010 lines (893 loc) • 35.3 kB
JavaScript
const mineflayer = require('mineflayer');
const express = require('express');
const net = require('net');
const PORT = process.env.SERVER_PORT || process.env.PORT || 3000 ;
const CHAT = process.env.CHAT || false ;
const MOVE = process.env.MOVE || false ;
// Minecraft服务器配置
const SERVERS = [
{
host: "127.0.0.1",
port: 25565,
minBots: 1,
maxBots: 3,
version: "1.20.1"
}
];
// 从环境变量读取服务器配置
if (process && process.env && process.env.SERVERS_JSON) {
try {
const envConfig = JSON.parse(process.env.SERVERS_JSON);
SERVERS.length = 0;
SERVERS.push(...envConfig);
console.log('从环境变量加载服务器配置,数量:', SERVERS.length, '项');
} catch (error) {
console.error('❌ [错误] 无法解析环境变量 SERVERS_JSON');
console.error('原因:', error.message);
console.error('原始内容:\n', process.env.SERVERS_JSON);
console.error('请检查 JSON 格式是否正确,例如引号、逗号是否缺失');
console.error('即将退出...');
process.exit(1);
}
}
/**
* 测试 IP 和端口是否可达
* @param {string} host - IP 或域名
* @param {number} port - 端口号
* @param {number} timeoutMs - 超时时间(毫秒)
* @returns {Promise<boolean>}
*/
function testConnection(host, port, timeoutMs = 5000) {
return new Promise((resolve) => {
const socket = new net.Socket();
// 成功连接
socket.once('connect', () => {
socket.destroy();
resolve(true);
});
// 出错或拒绝连接
socket.once('error', () => {
socket.destroy();
resolve(false);
});
// 超时
socket.setTimeout(timeoutMs, () => {
socket.destroy();
resolve(false);
});
// 尝试连接
socket.connect(port, host);
});
}
// 配置常量
const BOT_CONFIG = {
reconnectDelay: 5000,
maxReconnectAttempts: 5,
healthCheckInterval: 60000,
viewDistance: 4,
connectTimeout: 15000,
chat: CHAT,
move: MOVE
};
const SERVER_CONFIG = {
statusCheckInterval: 30000,
maxFailedAttempts: 3,
resetTimeout: 30000
};
// 全局状态存储
const globalServerStatus = {
servers: new Map()
};
function generateUsername() {
const adjectives = [
'Clever', 'Swift', 'Brave', 'Sneaky', 'Happy', 'Crazy', 'Silky',
'Fluffy', 'Shiny', 'Quick', 'Mighty', 'Tiny', 'Wise', 'Lazy'
];
const animals = [
'Fox', 'Wolf', 'Bear', 'Panda', 'Tiger', 'Eagle', 'Shark',
'Mole', 'Badger', 'Otter', 'Cat', 'Frog', 'Dog'
];
const adjective = adjectives[Math.floor(Math.random() * adjectives.length)];
const animal = animals[Math.floor(Math.random() * animals.length)];
return `${adjective}${animal}`;
}
// Minecraft机器人管理器
class MinecraftBotManager {
constructor(host, port, minBots, maxBots, version) {
this.host = host;
this.port = port;
this.minBots = minBots;
this.maxBots = maxBots;
this.version = version || "1.20.1";
this.currentBots = 0;
this.activeBots = new Map();
this.failedAttempts = 0;
this.lastUpdate = Date.now();
this.status = 'initializing';
this.monitoringInterval = null;
this.timeout= null;
this.reachable=false;
this.lastReachable = null;
this.resetTimer=null;
this.notice=true;
// 机器人名称池
this.botNames = Array.from({ length: 20 }, () => generateUsername());
// 注册到全局状态
globalServerStatus.servers.set(`${host}:${port}`, {
host: host,
port: port,
minBots: minBots,
maxBots: maxBots,
currentBots: 0,
activeBots: [],
lastUpdate: Date.now(),
status: 'initializing'
});
}
// 生成随机机器人名称
generateBotName() {
const baseName = this.botNames[Math.floor(Math.random() * this.botNames.length)];
const randomNum = Math.floor(Math.random() * 1000);
return `${baseName}${randomNum}`;
}
async testmc() {
const reachable = await testConnection(this.host, this.port, 3000);
this.reachable = reachable;
// 只有状态发生变化时才通知
if (this.reachable !== this.lastReachable) {
if (!this.reachable) {
console.log(`[${this.host}:${this.port}] MC服务器网络不可达`);
} else {
console.log(`[${this.host}:${this.port}] MC服务器恢复可达`);
}
this.lastReachable = this.reachable;
this.notice=true;
}
}
// 创建Minecraft机器人
async createBot(botName) {
if (this.currentBots >= this.maxBots) {
console.log(`[${this.host}:${this.port}] 已达到最大机器人限制: ${this.maxBots}`);
return null;
}
await this.testmc();
if (!this.reachable) {
return null;
}
if(!botName){
botName = this.generateBotName();
}
try {
console.log(`[${this.host}:${this.port}] 创建机器人: ${botName}`);
const bot = mineflayer.createBot({
host: this.host,
port: this.port,
username: botName,
version: this.version,
viewDistance: BOT_CONFIG.viewDistance,
auth: 'offline'
});
this.timeout = setTimeout(() => {
console.error(`[${this.host}:${this.port}] ${botName}连接超时,放弃等待`);
if (typeof bot.end === 'function') {
bot.end();
}
}, BOT_CONFIG.connectTimeout);
// 设置机器人事件处理
this.setupBotEvents(bot, botName);
this.activeBots.set(botName, bot);
this.currentBots++;
// this.failedAttempts = 0;
this.updateStatus();
return bot;
} catch (error) {
console.log(`[${this.host}:${this.port}] 创建机器人 ${botName} 失败:`, error.message);
this.handleBotFailure(botName);
return null;
}
}
// 设置机器人事件
setupBotEvents(bot, botName) {
bot.on('login', () => {
console.log(`[${this.host}:${this.port}] 机器人 ${botName} 登录成功`);
if (this.timeout) {
clearTimeout(this.timeout);
this.timeout = null;
}
this.updateStatus();
});
bot.on('spawn', () => {
console.log(`[${this.host}:${this.port}] 机器人 ${botName} 生成在世界中`);
// 机器人基础行为
this.setupBotBehavior(bot, botName);
});
bot.on('message', (message) => {
const text = message.toString();
console.log(`[${this.host}:${this.port}] ${botName} 收到消息: ${text}`);
});
bot.on('error', (error) => {
console.log(`[${this.host}:${this.port}] 机器人 ${botName} 错误:`, error.message);
// if (this.activeBots.has(botName) && this.failedAttempts <= SERVER_CONFIG.maxFailedAttempts) {
this.handleBotDisconnect(botName);
// } else {
// this.handleBotFailure(botName);
// }
});
bot.on('end', (reason) => {
console.log(`[${this.host}:${this.port}] 机器人 ${botName} 断开连接:`, reason);
console.log(`[${this.host}:${this.port}] ${botName}:失败次数${this.failedAttempts}`);
this.handleBotDisconnect(botName);
});
bot.on('kicked', (reason) => {
console.log(`[${this.host}:${this.port}] 机器人 ${botName} 被踢出:`, reason);
this.handleBotDisconnect(botName);
});
}
// 设置机器人行为
setupBotBehavior(bot, botName) {
// 随机移动
if (BOT_CONFIG.move){
setInterval(() => {
if (bot.entity && Math.random() < 0.3) {
const yaw = Math.random() * Math.PI * 2;
const pitch = Math.random() * Math.PI - Math.PI / 2;
bot.look(yaw, pitch, false);
if (Math.random() < 0.2) {
bot.setControlState('forward', true);
setTimeout(() => {
bot.setControlState('forward', false);
}, 1000);
}
}
}, 5000);
}
// 随机聊天(如果启用)
if (BOT_CONFIG.chat && Math.random() < 0.1) {
setInterval(() => {
const messages = ['Hello!', 'Nice server!', 'What\'s up?', 'Good game!'];
const randomMessage = messages[Math.floor(Math.random() * messages.length)];
bot.chat(randomMessage);
}, 30000 + Math.random() * 60000);
}
}
// 处理机器人断开连接 - 增强版本
handleBotDisconnect(botName) {
if (this.activeBots.has(botName)) {
console.log(`[${this.host}:${this.port}] 从活跃列表中移除机器人: ${botName}`);
this.activeBots.delete(botName);
this.currentBots = Math.max(0, this.currentBots - 1);
this.updateStatus();
// 记录断开连接时间,用于调试
console.log(`[${this.host}:${this.port}] 当前活跃机器人数量: ${this.currentBots}, 目标: ${this.minBots}`);
if(this.failedAttempts > SERVER_CONFIG.maxFailedAttempts){
console.log(`[${this.host}:${this.port}] 机器人 ${botName} 重连次数太多,跳过`);
return;
}
// 延迟重连,避免频繁重连
setTimeout(() => {
this.reconnect(botName);
}, BOT_CONFIG.reconnectDelay);
} else {
console.log(`[${this.host}:${this.port}] 机器人 ${botName} 不在活跃列表中,无需处理`);
}
}
// 处理机器人失败
handleBotFailure(botName) {
this.failedAttempts++;
this.updateStatus();
if (this.failedAttempts >= SERVER_CONFIG.maxFailedAttempts) {
console.log(`[${this.host}:${this.port}] 失败次数过多,${SERVER_CONFIG.resetTimeout / 1000}秒后再次尝试`);
setTimeout(() => {
this.failedAttempts = 0;
this.reconnect(botName);
}, SERVER_CONFIG.resetTimeout);
return;
}
setTimeout(() => {
this.reconnect(botName);
}, BOT_CONFIG.reconnectDelay);
}
// 维护机器人数目 - 增强版本
maintainBots() {
const neededBots = this.minBots - this.currentBots;
// console.log(`[${this.host}:${this.port}] 当前机器人: ${this.currentBots}, 需要: ${neededBots}, 失败次数: ${this.failedAttempts}`);
if (neededBots > 0 && this.failedAttempts < SERVER_CONFIG.maxFailedAttempts) {
if (this.notice) {
console.log(`[${this.host}:${this.port}] 需要启动 ${neededBots} 个机器人`);
this.notice=false;
}
for (let i = 0; i < neededBots; i++) {
setTimeout(() => {
this.createBot();
}, i * 8000); // 每隔8秒启动一个
}
}
// else if (neededBots > 0) {
// console.log(`[${this.host}:${this.port}] 由于失败次数过多,暂停创建新机器人`);
// }
this.updateStatus();
}
reconnect(botName){
if (this.failedAttempts < SERVER_CONFIG.maxFailedAttempts) {
console.log(`[${this.host}:${this.port}] 第${this.failedAttempts}次重连 ${botName} 机器人`);
this.failedAttempts++;
setTimeout(() => {
this.createBot(botName);
}, 5000);
} else{
// 如果还没有设置过 resetTimer,就设置一次
if (!this.resetTimer) {
this.resetTimer = setTimeout(() => {
this.failedAttempts = 0;
this.resetTimer = null; // 清理标记,允许下次再设置
console.log(
`[${this.host}:${this.port}] 失败次数已重置,可以重新尝试创建机器人`
);
}, SERVER_CONFIG.resetTimeout);
}
console.log(`[${this.host}:${this.port}] 由于失败次数过多,暂停创建新机器人`);
}
this.updateStatus();
}
// 更新状态
updateStatus() {
const serverInfo = globalServerStatus.servers.get(`${this.host}:${this.port}`);
if (serverInfo) {
serverInfo.currentBots = this.currentBots;
serverInfo.activeBots = Array.from(this.activeBots.keys());
serverInfo.lastUpdate = Date.now();
serverInfo.status = this.currentBots >= this.minBots ? 'healthy' :
this.failedAttempts >= SERVER_CONFIG.maxFailedAttempts ? 'failed' : 'degraded';
this.status = serverInfo.status;
}
}
// 启动监控
startMonitoring() {
this.maintainBots();
this.monitoringInterval = setInterval(() => {
this.maintainBots();
}, SERVER_CONFIG.statusCheckInterval);
}
// 停止所有机器人
stopAllBots() {
this.activeBots.forEach((bot, botName) => {
try {
bot.quit();
console.log(`[${this.host}:${this.port}] 停止机器人: ${botName}`);
} catch (error) {
console.log(`[${this.host}:${this.port}] 停止机器人 ${botName} 失败:`, error.message);
}
});
this.activeBots.clear();
this.currentBots = 0;
this.updateStatus();
if (this.monitoringInterval) {
clearInterval(this.monitoringInterval);
this.monitoringInterval = null;
}
}
// 获取状态信息
getStatus() {
return {
host: this.host,
port: this.port,
version: this.version,
minBots: this.minBots,
maxBots: this.maxBots,
currentBots: this.currentBots,
activeBots: Array.from(this.activeBots.keys()),
failedAttempts: this.failedAttempts,
status: this.status,
lastUpdate: this.lastUpdate
};
}
}
// 系统监控
class SystemMonitor {
constructor() {
this.memoryUsage = '未知';
this.uptime = 0;
this.monitoringInterval = null;
}
async getMemoryUsage() {
return new Promise((resolve) => {
const used = process.memoryUsage();
this.memoryUsage = `RSS: ${Math.round(used.rss / 1024 / 1024)}MB, Heap: ${Math.round(used.heapUsed / 1024 / 1024)}MB`;
resolve(this.memoryUsage);
});
}
startMonitoring() {
this.getMemoryUsage();
this.monitoringInterval = setInterval(async () => {
await this.getMemoryUsage();
this.uptime = process.uptime();
}, BOT_CONFIG.healthCheckInterval);
}
stopMonitoring() {
if (this.monitoringInterval) {
clearInterval(this.monitoringInterval);
}
}
getSystemInfo() {
return {
memoryUsage: this.memoryUsage,
uptime: this.uptime,
nodeVersion: process.version,
platform: process.platform
};
}
}
// Web状态服务器
class StatusServer {
constructor(port = PORT) {
this.port = port;
this.app = express();
this.server = null;
this.setupRoutes();
}
setupRoutes() {
this.app.get('/', (req, res) => {
const serversStatus = Array.from(globalServerStatus.servers.values());
const systemInfo = systemMonitor.getSystemInfo();
const { version } = require('./package.json');
const html = `
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Minecraft 机器人监控系统</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
min-height: 100vh;
padding: 20px;
color: #333;
}
.container {
max-width: 1200px;
margin: 0 auto;
}
.header {
text-align: center;
margin-bottom: 30px;
color: white;
}
.header h1 {
font-size: 2.5rem;
margin-bottom: 10px;
text-shadow: 2px 2px 4px rgba(0,0,0,0.3);
}
.header p {
font-size: 1.1rem;
opacity: 0.9;
}
.dashboard {
display: grid;
grid-template-columns: 1fr 2fr;
gap: 20px;
margin-bottom: 20px;
}
(max-width: 768px) {
.dashboard {
grid-template-columns: 1fr;
}
}
.system-card {
background: white;
border-radius: 15px;
padding: 25px;
box-shadow: 0 10px 30px rgba(0,0,0,0.2);
backdrop-filter: blur(10px);
}
.system-card h3 {
color: #4a5568;
margin-bottom: 20px;
font-size: 1.3rem;
border-bottom: 2px solid #e2e8f0;
padding-bottom: 10px;
}
.stats-grid {
display: grid;
gap: 15px;
}
.stat-item {
display: flex;
justify-content: space-between;
align-items: center;
padding: 12px;
background: #f7fafc;
border-radius: 10px;
border-left: 4px solid #4299e1;
}
.stat-label {
font-weight: 600;
color: #4a5568;
}
.stat-value {
font-weight: 700;
color: #2d3748;
}
.servers-section {
background: white;
border-radius: 15px;
padding: 25px;
box-shadow: 0 10px 30px rgba(0,0,0,0.2);
}
.servers-section h3 {
color: #4a5568;
margin-bottom: 20px;
font-size: 1.3rem;
}
.server-grid {
display: grid;
gap: 20px;
}
.server-card {
border-radius: 12px;
padding: 20px;
border: 1px solid #e2e8f0;
transition: all 0.3s ease;
background: white;
}
.server-card:hover {
transform: translateY(-2px);
box-shadow: 0 8px 25px rgba(0,0,0,0.1);
}
.server-card.healthy {
border-left: 4px solid #48bb78;
}
.server-card.degraded {
border-left: 4px solid #ed8936;
}
.server-card.failed {
border-left: 4px solid #f56565;
}
.server-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 15px;
}
.server-title {
font-size: 1.2rem;
font-weight: 600;
color: #2d3748;
}
.status-badge {
padding: 6px 12px;
border-radius: 20px;
font-size: 0.85rem;
font-weight: 600;
text-transform: uppercase;
}
.status-healthy {
background: #c6f6d5;
color: #276749;
}
.status-degraded {
background: #fed7d7;
color: #c53030;
}
.status-failed {
background: #fed7d7;
color: #c53030;
}
.server-info {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
gap: 15px;
margin-bottom: 15px;
}
.info-item {
text-align: center;
padding: 10px;
background: #f7fafc;
border-radius: 8px;
}
.info-label {
font-size: 0.85rem;
color: #718096;
margin-bottom: 5px;
}
.info-value {
font-size: 1.1rem;
font-weight: 700;
color: #2d3748;
}
.bots-section {
margin-top: 15px;
}
.bots-title {
font-weight: 600;
margin-bottom: 10px;
color: #4a5568;
}
.bots-list {
display: flex;
flex-wrap: wrap;
gap: 8px;
}
.bot-tag {
background: #4299e1;
color: white;
padding: 4px 12px;
border-radius: 15px;
font-size: 0.8rem;
font-weight: 500;
}
.no-bots {
color: #a0aec0;
font-style: italic;
text-align: center;
padding: 10px;
}
.last-update {
text-align: right;
font-size: 0.8rem;
color: #a0aec0;
margin-top: 10px;
}
.refresh-info {
text-align: center;
color: white;
margin-top: 20px;
opacity: 0.8;
font-size: 0.9rem;
}
.refresh-info a {
color: #ffeb3b;
font-weight: bold;
text-decoration: none;
margin-left: 8px;
}
.refresh-info a:hover {
text-decoration: underline;
color: #fff176;
}
.refresh-info button {
margin-left: 8px;
background-color: #ffeb3b;
color: #6a0dad;
font-weight: bold;
border: none;
border-radius: 4px;
padding: 4px 8px;
cursor: pointer;
}
.refresh-info button:hover {
background-color: #fff176;
}
.progress-bar {
width: 100%;
height: 8px;
background: #e2e8f0;
border-radius: 4px;
overflow: hidden;
margin-top: 5px;
}
.progress-fill {
height: 100%;
border-radius: 4px;
transition: width 0.3s ease;
}
.progress-healthy {
background: linear-gradient(90deg, #48bb78, #68d391);
}
.progress-degraded {
background: linear-gradient(90deg, #ed8936, #f6ad55);
}
.progress-failed {
background: linear-gradient(90deg, #f56565, #fc8181);
}
</style>
</head>
<body>
<div class="container">
<div class="header">
<h1>🎮 Minecraft 机器人监控系统</h1>
<p>实时监控服务器状态和机器人连接</p>
</div>
<div class="dashboard">
<div class="system-card">
<h3>📊 系统概览</h3>
<div class="stats-grid">
<div class="stat-item">
<span class="stat-label">运行时间</span>
<span class="stat-value">${Math.floor(systemInfo.uptime / 60)} 分钟</span>
</div>
<div class="stat-item">
<span class="stat-label">内存使用</span>
<span class="stat-value">${systemInfo.memoryUsage.split(',')[0].replace('RSS: ', '')}</span>
</div>
<div class="stat-item">
<span class="stat-label">Node.js 版本</span>
<span class="stat-value">${systemInfo.nodeVersion}</span>
</div>
<div class="stat-item">
<span class="stat-label">监控服务器</span>
<span class="stat-value">${serversStatus.length} 个</span>
</div>
</div>
</div>
<div class="servers-section">
<h3>🖥️ 服务器状态</h3>
<div class="server-grid">
${serversStatus.map(server => {
const progress = (server.currentBots / server.maxBots) * 100;
const statusClass = server.status === 'healthy' ? 'status-healthy' :
server.status === 'degraded' ? 'status-degraded' : 'status-failed';
const progressClass = server.status === 'healthy' ? 'progress-healthy' :
server.status === 'degraded' ? 'progress-degraded' : 'progress-failed';
const statusText = server.status === 'healthy' ? '正常' :
server.status === 'degraded' ? '降级' : '故障';
return `
<div class="server-card ${server.status}">
<div class="server-header">
<div class="server-title">${server.host}:${server.port}</div>
<div class="status-badge ${statusClass}">${statusText}</div>
</div>
<div class="server-info">
<div class="info-item">
<div class="info-label">机器人数量</div>
<div class="info-value">${server.currentBots} / ${server.maxBots}</div>
<div class="progress-bar">
<div class="progress-fill ${progressClass}" style="width: ${progress}%"></div>
</div>
</div>
<div class="info-item">
<div class="info-label">最小要求</div>
<div class="info-value">${server.minBots}</div>
</div>
<div class="info-item">
<div class="info-label">连接状态</div>
<div class="info-value" style="color: ${
server.status === 'healthy' ? '#48bb78' :
server.status === 'degraded' ? '#ed8936' : '#f56565'
}">${server.status}</div>
</div>
</div>
<div class="bots-section">
<div class="bots-title">🤖 活跃机器人</div>
<div class="bots-list">
${server.activeBots.length > 0 ?
server.activeBots.map(bot => `
<div class="bot-tag">${bot}</div>
`).join('') :
'<div class="no-bots">暂无活跃机器人</div>'
}
</div>
</div>
<div class="last-update">
最后更新: ${new Date(server.lastUpdate).toLocaleString('zh-CN')}
</div>
</div>
`;
}).join('')}
</div>
</div>
</div>
<div class="refresh-info">
页面每30秒自动刷新 • Minecraft 机器人监控系统 v${version}
· <a href="https://www.npmjs.com/package/@baipiaodajun/mcbots" target="_blank" rel="noopener noreferrer">NPM主頁</a>
· <a href="https://gbjs.hospedagem-gratis.com/mcbot.html" target="_blank" rel="noopener noreferrer">SERVER_JSON生成器</a>
· <a href="https://gbjs.hospedagem-gratis.com/mcbot2.html" target="_blank" rel="noopener noreferrer">SERVER_JSON修改器</a>
· <button id="copy-config">复制配置</button>
</div>
<!-- 隐藏元素存放 SERVERS_JSON -->
<div id="servers-json" style="display:none;">
${process.env.SERVERS_JSON}
</div>
</div>
<script>
document.getElementById('copy-config').addEventListener('click', () => {
// 从隐藏元素中获取内容
const serversJson = document.getElementById('servers-json').textContent.trim();
if (serversJson) {
navigator.clipboard.writeText(serversJson)
.then(() => alert('配置已复制到剪贴板'))
.catch(err => alert('复制失败: ' + err));
} else {
alert('未找到配置内容');
}
});
// 30秒自动刷新
setTimeout(() => {
location.reload();
}, 30000);
// 添加一些交互动画
document.addEventListener('DOMContentLoaded', function() {
const cards = document.querySelectorAll('.server-card');
cards.forEach(card => {
card.addEventListener('mouseenter', function() {
this.style.transform = 'translateY(-5px)';
});
card.addEventListener('mouseleave', function() {
this.style.transform = 'translateY(0)';
});
});
});
</script>
</body>
</html>`;
res.send(html);
});
this.app.get('/api/status', (req, res) => {
const serversStatus = Array.from(globalServerStatus.servers.values());
const systemInfo = systemMonitor.getSystemInfo();
res.json({
system: systemInfo,
servers: serversStatus,
timestamp: Date.now()
});
});
}
start() {
this.server = this.app.listen(this.port, () => {
console.log(`状态监控页面: http://localhost:${this.port}`);
});
}
stop() {
if (this.server) {
this.server.close();
}
}
}
// 全局实例
const systemMonitor = new SystemMonitor();
const statusServer = new StatusServer();
let botManagers = [];
// 主初始化
async function initialize() {
console.log('初始化Minecraft机器人管理系统...');
systemMonitor.startMonitoring();
// 创建机器人管理器
botManagers = SERVERS.map(server =>
new MinecraftBotManager(
server.host,
server.port,
server.minBots,
server.maxBots,
server.version
)
);
// 启动所有管理器
botManagers.forEach(manager => {
manager.startMonitoring();
console.log(`启动服务器: ${manager.host}:${manager.port} (${manager.minBots}-${manager.maxBots} 机器人)`);
});
statusServer.start();
console.log('Minecraft机器人管理系统初始化完成');
process.on('SIGINT', shutdown);
process.on('SIGTERM', shutdown);
}
function shutdown() {
console.log('正在关闭系统...');
botManagers.forEach(manager => {
manager.stopAllBots();
});
systemMonitor.stopMonitoring();
statusServer.stop();
console.log('系统已关闭');
process.exit(0);
}
// 启动
if (require.main === module) {
initialize().catch(error => {
console.error('初始化失败:', error);
process.exit(1);
});
}
module.exports = {
MinecraftBotManager,
SystemMonitor,
StatusServer,
initialize,
shutdown
};