187 lines
5.9 KiB
JavaScript
187 lines
5.9 KiB
JavaScript
const EventEmitter = require('events');
|
|
const { NetworkClient } = require('./Network');
|
|
const { FarmManager } = require('./FarmManager');
|
|
const { FriendManager } = require('./FriendManager');
|
|
const { WarehouseManager } = require('./WarehouseManager');
|
|
const { ShopManager } = require('./ShopManager');
|
|
const { log, logWarn, emitRuntimeHint } = require('../utils');
|
|
const { CONFIG } = require('../config');
|
|
|
|
class FarmBot extends EventEmitter {
|
|
constructor(config = {}) {
|
|
super();
|
|
// Merge provided config with default CONFIG
|
|
// Deep copy to avoid modifying global CONFIG if passed by reference (though usually it's shallow copy)
|
|
this.config = { ...CONFIG, ...config };
|
|
|
|
// Initialize components
|
|
this.network = new NetworkClient(this);
|
|
this.farmManager = new FarmManager(this);
|
|
this.friendManager = new FriendManager(this);
|
|
this.warehouseManager = new WarehouseManager(this);
|
|
this.shopManager = new ShopManager(this);
|
|
this.dailyClaimTimer = null;
|
|
|
|
// State
|
|
this.isRunning = false;
|
|
this.user = {
|
|
gid: 0,
|
|
name: 'Loading...',
|
|
level: 0,
|
|
gold: 0,
|
|
exp: 0,
|
|
tickets: 0,
|
|
fertilizer: 0,
|
|
freeMallClaimDate: ''
|
|
};
|
|
|
|
// Error handling
|
|
this.network.on('error', (err) => {
|
|
log('机器人', `网络错误: ${err.message}`);
|
|
this.emit('error', err);
|
|
});
|
|
|
|
this.network.on('disconnected', () => {
|
|
if (this.isRunning) {
|
|
log('机器人', '连接断开,正在尝试重新连接...');
|
|
// Reconnection logic is handled in NetworkClient, but we can monitor it here
|
|
}
|
|
});
|
|
}
|
|
|
|
async start() {
|
|
if (this.isRunning) return;
|
|
this.isRunning = true;
|
|
|
|
this.log('系统', `正在启动农场小助手... 平台: ${this.config.platform}`);
|
|
emitRuntimeHint(true);
|
|
|
|
try {
|
|
// 1. Connect
|
|
this.log('系统', '正在连接服务器...');
|
|
await new Promise((resolve, reject) => {
|
|
const timeout = setTimeout(() => reject(new Error('连接超时')), 10000);
|
|
this.network.connect((success) => {
|
|
clearTimeout(timeout);
|
|
if (success) resolve();
|
|
else reject(new Error('连接失败'));
|
|
});
|
|
});
|
|
|
|
// 2. Login
|
|
this.log('系统', '正在登录...');
|
|
await new Promise((resolve, reject) => {
|
|
const timeout = setTimeout(() => reject(new Error('登录超时')), 10000);
|
|
this.network.sendLogin((success) => {
|
|
clearTimeout(timeout);
|
|
if (success) resolve();
|
|
else reject(new Error('登录失败'));
|
|
});
|
|
});
|
|
|
|
// 3. Start Loops
|
|
this.log('系统', '开始自动化作业...');
|
|
this.farmManager.startLoop();
|
|
if (this.config.enableFriendOps !== false) {
|
|
this.friendManager.startLoop();
|
|
}
|
|
if (this.config.enableAutoSell !== false) {
|
|
this.warehouseManager.startLoop();
|
|
}
|
|
this.startDailyClaimLoop();
|
|
|
|
this.emit('started');
|
|
this.log('系统', '农场小助手启动成功!');
|
|
|
|
} catch (error) {
|
|
this.log('系统', `启动失败: ${error.message}`);
|
|
this.stop();
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
stop() {
|
|
this.isRunning = false;
|
|
this.farmManager.stopLoop();
|
|
this.friendManager.stopLoop();
|
|
this.warehouseManager.stopLoop();
|
|
this.stopDailyClaimLoop();
|
|
|
|
// Stop network
|
|
if (this.network.ws) {
|
|
this.network.ws.close();
|
|
}
|
|
|
|
this.emit('stopped');
|
|
log('系统', '农场小助手已停止');
|
|
}
|
|
|
|
log(tag, msg) {
|
|
log(tag, msg);
|
|
this.emit('log', {
|
|
tag,
|
|
msg,
|
|
time: Date.now()
|
|
});
|
|
}
|
|
|
|
logWarn(tag, msg) {
|
|
logWarn(tag, msg);
|
|
this.emit('log', {
|
|
tag,
|
|
msg,
|
|
type: 'warn',
|
|
time: Date.now()
|
|
});
|
|
}
|
|
|
|
getTodayKey() {
|
|
const now = new Date();
|
|
const y = now.getFullYear();
|
|
const m = `${now.getMonth() + 1}`.padStart(2, '0');
|
|
const d = `${now.getDate()}`.padStart(2, '0');
|
|
return `${y}-${m}-${d}`;
|
|
}
|
|
|
|
async runDailyClaims() {
|
|
if (!this.isRunning) return;
|
|
await this.network.tryClaimShareReward(1);
|
|
const todayKey = this.getTodayKey();
|
|
if (this.user.freeMallClaimDate === todayKey) return;
|
|
try {
|
|
await this.shopManager.purchaseMallItem(1001, 1);
|
|
this.user.freeMallClaimDate = todayKey;
|
|
this.emit('userUpdate', this.user);
|
|
this.log('商城', '已领取每日免费礼包');
|
|
} catch (e) {
|
|
this.logWarn('商城', `领取失败: ${e.message}`);
|
|
}
|
|
}
|
|
|
|
startDailyClaimLoop() {
|
|
if (this.dailyClaimTimer) return;
|
|
const scheduleNext = () => {
|
|
if (!this.isRunning) return;
|
|
const now = new Date();
|
|
const next = new Date(now);
|
|
next.setHours(24, 0, 0, 0);
|
|
const delay = Math.max(1000, next.getTime() - now.getTime());
|
|
this.dailyClaimTimer = setTimeout(async () => {
|
|
this.dailyClaimTimer = null;
|
|
await this.runDailyClaims();
|
|
scheduleNext();
|
|
}, delay);
|
|
};
|
|
scheduleNext();
|
|
}
|
|
|
|
stopDailyClaimLoop() {
|
|
if (this.dailyClaimTimer) {
|
|
clearTimeout(this.dailyClaimTimer);
|
|
this.dailyClaimTimer = null;
|
|
}
|
|
}
|
|
}
|
|
|
|
module.exports = { FarmBot };
|