| ; | |
| /** | |
| * โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ | |
| * Server Optimizer โ v1.0 | ุชุญุณูู ุงูุณูุฑูุฑ ูู ุงูุฃููุงุช ุงูุญุฑุฌุฉ ูุงูู ุชูุณุทุฉ โ | |
| * โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโฃ | |
| * โ ู ุฑุงูุจุฉ ู ุณุชู ุฑุฉ: TPS + RAM + Entities + Chunks + Players โ | |
| * โ 3 ุฃูุถุงุน: CRITICAL / MODERATE / NORMAL โ | |
| * โ ุชุญุณูู ุชููุงุฆู: ุชูููู ุงูุจูุชุงุช + ุชุนุทูู Pathfinding + ุชูููู ุงูุฑุณุงุฆู โ | |
| * โ ุชุญููู ุฐูู: ุฃูู ุงุท ุงูุฃุฏุงุก + ุชูุตูุงุช + ุชูุจุค ุจุงูู ุดุงูู โ | |
| * โ ุชูุณูู ู ุน ุงูุจูุชุงุช: ุฅุฑุณุงู ุฃูุงู ุฑ ุชุนุทูู/ุชูุนูู ุญุณุจ ุงูุญุงูุฉ โ | |
| * โ ุชูุงุฑูุฑ ุฏูุฑูุฉ: ู ูุฎุต ุฃุฏุงุก ูู 5 ุฏูุงุฆู โ | |
| * โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ | |
| */ | |
| const { EventEmitter } = require('events'); | |
| const tsNow = () => new Date().toISOString().replace('T', ' ').slice(0, 19); | |
| const sleep = ms => new Promise(r => setTimeout(r, Math.max(0, ms))); | |
| // โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ | |
| // ุงูุญุฏูุฏ ูุงูุนุชุจุงุช (Thresholds) | |
| // โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ | |
| const THRESHOLDS = { | |
| // โโโ CRITICAL (ุฃูู ู ู ูุฏู ุงูุณูุฑูุฑ ุจูู ูุช) โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ | |
| critical: { | |
| tps: 10, // TPS ุฃูู ู ู 10 | |
| ram: 92, // RAM ุฃุนูู ู ู 92% | |
| entities: 200, // Entities ุฃุนูู ู ู 200 | |
| chunkRate: 50, // Chunks per second ุฃูู ู ู 50 | |
| playerPing: 500, // Ping ุฃุนูู ู ู 500ms | |
| }, | |
| // โโโ MODERATE (ููู ุถุบุท ุจุณ ูุณู ุดุบุงู) โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ | |
| moderate: { | |
| tps: 16, // TPS ุฃูู ู ู 16 | |
| ram: 80, // RAM ุฃุนูู ู ู 80% | |
| entities: 120, // Entities ุฃุนูู ู ู 120 | |
| chunkRate: 100, // Chunks per second ุฃูู ู ู 100 | |
| playerPing: 300, // Ping ุฃุนูู ู ู 300ms | |
| }, | |
| // โโโ NORMAL (ูู ุญุงุฌุฉ ุชู ุงู ) โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ | |
| normal: { | |
| tps: 19, | |
| ram: 65, | |
| entities: 60, | |
| chunkRate: 200, | |
| playerPing: 150, | |
| } | |
| }; | |
| // โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ | |
| // ุฅุนุฏุงุฏุงุช ูู ูุถุน | |
| // โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ | |
| const MODE_CONFIGS = { | |
| // โโโ CRITICAL: ุฃูู ูุดุงุท ู ู ูู โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ | |
| critical: { | |
| label: '๐ด ุญุฑุฌ', | |
| botActivity: 'minimal', // ุฃูู ูุดุงุท | |
| pathfinding: false, // ุชุนุทูู Pathfinding ุชู ุงู ุงู | |
| chatFrequency: 0, // ุชุนุทูู ุงูุฑุณุงุฆู | |
| taskInterval: 60000, // ุงูู ูุงู ูู ุฏูููุฉ | |
| maxActiveBots: 2, // ุฃูู ุนุฏุฏ ุจูุชุงุช ุดุบุงูุฉ | |
| autoEat: true, // ุงูุฃูู ุดุบุงู ุฏุงูู ุงู | |
| autoSleep: true, // ุงูููู ุดุบุงู | |
| combatResponse: 'flee', // ุงููุฑูุจ ุจุณ | |
| miningEnabled: false, // ุชุนุทูู ุงูุชุนุฏูู | |
| buildingEnabled: false, // ุชุนุทูู ุงูุจูุงุก | |
| farmingEnabled: false, // ุชุนุทูู ุงูุฒุฑุงุนุฉ | |
| explorationEnabled: false, // ุชุนุทูู ุงูุงุณุชูุดุงู | |
| tradingEnabled: false, // ุชุนุทูู ุงูุชุฌุงุฑุฉ | |
| socialEnabled: false, // ุชุนุทูู ุงูุชูุงุนู | |
| dailyRoutine: false, // ุชุนุทูู ุงูุฑูุชูู ุงูููู ู | |
| antiAfk: 'sleep', // ุจุณ ููู | |
| viewDistance: 'tiny', // ุฃูู ู ุณุงูุฉ ุฑุคูุฉ | |
| }, | |
| // โโโ MODERATE: ูุดุงุท ู ุชูุณุท โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ | |
| moderate: { | |
| label: '๐ก ู ุชูุณุท', | |
| botActivity: 'reduced', // ูุดุงุท ู ุฎูู | |
| pathfinding: true, // Pathfinding ุดุบุงู ุจุณ ุจุทูุก | |
| chatFrequency: 0.3, // 30% ู ู ุงูุฑุณุงุฆู ุงูุนุงุฏูุฉ | |
| taskInterval: 30000, // ุงูู ูุงู ูู 30 ุซุงููุฉ | |
| maxActiveBots: 4, // 4 ุจูุชุงุช ูุญุฏ ุฃูุตู | |
| autoEat: true, | |
| autoSleep: true, | |
| combatResponse: 'fight', // ูุชุงู ุนุงุฏู | |
| miningEnabled: true, | |
| buildingEnabled: true, | |
| farmingEnabled: true, | |
| explorationEnabled: false, // ุงูุงุณุชูุดุงู ู ุชููู | |
| tradingEnabled: false, // ุงูุชุฌุงุฑุฉ ู ุชูููุฉ | |
| socialEnabled: true, | |
| dailyRoutine: true, | |
| antiAfk: 'moderate', // ุญุฑูุฉ ู ุชูุณุทุฉ | |
| viewDistance: 'short', // ู ุณุงูุฉ ุฑุคูุฉ ูุตูุฑุฉ | |
| }, | |
| // โโโ NORMAL: ูู ุญุงุฌุฉ ุดุบุงูุฉ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ | |
| normal: { | |
| label: '๐ข ุทุจูุนู', | |
| botActivity: 'full', // ูุดุงุท ูุงู ู | |
| pathfinding: true, | |
| chatFrequency: 1.0, // ูู ุงูุฑุณุงุฆู | |
| taskInterval: 15000, // ุงูู ูุงู ูู 15 ุซุงููุฉ | |
| maxActiveBots: 10, // ูู ุงูุจูุชุงุช | |
| autoEat: true, | |
| autoSleep: true, | |
| combatResponse: 'fight', | |
| miningEnabled: true, | |
| buildingEnabled: true, | |
| farmingEnabled: true, | |
| explorationEnabled: true, | |
| tradingEnabled: true, | |
| socialEnabled: true, | |
| dailyRoutine: true, | |
| antiAfk: 'full', // ุญุฑูุฉ ูุงู ูุฉ | |
| viewDistance: 'normal', // ู ุณุงูุฉ ุฑุคูุฉ ุนุงุฏูุฉ | |
| } | |
| }; | |
| // โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ | |
| // ServerOptimizer Class | |
| // โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ | |
| class ServerOptimizer extends EventEmitter { | |
| constructor(config = {}) { | |
| super(); | |
| this.config = { | |
| checkInterval: config.checkInterval || 10000, // ูุญุต ูู 10 ุซูุงูู | |
| reportInterval: config.reportInterval || 300000, // ุชูุฑูุฑ ูู 5 ุฏูุงุฆู | |
| historySize: config.historySize || 300, // 50 ุฏูููุฉ ู ู ุงูุจูุงูุงุช | |
| recoveryDelay: config.recoveryDelay || 60000, // ุฏูููุฉ ูุจู ุงูุฑุฌูุน ู ู CRITICAL | |
| autoModeSwitch: config.autoModeSwitch !== false, // ุชุบููุฑ ุชููุงุฆู ูููุถุน | |
| ...config | |
| }; | |
| // โโโ ุงูุญุงูุฉ ุงูุญุงููุฉ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ | |
| this.currentMode = 'normal'; // ุงููุถุน ุงูุญุงูู | |
| this.previousMode = 'normal'; // ุงููุถุน ุงูุณุงุจู | |
| this.modeStartTime = Date.now(); // ููุช ุจุฏุก ุงููุถุน ุงูุญุงูู | |
| this.modeTransitionPending = null; // ุชุบููุฑ ูุดูู | |
| this.modeTransitionTimer = null; // ู ุคูุช ุงูุชุบููุฑ | |
| // โโโ ุงูุจูุงูุงุช โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ | |
| this.metrics = { | |
| tps: 20, | |
| ram: 50, | |
| entities: 0, | |
| chunks: 0, | |
| players: 0, | |
| ping: 0, | |
| worldTime: 0, | |
| uptime: 0, | |
| botCount: 0, | |
| activeBots: 0, | |
| }; | |
| this.history = []; | |
| this.alerts = []; | |
| this.optimizations = []; | |
| this.stats = { | |
| modeChanges: 0, | |
| optimizationsApplied: 0, | |
| criticalEvents: 0, | |
| moderateEvents: 0, | |
| normalEvents: 0, | |
| totalChecks: 0, | |
| avgTps: 20, | |
| avgRam: 50, | |
| worstTps: 20, | |
| worstRam: 50, | |
| }; | |
| // โโโ ุงูุจูุชุงุช ุงูู ุชุตูุฉ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ | |
| this.connectedBots = new Map(); // botId โ { bot, mode, lastAction } | |
| this._running = false; | |
| this._checkTimer = null; | |
| this._reportTimer = null; | |
| this._log('OPTIMIZER', 'ุชู ุฅูุดุงุก Server Optimizer v1.0'); | |
| } | |
| _log(tag, msg) { | |
| console.log(`[${tsNow()}] [OPTIMIZER] ${tag} ${msg}`); | |
| } | |
| // โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ | |
| // ุจุฏุก/ุฅููุงู ุงูุชุญุณูู | |
| // โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ | |
| start() { | |
| if (this._running) return; | |
| this._running = true; | |
| this._log('๐ข', 'ุจุฏุก ู ุฑุงูุจุฉ ูุชุญุณูู ุงูุณูุฑูุฑ...'); | |
| this._checkTimer = setInterval(() => this._check(), this.config.checkInterval); | |
| this._reportTimer = setInterval(() => this._report(), this.config.reportInterval); | |
| this._optimCycleTimer = setInterval(() => this._runOptimizationCycle(), 30000); | |
| this._check(); | |
| this._report(); | |
| } | |
| stop() { | |
| this._running = false; | |
| if (this._checkTimer) { clearInterval(this._checkTimer); this._checkTimer = null; } | |
| if (this._reportTimer) { clearInterval(this._reportTimer); this._reportTimer = null; } | |
| if (this.modeTransitionTimer) { clearTimeout(this.modeTransitionTimer); this.modeTransitionTimer = null; } | |
| if (this._optimCycleTimer) { clearInterval(this._optimCycleTimer); this._optimCycleTimer = null; } | |
| this._log('๐ด', 'ุฅููุงู Server Optimizer'); | |
| } | |
| // โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ | |
| // ุงูุชุญูู ุงูุฑุฆูุณู (ูู 10 ุซูุงูู) | |
| // โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ | |
| async _check() { | |
| if (!this._running) return; | |
| this.stats.totalChecks++; | |
| try { | |
| // โโโ ุชุญููู ุงูุญุงูุฉ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ | |
| const analysis = this._analyzeMetrics(); | |
| const newMode = analysis.recommendedMode; | |
| // โโโ ุชุญุฏูุซ ุงูุฅุญุตุงุฆูุงุช โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ | |
| this._updateStats(); | |
| // โโโ ุญูุธ ูู ุงูุชุงุฑูุฎ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ | |
| this.history.push({ | |
| time: Date.now(), | |
| mode: this.currentMode, | |
| tps: this.metrics.tps, | |
| ram: this.metrics.ram, | |
| entities: this.metrics.entities, | |
| players: this.metrics.players, | |
| analysis: analysis.reasons | |
| }); | |
| if (this.history.length > this.config.historySize) this.history.shift(); | |
| // โโโ ุชุบููุฑ ุงููุถุน ุฅุฐุง ูุฒู โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ | |
| if (this.config.autoModeSwitch && newMode !== this.currentMode) { | |
| this._requestModeChange(newMode, analysis.reasons); | |
| } | |
| // โโโ ุชุทุจูู ุงูุชุญุณููุงุช ุนูู ุงูุจูุชุงุช โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ | |
| this._applyOptimizations(); | |
| // โโโ ุฅุฑุณุงู ุงูุฃุญุฏุงุซ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ | |
| this.emit('check', { mode: this.currentMode, metrics: { ...this.metrics }, analysis }); | |
| } catch (err) { | |
| this._log('โ', `ุฎุทุฃ ูู ุงููุญุต: ${err.message}`); | |
| } | |
| } | |
| // โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ | |
| // ุชุญููู ุงูู ูุงููุณ ูุชุญุฏูุฏ ุงููุถุน | |
| // โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ | |
| _analyzeMetrics() { | |
| const m = this.metrics; | |
| const reasons = []; | |
| let score = 0; // 0-100 (0=ุญุฑุฌ, 100=ู ู ุชุงุฒ) | |
| // โโโ ุชุญููู TPS โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ | |
| if (m.tps <= THRESHOLDS.critical.tps) { | |
| score -= 40; | |
| reasons.push(`TPS ุญุฑุฌ: ${m.tps}`); | |
| } else if (m.tps <= THRESHOLDS.moderate.tps) { | |
| score -= 20; | |
| reasons.push(`TPS ู ูุฎูุถ: ${m.tps}`); | |
| } else { | |
| score += 20; | |
| } | |
| // โโโ ุชุญููู RAM โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ | |
| if (m.ram >= THRESHOLDS.critical.ram) { | |
| score -= 30; | |
| reasons.push(`RAM ุญุฑุฌ: ${m.ram}%`); | |
| } else if (m.ram >= THRESHOLDS.moderate.ram) { | |
| score -= 15; | |
| reasons.push(`RAM ู ุฑุชูุน: ${m.ram}%`); | |
| } else { | |
| score += 15; | |
| } | |
| // โโโ ุชุญููู Entities โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ | |
| if (m.entities >= THRESHOLDS.critical.entities) { | |
| score -= 15; | |
| reasons.push(`Entities ูุชูุฑ: ${m.entities}`); | |
| } else if (m.entities >= THRESHOLDS.moderate.entities) { | |
| score -= 8; | |
| reasons.push(`Entities ู ุชูุณุท: ${m.entities}`); | |
| } else { | |
| score += 10; | |
| } | |
| // โโโ ุชุญููู ุงููุงุนุจูู โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ | |
| if (m.players > 10) { | |
| score -= 10; | |
| reasons.push(`ูุงุนุจูู ูุชูุฑ: ${m.players}`); | |
| } else if (m.players > 5) { | |
| score -= 5; | |
| } else { | |
| score += 5; | |
| } | |
| // โโโ ุชุญููู ุงูุจูุชุงุช โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ | |
| const activeBots = this.connectedBots.size; | |
| if (activeBots > 6) { | |
| score -= 10; | |
| reasons.push(`ุจูุชุงุช ูุชูุฑ ุดุบุงูุฉ: ${activeBots}`); | |
| } else if (activeBots > 3) { | |
| score -= 5; | |
| } else { | |
| score += 5; | |
| } | |
| // โโโ ุชุญุฏูุฏ ุงููุถุน โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ | |
| let recommendedMode; | |
| if (score <= 20) { | |
| recommendedMode = 'critical'; | |
| } else if (score <= 35) { | |
| recommendedMode = 'moderate'; | |
| } else { | |
| recommendedMode = 'normal'; | |
| } | |
| // โโโ ุชุญููู ุงูุงุชุฌุงู (ูู Situation ุจุชุชุญุณู ุฃู ุจุช tแปุ) โโโโโโโโโโโโโโโโโโ | |
| const trend = this._analyzeTrend(); | |
| return { | |
| score: Math.max(0, Math.min(100, score)), | |
| recommendedMode, | |
| reasons, | |
| trend, | |
| details: { | |
| tpsStatus: m.tps >= 19 ? '๐ข' : m.tps >= 16 ? '๐ก' : '๐ด', | |
| ramStatus: m.ram <= 65 ? '๐ข' : m.ram <= 80 ? '๐ก' : '๐ด', | |
| entityStatus: m.entities <= 60 ? '๐ข' : m.entities <= 120 ? '๐ก' : '๐ด', | |
| } | |
| }; | |
| } | |
| _analyzeTrend() { | |
| if (this.history.length < 10) return 'stable'; | |
| const recent = this.history.slice(-10); | |
| const older = this.history.slice(-20, -10); | |
| if (older.length === 0) return 'stable'; | |
| const recentAvgTps = recent.reduce((s, h) => s + h.tps, 0) / recent.length; | |
| const olderAvgTps = older.reduce((s, h) => s + h.tps, 0) / older.length; | |
| if (recentAvgTps > olderAvgTps + 2) return 'improving'; | |
| if (recentAvgTps < olderAvgTps - 2) return 'worsening'; | |
| return 'stable'; | |
| } | |
| // โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ | |
| // ุชุบููุฑ ุงููุถุน | |
| // โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ | |
| _requestModeChange(newMode, reasons) { | |
| // โโโ CRITICAL: ุชุบููุฑ ููุฑู โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ | |
| if (newMode === 'critical') { | |
| this._switchMode(newMode, reasons); | |
| return; | |
| } | |
| // โโโ MODERATE โ NORMAL: ุงูุชุธุงุฑ 30 ุซุงููุฉ ููุชุฃูุฏ โโโโโโโโโโโโโโโโโโโโโโโโโโ | |
| if (this.currentMode === 'critical' && newMode === 'moderate') { | |
| if (this.modeTransitionPending === 'moderate') { | |
| // ุงูุชุธุฑ ุฃูุซุฑ | |
| return; | |
| } | |
| this.modeTransitionPending = 'moderate'; | |
| this._log('โณ', 'ุงูุชุธุงุฑ 30 ุซุงููุฉ ููุฑุฌูุน ู ู CRITICAL...'); | |
| this.modeTransitionTimer = setTimeout(() => { | |
| this._switchMode('moderate', reasons); | |
| this.modeTransitionPending = null; | |
| }, 30000); | |
| return; | |
| } | |
| // โโโ MODERATE โ NORMAL: ุงูุชุธุงุฑ ุฏูููุฉ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ | |
| if (this.currentMode === 'moderate' && newMode === 'normal') { | |
| if (this.modeTransitionPending === 'normal') return; | |
| this.modeTransitionPending = 'normal'; | |
| this._log('โณ', 'ุงูุชุธุงุฑ 60 ุซุงููุฉ ููุฑุฌูุน ู ู MODERATE...'); | |
| this.modeTransitionTimer = setTimeout(() => { | |
| this._switchMode('normal', reasons); | |
| this.modeTransitionPending = null; | |
| }, 60000); | |
| return; | |
| } | |
| // โโโ ุฃู ุชุบููุฑ ุชุงูู: ููุฑู โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ | |
| this._switchMode(newMode, reasons); | |
| } | |
| _switchMode(newMode, reasons) { | |
| if (this.modeTransitionTimer) { | |
| clearTimeout(this.modeTransitionTimer); | |
| this.modeTransitionTimer = null; | |
| } | |
| this.modeTransitionPending = null; | |
| const oldMode = this.currentMode; | |
| this.previousMode = oldMode; | |
| this.currentMode = newMode; | |
| this.modeStartTime = Date.now(); | |
| this.stats.modeChanges++; | |
| if (newMode === 'critical') this.stats.criticalEvents++; | |
| else if (newMode === 'moderate') this.stats.moderateEvents++; | |
| else this.stats.normalEvents++; | |
| const config = MODE_CONFIGS[newMode]; | |
| this._log('๐', `ุชุบููุฑ ุงููุถุน: ${MODE_CONFIGS[oldMode].label} โ ${config.label}`); | |
| this._log('๐', `ุงูุฃุณุจุงุจ: ${reasons.join(', ')}`); | |
| // โโโ ุฅุฑุณุงู ุฃุญุฏุงุซ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ | |
| this.emit('modeChange', { | |
| from: oldMode, | |
| to: newMode, | |
| config, | |
| reasons, | |
| timestamp: Date.now() | |
| }); | |
| // โโโ ุฅุดุนุงุฑ ุงูุจูุชุงุช โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ | |
| this._notifyBotsModeChange(newMode, config); | |
| } | |
| // โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ | |
| // ุฅุฏุงุฑุฉ ุงูุจูุชุงุช ุงูู ุชุตูุฉ | |
| // โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ | |
| registerBot(botId, bot) { | |
| this.connectedBots.set(botId, { | |
| bot, | |
| mode: this.currentMode, | |
| lastAction: Date.now(), | |
| disabled: false, | |
| pathfindingEnabled: true, | |
| chatEnabled: true, | |
| }); | |
| this._log('๐ค', `ุจูุช ู ุณุฌู: ${botId} (${this.connectedBots.size} ุจูุช)`); | |
| this._applyBotMode(botId); | |
| } | |
| unregisterBot(botId) { | |
| this.connectedBots.delete(botId); | |
| this._log('๐', `ุจูุช ุงููุตู: ${botId} (${this.connectedBots.size} ุจูุช)`); | |
| } | |
| _notifyBotsModeChange(newMode, config) { | |
| this.connectedBots.forEach((data, botId) => { | |
| data.mode = newMode; | |
| this._applyBotMode(botId); | |
| }); | |
| } | |
| _applyBotMode(botId) { | |
| const data = this.connectedBots.get(botId); | |
| if (!data || !data.bot) return; | |
| const config = MODE_CONFIGS[this.currentMode]; | |
| try { | |
| // โโโ ุชุนุทูู/ุชูุนูู Pathfinding โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ | |
| data.pathfindingEnabled = config.pathfinding; | |
| // โโโ ุชุนุทูู/ุชูุนูู ุงูุฑุณุงุฆู โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ | |
| data.chatEnabled = config.chatFrequency > 0; | |
| // โโโ ุชูููู ูุดุงุท ุงูุจูุช โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ | |
| if (config.botActivity === 'minimal') { | |
| data.bot._optimizerMode = 'minimal'; | |
| } else if (config.botActivity === 'reduced') { | |
| data.bot._optimizerMode = 'reduced'; | |
| } else { | |
| data.bot._optimizerMode = 'full'; | |
| } | |
| this._log('โ๏ธ', ` Bot ${botId}: ูุถุน ${config.label}`); | |
| } catch (err) { | |
| this._log('โ', `ุฎุทุฃ ูู ุชุทุจูู ุงููุถุน ุนูู ${botId}: ${err.message}`); | |
| } | |
| } | |
| _runOptimizationCycle() { | |
| const bots = [...this.connectedBots.values()].filter(d => d.bot && !d.disabled); | |
| if (bots.length === 0) return; | |
| const b = bots[0].bot; | |
| if (!b) return; | |
| try { b.chat('/tps'); } catch(_) {} | |
| setTimeout(() => { | |
| if (!b) return; | |
| try { b.chat('/lagg clear'); } catch(_) {} | |
| if (this.currentMode === 'critical') { | |
| setTimeout(() => { | |
| if (!b) return; | |
| try { b.chat('/lagg clear'); } catch(_) {} | |
| setTimeout(() => { | |
| if (!b) return; | |
| try { b.chat('/minecraft:kill @e[type=item]'); } catch(_) {} | |
| }, 500); | |
| }, 500); | |
| } | |
| }, 500); | |
| } | |
| _applyOptimizations() { | |
| const config = MODE_CONFIGS[this.currentMode]; | |
| this.connectedBots.forEach((data, botId) => { | |
| if (!data.bot) return; | |
| try { | |
| // โโโ ูู ุงููุถุน ุงูุญุฑุฌ: ุชูููู ูู ุญุงุฌุฉ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ | |
| if (this.currentMode === 'critical') { | |
| // โโโ ุฅููุงู ุฃู ุญุฑูุฉ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ | |
| if (data.bot.pathfinder && data.pathfindingEnabled) { | |
| data.pathfindingEnabled = false; | |
| } | |
| // โโโ ุฅููุงู ุงูุชุนุฏูู โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ | |
| if (data.bot._mining && config.miningEnabled === false) { | |
| data.bot._mining = false; | |
| } | |
| // โโโ ุฅููุงู ุงูุจูุงุก โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ | |
| if (data.bot._building && config.buildingEnabled === false) { | |
| data.bot._building = false; | |
| } | |
| } | |
| // โโโ ูู ุงููุถุน ุงูู ุชูุณุท: ุชูููู ุงููุดุงุท โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ | |
| if (this.currentMode === 'moderate') { | |
| // โโโ ุชูููู ุณุฑุนุฉ Pathfinding โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ | |
| if (data.bot.pathfinder && data.pathfindingEnabled) { | |
| data.bot.pathfinder.setTicksPerTick(2); // ุจุทูุก | |
| } | |
| } | |
| // โโโ ูู ุงููุถุน ุงูุทุจูุนู: ูู ุญุงุฌุฉ ุดุบุงูุฉ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ | |
| if (this.currentMode === 'normal') { | |
| if (data.bot.pathfinder && !data.pathfindingEnabled) { | |
| data.pathfindingEnabled = true; | |
| } | |
| if (data.bot.pathfinder) { | |
| data.bot.pathfinder.setTicksPerTick(1); // ุนุงุฏู | |
| } | |
| } | |
| } catch (err) { | |
| // ุชุฌุงูู ุงูุฃุฎุทุงุก | |
| } | |
| }); | |
| } | |
| // โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ | |
| // ุชุญุฏูุซ ุงูู ูุงููุณ (ูุชู ุงุณุชุฏุนุงุคู ู ู ะฒะฝะตัะฝะธะต ุฃูุธู ุฉ) | |
| // โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ | |
| updateMetrics(newMetrics) { | |
| Object.assign(this.metrics, newMetrics); | |
| } | |
| updateTps(tps) { | |
| this.metrics.tps = tps; | |
| } | |
| updateRam(ramPercent) { | |
| this.metrics.ram = ramPercent; | |
| } | |
| updateEntities(count) { | |
| this.metrics.entities = count; | |
| } | |
| updatePlayers(count) { | |
| this.metrics.players = count; | |
| } | |
| // โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ | |
| // ุชุญุฏูุซ ุงูุฅุญุตุงุฆูุงุช | |
| // โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ | |
| _updateStats() { | |
| const m = this.metrics; | |
| const n = this.stats.totalChecks; | |
| this.stats.avgTps = ((this.stats.avgTps * (n - 1)) + m.tps) / n; | |
| this.stats.avgRam = ((this.stats.avgRam * (n - 1)) + m.ram) / n; | |
| this.stats.worstTps = Math.min(this.stats.worstTps, m.tps); | |
| this.stats.worstRam = Math.max(this.stats.worstRam, m.ram); | |
| } | |
| // โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ | |
| // ุงูุชูุงุฑูุฑ ุงูุฏูุฑูุฉ | |
| // โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ | |
| _report() { | |
| if (!this._running) return; | |
| const m = this.metrics; | |
| const config = MODE_CONFIGS[this.currentMode]; | |
| const uptime = Date.now() - this.modeStartTime; | |
| const uptimeMin = Math.floor(uptime / 60000); | |
| this._log('๐', 'โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ'); | |
| this._log('๐', `ุงููุถุน ุงูุญุงูู: ${config.label}`); | |
| this._log('๐', `TPS: ${m.tps} | RAM: ${m.ram}% | Entities: ${m.entities} | Players: ${m.players}`); | |
| this._log('๐', `ุจูุชุงุช ู ุชุตูุฉ: ${this.connectedBots.size}`); | |
| this._log('๐', `ู ุฏุฉ ุงููุถุน ุงูุญุงูู: ${uptimeMin} ุฏูููุฉ`); | |
| this._log('๐', `ุชุบููุฑุงุช ุงููุถุน: ${this.stats.modeChanges} | ุฃุญุฏุงุซ ุญุฑุฌุฉ: ${this.stats.criticalEvents}`); | |
| this._log('๐', `TPS ุงูู ุชูุณุท: ${this.stats.avgTps.toFixed(1)} | Worst: ${this.stats.worstTps}`); | |
| this._log('๐', `RAM ุงูู ุชูุณุท: ${this.stats.avgRam.toFixed(1)}% | Worst: ${this.stats.worstRam}%`); | |
| this._log('๐', 'โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ'); | |
| this.emit('report', this.getStatus()); | |
| } | |
| // โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ | |
| // ุงูุญุตูู ุนูู ุงูุญุงูุฉ ุงููุงู ูุฉ | |
| // โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ | |
| getStatus() { | |
| const config = MODE_CONFIGS[this.currentMode]; | |
| const uptime = Date.now() - this.modeStartTime; | |
| return { | |
| running: this._running, | |
| currentMode: this.currentMode, | |
| modeLabel: config.label, | |
| previousMode: this.previousMode, | |
| modeUptime: uptime, | |
| modeUptimeMin: Math.floor(uptime / 60000), | |
| metrics: { ...this.metrics }, | |
| config: { ...config }, | |
| stats: { ...this.stats }, | |
| connectedBots: this.connectedBots.size, | |
| historySize: this.history.length, | |
| analysis: this._analyzeMetrics(), | |
| recommendations: this._getRecommendations(), | |
| }; | |
| } | |
| // โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ | |
| // ุงูุชูุตูุงุช ุงูุฐููุฉ | |
| // โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ | |
| _getRecommendations() { | |
| const recs = []; | |
| const m = this.metrics; | |
| if (m.tps < 14) { | |
| recs.push({ | |
| priority: 'high', | |
| type: 'tps', | |
| message: 'TPS ู ูุฎูุถ ุฌุฏุงู โ ููู ุนุฏุฏ ุงูุจูุชุงุช ุฃู ุนุทูู ุจุนุถ ุงูู ูุฒุงุช', | |
| action: 'reduce_bots' | |
| }); | |
| } | |
| if (m.ram > 85) { | |
| recs.push({ | |
| priority: 'high', | |
| type: 'ram', | |
| message: 'RAM ุนุงูู ุฌุฏุงู โ ุดุบูู GC ูุฏููุงู ุฃู ููู ุงููุงุด', | |
| action: 'force_gc' | |
| }); | |
| } | |
| if (m.entities > 150) { | |
| recs.push({ | |
| priority: 'medium', | |
| type: 'entities', | |
| message: 'ุนุฏุฏ Entities ูุจูุฑ โ ููู ู ุณุงูุฉ ุงูุฑุคูุฉ ุฃู ุนุทูู ุจุนุถ ุงูู ูุฒุงุช', | |
| action: 'reduce_view' | |
| }); | |
| } | |
| if (this.connectedBots.size > 5) { | |
| recs.push({ | |
| priority: 'medium', | |
| type: 'bots', | |
| message: `ุนุฏุฏ ุงูุจูุชุงุช ูุจูุฑ (${this.connectedBots.size}) โ ููู ุงูุนุฏุฏ`, | |
| action: 'reduce_bots' | |
| }); | |
| } | |
| if (this.stats.worstTps < 8) { | |
| recs.push({ | |
| priority: 'low', | |
| type: 'history', | |
| message: `ูุตู TPS ูู ${this.stats.worstTps} ูุจู ูุฏู โ ุฑุงูุจ ุงูุฃุณุจุงุจ`, | |
| action: 'monitor' | |
| }); | |
| } | |
| return recs; | |
| } | |
| // โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ | |
| // ุงูุชุญูู ุงููุฏูู | |
| // โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ | |
| setMode(mode) { | |
| if (!MODE_CONFIGS[mode]) { | |
| this._log('โ', `ูุถุน ุบูุฑ ุตุญูุญ: ${mode}`); | |
| return false; | |
| } | |
| this._switchMode(mode, ['manual_override']); | |
| this._log(' manual', `ุชู ุชุบููุฑ ุงููุถุน ูุฏููุงู ุฅูู: ${MODE_CONFIGS[mode].label}`); | |
| return true; | |
| } | |
| forceOptimization() { | |
| this._log('๐ง', 'ุชุญุณูู ุฅุฌุจุงุฑู...'); | |
| this._applyOptimizations(); | |
| this.stats.optimizationsApplied++; | |
| return true; | |
| } | |
| getModeConfig(mode) { | |
| return MODE_CONFIGS[mode] ? { ...MODE_CONFIGS[mode] } : null; | |
| } | |
| getHistory(minutes = 30) { | |
| const cutoff = Date.now() - (minutes * 60000); | |
| return this.history.filter(h => h.time >= cutoff); | |
| } | |
| destroy() { | |
| this.stop(); | |
| this.connectedBots.clear(); | |
| this.history = []; | |
| this.alerts = []; | |
| this.optimizations = []; | |
| this.removeAllListeners(); | |
| } | |
| } | |
| module.exports = { ServerOptimizer, THRESHOLDS, MODE_CONFIGS }; | |