crop_id != 0) return ResultStatusServices::RS_LAND_HAS_CROP; $itemConfig = GameConfigServices::getParamByPath('item_list.' . $itemID); if (empty($itemConfig)) return ResultStatusServices::RS_NOT_FIND_IN_CONFIG; $cropConfig = GameConfigServices::getParamByPath('crop_list.' . $itemConfig['effect_id']); if (empty($cropConfig)) return ResultStatusServices::RS_NOT_FIND_IN_CONFIG; //修改农田数据 $landDbData->crop_id = $cropConfig['id']; $landDbData->crop_start_time = time(); $landDbData->crop_gather_time = time() + intval($cropConfig['seedling_time']) + intval($cropConfig['grow_time']) + intval($cropConfig['ripe_time']); $landDbData->is_mystery_seed = $isMysterySeed; if (!$landDbData->save()) return ResultStatusServices::RS_SAVE_DB_ERROR; } finally { } return ResultStatusServices::RS_OPERATION_SUCCESS; } /** * 收获作物 * @param $farmID * @param $position * @param $output * @param $itemID * @return int */ public static function gatherCrop($farmID, $position, &$output, &$itemID) { $output = 0; $itemID = null; //加锁 $lock = new RedisLock(Yii::$app->redis, RedisKeyUtil::lockLand($farmID, $position), RedisLock::FLAG_CATCH_EXCEPTIONS); if (!$lock->acquire(10)) return ResultStatusServices::RS_SAME_TIME_OPERATION; try { $landDbData = Land::findByFarmIDAndPosition($farmID, $position); if (!$landDbData) return ResultStatusServices::RS_NOT_FIND_IN_DB; //检查农作物 if ($landDbData->crop_id == 0) return ResultStatusServices::RS_LAND_NOT_CROP; //判断时间,农作物是否可收获 if ($landDbData->is_ripe != 1) return ResultStatusServices::RS_CROP_NOT_RIPE; //检查是否已收获过 if ($landDbData->has_gather != 0) return ResultStatusServices::RS_CROP_HAD_GATHER; //获取配置 $cropConfig = GameConfigServices::getParamByPath('crop_list.' . $landDbData->crop_id); if (empty($cropConfig)) return ResultStatusServices::RS_NOT_FIND_IN_CONFIG; //设置收获的物品 $itemID = $cropConfig['item_id']; //收获产量 $output = $landDbData->crop_num; //设置已收获标志 $landDbData->has_gather = 1; //保存数据 if (!$landDbData->save()) return ResultStatusServices::RS_SAVE_DB_ERROR; } finally { $lock->release(); } return ResultStatusServices::RS_OPERATION_SUCCESS; } /** * 更新所有农作物状态 * @param $farmID * @param $farmLevel * @return int */ public static function updateAllCropStatus($userID, $farmID, $farmLevel) { $landDbList = Land::findAll(['farm_id' => $farmID]); foreach ($landDbList as $land) { //检查是否需要更新 if ($land->crop_id != 0) { //更新单个农作物状态 $rs = self::updateCropStatus($userID, $farmID, $land->position, $farmLevel); if ($rs != ResultStatusServices::RS_OPERATION_SUCCESS) return $rs; } } return ResultStatusServices::RS_OPERATION_SUCCESS; } /** * 更新单个农作物状态 * @param $farmID * @param $position * @param $farmLevel * @return int */ public static function updateCropStatus($userID, $farmID, $position, $farmLevel) { //加锁 $lock = new RedisLock(Yii::$app->redis, RedisKeyUtil::lockLand($farmID, $position), RedisLock::FLAG_CATCH_EXCEPTIONS); if (!$lock->acquire(10)) return ResultStatusServices::RS_SAME_TIME_OPERATION; try { $landDbData = Land::findRedis($farmID, $position); if (!$landDbData) return ResultStatusServices::RS_NOT_FIND_IN_DB; //检查农作物 if ($landDbData->crop_id == 0) return ResultStatusServices::RS_LAND_NOT_CROP; //农作物是收获状态,直接返回 if ($landDbData->is_ripe == 1) return ResultStatusServices::RS_OPERATION_SUCCESS; $cropConfig = GameConfigServices::getParamByPath('crop_list.' . $landDbData->crop_id); $change = false; //判断是否达到收获时间 if (time() < self::getLandCropGatherTime($landDbData)) { //未成熟,随机病虫害 $growPhaseTime1 = $landDbData->crop_start_time + $cropConfig['seedling_time']; if (time() > $growPhaseTime1) { //种子期不随机虫 //计算需要随机的次数 if ($landDbData->disease_rand_time == 0) $lastRandTime = time() - $landDbData->crop_start_time - $cropConfig['seedling_time']; else $lastRandTime = time() - $landDbData->disease_rand_time; $time = GameConfigServices::getCommonNumByID(GameConfigServices::COMMON_DISEASE_RAND_TIME); if ($time == 0) $time = 1; $randCount = intval($lastRandTime / $time); if ($randCount <= 0) $randCount = 0; if ($randCount > 10) $randCount = 10; //随机病害 for ($i = 0; $i < $randCount; $i++) { if ($landDbData->has_dry == 0 && RandServices::randLandDisease(GameConfigServices::COMMON_DRY_RAND_NUM)) $landDbData->has_dry = 1; if ($landDbData->has_bug == 0 && RandServices::randLandDisease(GameConfigServices::COMMON_BUG_RAND_NUM)) $landDbData->has_bug = 1; if ($landDbData->has_grass == 0 && RandServices::randLandDisease(GameConfigServices::COMMON_GRASS_RAND_NUM)) $landDbData->has_grass = 1; } //更新随机时间 if ($randCount > 0) $landDbData->disease_rand_time = time(); $change = true; } } else { //农作物成熟,计算产量 //农场增产量 $farmConfig = GameConfigServices::getParamByPath('farm_level.' . $farmLevel); $farmOutput = intval($farmConfig['output']); //农作物产量 $cropOutput = intval($cropConfig['output']); //农田等级产量 $landConfig = GameConfigServices::getLandUpgradeByLevelAndPosition($landDbData->level, $landDbData->position); $landOutput = intval($landConfig['output']); //vip // $vip = CardUtil::findByUserID($userID); // $vipConfig = GameConfigServices::getParamByPath('vip_list.' . $vip->level); // $vipCount = 0; // if (!empty($vipConfig)) $vipCount = (int)$vipConfig['fruit']; //总产量 // $totalOutput = $farmOutput + $cropOutput + $landOutput ; $addPercent = floatval($farmOutput) / 100 + floatval($landOutput) / 100; $totalOutput = $cropOutput * (1 + $addPercent); //计算保底产量 $minOutputPercent = GameConfigServices::getCommonNumByID(GameConfigServices::COMMON_MIN_OUTPUT_ID) / 100; $landDbData->crop_min_num = $totalOutput * $minOutputPercent; if ($landDbData->crop_min_num < 0) $landDbData->crop_min_num = 0; //干旱减产百分比 $dryReductionPercent = 0; if ($landDbData->has_dry) $dryReductionPercent = floatval(GameConfigServices::getCommonNumByID(GameConfigServices::COMMON_DRY_ID)) / 100; //虫害减产百分比 $bugReductionPercent = 0; if ($landDbData->has_bug) $bugReductionPercent = floatval(GameConfigServices::getCommonNumByID(GameConfigServices::COMMON_BUG_ID)) / 100; //杂草减产百分比 $grassReductionPercent = 0; if ($landDbData->has_grass) $grassReductionPercent = floatval(GameConfigServices::getCommonNumByID(GameConfigServices::COMMON_GRASS_ID)) / 100; //总减产百分比 $totalReductionPercent = $dryReductionPercent + $bugReductionPercent + $grassReductionPercent; //最终产量 $landDbData->crop_num = $totalOutput * (1 - $totalReductionPercent); if ($landDbData->crop_num < $landDbData->crop_min_num) $landDbData->crop_num = $landDbData->crop_min_num; $landDbData->crop_num = intval($landDbData->crop_num); //更改成熟状态 $landDbData->is_ripe = 1; $change = true; } //保存 if ($change && !$landDbData->save()) ResultStatusServices::RS_SAVE_DB_ERROR; } finally { $lock->release(); } return ResultStatusServices::RS_OPERATION_SUCCESS; } /** * 清理农田 * @param $farmID * @param $position * @return int */ public static function clearLand($farmID, $position) { try { $landDbData = Land::findByFarmIDAndPosition($farmID, $position); if (!$landDbData) return ResultStatusServices::RS_NOT_FIND_IN_DB; //检查是否需要清理 if ($landDbData->crop_id == 0) return ResultStatusServices::RS_LAND_NOT_NEED_CLEAR; $landDbData->crop_id = 0; $landDbData->crop_start_time = 0; $landDbData->is_ripe = 0; $landDbData->crop_num = 0; $landDbData->crop_min_num = 0; $landDbData->has_dry = 0; $landDbData->has_bug = 0; $landDbData->has_grass = 0; $landDbData->has_gather = 0; $landDbData->disease_rand_time = 0; //保存 if (!$landDbData->save()) ResultStatusServices::RS_SAVE_DB_ERROR; } finally { } return ResultStatusServices::RS_OPERATION_SUCCESS; } /** * 初始化新数据 * @param Land $landDbData * @param $farmID * @param $position * @return bool */ public static function initNewFarmDataAndSave(Land $landDbData, $farmID, $position) { $landDbData->farm_id = $farmID; $landDbData->position = $position; return $landDbData->save(); } /**获取农田可交互类型 * @param $fromUserID * @param $beUserID * @param $landDbData * @return array */ public static function getLandInteractionType($fromUserID, $beUserID, Land $landDbData) { if (!Friend::findOne(['user_id' => $fromUserID, 'friend_user_id' => $beUserID, 'status' => EnumUtil::FRIEND_AGREE]) && !Friend::findOne(['user_id' => $beUserID, 'friend_user_id' => $fromUserID, 'status' => EnumUtil::FRIEND_AGREE]) ) return []; if (!$landDbData || $landDbData->crop_id == 0) return []; $typeList = []; //是否偷取过 if ($landDbData->is_ripe && !$landDbData->has_gather && !Interaction::findRedis($fromUserID, $beUserID, $landDbData->crop_start_time, $landDbData->position, EnumUtil::INTERACTION_TYPE_STEAL) && $landDbData->crop_num > $landDbData->crop_min_num ) { array_push($typeList, EnumUtil::INTERACTION_TYPE_STEAL); } //是否可以放虫 if (!$landDbData->is_ripe && !$landDbData->has_bug && !Interaction::findRedis($fromUserID, $beUserID, $landDbData->crop_start_time, $landDbData->position, EnumUtil::INTERACTION_TYPE_BUG) ) { array_push($typeList, EnumUtil::INTERACTION_TYPE_BUG); } //是否可以放草 if (!$landDbData->is_ripe && !$landDbData->has_grass && !Interaction::findRedis($fromUserID, $beUserID, $landDbData->crop_start_time, $landDbData->position, EnumUtil::INTERACTION_TYPE_GRASS) ) { array_push($typeList, EnumUtil::INTERACTION_TYPE_GRASS); } //是否可以浇水 if (!$landDbData->is_ripe && $landDbData->has_dry && !Interaction::findRedis($fromUserID, $beUserID, $landDbData->crop_start_time, $landDbData->position, EnumUtil::INTERACTION_TYPE_WATERING) ) { array_push($typeList, EnumUtil::INTERACTION_TYPE_WATERING); } //是否可以除虫 if (!$landDbData->is_ripe && $landDbData->has_bug && !Interaction::findRedis($fromUserID, $beUserID, $landDbData->crop_start_time, $landDbData->position, EnumUtil::INTERACTION_TYPE_DISINSECTION) ) { array_push($typeList, EnumUtil::INTERACTION_TYPE_DISINSECTION); } //是否可以除草 if (!$landDbData->is_ripe && $landDbData->has_grass && !Interaction::findRedis($fromUserID, $beUserID, $landDbData->crop_start_time, $landDbData->position, EnumUtil::INTERACTION_TYPE_WEEDING) ) { array_push($typeList, EnumUtil::INTERACTION_TYPE_WEEDING); } return $typeList; } /** * 偷菜 * @param $farmID * @param $position * @param $stealCount * @return int */ public static function steal($farmID, $position, &$stealCount) { //加锁 $lock = new RedisLock(Yii::$app->redis, RedisKeyUtil::lockLand($farmID, $position), RedisLock::FLAG_CATCH_EXCEPTIONS); if (!$lock->acquire(10)) return ResultStatusServices::RS_SAME_TIME_OPERATION; try { $landDbData = Land::findByFarmIDAndPosition($farmID, $position); if (!$landDbData) return ResultStatusServices::RS_NOT_FIND_IN_DB; //检查农作物 if ($landDbData->crop_id == 0) return ResultStatusServices::RS_LAND_NOT_CROP; //农作物是否成熟状态 if ($landDbData->is_ripe != 1) return ResultStatusServices::RS_CROP_NOT_RIPE; //农作物是否被收获过 if ($landDbData->has_gather == 1) return ResultStatusServices::RS_CROP_HAD_GATHER; //可偷取数量 $stealCount = GameConfigServices::getCommonNumByID(GameConfigServices::COMMON_STEAL_NUM); //收获保底数量 if ($landDbData->crop_num - $stealCount < $landDbData->crop_min_num) $stealCount = $landDbData->crop_num - $landDbData->crop_min_num; //没有可偷取的数量 if ($stealCount <= 0) return ResultStatusServices::RS_CROP_STEAL_NOT_NUM; //偷取 $landDbData->crop_num -= $stealCount; //保存 if (!$landDbData->save()) ResultStatusServices::RS_SAVE_DB_ERROR; } finally { $lock->release(); } return ResultStatusServices::RS_OPERATION_SUCCESS; } /**获取农田收获时间 * @param Land $landDbData * @return int */ public static function getLandCropGatherTime(Land $landDbData) { $cropConfig = GameConfigServices::getParamByPath('crop_list.' . $landDbData->crop_id); if (empty($cropConfig)) return $landDbData->crop_start_time; //配置表生长周期是单个周期的时间差,为了方便计算,把生长周期变成从播种开始的时间 return $landDbData->crop_start_time + $cropConfig['seedling_time'] + $cropConfig['grow_time'] + $cropConfig['ripe_time']; } /** * 获取农作物当前阶段 * @param Land $landDbData * @return int */ public static function getLandCropPhase(Land $landDbData) { $cropConfig = GameConfigServices::getParamByPath('crop_list.' . $landDbData->crop_id); //配置表生长周期是单个周期的时间差,为了方便计算,把生长周期变成从播种开始的时间 $growPhaseTime1 = $landDbData->crop_start_time + $cropConfig['seedling_time']; $growPhaseTime2 = $growPhaseTime1 + $cropConfig['grow_time']; $growPhaseTime3 = $growPhaseTime2 + $cropConfig['ripe_time']; //每个阶段还需要的时间 if (time() < $growPhaseTime1) return EnumUtil::CROP_PHASE_SEED; elseif (time() < $growPhaseTime2) return EnumUtil::CROP_PHASE_SEEDLING; elseif (time() < $growPhaseTime3) return EnumUtil::CROP_PHASE_GROW; else return EnumUtil::CROP_PHASE_RIPE; } }