| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156 |
- <?php
- namespace App\Module\Pet\Logic;
- use App\Module\Farm\Dtos\LandInfoDto;
- use App\Module\Pet\Models\PetActiveSkill;
- use App\Module\Farm\Services\CropService;
- use App\Module\Farm\Services\LandService;
- use App\Module\GameItems\Services\ItemService;
- use Illuminate\Support\Facades\Log;
- use UCore\Dto\Res;
- use UCore\Helper\Logger;
- /**
- * 宠物自动技能处理逻辑
- *
- * 处理宠物激活技能的自动执行逻辑
- */
- class PetAutoSkillLogic
- {
- /**
- * 处理自动收菜技能
- *
- * @param PetActiveSkill $activeSkill 激活的技能
- * @return void
- * @throws \Exception
- */
- public function processAutoHarvest(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
- ]);
-
- // 获取用户所有可收获的土地
- $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
- ];
- }
- }
- }
|