pet; $userId = $pet->user_id; Log::info('开始处理自动收菜技能', [ 'active_skill_id' => $activeSkill->id, 'pet_id' => $pet->id, 'user_id' => $userId ]); // 获取用户所有可收获的土地 $harvestableLands = LandService::getHarvestableLands($userId); $harvestCount = 0; $harvestResults = []; if (!$harvestableLands->isEmpty()) { foreach ($harvestableLands as $land) { // 调用收获服务 $result = CropService::harvestCrop($userId, $land->id); if ($result instanceof Res && !$result->error) { $harvestCount++; $harvestResults[] = [ 'land_id' => $land->id, 'success' => true, 'auto_cleared' => false ]; Log::info('自动收菜成功', [ 'user_id' => $userId, 'pet_id' => $pet->id, 'land_id' => $land->id ]); } else { Log::warning('自动收菜失败', [ 'user_id' => $userId, 'pet_id' => $pet->id, 'land_id' => $land->id, 'error' => $result->error ?? '未知错误' ]); } } } // 记录统计信息 $this->recordSkillStatistics($activeSkill, 'auto_harvest', [ 'harvest_count' => $harvestCount, 'total_lands_checked' => $harvestableLands->count(), 'harvest_results' => $harvestResults ]); Log::info('自动收菜技能处理完成', [ 'active_skill_id' => $activeSkill->id, 'pet_id' => $pet->id, 'user_id' => $userId, 'harvest_count' => $harvestCount, 'total_lands' => $harvestableLands->count() ]); } /** * 处理自动播种技能 * * @param PetActiveSkill $activeSkill 激活的技能 * @return void * @throws \Exception */ public function processAutoPlant(PetActiveSkill $activeSkill): void { // 检查事务是否已开启 \UCore\Db\Helper::check_tr(); $pet = $activeSkill->pet; $userId = $pet->user_id; Log::info('开始处理自动播种技能', [ 'active_skill_id' => $activeSkill->id, 'pet_id' => $pet->id, 'user_id' => $userId ]); // 获取用户所有空闲的土地 $idleLands = LandService::getIdleLands($userId); if ($idleLands->isEmpty()) { Log::info('没有空闲的土地', [ 'user_id' => $userId, 'pet_id' => $pet->id ]); return; } // 获取优先使用的种子列表 $preferredSeeds = $activeSkill->getConfigValue('preferred_seeds', []); // 获取用户拥有的种子物品 $availableSeeds = $this->getAvailableSeeds($userId, $preferredSeeds); if (empty($availableSeeds)) { Log::info('没有可用的种子', [ 'user_id' => $userId, 'pet_id' => $pet->id ]); return; } $plantCount = 0; $plantResults = []; foreach ($idleLands as $land) { if (empty($availableSeeds)) { break; // 种子用完了 } // 选择种子(优先使用配置的种子) $seedItemId = array_shift($availableSeeds); // 先消耗种子物品 ItemService::consumeItem($userId, $seedItemId, null, 1, [ 'source' => 'pet_auto_plant' ]); // 调用种植服务 $result = CropService::plantCrop($userId, $land->id, $seedItemId); if ($result) { $plantCount++; $plantResults[] = [ 'land_id' => $land->id, 'seed_item_id' => $seedItemId, 'result' => $result ]; Log::info('自动播种成功', [ 'user_id' => $userId, 'pet_id' => $pet->id, 'land_id' => $land->id, 'seed_item_id' => $seedItemId ]); } else { Log::warning('自动播种失败', [ 'user_id' => $userId, 'pet_id' => $pet->id, 'land_id' => $land->id, 'seed_item_id' => $seedItemId, 'error' => '种植服务返回失败' ]); } } // 记录统计信息 $this->recordSkillStatistics($activeSkill, 'auto_plant', [ 'plant_count' => $plantCount, 'total_lands_checked' => $idleLands->count(), 'plant_results' => $plantResults ]); Log::info('自动播种技能处理完成', [ 'active_skill_id' => $activeSkill->id, 'pet_id' => $pet->id, 'user_id' => $userId, 'plant_count' => $plantCount, 'total_lands' => $idleLands->count() ]); } /** * 获取用户可用的种子 * * @param int $userId 用户ID * @param array $preferredSeeds 优先种子列表 * @return array 可用种子ID列表 */ protected function getAvailableSeeds(int $userId, array $preferredSeeds = []): array { // 调用物品服务获取用户拥有的种子 $allSeeds = ItemService::getUserSeedItems($userId); $availableSeeds = []; // 优先添加配置的种子 foreach ($preferredSeeds as $seedId) { if (isset($allSeeds[$seedId]) && $allSeeds[$seedId] > 0) { for ($i = 0; $i < $allSeeds[$seedId]; $i++) { $availableSeeds[] = $seedId; } } } // 添加其他种子 foreach ($allSeeds as $seedId => $quantity) { if (!in_array($seedId, $preferredSeeds) && $quantity > 0) { for ($i = 0; $i < $quantity; $i++) { $availableSeeds[] = $seedId; } } } return $availableSeeds; } /** * 获取清除灾害的道具 * * @param int $userId 用户ID * @param int $disasterType 灾害类型 * @return array|null 道具信息 */ protected function getDisasterClearItem(int $userId, int $disasterType): ?array { // 根据灾害类型获取对应的清除道具ID $clearItemMap = [ \App\Module\Farm\Enums\DISASTER_TYPE::DROUGHT->value => 24, // 干旱清除道具ID(洒水壶) \App\Module\Farm\Enums\DISASTER_TYPE::PEST->value => 23, // 虫害清除道具ID(杀虫剂) \App\Module\Farm\Enums\DISASTER_TYPE::WEED->value => 22, // 杂草清除道具ID(除草剂) ]; $itemId = $clearItemMap[$disasterType] ?? null; if (!$itemId) { return null; } // 检查用户是否拥有该道具 $checkResult = \App\Module\GameItems\Services\ItemService::checkItemQuantity($userId, $itemId, 1); if ($checkResult->error) { return null; } return [ 'item_id' => $itemId, 'disaster_type' => $disasterType ]; } /** * 处理自动除草技能 * * @param PetActiveSkill $activeSkill 激活的技能 * @return void * @throws \Exception */ public function processAutoWeeding(PetActiveSkill $activeSkill): void { // 检查事务是否已开启 \UCore\Db\Helper::check_tr(); // 记录开始时间用于性能监控 $startTime = microtime(true); $pet = $activeSkill->pet; $userId = $pet->user_id; Log::info('开始处理自动除草技能', [ 'active_skill_id' => $activeSkill->id, 'pet_id' => $pet->id, 'user_id' => $userId ]); // 获取用户所有有作物的土地 $landsWithCrops = LandService::getLandsWithCrops($userId); if ($landsWithCrops->isEmpty()) { Log::info('没有种植作物的土地', [ 'user_id' => $userId, 'pet_id' => $pet->id ]); return; } $weedingCount = 0; $disasterType = \App\Module\Farm\Enums\DISASTER_TYPE::WEED->value; foreach ($landsWithCrops as $land) { $landResult = $this->processLandDisasters($userId, $pet, $land, $disasterType, 'weed'); $weedingCount += $landResult['cleared_count']; // 如果遇到道具不足,记录并可能提前结束 if ($landResult['stopped_reason'] === 'insufficient_items') { Log::warning('自动除草因道具不足停止', [ 'user_id' => $userId, 'pet_id' => $pet->id, 'land_id' => $land->id, 'cleared_count' => $landResult['cleared_count'] ]); // 可以选择继续处理其他土地或者停止 // 这里选择继续处理其他土地 } } // 记录统计信息 $this->recordSkillStatistics($activeSkill, 'auto_weeding', [ 'weeding_count' => $weedingCount, 'total_lands_checked' => $landsWithCrops->count(), 'processing_time_ms' => (microtime(true) - $startTime) * 1000 ]); Log::info('自动除草技能处理完成', [ 'active_skill_id' => $activeSkill->id, 'pet_id' => $pet->id, 'user_id' => $userId, 'weeding_count' => $weedingCount, 'total_lands' => $landsWithCrops->count(), 'processing_time_ms' => round((microtime(true) - $startTime) * 1000, 2) ]); } /** * 处理自动浇水技能 * * @param PetActiveSkill $activeSkill 激活的技能 * @return array 返回处理结果统计 */ public function processAutoWatering(PetActiveSkill $activeSkill): array { // 检查事务是否已开启 \UCore\Db\Helper::check_tr(); // 记录开始时间用于性能监控 $startTime = microtime(true); try { $pet = $activeSkill->pet; $userId = $pet->user_id; Log::info('开始处理自动浇水技能', [ 'active_skill_id' => $activeSkill->id, 'pet_id' => $pet->id, 'user_id' => $userId ]); // 获取用户所有有作物的土地 $landsWithCrops = LandService::getLandsWithCrops($userId); if ($landsWithCrops->isEmpty()) { Log::info('没有种植作物的土地', [ 'user_id' => $userId, 'pet_id' => $pet->id ]); return [ 'watering_count' => 0, 'total_lands_checked' => 0, 'reason' => '没有种植作物的土地' ]; } $wateringCount = 0; $disasterType = \App\Module\Farm\Enums\DISASTER_TYPE::DROUGHT->value; foreach ($landsWithCrops as $land) { $landResult = $this->processLandDisasters($userId, $pet, $land, $disasterType, 'watering'); $wateringCount += $landResult['cleared_count']; // 如果遇到道具不足,记录并可能提前结束 if ($landResult['stopped_reason'] === 'insufficient_items') { Log::warning('自动浇水因道具不足停止', [ 'user_id' => $userId, 'pet_id' => $pet->id, 'land_id' => $land->id, 'cleared_count' => $landResult['cleared_count'] ]); } } // 记录统计信息 $statistics = [ 'watering_count' => $wateringCount, 'total_lands_checked' => $landsWithCrops->count(), 'processing_time_ms' => (microtime(true) - $startTime) * 1000 ]; $this->recordSkillStatistics($activeSkill, 'auto_watering', $statistics); Log::info('自动浇水技能处理完成', [ 'active_skill_id' => $activeSkill->id, 'pet_id' => $pet->id, 'user_id' => $userId, 'watering_count' => $wateringCount, 'total_lands' => $landsWithCrops->count(), 'processing_time_ms' => round((microtime(true) - $startTime) * 1000, 2) ]); return $statistics; } catch (\Exception $e) { Log::error('处理自动浇水技能失败', [ 'active_skill_id' => $activeSkill->id, 'error' => $e->getMessage(), 'trace' => $e->getTraceAsString() ]); return [ 'watering_count' => 0, 'total_lands_checked' => 0, 'error' => $e->getMessage(), 'reason' => '处理自动浇水技能失败' ]; } } /** * 处理自动杀虫技能 * * @param PetActiveSkill $activeSkill 激活的技能 * @return void */ public function processAutoPestControl(PetActiveSkill $activeSkill): void { // 记录开始时间用于性能监控 $startTime = microtime(true); try { $pet = $activeSkill->pet; $userId = $pet->user_id; Log::info('开始处理自动杀虫技能', [ 'active_skill_id' => $activeSkill->id, 'pet_id' => $pet->id, 'user_id' => $userId ]); // 获取用户所有有作物的土地 $landsWithCrops = LandService::getLandsWithCrops($userId); if ($landsWithCrops->isEmpty()) { Log::info('没有种植作物的土地', [ 'user_id' => $userId, 'pet_id' => $pet->id ]); return; } Log::info('开始处理自动杀虫技能', [ 'land——number' => $landsWithCrops->count() ]); $pestControlCount = 0; $disasterType = \App\Module\Farm\Enums\DISASTER_TYPE::PEST->value; foreach ($landsWithCrops as $land) { $landResult = $this->processLandDisasters($userId, $pet, $land, $disasterType, 'pest_control'); $pestControlCount += $landResult['cleared_count']; // 如果遇到道具不足,记录并可能提前结束 if ($landResult['stopped_reason'] === 'insufficient_items') { Log::warning('自动杀虫因道具不足停止', [ 'user_id' => $userId, 'pet_id' => $pet->id, 'land_id' => $land->id, 'cleared_count' => $landResult['cleared_count'] ]); } } // 记录统计信息 $this->recordSkillStatistics($activeSkill, 'auto_pest_control', [ 'pest_control_count' => $pestControlCount, 'total_lands_checked' => $landsWithCrops->count(), 'processing_time_ms' => (microtime(true) - $startTime) * 1000 ]); Log::info('自动杀虫技能处理完成', [ 'active_skill_id' => $activeSkill->id, 'pet_id' => $pet->id, 'user_id' => $userId, 'pest_control_count' => $pestControlCount, 'total_lands' => $landsWithCrops->count(), 'processing_time_ms' => round((microtime(true) - $startTime) * 1000, 2) ]); } catch (\Exception $e) { Log::error('处理自动杀虫技能失败', [ 'active_skill_id' => $activeSkill->id, 'error' => $e->getMessage(), 'trace' => $e->getTraceAsString() ]); } } /** * 处理单块土地上的特定类型灾害 * * @param int $userId 用户ID * @param mixed $pet 宠物对象 * @param LandInfoDto $land 土地对象 * @param int $disasterType 灾害类型 * @param string $disasterName 灾害名称(用于日志) * @return array 处理结果 */ protected function processLandDisasters(int $userId, $pet, LandInfoDto $land, int $disasterType, string $disasterName): array { $clearedCount = 0; $maxAttempts = 10; // 防止无限循环的最大尝试次数 $attempts = 0; $stoppedReason = 'completed'; // completed, insufficient_items, max_attempts, error while ($attempts < $maxAttempts) { $attempts++; // 检查土地是否还有该类型的灾害 if (!$this->checkSpecificDisaster($land, $disasterType)) { // 没有该类型灾害了,正常完成 $stoppedReason = 'completed'; break; } // 尝试清除灾害 try { $cleared = $this->autoClearSpecificDisaster($userId, $land, $disasterType); if ($cleared) { $clearedCount++; // 重新获取土地信息以确保数据最新 $land = $this->refreshLandInfo($land); } else { // 清除失败,通常是道具不足 $stoppedReason = 'insufficient_items'; break; } } catch (\Exception $e) { Log::error("自动{$disasterName}处理异常", [ 'user_id' => $userId, 'pet_id' => $pet->id, 'land_id' => $land->id, 'disaster_type' => $disasterType, 'attempts' => $attempts, 'cleared_count' => $clearedCount, 'error' => $e->getMessage() ]); $stoppedReason = 'error'; break; } } // 如果达到最大尝试次数 if ($attempts >= $maxAttempts) { $stoppedReason = 'max_attempts'; Log::warning("自动{$disasterName}达到最大尝试次数", [ 'user_id' => $userId, 'pet_id' => $pet->id, 'land_id' => $land->id, 'max_attempts' => $maxAttempts, 'cleared_count' => $clearedCount ]); } // 记录土地处理结果 if ($clearedCount > 0) { Log::info("土地{$disasterName}处理完成", [ 'user_id' => $userId, 'pet_id' => $pet->id, 'land_id' => $land->id, 'cleared_count' => $clearedCount, 'attempts' => $attempts, 'stopped_reason' => $stoppedReason ]); } return [ 'cleared_count' => $clearedCount, 'attempts' => $attempts, 'stopped_reason' => $stoppedReason ]; } /** * 刷新土地信息 * * @param LandInfoDto $land 土地对象 * @return LandInfoDto 刷新后的土地对象 */ protected function refreshLandInfo(LandInfoDto $land): LandInfoDto { try { // 重新从服务层获取土地信息 $refreshedLands = LandService::getLandsWithCrops($land->userId); foreach ($refreshedLands as $refreshedLand) { if ($refreshedLand->id === $land->id) { return $refreshedLand; } } // 如果没找到,返回原对象 return $land; } catch (\Exception $e) { Log::warning('刷新土地信息失败', [ 'land_id' => $land->id, 'error' => $e->getMessage() ]); return $land; } } /** * 检查特定类型的灾害 * * @param mixed $land 土地对象 * @param int $disasterType 灾害类型 * @return bool */ protected function checkSpecificDisaster(LandInfoDto $land, int $disasterType): bool { // 获取土地上的作物 $crop = $land->crop; if (!$crop) { return false; } // 检查作物是否有指定类型的活跃灾害 // 注意:根据2025年07月06日的修复,作物灾害与土地状态无关 // 作物可以有灾害但土地状态仍然是PLANTING,而不是DISASTER $disasters = $crop->disasters ?? []; foreach ($disasters as $disaster) { if (($disaster['status'] ?? '') === 'active' && ($disaster['type'] ?? 0) == $disasterType) { return true; } } return false; } /** * 自动清除特定类型的灾害 * * @param int $userId 用户ID * @param mixed $land 土地对象 * @param int $disasterType 灾害类型 * @return bool */ protected function autoClearSpecificDisaster(int $userId, $land, int $disasterType): bool { // 检查事务是否已开启 \UCore\Db\Helper::check_tr(); // 获取对应的清除道具 $clearItem = $this->getDisasterClearItem($userId, $disasterType); if (!$clearItem) { Log::debug('没有找到清除道具', [ 'user_id' => $userId, 'land_id' => $land->id, 'disaster_type' => $disasterType ]); return false; } // 先消耗道具 \App\Module\GameItems\Services\ItemService::consumeItem( $userId, $clearItem['item_id'], null, 1, ['source' => 'pet_auto_specific_disaster_clear'] ); // 调用农场服务清除灾害 $result = \App\Module\Farm\Services\CropService::clearDisaster($userId, $land->id, $disasterType); if ($result) { Log::info('宠物自动清除特定灾害成功', [ 'user_id' => $userId, 'land_id' => $land->id, 'disaster_type' => $disasterType, 'item_id' => $clearItem['item_id'] ]); return true; } else { Log::warning('宠物自动清除特定灾害失败', [ 'user_id' => $userId, 'land_id' => $land->id, 'disaster_type' => $disasterType, 'error' => '清除灾害服务返回失败' ]); return false; } } /** * 记录技能统计信息 * * @param PetActiveSkill $activeSkill 激活的技能 * @param string $actionType 操作类型 * @param array $statistics 统计数据 * @return void */ public function recordSkillStatistics(PetActiveSkill $activeSkill, string $actionType, array $statistics): void { $config = $activeSkill->config; // 确保config是数组类型 if (!is_array($config)) { // 如果是字符串,尝试解析JSON if (is_string($config)) { $config = json_decode($config, true); if (json_last_error() !== JSON_ERROR_NONE) { $config = []; } } else { $config = []; } } if (!isset($config['statistics'])) { $config['statistics'] = []; } $config['statistics'][] = [ 'action_type' => $actionType, 'timestamp' => now()->toDateTimeString(), 'data' => $statistics ]; // 只保留最近10条统计记录 if (count($config['statistics']) > 10) { $config['statistics'] = array_slice($config['statistics'], -10); } $activeSkill->config = $config; $activeSkill->save(); } /** * 清理所有枯萎的作物(不使用道具) * * 直接查找枯萎状态的作物,而不是通过土地状态 * * @param int $userId 用户ID * @return int 清理的数量 * @throws \Exception */ public function clearAllWitheredCrops(int $userId): int { // 检查事务是否已开启 \UCore\Db\Helper::check_tr(); // 直接查找所有枯萎状态的作物 $witheredCrops = \App\Module\Farm\Models\FarmCrop::whereHas('land', function($query) use ($userId) { $query->where('user_id', $userId); }) ->where('growth_stage', \App\Module\Farm\Enums\GROWTH_STAGE::WITHERED->value) ->get(); $clearedCount = 0; foreach ($witheredCrops as $crop) { $clearResult = $this->autoClearWitheredCrop($userId, $crop->land_id); if ($clearResult) { $clearedCount++; Log::info('自动清理枯萎作物成功', [ 'user_id' => $userId, 'land_id' => $crop->land_id, 'crop_id' => $crop->id ]); } else { Log::warning('自动清理枯萎作物失败', [ 'user_id' => $userId, 'land_id' => $crop->land_id, 'crop_id' => $crop->id, 'error' => '清理操作返回失败' ]); } } if ($clearedCount > 0) { Log::info('批量清理枯萎作物完成', [ 'user_id' => $userId, 'cleared_count' => $clearedCount, 'total_withered_crops' => $witheredCrops->count() ]); } return $clearedCount; } /** * 自动铲除枯萎的作物 * * @param int $userId 用户ID * @param int $landId 土地ID * @return bool 是否成功铲除 */ protected function autoClearWitheredCrop(int $userId, int $landId): bool { // 获取土地信息 $land = \App\Module\Farm\Models\FarmLand::where('id', $landId) ->where('user_id', $userId) ->first(); if (!$land) { Logger::warning('自动清理枯萎作物失败', [ 'user_id' => $userId, 'land_id' => $landId, 'error' => '土地不存在' ]); return false; } // 获取土地上的作物 $crop = \App\Module\Farm\Models\FarmCrop::where('land_id', $landId)->first(); if (!$crop) { // 如果没有作物但土地状态是枯萎,修正土地状态为空闲 $land->status = \App\Module\Farm\Enums\LAND_STATUS::IDLE->value; $land->save(); return true; } // 检查作物是否为枯萎状态 $cropStageValue = is_object($crop->growth_stage) ? $crop->growth_stage->value : $crop->growth_stage; if ($cropStageValue !== \App\Module\Farm\Enums\GROWTH_STAGE::WITHERED->value) { Logger::warning('自动清理枯萎作物失败', [ 'user_id' => $userId, 'land_id' => $landId, 'error' => '作物不是枯萎状态' ]); return false; } // 调用农场服务铲除作物(宠物自动铲除,工具ID为0) $result = \App\Module\Farm\Services\CropService::removeCrop($userId, $landId, 0); if ($result['success']) { Log::info('宠物自动铲除枯萎作物成功', [ 'user_id' => $userId, 'land_id' => $landId, 'crop_id' => $crop->id ]); return true; } else { Logger::warning('自动清理枯萎作物失败', [ 'user_id' => $userId, 'land_id' => $landId, 'error' => '铲除作物失败' ]); } return false; } /** * 处理自动施肥技能 * * @param PetActiveSkill $activeSkill 激活的技能 * @return void */ public function processAutoFertilizing(PetActiveSkill $activeSkill): void { try { $pet = $activeSkill->pet; $userId = $pet->user_id; Log::info('开始处理自动施肥技能', [ 'active_skill_id' => $activeSkill->id, 'pet_id' => $pet->id, 'user_id' => $userId ]); // 获取用户所有有作物的土地 $landsWithCrops = LandService::getLandsWithCrops($userId); if ($landsWithCrops->isEmpty()) { Log::info('没有种植作物的土地', [ 'user_id' => $userId, 'pet_id' => $pet->id ]); return; } $fertilizingCount = 0; $fertilizingResults = []; foreach ($landsWithCrops as $land) { try { // 检查土地是否可以施肥 $canFertilize = $this->checkCanFertilize($land); if ($canFertilize) { // 自动施肥 $fertilized = $this->autoFertilizeCrop($userId, $land); if ($fertilized) { $fertilizingCount++; $fertilizingResults[] = [ 'land_id' => $land->id, 'success' => true ]; Log::info('自动施肥成功', [ 'user_id' => $userId, 'pet_id' => $pet->id, 'land_id' => $land->id ]); } } } catch (\Exception $e) { Log::warning('自动施肥处理失败', [ 'user_id' => $userId, 'pet_id' => $pet->id, 'land_id' => $land->id, 'error' => $e->getMessage() ]); } } // 记录技能统计信息 $this->recordSkillStatistics($activeSkill, 'auto_fertilizing', [ 'fertilizing_count' => $fertilizingCount, 'total_lands_checked' => $landsWithCrops->count(), 'fertilizing_results' => $fertilizingResults ]); Log::info('自动施肥技能处理完成', [ 'active_skill_id' => $activeSkill->id, 'pet_id' => $pet->id, 'user_id' => $userId, 'fertilizing_count' => $fertilizingCount, 'total_lands_checked' => $landsWithCrops->count() ]); } catch (\Exception $e) { Log::error('自动施肥技能处理异常', [ 'active_skill_id' => $activeSkill->id, 'error' => $e->getMessage(), 'trace' => $e->getTraceAsString() ]); } } /** * 检查作物是否可以施肥 * * @param mixed $land 土地对象 * @return bool */ protected function checkCanFertilize($land): bool { // 获取土地上的作物 $crop = \App\Module\Farm\Models\FarmCrop::where('land_id', $land->id)->first(); if (!$crop) { return false; } // 检查作物是否已经施肥 if ($crop->fertilized) { return false; } // 检查作物生长阶段是否允许施肥(种子期、发芽期、生长期可以施肥) $growthStage = is_object($crop->growth_stage) ? $crop->growth_stage->value : $crop->growth_stage; $allowedStages = [ \App\Module\Farm\Enums\GROWTH_STAGE::SEED->value, \App\Module\Farm\Enums\GROWTH_STAGE::SPROUT->value, \App\Module\Farm\Enums\GROWTH_STAGE::GROWTH->value ]; return in_array($growthStage, $allowedStages); } /** * 自动为作物施肥 * * @param int $userId 用户ID * @param mixed $land 土地对象 * @return bool */ protected function autoFertilizeCrop(int $userId, $land): bool { // 检查事务是否已开启 \UCore\Db\Helper::check_tr(); // 获取用户的肥料道具 $fertilizerItem = $this->getFertilizerItem($userId); if (!$fertilizerItem) { Log::debug('没有找到肥料道具', [ 'user_id' => $userId, 'land_id' => $land->id ]); return false; } // 获取作物信息 $crop = \App\Module\Farm\Models\FarmCrop::where('land_id', $land->id)->first(); if (!$crop) { return false; } // 先消耗肥料道具 ItemService::consumeItem( $userId, $fertilizerItem['item_id'], null, 1, ['source' => 'pet_auto_fertilizing', 'land_id' => $land->id] ); // 使用肥料 $result = CropService::useFertilizer($crop->id, $fertilizerItem['crop_growth_time']); if ($result instanceof Res && !$result->error) { return true; } else { Log::warning('自动施肥失败', [ 'user_id' => $userId, 'land_id' => $land->id, 'error' => $result->error ?? '使用肥料失败' ]); return false; } } /** * 获取用户的肥料道具 * * @param int $userId 用户ID * @return array|null */ protected function getFertilizerItem(int $userId): ?array { // 获取用户所有物品 $userItems = ItemService::getUserItems($userId); foreach ($userItems as $userItem) { // 检查物品是否为肥料类型 $cropGrowthTime = ItemService::getItemNumericAttribute($userItem->itemId, 'crop_growth_time', 0); if ($cropGrowthTime > 0 && $userItem->quantity > 0) { return [ 'item_id' => $userItem->itemId, 'crop_growth_time' => $cropGrowthTime ]; } } return null; } /** * 收获后自动铲除枯萎的作物 * * 收获后作物会自动变成枯萎状态,此方法专门处理收获后的枯萎作物铲除 * 直接检查作物状态,而不是土地状态 * * @param int $userId 用户ID * @param int $landId 土地ID * @return array 返回操作结果 ['success' => bool, 'reason' => string, 'crop_id' => int|null] */ protected function autoClearWitheredCropAfterHarvest(int $userId, int $landId): array { try { // 获取土地信息 $land = \App\Module\Farm\Models\FarmLand::where('id', $landId) ->where('user_id', $userId) ->first(); if (!$land) { return ['success' => false, 'reason' => '土地不存在', 'crop_id' => null]; } // 获取土地上的作物(直接检查作物状态,不依赖土地状态) $crop = \App\Module\Farm\Models\FarmCrop::where('land_id', $landId)->first(); if (!$crop) { return ['success' => false, 'reason' => '土地上没有作物', 'crop_id' => null]; } // 检查作物是否为枯萎状态 $cropStageValue = is_object($crop->growth_stage) ? $crop->growth_stage->value : $crop->growth_stage; if ($cropStageValue !== \App\Module\Farm\Enums\GROWTH_STAGE::WITHERED->value) { return ['success' => false, 'reason' => '作物不是枯萎状态,当前状态: ' . $cropStageValue, 'crop_id' => $crop->id]; } // 调用农场服务铲除作物(宠物自动铲除,工具ID为0) $result = \App\Module\Farm\Services\CropService::removeCrop($userId, $landId, 0); if ($result['success']) { return [ 'success' => true, 'reason' => '宠物自动铲除枯萎作物成功', 'crop_id' => $crop->id ]; } else { return [ 'success' => false, 'reason' => '铲除作物失败', 'crop_id' => $crop->id ]; } } catch (\Exception $e) { Log::error('宠物自动铲除收获后枯萎作物失败', [ 'user_id' => $userId, 'land_id' => $landId, 'error' => $e->getMessage(), 'trace' => $e->getTraceAsString() ]); return [ 'success' => false, 'reason' => '铲除作物异常: ' . $e->getMessage(), 'crop_id' => null ]; } } }