PetTemp.php 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335
  1. <?php
  2. namespace App\Module\Game\Logics;
  3. use App\Module\Game\Dtos\PetCreatedTempDto;
  4. use App\Module\Game\Dtos\PetDataSimpleTempDto;
  5. use App\Module\Game\Dtos\PetStatusTempDto;
  6. use App\Module\Pet\Events\PetCreatedEvent;
  7. use App\Module\Pet\Events\PetStatusChangedEvent;
  8. use App\Module\Pet\Events\PetUpdateEvent;
  9. use App\Module\Pet\Services\PetService;
  10. use Illuminate\Support\Facades\Log;
  11. use UCore\Helper\Cache;
  12. /**
  13. * 宠物临时数据逻辑类
  14. *
  15. * 负责处理宠物相关事件的临时数据存储逻辑,包括:
  16. * 1. 将宠物创建数据临时存储
  17. * 2. 将宠物状态变更数据临时存储
  18. * 3. 按照用户进行存储
  19. * 4. 同一宠物多次变更进行数据覆盖
  20. */
  21. class PetTemp
  22. {
  23. // 已移除 TEMP_KEY_CREATED_PREFIX,与 TEMP_KEY_UPDATE_PREFIX 合并
  24. /**
  25. * 临时数据键前缀 - 宠物状态变更
  26. */
  27. const TEMP_KEY_STATUS_PREFIX = 'game:pet:status:';
  28. /**
  29. * 临时数据键前缀 - 宠物更新
  30. */
  31. const TEMP_KEY_UPDATE_PREFIX = 'game:pet:update:';
  32. /**
  33. * 临时数据过期时间(秒)
  34. */
  35. const TEMP_TTL = 3600; // 1小时
  36. /**
  37. * 处理宠物完整数据事件
  38. *
  39. * 将宠物完整数据临时存储,按用户ID进行存储
  40. * 这是一个通用方法,用于处理PetCreatedEvent和PetUpdateEvent事件
  41. *
  42. * @param int $userId 用户ID
  43. * @param int $petId 宠物ID
  44. * @param string $eventType 事件类型,用于日志
  45. * @return void
  46. */
  47. private static function handlePetFullData(int $userId, int $petId, string $eventType): void
  48. {
  49. try {
  50. // 构建临时数据键,按用户ID进行存储
  51. $tempKey = self::TEMP_KEY_UPDATE_PREFIX . $userId;
  52. // 获取当前用户的宠物临时数据
  53. $userPetsTemp = Cache::get($tempKey, []);
  54. try {
  55. // 使用服务层获取宠物数据,避免跨模块直接访问Model
  56. // 创建PetStatusTempDto对象
  57. $tempDto = new PetStatusTempDto();
  58. // 直接复制对象属性,避免toArray()导致的对象数组转换问题
  59. $tempDto->id = $petId;
  60. // 设置更新时间
  61. $tempDto->updatedAt = time();
  62. // 使用宠物ID作为键,实现同一宠物多次变更的数据覆盖
  63. // 直接存储DTO对象,而不是转换为数组
  64. $userPetsTemp[$petId] = $tempDto;
  65. // 将更新后的数据存回临时存储
  66. Cache::put($tempKey, $userPetsTemp, self::TEMP_TTL);
  67. Log::info("宠物{$eventType}数据已临时存储", [
  68. 'user_id' => $userId,
  69. 'pet_id' => $petId,
  70. 'updated_at' => $tempDto->updatedAt,
  71. ]);
  72. } catch (\Exception $e) {
  73. // 如果服务层调用失败,记录错误并抛出异常
  74. Log::error("获取宠物数据失败", [
  75. 'error' => $e->getMessage(),
  76. 'user_id' => $userId,
  77. 'pet_id' => $petId,
  78. ]);
  79. throw $e;
  80. }
  81. } catch (\Exception $e) {
  82. Log::error("宠物{$eventType}数据临时存储失败", [
  83. 'error' => $e->getMessage(),
  84. 'user_id' => $userId,
  85. 'pet_id' => $petId,
  86. ]);
  87. }
  88. }
  89. /**
  90. * 处理宠物创建事件
  91. *
  92. * 将宠物创建数据临时存储,按用户ID进行存储
  93. *
  94. * @param PetCreatedEvent $event 宠物创建事件
  95. * @return void
  96. */
  97. public static function handlePetCreated(PetCreatedEvent $event): void
  98. {
  99. self::handlePetFullData($event->userId, $event->petId, '创建');
  100. }
  101. /**
  102. * 处理宠物状态变更事件
  103. *
  104. * 将宠物状态变更数据临时存储,按用户ID进行存储
  105. *
  106. * @param PetStatusChangedEvent $event 宠物状态变更事件
  107. * @return void
  108. */
  109. public static function handlePetStatusChanged(PetStatusChangedEvent $event): void
  110. {
  111. try {
  112. // 构建临时数据键,按用户ID进行存储
  113. $tempKey = self::TEMP_KEY_STATUS_PREFIX . $event->userId;
  114. // 获取当前用户的宠物状态变更临时数据
  115. $userPetsStatusTemp = Cache::get($tempKey, []);
  116. // 创建PetDataSimpleTempDto对象
  117. $tempDto = new PetDataSimpleTempDto();
  118. // 从事件中复制宠物基本数据
  119. $tempDto->id = $event->petId;
  120. $tempDto->typeId = $event->petData->typeId;
  121. $tempDto->name = $event->petData->name;
  122. $tempDto->level = $event->petData->level;
  123. $tempDto->exp = $event->petData->exp;
  124. $tempDto->power = $event->petData->power;
  125. $tempDto->maxpower = $event->petData->maxpower;
  126. $tempDto->score = $event->petData->score;
  127. $tempDto->status = $event->newStatusData->status;
  128. // $tempDto->grade = $event->petData->grade;
  129. // 设置状态变更相关属性
  130. $tempDto->oldStatus = $event->oldStatusData->status;
  131. $tempDto->newStatus = $event->newStatusData->status;
  132. $tempDto->reason = $event->reason;
  133. $tempDto->updatedAt = time();
  134. // 使用宠物ID作为键,实现同一宠物多次变更的数据覆盖
  135. // 直接存储DTO对象,而不是转换为数组
  136. $userPetsStatusTemp[$event->petId] = $tempDto;
  137. // 将更新后的数据存回临时存储
  138. Cache::put($tempKey, $userPetsStatusTemp, self::TEMP_TTL);
  139. Log::info('宠物状态变更数据已临时存储', [
  140. 'user_id' => $event->userId,
  141. 'pet_id' => $event->petId,
  142. 'old_status' => $event->oldStatusData->status,
  143. 'new_status' => $event->newStatusData->status,
  144. 'pet_name' => $event->petData->name,
  145. ]);
  146. } catch (\Exception $e) {
  147. Log::error('宠物状态变更数据临时存储失败', [
  148. 'error' => $e->getMessage(),
  149. 'user_id' => $event->userId,
  150. 'pet_id' => $event->petId,
  151. ]);
  152. }
  153. }
  154. /**
  155. * 获取用户的宠物创建临时数据
  156. *
  157. * @param int $userId 用户ID
  158. * @return PetStatusTempDto[] 用户的宠物创建数据
  159. */
  160. public static function getUserPetCreated(int $userId): array
  161. {
  162. // 使用统一的前缀,与宠物更新数据共用一个缓存键
  163. return self::getUserPetUpdates($userId);
  164. }
  165. /**
  166. * 获取用户特定宠物的创建临时数据
  167. *
  168. * @param int $userId 用户ID
  169. * @param int $petId 宠物ID
  170. * @return PetStatusTempDto|null 宠物创建数据,不存在时返回null
  171. */
  172. public static function getUserPetCreatedById(int $userId, int $petId): ?PetStatusTempDto
  173. {
  174. // 使用统一的方法,与宠物更新数据共用一个获取方法
  175. return self::getUserPetUpdateById($userId, $petId);
  176. }
  177. /**
  178. * 获取用户的宠物状态变更临时数据
  179. *
  180. * @param int $userId 用户ID
  181. * @return PetDataSimpleTempDto[] 用户的宠物状态变更数据
  182. */
  183. public static function getUserPetStatus(int $userId): array
  184. {
  185. $tempKey = self::TEMP_KEY_STATUS_PREFIX . $userId;
  186. $cachedData = Cache::get($tempKey, []);
  187. // 使用fromCache方法处理缓存数据,确保返回正确类型的DTO对象
  188. return PetDataSimpleTempDto::fromCache($cachedData);
  189. }
  190. /**
  191. * 获取用户特定宠物的状态变更临时数据
  192. *
  193. * @param int $userId 用户ID
  194. * @param int $petId 宠物ID
  195. * @return PetDataSimpleTempDto|null 宠物状态变更数据,不存在时返回null
  196. */
  197. public static function getUserPetStatusById(int $userId, int $petId): ?PetDataSimpleTempDto
  198. {
  199. $userPetStatus = self::getUserPetStatus($userId);
  200. return $userPetStatus[$petId] ?? null;
  201. }
  202. /**
  203. * 处理宠物更新事件
  204. *
  205. * 将宠物更新数据临时存储,按用户ID进行存储
  206. *
  207. * @param PetUpdateEvent $event 宠物更新事件
  208. * @return void
  209. */
  210. public static function handlePetUpdate(PetUpdateEvent $event): void
  211. {
  212. self::handlePetFullData($event->userId, $event->petId, '更新');
  213. }
  214. /**
  215. * 处理宠物技能使用事件
  216. *
  217. * 将宠物技能使用后的数据临时存储,按用户ID进行存储
  218. *
  219. * @param \App\Module\Pet\Events\PetSkillUsedEvent $event 宠物技能使用事件
  220. * @return void
  221. */
  222. public static function handlePetSkillUsed(\App\Module\Pet\Events\PetSkillUsedEvent $event): void
  223. {
  224. self::handlePetFullData($event->userId, $event->petId, '技能使用');
  225. }
  226. /**
  227. * 获取用户的宠物更新临时数据
  228. *
  229. * @param int $userId 用户ID
  230. * @return PetStatusTempDto[] 用户的宠物更新数据
  231. */
  232. public static function getUserPetUpdates(int $userId): array
  233. {
  234. $tempKey = self::TEMP_KEY_UPDATE_PREFIX . $userId;
  235. $cachedData = Cache::get($tempKey, []);
  236. // 使用fromCache方法处理缓存数据,确保返回正确类型的DTO对象
  237. return PetStatusTempDto::fromCache($cachedData);
  238. }
  239. /**
  240. * 获取用户特定宠物的更新临时数据
  241. *
  242. * @param int $userId 用户ID
  243. * @param int $petId 宠物ID
  244. * @return PetStatusTempDto|null 宠物更新数据,不存在时返回null
  245. */
  246. public static function getUserPetUpdateById(int $userId, int $petId): ?PetStatusTempDto
  247. {
  248. $userPetUpdates = self::getUserPetUpdates($userId);
  249. return $userPetUpdates[$petId] ?? null;
  250. }
  251. /**
  252. * 清除用户的宠物更新临时数据
  253. *
  254. * @param int $userId 用户ID
  255. * @return void
  256. */
  257. public static function clearUserPetUpdates(int $userId): void
  258. {
  259. $tempKey = self::TEMP_KEY_UPDATE_PREFIX . $userId;
  260. Cache::put($tempKey, [], 0);
  261. }
  262. /**
  263. * 清除用户的宠物创建临时数据
  264. *
  265. * @param int $userId 用户ID
  266. * @return void
  267. */
  268. public static function clearUserPetCreated(int $userId): void
  269. {
  270. // 使用统一的方法,与宠物更新数据共用一个清除方法
  271. self::clearUserPetUpdates($userId);
  272. }
  273. /**
  274. * 清除用户的宠物状态变更临时数据
  275. *
  276. * @param int $userId 用户ID
  277. * @return void
  278. */
  279. public static function clearUserPetStatus(int $userId): void
  280. {
  281. $tempKey = self::TEMP_KEY_STATUS_PREFIX . $userId;
  282. Cache::put($tempKey, [], 0);
  283. }
  284. /**
  285. * 清除用户的所有宠物临时数据
  286. *
  287. * @param int $userId 用户ID
  288. * @return void
  289. */
  290. public static function clearUserAllPetTemp(int $userId): void
  291. {
  292. self::clearUserPetCreated($userId);
  293. self::clearUserPetStatus($userId);
  294. }
  295. }