feat: initial commit for TheFarmer project
This commit is contained in:
186
211/server/src/core/FarmBot.js
Normal file
186
211/server/src/core/FarmBot.js
Normal file
@@ -0,0 +1,186 @@
|
||||
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 };
|
||||
Reference in New Issue
Block a user