# 宠物生活技能LastData修复 ## 任务概述 修复宠物生活技能使用成功后,LastData没有进行宠物和生活技能状态同步的问题。 ## 问题分析 ### 问题现象 - 宠物生活技能使用成功,技能生效了 - 但是LastData没有包含宠物状态数据 - 前端无法获取到宠物的最新状态(如体力消耗、技能冷却等) ### 问题根因 通过代码分析发现: 1. **PetLogic::useSkill** 方法在技能使用成功后触发了 `PetSkillUsedEvent` 事件 2. **Game模块** 有处理其他宠物事件的监听器: - `PetCreatedListener` - 处理宠物创建事件 - `PetUpdateListener` - 处理宠物更新事件 - `PetStatusChangedListener` - 处理宠物状态变更事件 3. **但是缺少 `PetSkillUsedListener`** 来监听 `PetSkillUsedEvent` 事件 4. **AppGameProtobufResponseListener** 统一处理LastData,但没有获取到宠物技能使用后的数据 ### 事件流程分析 正常流程应该是: 1. 用户调用宠物生活技能使用接口 2. PetLogic::useSkill 执行技能逻辑,消耗体力,记录日志 3. 触发 PetSkillUsedEvent 事件 4. PetSkillUsedListener 监听到事件,调用 PetTemp::handlePetSkillUsed 5. PetTemp 将宠物最新状态存储到临时缓存 6. AppGameProtobufResponseListener 从临时缓存获取宠物数据,设置到LastData 7. 前端收到包含宠物状态的LastData 实际流程中第4-6步缺失,导致LastData中没有宠物状态数据。 ## 修复内容 ### 1. 创建PetSkillUsedListener监听器 **文件**: `app/Module/Game/Listeners/PetSkillUsedListener.php` - 监听 `PetSkillUsedEvent` 事件 - 调用 `PetTemp::handlePetSkillUsed` 处理宠物数据暂存 - 添加完整的错误处理和日志记录 - 与其他宠物事件监听器保持一致的结构 ### 2. 在PetTemp中添加处理方法 **文件**: `app/Module/Game/Logics/PetTemp.php` - 添加 `handlePetSkillUsed` 方法 - 复用现有的 `handlePetFullData` 方法进行数据处理 - 确保宠物技能使用后的完整状态被正确存储 ### 3. 注册事件监听器 **文件**: `app/Module/Game/Providers/GameServiceProvider.php` - 添加 `PetSkillUsedListener` 的import - 添加 `PetSkillUsedEvent` 的import - 在boot方法中注册事件监听器映射 ## 修复原理 ### 事件驱动架构 宠物模块使用事件驱动架构实现模块间通信: - 宠物模块负责业务逻辑和事件发布 - Game模块负责数据暂存和LastData处理 - AppGame模块负责统一的LastData响应 ### 数据流转机制 1. **事件触发**: 宠物技能使用成功后触发事件 2. **数据暂存**: Game模块监听事件,将宠物最新状态存储到临时缓存 3. **数据同步**: AppGameProtobufResponseListener从临时缓存获取数据,设置到LastData 4. **前端更新**: 前端收到LastData,更新宠物状态显示 ### 一致性保证 - 所有宠物相关事件都通过统一的PetTemp处理 - 使用相同的数据格式和存储机制 - 确保事件处理的原子性和一致性 ## 测试验证 修复后需要验证以下场景: 1. **宠物生活技能使用** - 使用宠物生活技能 - 验证LastData中包含宠物状态数据 - 验证宠物体力、技能冷却等状态正确更新 2. **多技能连续使用** - 连续使用多个宠物技能 - 验证每次使用后LastData都正确更新 - 验证宠物状态累积变化正确 3. **技能使用失败场景** - 体力不足时使用技能 - 技能冷却期间使用技能 - 验证失败时不触发LastData更新 4. **其他宠物事件** - 验证宠物创建、更新、状态变更等其他事件仍正常工作 - 确保新增监听器不影响现有功能 ## 影响范围 - **Game模块**: 新增PetSkillUsedListener监听器 - **宠物模块**: 无变更,继续发布PetSkillUsedEvent事件 - **AppGame模块**: 无变更,继续统一处理LastData - **前端**: 可以正常接收到宠物状态更新 ## 后续修复 ### 问题:宠物技能使用数据临时存储错误 在添加监听器后,发现新的错误:"Attempt to read property \"value\" on int" **根因分析**: - PetDtoFactory::createPetDataDto方法中试图访问`$pet->grade->value` - 但PetUser模型中grade字段只是integer类型,不是枚举 - 而status字段被正确转换为PetStatus枚举 **修复内容**: 1. 创建缺失的PetGrade枚举 2. 修复PetDtoFactory中的属性访问: - grade字段直接使用integer值 - status字段使用枚举的value属性 3. 修复DTO属性名称不匹配问题 ### 问题:宠物技能使用数据临时存储中lifeSkills对象数组转换问题 在修复属性访问问题后,发现新的错误:"Attempt to read property \"skillId\" on array" **根因分析**: - PetTemp::handlePetFullData方法中使用`$petDto->toArray()`复制属性 - BaseDto的toArray方法会将对象数组转换为普通数组 - 导致lifeSkills从PetLifeSkillDto对象数组变成了普通数组 - AppGameProtobufResponseListener访问`$lifeSkill->skillId`时出错 **修复内容**: - 修改PetTemp::handlePetFullData方法,直接复制对象属性而不使用toArray() - 确保lifeSkills保持为PetLifeSkillDto对象数组类型 - 避免BaseDto::toArray()方法导致的对象类型转换问题 ### 问题:PetStatusTempDto的fromCache方法无法正确恢复lifeSkills对象数组 在修复对象属性复制问题后,发现缓存恢复时仍然出现"Attempt to read property \"skillId\" on array"错误 **根因分析**: - BaseDto的fromCache方法只是简单调用fromArray方法 - fromArray方法不能正确处理嵌套的对象数组(如lifeSkills) - 当缓存中的数据被恢复时,lifeSkills数组中的PetLifeSkillDto对象变成了普通数组 - AppGameProtobufResponseListener访问`$lifeSkill->skillId`时出错,因为$lifeSkill是数组而不是对象 **修复内容**: - 为PetStatusTempDto创建自定义的fromCache方法 - 重写方法以正确处理lifeSkills数组的恢复 - 确保数组中的每个元素都被正确转换为PetLifeSkillDto对象 - 在AppGameProtobufResponseListener中添加兼容性处理,支持对象和数组两种格式 - 添加验证脚本验证修复效果 ### 最终解决方案:兼容性处理 经过测试发现,虽然fromCache方法能够正确处理部分情况,但Laravel的缓存序列化机制仍然可能导致lifeSkills变成数组格式。 **最终修复方案**: - 在AppGameProtobufResponseListener中添加兼容性处理 - 支持lifeSkills的对象和数组两种格式 - 确保无论缓存恢复时数据是什么格式,都能正确处理 ## 提交信息 ``` 修复宠物生活技能使用后LastData缺少宠物状态同步问题:添加PetSkillUsedListener监听器 修复宠物技能使用数据临时存储错误:创建PetGrade枚举并修复PetDtoFactory属性访问问题 修复宠物技能使用数据临时存储中lifeSkills对象数组转换问题:直接复制对象属性避免toArray()导致的类型转换 添加AppGameProtobufResponseListener调试信息:诊断lifeSkills数据类型问题 完善PetStatusTempDto的fromCache方法:彻底修复lifeSkills对象数组的缓存恢复问题 移除调试信息并完善AppGameProtobufResponseListener的兼容性处理:支持lifeSkills的对象和数组两种格式 ``` ## 测试验证 通过Protobuf请求测试验证修复效果: - 宠物技能使用成功 - LastData正确包含宠物状态数据 - 生活技能信息完整显示 - 不再出现"Attempt to read property \"skillId\" on array"错误 ## 完成时间 2025-05-27 15:00(包含所有后续修复、验证和兼容性处理)