PetTemp.php 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316
  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. $petDto = PetService::getPetStatus($userId, $petId);
  57. // 创建PetStatusTempDto对象
  58. $tempDto = new PetStatusTempDto();
  59. // 复制属性
  60. foreach ($petDto->toArray() as $key => $value) {
  61. $property = \UCore\Dto\BaseDto::snakeToCamel($key);
  62. if (property_exists($tempDto, $property)) {
  63. $tempDto->{$property} = $value;
  64. }
  65. }
  66. // 设置更新时间
  67. $tempDto->updatedAt = time();
  68. // 使用宠物ID作为键,实现同一宠物多次变更的数据覆盖
  69. // 直接存储DTO对象,而不是转换为数组
  70. $userPetsTemp[$petId] = $tempDto;
  71. // 将更新后的数据存回临时存储
  72. Cache::put($tempKey, $userPetsTemp, self::TEMP_TTL);
  73. Log::info("宠物{$eventType}数据已临时存储", [
  74. 'user_id' => $userId,
  75. 'pet_id' => $petId,
  76. 'name' => $tempDto->name,
  77. 'level' => $tempDto->level,
  78. 'grade' => $tempDto->grade,
  79. ]);
  80. } catch (\Exception $e) {
  81. // 如果服务层调用失败,记录错误并抛出异常
  82. Log::error("获取宠物数据失败", [
  83. 'error' => $e->getMessage(),
  84. 'user_id' => $userId,
  85. 'pet_id' => $petId,
  86. ]);
  87. throw $e;
  88. }
  89. } catch (\Exception $e) {
  90. Log::error("宠物{$eventType}数据临时存储失败", [
  91. 'error' => $e->getMessage(),
  92. 'user_id' => $userId,
  93. 'pet_id' => $petId,
  94. ]);
  95. }
  96. }
  97. /**
  98. * 处理宠物创建事件
  99. *
  100. * 将宠物创建数据临时存储,按用户ID进行存储
  101. *
  102. * @param PetCreatedEvent $event 宠物创建事件
  103. * @return void
  104. */
  105. public static function handlePetCreated(PetCreatedEvent $event): void
  106. {
  107. self::handlePetFullData($event->userId, $event->petId, '创建');
  108. }
  109. /**
  110. * 处理宠物状态变更事件
  111. *
  112. * 将宠物状态变更数据临时存储,按用户ID进行存储
  113. *
  114. * @param PetStatusChangedEvent $event 宠物状态变更事件
  115. * @return void
  116. */
  117. public static function handlePetStatusChanged(PetStatusChangedEvent $event): void
  118. {
  119. try {
  120. // 构建临时数据键,按用户ID进行存储
  121. $tempKey = self::TEMP_KEY_STATUS_PREFIX . $event->userId;
  122. // 获取当前用户的宠物状态变更临时数据
  123. $userPetsStatusTemp = Cache::get($tempKey, []);
  124. // 创建PetDataSimpleTempDto对象
  125. $tempDto = new PetDataSimpleTempDto();
  126. // 从事件中复制宠物基本数据
  127. $tempDto->id = $event->petId;
  128. $tempDto->typeId = $event->petData->typeId;
  129. $tempDto->name = $event->petData->name;
  130. $tempDto->level = $event->petData->level;
  131. $tempDto->exp = $event->petData->exp;
  132. $tempDto->power = $event->petData->power;
  133. $tempDto->maxpower = $event->petData->maxpower;
  134. $tempDto->score = $event->petData->score;
  135. $tempDto->status = $event->newStatusData->status;
  136. $tempDto->grade = $event->petData->grade;
  137. // 设置状态变更相关属性
  138. $tempDto->oldStatus = $event->oldStatusData->status;
  139. $tempDto->newStatus = $event->newStatusData->status;
  140. $tempDto->reason = $event->reason;
  141. $tempDto->updatedAt = time();
  142. // 使用宠物ID作为键,实现同一宠物多次变更的数据覆盖
  143. // 直接存储DTO对象,而不是转换为数组
  144. $userPetsStatusTemp[$event->petId] = $tempDto;
  145. // 将更新后的数据存回临时存储
  146. Cache::put($tempKey, $userPetsStatusTemp, self::TEMP_TTL);
  147. Log::info('宠物状态变更数据已临时存储', [
  148. 'user_id' => $event->userId,
  149. 'pet_id' => $event->petId,
  150. 'old_status' => $event->oldStatusData->status,
  151. 'new_status' => $event->newStatusData->status,
  152. 'pet_name' => $event->petData->name,
  153. ]);
  154. } catch (\Exception $e) {
  155. Log::error('宠物状态变更数据临时存储失败', [
  156. 'error' => $e->getMessage(),
  157. 'user_id' => $event->userId,
  158. 'pet_id' => $event->petId,
  159. ]);
  160. }
  161. }
  162. /**
  163. * 获取用户的宠物创建临时数据
  164. *
  165. * @param int $userId 用户ID
  166. * @return PetStatusTempDto[] 用户的宠物创建数据
  167. */
  168. public static function getUserPetCreated(int $userId): array
  169. {
  170. // 使用统一的前缀,与宠物更新数据共用一个缓存键
  171. return self::getUserPetUpdates($userId);
  172. }
  173. /**
  174. * 获取用户特定宠物的创建临时数据
  175. *
  176. * @param int $userId 用户ID
  177. * @param int $petId 宠物ID
  178. * @return PetStatusTempDto|null 宠物创建数据,不存在时返回null
  179. */
  180. public static function getUserPetCreatedById(int $userId, int $petId): ?PetStatusTempDto
  181. {
  182. // 使用统一的方法,与宠物更新数据共用一个获取方法
  183. return self::getUserPetUpdateById($userId, $petId);
  184. }
  185. /**
  186. * 获取用户的宠物状态变更临时数据
  187. *
  188. * @param int $userId 用户ID
  189. * @return PetDataSimpleTempDto[] 用户的宠物状态变更数据
  190. */
  191. public static function getUserPetStatus(int $userId): array
  192. {
  193. $tempKey = self::TEMP_KEY_STATUS_PREFIX . $userId;
  194. $cachedData = Cache::get($tempKey, []);
  195. // 使用fromCache方法处理缓存数据,确保返回正确类型的DTO对象
  196. return PetDataSimpleTempDto::fromCache($cachedData);
  197. }
  198. /**
  199. * 获取用户特定宠物的状态变更临时数据
  200. *
  201. * @param int $userId 用户ID
  202. * @param int $petId 宠物ID
  203. * @return PetDataSimpleTempDto|null 宠物状态变更数据,不存在时返回null
  204. */
  205. public static function getUserPetStatusById(int $userId, int $petId): ?PetDataSimpleTempDto
  206. {
  207. $userPetStatus = self::getUserPetStatus($userId);
  208. return $userPetStatus[$petId] ?? null;
  209. }
  210. /**
  211. * 处理宠物更新事件
  212. *
  213. * 将宠物更新数据临时存储,按用户ID进行存储
  214. *
  215. * @param PetUpdateEvent $event 宠物更新事件
  216. * @return void
  217. */
  218. public static function handlePetUpdate(PetUpdateEvent $event): void
  219. {
  220. self::handlePetFullData($event->userId, $event->petId, '更新');
  221. }
  222. /**
  223. * 获取用户的宠物更新临时数据
  224. *
  225. * @param int $userId 用户ID
  226. * @return PetStatusTempDto[] 用户的宠物更新数据
  227. */
  228. public static function getUserPetUpdates(int $userId): array
  229. {
  230. $tempKey = self::TEMP_KEY_UPDATE_PREFIX . $userId;
  231. $cachedData = Cache::get($tempKey, []);
  232. // 使用fromCache方法处理缓存数据,确保返回正确类型的DTO对象
  233. return PetStatusTempDto::fromCache($cachedData);
  234. }
  235. /**
  236. * 获取用户特定宠物的更新临时数据
  237. *
  238. * @param int $userId 用户ID
  239. * @param int $petId 宠物ID
  240. * @return PetStatusTempDto|null 宠物更新数据,不存在时返回null
  241. */
  242. public static function getUserPetUpdateById(int $userId, int $petId): ?PetStatusTempDto
  243. {
  244. $userPetUpdates = self::getUserPetUpdates($userId);
  245. return $userPetUpdates[$petId] ?? null;
  246. }
  247. /**
  248. * 清除用户的宠物创建临时数据
  249. *
  250. * @param int $userId 用户ID
  251. * @return void
  252. */
  253. public static function clearUserPetCreated(int $userId): void
  254. {
  255. // 使用统一的方法,与宠物更新数据共用一个清除方法
  256. self::clearUserPetUpdates($userId);
  257. }
  258. /**
  259. * 清除用户的宠物状态变更临时数据
  260. *
  261. * @param int $userId 用户ID
  262. * @return void
  263. */
  264. public static function clearUserPetStatus(int $userId): void
  265. {
  266. $tempKey = self::TEMP_KEY_STATUS_PREFIX . $userId;
  267. Cache::put($tempKey, [], 0);
  268. }
  269. /**
  270. * 清除用户的所有宠物临时数据
  271. *
  272. * @param int $userId 用户ID
  273. * @return void
  274. */
  275. public static function clearUserAllPetTemp(int $userId): void
  276. {
  277. self::clearUserPetCreated($userId);
  278. self::clearUserPetStatus($userId);
  279. }
  280. }