# 物品合成系统文档 > 最后更新时间:2025年5月29日 ## 1. 系统概述 物品合成系统是一个**混合架构**的系统,同时支持传统的材料表模式和新的组系统模式: ### 1.1 双重架构设计 #### 传统模式(当前主要使用) - **ItemRecipeMaterial**:通过材料表定义合成所需的具体材料 - **直接字段**:使用`result_item_id`、`coin_cost`、`level_required`等字段 - **JSON配置**:使用`unlock_condition`等JSON字段存储复杂条件 #### 组系统模式(预留扩展) - **消耗组**:通过`consume_group_id`管理合成时需要消耗的材料和资源 - **奖励组**:通过`reward_group_id`管理合成成功后获得的奖励 - **条件组**:通过`condition_group_id`管理解锁配方需要满足的条件 ### 1.2 系统特点 - **向后兼容**:保留传统字段,确保现有功能正常运行 - **渐进升级**:可以逐步迁移到组系统,无需一次性重构 - **灵活配置**:支持复杂的合成逻辑和条件判断 ## 2. 数据库结构 ### 2.1 核心表结构 #### 2.1.1 item_recipes(合成配方表) | 字段名 | 类型 | 说明 | 使用状态 | |--------|------|------|----------| | `id` | int | 配方ID,主键 | ✅ 使用中 | | `name` | varchar(255) | 配方名称 | ✅ 使用中 | | `code` | varchar(100) | 配方编码(唯一) | ✅ 使用中 | | `description` | text | 配方描述 | ✅ 使用中 | | `consume_group_id` | int | 消耗组ID | ⚠️ 预留字段 | | `reward_group_id` | int | 奖励组ID | ⚠️ 预留字段 | | `condition_group_id` | int | 条件组ID | ⚠️ 预留字段 | | `result_item_id` | int | 产出物品ID | ✅ 使用中 | | `result_min_quantity` | int | 最小产出数量 | ✅ 使用中 | | `result_max_quantity` | int | 最大产出数量 | ✅ 使用中 | | `success_rate` | decimal(5,2) | 成功率(百分比) | ✅ 使用中 | | `coin_cost` | json | 货币成本 | ✅ 使用中 | | `level_required` | int | 所需等级 | ✅ 使用中 | | `is_default_unlocked` | tinyint | 是否默认解锁 | ✅ 使用中 | | `unlock_condition` | json | 解锁条件 | ✅ 使用中 | | `cooldown_seconds` | int | 冷却时间(秒) | ✅ 使用中 | | `category_id` | int | 配方分类ID | ✅ 使用中 | | `sort_order` | int | 排序权重 | ✅ 使用中 | | `is_active` | tinyint | 是否激活 | ✅ 使用中 | #### 2.1.2 item_recipe_materials(配方材料表) | 字段名 | 类型 | 说明 | |--------|------|------| | `id` | int | 记录ID,主键 | | `recipe_id` | int | 配方ID | | `item_id` | int | 材料物品ID | | `quantity` | int | 所需数量 | | `is_consumed` | tinyint | 是否消耗(0:不消耗, 1:消耗) | #### 2.1.3 item_user_recipes(用户配方解锁状态表) | 字段名 | 类型 | 说明 | |--------|------|------| | `id` | int | 记录ID,主键 | | `user_id` | int | 用户ID | | `recipe_id` | int | 配方ID | | `is_unlocked` | tinyint | 是否已解锁 | | `unlock_time` | timestamp | 解锁时间 | | `last_craft_time` | timestamp | 最后合成时间 | | `craft_count` | int | 合成次数 | #### 2.1.4 item_craft_logs(合成记录表) | 字段名 | 类型 | 说明 | |--------|------|------| | `id` | int | 记录ID,主键 | | `user_id` | int | 用户ID | | `recipe_id` | int | 配方ID | | `materials` | json | 消耗的材料 | | `result_item_id` | int | 获得的物品ID | | `result_instance_id` | int | 获得的单独属性物品ID | | `result_quantity` | int | 获得的物品数量 | | `is_success` | tinyint | 是否成功 | | `craft_time` | timestamp | 合成时间 | | `ip_address` | varchar(100) | 操作IP地址 | | `device_info` | text | 设备信息 | ### 2.2 数据模型关系 #### 核心模型 - **ItemRecipe**:合成配方模型,包含配方的基本信息 - **ItemRecipeMaterial**:配方材料模型,定义合成所需的具体材料 - **ItemUserRecipe**:用户配方解锁状态模型 - **ItemCraftLog**:合成记录模型,记录所有合成操作 #### 组系统模型(预留) - **GameConsumeGroup**:消耗组,定义合成时需要消耗的资源 - **GameRewardGroup**:奖励组,定义合成成功后获得的奖励 - **GameConditionGroup**:条件组,定义解锁配方的条件 ## 3. 系统架构 ### 3.1 服务层架构 #### 3.1.1 CraftService(合成服务) - **位置**:`app/Module/GameItems/Services/CraftService.php` - **功能**:对外提供合成相关的服务接口 - **主要方法**: - `craftItem()` - 合成物品 - `getUserAvailableRecipes()` - 获取用户可合成配方列表 - `unlockRecipe()` - 解锁配方 #### 3.1.2 逻辑层 - **Recipe Logic**:`app/Module/GameItems/Logics/Recipe.php` - 配方相关逻辑 - **UserRecipe Logic**:`app/Module/GameItems/Logics/UserRecipe.php` - 用户配方逻辑 - **Item Logic**:`app/Module/GameItems/Logics/Item.php` - 物品操作逻辑 ### 3.2 当前实现模式 #### 3.2.1 传统材料表模式(主要使用) **创建配方步骤**: 1. **创建配方记录**:在`item_recipes`表中创建配方 2. **添加材料需求**:在`item_recipe_materials`表中定义所需材料 3. **设置产出物品**:通过`result_item_id`等字段定义产出 4. **配置解锁条件**:通过`level_required`、`unlock_condition`等字段 **配方验证流程**: 1. **检查配方状态**:配方是否激活(`is_active`) 2. **检查解锁状态**:用户是否已解锁该配方 3. **检查等级要求**:用户等级是否满足`level_required` 4. **检查冷却时间**:是否在冷却期内 5. **检查材料充足**:是否有足够的材料和货币 **合成执行流程**: 1. **验证配方**:执行上述验证流程 2. **消耗材料**:扣除`item_recipe_materials`定义的材料 3. **消耗货币**:扣除`coin_cost`定义的货币 4. **判断成功率**:根据`success_rate`判断是否成功 5. **发放奖励**:如果成功,发放`result_item_id`定义的物品 6. **记录日志**:在`item_craft_logs`表中记录操作 #### 3.2.2 组系统模式(预留扩展) **预留字段**: - `consume_group_id` - 消耗组ID - `reward_group_id` - 奖励组ID - `condition_group_id` - 条件组ID **模型关系**: ```php // ItemRecipe模型中已定义的关系 public function consumeGroup(): BelongsTo public function rewardGroup(): BelongsTo public function conditionGroup(): BelongsTo ``` **使用方式**: ```php // 检查条件组(代码中已预留) if ($this->condition_group_id && $this->conditionGroup) { $conditionService = app(\App\Module\Game\Services\ConditionService::class); $conditionResult = $conditionService->checkConditionGroup($userId, $this->condition_group_id); } ``` ## 4. 代码使用示例 ### 4.1 合成物品 ```php use App\Module\GameItems\Services\CraftService; // 合成物品 $result = CraftService::craftItem( userId: 1001, recipeId: 1, options: [ 'quantity' => 1, 'ip_address' => '127.0.0.1', 'device_info' => 'Web Browser' ] ); if ($result) { echo "合成成功!"; // $result 包含合成结果信息 } else { echo "合成失败!"; } ``` ### 4.2 获取用户可合成配方 ```php // 获取用户可合成的配方列表 $recipes = CraftService::getUserAvailableRecipes( userId: 1001, filters: [ 'category_id' => 1 // 可选:按分类过滤 ] ); foreach ($recipes as $recipe) { echo "配方:{$recipe->name},成功率:{$recipe->success_rate}%\n"; } ``` ### 4.3 检查配方是否可合成 ```php $recipe = ItemRecipe::find(1); $canCraft = $recipe->canCraftByUser(1001); if ($canCraft['can_craft']) { echo "可以合成"; } else { echo "不能合成:" . $canCraft['reason']; } ``` ## 5. 配置示例 ### 5.1 简单配方示例 **木板制作配方**: ```sql -- 1. 创建配方 INSERT INTO item_recipes ( name, code, description, result_item_id, result_min_quantity, result_max_quantity, success_rate, level_required, is_default_unlocked, cooldown_seconds, is_active ) VALUES ( '木板制作', 'craft_wooden_plank', '将木材制作成木板', 1002, 4, 4, -- 产出4个木板(物品ID 1002) 100.00, 1, 1, -- 100%成功率,1级解锁,默认解锁 0, 1 -- 无冷却,激活状态 ); -- 2. 添加材料需求 INSERT INTO item_recipe_materials ( recipe_id, item_id, quantity, is_consumed ) VALUES ( 1, 1001, 1, 1 -- 需要1个木材(物品ID 1001),消耗 ); ``` ### 5.2 复杂配方示例 **高级装备制作**: ```sql -- 1. 创建配方 INSERT INTO item_recipes ( name, code, description, result_item_id, result_min_quantity, result_max_quantity, success_rate, coin_cost, level_required, is_default_unlocked, unlock_condition, cooldown_seconds, is_active ) VALUES ( '高级装备制作', 'craft_advanced_equipment', '制作高级装备', 2001, 1, 1, -- 产出1个高级装备 80.00, '{"gold": 100}', 20, 0, -- 80%成功率,消耗100金币,20级要求,非默认解锁 '{"skills": ["blacksmith"]}', 3600, 1 -- 需要铁匠技能,1小时冷却 ); -- 2. 添加材料需求 INSERT INTO item_recipe_materials (recipe_id, item_id, quantity, is_consumed) VALUES (2, 1003, 5, 1), -- 5个铁锭 (2, 1004, 2, 1); -- 2个宝石 ``` ## 6. 系统特点 ### 6.1 当前优势 1. **成熟稳定**:传统材料表模式经过充分测试,稳定可靠 2. **功能完整**:支持复杂的合成逻辑和条件判断 3. **性能良好**:直接查询,无额外的组系统开销 4. **易于理解**:数据结构清晰,便于开发和维护 ### 6.2 扩展能力 1. **向后兼容**:保留所有传统字段,确保现有功能不受影响 2. **渐进升级**:可以逐步迁移到组系统,无需一次性重构 3. **双重支持**:同时支持传统模式和组系统模式 4. **灵活配置**:支持JSON格式的复杂条件配置 ### 6.3 日志记录 - **完整记录**:记录所有合成操作,包括成功和失败 - **详细信息**:记录消耗的材料、获得的物品、操作时间等 - **追踪能力**:支持IP地址和设备信息记录 - **数据分析**:便于进行合成数据分析和游戏平衡调整 ## 7. 代码一致性检查结果 ### 7.1 ✅ 实际实现与预期一致的部分 1. **数据库结构**:表结构与模型定义完全一致 2. **服务层架构**:CraftService提供完整的合成服务 3. **业务逻辑**:合成流程、验证逻辑、日志记录等功能完整 4. **模型关系**:各模型之间的关系定义正确 ### 7.2 ⚠️ 发现的架构特点 1. **混合架构**:同时保留传统字段和组系统字段 2. **预留扩展**:组系统相关代码已预留,但主要使用传统模式 3. **向后兼容**:确保现有功能不受影响的设计 ### 7.3 📊 系统评估 - **功能完整度**:⭐⭐⭐⭐⭐ (5/5) - 功能完整,逻辑清晰 - **代码质量**:⭐⭐⭐⭐⭐ (5/5) - 代码结构良好,注释完善 - **扩展性**:⭐⭐⭐⭐⭐ (5/5) - 预留组系统扩展,架构灵活 - **稳定性**:⭐⭐⭐⭐⭐ (5/5) - 传统模式成熟稳定 ## 8. 总结 物品合成系统采用了**智能的混合架构设计**,既保持了传统材料表模式的稳定性和性能,又为未来的组系统升级预留了完整的扩展能力。这种设计体现了优秀的软件架构思维: - **渐进式演进**:不破坏现有功能的前提下预留扩展空间 - **向后兼容**:确保系统升级不影响现有业务 - **架构前瞻性**:为未来的功能扩展做好准备 当前系统完全可以满足合成需求,同时具备了向更灵活的组系统架构演进的能力。