27日1200-宠物生活技能LastData修复.md 7.5 KB

宠物生活技能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(包含所有后续修复、验证和兼容性处理)