PlayerDataHandler.php 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318
  1. <?php
  2. namespace App\Module\AppGame\Handler\Public;
  3. use App\Module\AppGame\Handler\BaseHandler;
  4. use App\Module\Farm\Services\BuffService;
  5. use App\Module\Farm\Services\FarmService;
  6. use App\Module\Farm\Services\LandService;
  7. use App\Module\Fund\Services\AccountService;
  8. use App\Module\Game\Services\SkinService;
  9. use App\Module\GameItems\Services\ItemService;
  10. use App\Module\Pet\Services\PetService;
  11. use App\Module\User\Services\UserService;
  12. use Google\Protobuf\Internal\Message;
  13. use Uraus\Kku\Request\RequestPublicPlayerData;
  14. use Uraus\Kku\Response\ResponsePublicPlayerData;
  15. use Uraus\Kku\Response\PublicUserInfo;
  16. use Uraus\Kku\Response\PublicGod;
  17. use Uraus\Kku\Response\PublicLand;
  18. use Uraus\Kku\Response\PublicPet;
  19. use Uraus\Kku\Response\PublicZichan;
  20. /**
  21. * 处理玩家数据请求(公共数据)
  22. *
  23. */
  24. class PlayerDataHandler extends BaseHandler
  25. {
  26. /**
  27. * 是否需要登录
  28. * @var bool
  29. */
  30. protected bool $need_login = true;
  31. /**
  32. * 处理玩家数据请求
  33. *
  34. * @param RequestPublicPlayerData $data 玩家数据请求数据
  35. * @return ResponsePublicPlayerData 玩家数据响应
  36. */
  37. public function handle(Message $data): Message
  38. {
  39. // 获取请求的用户ID
  40. $targetUserId = $data->getUserId();
  41. // 创建响应对象
  42. $response = new ResponsePublicPlayerData();
  43. // 获取用户基本信息
  44. $this->setUserInfo($response, $targetUserId);
  45. // 获取神像数据
  46. $this->setGodsInfo($response, $targetUserId);
  47. // 获取土地数据
  48. $this->setLandInfo($response, $targetUserId);
  49. // 获取宠物数据
  50. $this->setPetInfo($response, $targetUserId);
  51. // 获取资产数据
  52. $this->setZichanInfo($response, $targetUserId);
  53. return $response;
  54. }
  55. /**
  56. * 设置用户基本信息
  57. *
  58. * @param ResponsePublicPlayerData $response
  59. * @param int $userId
  60. * @return void
  61. */
  62. private function setUserInfo(ResponsePublicPlayerData $response, int $userId): void
  63. {
  64. // 获取用户基本信息
  65. $userInfo = UserService::info($userId);
  66. $userDetailInfo = UserService::infoinfo($userId);
  67. if (!$userInfo || !$userDetailInfo) {
  68. return;
  69. }
  70. // 获取用户皮肤信息
  71. $currentSkinId = SkinService::getCurrentSkinId($userId);
  72. // 获取用户房屋等级
  73. $houseLevel = 1; // 默认等级为1
  74. $farmInfo = FarmService::getFarmInfo($userId);
  75. if ($farmInfo) {
  76. $houseLevel = $farmInfo->houseLevel;
  77. }
  78. // 创建PublicUserInfo对象
  79. $publicUserInfo = new PublicUserInfo();
  80. $publicUserInfo->setUserD($userId); // 注意:protobuf中字段名是user_d
  81. $publicUserInfo->setSkinId($currentSkinId);
  82. $publicUserInfo->setAvatar($userDetailInfo->avatar ?? 0);
  83. $publicUserInfo->setNickName($userDetailInfo->nickname ?? '');
  84. $publicUserInfo->setHouseLevel($houseLevel); // 设置房屋等级
  85. $response->setUserInfo($publicUserInfo);
  86. }
  87. /**
  88. * 设置神像数据
  89. *
  90. * @param ResponsePublicPlayerData $response
  91. * @param int $userId
  92. * @return void
  93. */
  94. private function setGodsInfo(ResponsePublicPlayerData $response, int $userId): void
  95. {
  96. $godsInfo = [];
  97. // 遍历所有可能的神像类型(1-4)
  98. for ($godId = 1; $godId <= 4; $godId++) {
  99. $publicGod = new PublicGod();
  100. $publicGod->setId($godId);
  101. // 检查用户是否有该类型的有效神灵加持
  102. $activeBuff = BuffService::getActiveUserBuff($userId, $godId);
  103. $publicGod->setStatus($activeBuff !== null);
  104. $godsInfo[] = $publicGod;
  105. }
  106. $response->setGodsInfo($godsInfo);
  107. }
  108. /**
  109. * 设置土地数据
  110. *
  111. * @param ResponsePublicPlayerData $response
  112. * @param int $userId
  113. * @return void
  114. */
  115. private function setLandInfo(ResponsePublicPlayerData $response, int $userId): void
  116. {
  117. // 获取用户的所有土地
  118. $userLands = LandService::getUserLands($userId);
  119. $landInfo = [];
  120. foreach ($userLands as $landDto) {
  121. $publicLand = new PublicLand();
  122. $publicLand->setId($landDto->id);
  123. $publicLand->setIndex($landDto->position); // 使用position作为index
  124. $publicLand->setLevel($landDto->landType); // 使用landType作为level
  125. $publicLand->setStatus($landDto->status); // status已经是int类型
  126. // 设置种植相关信息
  127. if ($landDto->crop) {
  128. // 种植时间(使用plantTime字段)
  129. $plantTime = 0;
  130. if ($landDto->crop->plantTime) {
  131. if (is_string($landDto->crop->plantTime)) {
  132. $plantTime = strtotime($landDto->crop->plantTime);
  133. } elseif ($landDto->crop->plantTime instanceof \Carbon\Carbon) {
  134. $plantTime = $landDto->crop->plantTime->timestamp;
  135. } else {
  136. $plantTime = $landDto->crop->plantTime;
  137. }
  138. }
  139. $publicLand->setSeedPlantingTimes($plantTime);
  140. $publicLand->setSeedId($landDto->crop->seedId ?? 0);
  141. $publicLand->setFruitId($landDto->crop->finalOutputItemId ?? 0);
  142. $publicLand->setPlantId($landDto->crop->id ?? 0); // 使用作物ID作为植株ID
  143. $publicLand->setSeedStatus($landDto->crop->growthStage ?? 0);
  144. // 阶段开始时间
  145. $stageStartTime = 0;
  146. if ($landDto->crop->stageStartTime) {
  147. $stageStartTime = $landDto->crop->stageStartTime->timestamp ?? 0;
  148. }
  149. $publicLand->setStageStartTimes($stageStartTime);
  150. // 阶段结束时间
  151. $stageEndTime = 0;
  152. if ($landDto->crop->stageEndTime) {
  153. $stageEndTime = $landDto->crop->stageEndTime->timestamp ?? 0;
  154. }
  155. $publicLand->setStageNextTimes($stageEndTime);
  156. } else {
  157. $publicLand->setSeedPlantingTimes(0);
  158. $publicLand->setSeedId(0);
  159. $publicLand->setFruitId(0);
  160. $publicLand->setPlantId(0);
  161. $publicLand->setSeedStatus(0);
  162. $publicLand->setStageStartTimes(0);
  163. $publicLand->setStageNextTimes(0);
  164. }
  165. // 设置灾害信息(暂时为空数组)
  166. $publicLand->setDisasters([]);
  167. $landInfo[] = $publicLand;
  168. }
  169. $response->setLandInfo($landInfo);
  170. }
  171. /**
  172. * 设置宠物数据
  173. *
  174. * @param ResponsePublicPlayerData $response
  175. * @param int $userId
  176. * @return void
  177. */
  178. private function setPetInfo(ResponsePublicPlayerData $response, int $userId): void
  179. {
  180. try {
  181. // 获取用户的宠物列表
  182. $userPets = PetService::getUserPets($userId);
  183. // 如果用户没有宠物,则不设置宠物信息
  184. if ($userPets->isEmpty()) {
  185. return;
  186. }
  187. // 获取第一个宠物作为公共展示的宠物(通常是主宠物)
  188. $mainPet = $userPets->first();
  189. // 创建PublicPet对象
  190. $publicPet = new PublicPet();
  191. // 宠物种族ID:由于当前数据库设计中PetUser表没有type_id字段,
  192. // 我们使用默认值1(对应松狮),或者可以根据业务需求进行调整
  193. $typeId = 1; // 默认为松狮(ID=1)
  194. $publicPet->setTypeId($typeId);
  195. $publicPet->setName($mainPet->name ?? '');
  196. $publicPet->setLevel($mainPet->level ?? 1);
  197. $publicPet->setPower($mainPet->stamina ?? 0);
  198. $response->setPetInfo($publicPet);
  199. } catch (\Exception $e) {
  200. // 如果获取宠物信息失败,记录日志但不影响其他数据的返回
  201. \Illuminate\Support\Facades\Log::warning('获取用户宠物公共信息失败', [
  202. 'user_id' => $userId,
  203. 'error' => $e->getMessage()
  204. ]);
  205. }
  206. }
  207. /**
  208. * 设置资产数据
  209. *
  210. * @param ResponsePublicPlayerData $response
  211. * @param int $userId
  212. * @return void
  213. */
  214. private function setZichanInfo(ResponsePublicPlayerData $response, int $userId): void
  215. {
  216. try {
  217. // 创建PublicZichan对象
  218. $publicZichan = new PublicZichan();
  219. // 获取钻石余额(fund_id = 2)
  220. $diamondBalance = 0;
  221. try {
  222. $accounts = AccountService::list4user($userId);
  223. foreach ($accounts as $account) {
  224. if ($account->getFundId() == 2) { // 钻石的fund_id是2
  225. $diamondBalance = $account->balance;
  226. break;
  227. }
  228. }
  229. } catch (\Exception $e) {
  230. \Illuminate\Support\Facades\Log::warning('获取用户钻石余额失败', [
  231. 'user_id' => $userId,
  232. 'error' => $e->getMessage()
  233. ]);
  234. }
  235. // 获取建筑材料数量
  236. $woodQuantity = 0; // 木材 (item_id = 33)
  237. $stoneQuantity = 0; // 石材 (item_id = 34)
  238. $steelQuantity = 0; // 钢材 (item_id = 35)
  239. try {
  240. // 获取木材数量
  241. $woodItems = ItemService::getUserItems($userId, ['item_id' => 33]);
  242. $woodQuantity = $woodItems->sum('quantity');
  243. // 获取石材数量
  244. $stoneItems = ItemService::getUserItems($userId, ['item_id' => 34]);
  245. $stoneQuantity = $stoneItems->sum('quantity');
  246. // 获取钢材数量
  247. $steelItems = ItemService::getUserItems($userId, ['item_id' => 35]);
  248. $steelQuantity = $steelItems->sum('quantity');
  249. } catch (\Exception $e) {
  250. \Illuminate\Support\Facades\Log::warning('获取用户建筑材料数量失败', [
  251. 'user_id' => $userId,
  252. 'error' => $e->getMessage()
  253. ]);
  254. }
  255. // 设置资产信息
  256. $publicZichan->setZuanshi((float)$diamondBalance);
  257. $publicZichan->setMucai((float)$woodQuantity);
  258. $publicZichan->setShicai((float)$stoneQuantity);
  259. $publicZichan->setGangcai((float)$steelQuantity);
  260. $response->setZichan($publicZichan);
  261. } catch (\Exception $e) {
  262. // 如果获取资产信息失败,记录日志但不影响其他数据的返回
  263. \Illuminate\Support\Facades\Log::warning('获取用户资产公共信息失败', [
  264. 'user_id' => $userId,
  265. 'error' => $e->getMessage()
  266. ]);
  267. }
  268. }
  269. }