原有的灾害生成系统存在以下问题:
DisasterLogic、GenerateDisasterListener、GenerateDisastersCommand 三个地方重复实现GenerateDisastersCommand 每分钟执行时会扫描所有发芽期和生长期的作物,没有状态标识在 farm_crops 表中添加两个字段:
last_disaster_check_time:
timestamp NULLcan_disaster:
tinyint(1) NOT NULL DEFAULT '1'idx_disaster_check (can_disaster, last_disaster_check_time)idx_can_disaster (can_disaster)getDisasterKey() 公共方法,统一灾害类型键名映射getCheckInterval() 方法,配置灾害检查间隔(默认5分钟)新增方法:
tryGenerateDisasterForCrop() - 核心灾害生成逻辑applyDisasterToCrop() - 将灾害应用到作物batchGenerateDisasters() - 批量生成灾害(优化版)优化特性:
with() 预加载关联数据性能提升:
last_disaster_check_time)代码简化:
DisasterLogic::batchGenerateDisasters()DisasterLogic::generateDisaster()last_disaster_check_time,确保能立即检查last_disaster_check_time 字段到 $fillable 和 $casts// 每次都查询所有发芽期和生长期的作物
$crops = FarmCrop::whereIn('growth_stage', [GROWTH_STAGE::SPROUT, GROWTH_STAGE::GROWTH])->get();
// 对每个作物都要查询关联数据
foreach ($crops as $crop) {
$land = $crop->land;
$seed = $crop->seed;
$activeBuffs = FarmGodBuff::where('user_id', $userId)->get();
// ... 重复的灾害生成逻辑
}
// 只查询需要检查的作物(基于时间戳)
$crops = FarmCrop::whereIn('growth_stage', [GROWTH_STAGE::SPROUT, GROWTH_STAGE::GROWTH])
->where(function ($query) use ($checkTime) {
$query->whereNull('last_disaster_check_time')
->orWhere('last_disaster_check_time', '<', $checkTime);
})
->with(['land.landType', 'seed', 'user.buffs']) // 预加载关联数据
->get();
with() 预加载,避免 N+1 查询last_disaster_check_time 添加索引DisasterService::getCheckInterval()最终概率 = 基础概率(0.9) - 种子抵抗/100 - 土地抵抗/100
示例:
# 手动执行灾害生成
php artisan farm:generate-disasters
// 在 Kernel.php 中配置
$schedule->command('farm:generate-disasters')->everyMinute();
// 单个作物灾害生成
$disasterLogic = new DisasterLogic();
$disasterInfo = $disasterLogic->generateDisaster($cropId);
// 批量灾害生成
$result = $disasterLogic->batchGenerateDisasters();
disasters JSON字段中// 对每种灾害类型都进行独立判定
foreach ($disasterTypes as $disasterType => $baseProb) {
// 计算该类型灾害的最终概率
$finalProb = $baseProb - $seedResistance - $landResistance;
// 独立的随机数判定
if (mt_rand(1, 100) <= $finalProb * 100) {
$generatedDisasters[] = $disasterInfo;
}
}
{
"disasters": [
{
"type": 1,
"generated_ts": "2025-05-24 11:46:51",
"status": "active"
},
{
"type": 3,
"generated_ts": "2025-05-24 11:46:51",
"status": "active"
}
]
}