can_dismantle) { throw new Exception("该物品不可分解"); } // 检查用户是否拥有该物品 $userItem = ItemUser::where('user_id', $userId) ->where('item_id', $itemId); if ($instanceId) { $userItem->where('instance_id', $instanceId); } $userItem = $userItem->first(); if (!$userItem || $userItem->quantity < $quantity) { throw new Exception("物品数量不足"); } // 获取分解规则 $rule = self::getDismantleRule($itemId); if (!$rule) { throw new Exception("没有找到适用的分解规则"); } // 开启事务 DB::beginTransaction(); // 消耗物品 ItemService::consumeItem($userId, $itemId, $instanceId, $quantity, [ 'source_type' => 'dismantle', 'source_id' => $rule->id, 'details' => [ 'rule_id' => $rule->id, 'rule_name' => $rule->name ] ]); // 获取分解结果 $dismantleResults = []; for ($i = 0; $i < $quantity; $i++) { $results = $rule->getDismantleResults(); foreach ($results as $result) { // 添加到分解结果 if (isset($dismantleResults[$result['item_id']])) { $dismantleResults[$result['item_id']]['quantity'] += $result['quantity']; } else { $dismantleResults[$result['item_id']] = $result; } } } // 添加分解结果物品到用户背包 $addedItems = []; foreach ($dismantleResults as $resultItemId => $resultData) { $resultQuantity = $resultData['quantity']; if ($resultQuantity > 0) { // 添加物品到用户背包 $addResult = ItemService::addItem($userId, $resultItemId, $resultQuantity, [ 'source_type' => REWARD_SOURCE_TYPE::DISMANTLE, 'source_id' => $rule->id, 'details' => [ 'rule_id' => $rule->id, 'rule_name' => $rule->name, 'original_item_id' => $itemId, 'original_item_name' => $item->name ] ]); $addedItems[] = [ 'item_id' => $resultItemId, 'item_name' => $resultData['item_name'], 'quantity' => $resultQuantity, 'instance_id' => $addResult['instance_id'] ?? null ]; } } // 计算返还金币 $coinReturn = 0; if ($rule->coin_return_rate > 0 && $item->sell_price > 0) { $coinReturn = floor($item->sell_price * $rule->coin_return_rate * $quantity); if ($coinReturn > 0) { // TODO: 添加金币到用户账户 // 这里需要调用Fund模块的服务来添加金币 } } // 创建分解记录 $dismantleLog = new ItemDismantleLog([ 'user_id' => $userId, 'rule_id' => $rule->id, 'item_id' => $itemId, 'instance_id' => $instanceId, 'quantity' => $quantity, 'results' => $addedItems, 'coin_return' => $coinReturn, 'dismantle_time' => now(), 'ip_address' => $options['ip_address'] ?? request()->ip(), 'device_info' => $options['device_info'] ?? request()->userAgent(), ]); $dismantleLog->save(); // 提交事务 DB::commit(); // 返回结果 return [ 'success' => true, 'dismantled_item' => [ 'item_id' => $itemId, 'item_name' => $item->name, 'quantity' => $quantity, 'instance_id' => $instanceId ], 'results' => $addedItems, 'coin_return' => $coinReturn ]; } catch (Exception $e) { // 回滚事务 if (DB::transactionLevel() > 0) { DB::rollBack(); } Log::error('分解物品失败', [ 'user_id' => $userId, 'item_id' => $itemId, 'instance_id' => $instanceId, 'quantity' => $quantity, 'error' => $e->getMessage(), 'trace' => $e->getTraceAsString() ]); return false; } } /** * 获取物品分解预览 * * @param int $userId 用户ID * @param int $itemId 物品ID * @param int|null $instanceId 物品实例ID(单独属性物品) * @return array 分解预览 */ public static function getDismantlePreview(int $userId, int $itemId, ?int $instanceId = null): array { try { // 获取物品信息 $item = Item::findOrFail($itemId); // 检查物品是否可分解 if (!$item->can_dismantle) { return [ 'can_dismantle' => false, 'reason' => '该物品不可分解' ]; } // 获取分解规则 $rule = self::getDismantleRule($itemId); if (!$rule) { return [ 'can_dismantle' => false, 'reason' => '没有找到适用的分解规则' ]; } // 获取分解结果预览(使用新的奖励组系统) // 旧的分解结果表已废弃,现在通过奖励组系统获取分解奖励 $results = []; // TODO: 实现通过奖励组获取分解预览的逻辑 // if ($rule->reward_group_id) { // $rewardService = app(\App\Module\Game\Services\RewardService::class); // $results = $rewardService->getRewardPreview($rule->reward_group_id); // } // 计算返还金币 $coinReturn = 0; if ($rule->coin_return_rate > 0 && $item->sell_price > 0) { $coinReturn = floor($item->sell_price * $rule->coin_return_rate); } return [ 'can_dismantle' => true, 'item' => [ 'item_id' => $itemId, 'item_name' => $item->name, 'instance_id' => $instanceId ], 'possible_results' => $results, 'coin_return' => $coinReturn ]; } catch (Exception $e) { Log::error('获取分解预览失败', [ 'user_id' => $userId, 'item_id' => $itemId, 'instance_id' => $instanceId, 'error' => $e->getMessage(), 'trace' => $e->getTraceAsString() ]); return [ 'can_dismantle' => false, 'reason' => '系统错误' ]; } } /** * 获取物品的分解规则 * * @param int $itemId 物品ID * @return ItemDismantleRule|null 分解规则 */ private static function getDismantleRule(int $itemId): ?ItemDismantleRule { // 获取物品信息 $item = Item::find($itemId); if (!$item) { return null; } // 获取物品稀有度(从numeric_attributes中获取,如果没有则默认为1) $rarity = 1; if ($item->numeric_attributes && isset($item->numeric_attributes['rarity'])) { $rarity = (int)$item->numeric_attributes['rarity']; } // 1. 优先查找针对特定物品的规则(包含稀有度匹配) $rule = ItemDismantleRule::where('item_id', $itemId) ->where('is_active', true) ->where('min_rarity', '<=', $rarity) ->where('max_rarity', '>=', $rarity) ->orderBy('priority', 'desc') ->first(); if ($rule) { return $rule; } // 2. 查找针对物品分类的规则(包含稀有度匹配) $rule = ItemDismantleRule::where('category_id', $item->category_id) ->whereNull('item_id') ->where('is_active', true) ->where('min_rarity', '<=', $rarity) ->where('max_rarity', '>=', $rarity) ->orderBy('priority', 'desc') ->first(); if ($rule) { return $rule; } // 3. 查找通用规则(包含稀有度匹配) $rule = ItemDismantleRule::whereNull('item_id') ->whereNull('category_id') ->where('is_active', true) ->where('min_rarity', '<=', $rarity) ->where('max_rarity', '>=', $rarity) ->orderBy('priority', 'desc') ->first(); return $rule; } }