SystemProc.php 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449
  1. <?php
  2. namespace loyalsoft;
  3. // <editor-fold defaultstate="collapsed" desc=" 定义 ">
  4. /**
  5. * 约定好的消息类型
  6. */
  7. class SysMessageType extends Enum {
  8. /** (1)XXX(玩家名称)解锁英雄XXX(紫色橙色英雄) */
  9. const GetHero = 1;
  10. /** (2)XXX(玩家名称)的英雄XXX(紫色橙色英雄)神血升值40%+(40%都有) */
  11. const Hero_purification = 2;
  12. /** (3)XXX 获得XXX(紫色橙色装备) */
  13. const GetEquip = 3;
  14. /** (4)XXX(玩家名称)购买公会钻石礼包 */
  15. const BuyGuild_CashPack = 4;
  16. /** (5)XXX(玩家名称)升到XX级别(20级以上) */
  17. const UserLevelUp = 5;
  18. /** (6)XXX(玩家名称)达到XX段位(黄金以上) */
  19. const PVP_League = 6;
  20. /** (7) XXX(玩家名称)打败噩梦关八岐大蛇,获得铂金宝箱,可喜可贺!
  21. * 通过副本
  22. * */
  23. const Pass_carbon = 7;
  24. /** (4)装备-强化 */
  25. const Weapon_Promote = 4000;
  26. /**
  27. * (99)玩家自己购买的全服消息(本分区)
  28. */
  29. const UserSendMessage = 99;
  30. }
  31. /**
  32. * 系统消息对象
  33. */
  34. class SysMessageModel extends Object_ext {
  35. /** @var SysMessageType */
  36. public $type;
  37. /** @var array 消息数据 */
  38. public $datas;
  39. /** @var int */
  40. public $ts;
  41. }
  42. //
  43. // </editor-fold>
  44. /**
  45. * 系统消息逻辑处理流程
  46. * @author gwang
  47. */
  48. class SystemProc {
  49. /**
  50. * 系统消息的过期时间(秒)
  51. * @var int
  52. */
  53. const SYS_MSG_OUTTS = 3600;
  54. /**
  55. * 主逻辑分发
  56. * @param type $req
  57. * @return type
  58. */
  59. static function procMain($req) {
  60. switch ($req->cmd) {
  61. case CmdCode::cmd_system_userSendsysmessage: # 6904 玩家发送系统广播
  62. return self::userPushSysMessage($req);
  63. case CmdCode::cmd_system_getsysmessage: # 6901 拉取系统消息
  64. return self::getSysMessage($req);
  65. case CmdCode::cmd_system_logreport: # 6902 客户端上报日志
  66. return self::logReport($req);
  67. case CmdCode::cmd_system_clienttick: # 6903 客户端心跳包
  68. // return ResponseVo::ErrResponse($req, ErrCode::err_msg_methodobsoleted);
  69. return self::mock($req); # 模拟方法s
  70. // return self::clientTick($req);
  71. default :
  72. return Resp::err(ErrCode::cmd_err);
  73. }
  74. }
  75. /**
  76. * 模拟
  77. * @param Req $req
  78. */
  79. static function mock($req) {
  80. if (GAME_ONLINE) {
  81. return;
  82. }
  83. self::insertHero_Star($req->zoneid, $req->uid, $req->userInfo->game->name, "王小刚", 100);
  84. self::insertHero_StageUp($req->zoneid, $req->uid, $req->userInfo->game->name, "王小刚", 100);
  85. self::insertWeapon_promoteUp($req->zoneid, $req->uid, $req->userInfo->game->name, "小小刚", 100);
  86. return Resp::ok(array('ret' => '你懂的!'));
  87. }
  88. //
  89. // <editor-fold defaultstate="collapsed" desc=" 暂时不管 ">
  90. //
  91. /**
  92. * 客户端心跳包
  93. * @param Req $req
  94. */
  95. static function clientTick($req) {
  96. $Tmem = $req->mem;
  97. $user = $req->userInfo->user;
  98. if (!CommUtil::isPropertyExists($user, "tick")) {
  99. $user->tick = 0;
  100. }
  101. $user->tick += 1; // 玩家在线时长字段
  102. $tickList = $Tmem->get("client-tick");
  103. if ($tickList == null) {
  104. $tickList = "";
  105. } else {
  106. $tickList .= ",";
  107. }
  108. $tickList .= "(\"" . $user->oId . "\",\"" . $user->name . "\",\"" . CommUtil::dtCurrent()->toString() . "\",\"" . "1" . "\")";
  109. $Tmem->set("client-tick", $tickList);
  110. // self::serialStatData($Tmem);
  111. $resp = Resp::myRetResponse($req, "succeed!");
  112. UserProc::updateUserInfo($req);
  113. return $resp;
  114. }
  115. /**
  116. * 客户端日志上报
  117. * @param Req $req
  118. * @return type
  119. */
  120. static function logReport($req) {
  121. $mem = $req->mem;
  122. //客户端参数解析
  123. $openId = $req->oid; //fromoid
  124. $log = $req->paras[0]; //消息列表有效时间戳
  125. $logList = $mem->get("report-log"); # 读记录
  126. if ($logList == null) {
  127. $logList = ArrayInit();
  128. }
  129. # 错误记录上限300条
  130. if (StlUtil::count($logList) >= 300) {
  131. StlUtil::arrayRemoveAt($logList, 0);
  132. }
  133. $logItem = ObjectInit();
  134. $logItem->oid = $openId;
  135. $logItem->log = $log;
  136. $logItem->ts = CommUtil::tsCurrent();
  137. $logList[] = $logItem;
  138. $mem->set("report-log", $logList); # 回写记录
  139. $resp = Resp::myRetResponse($req, "copy!");
  140. return $resp;
  141. }
  142. //
  143. //
  144. // </editor-fold>
  145. //
  146. /**
  147. * 玩家通过xx副本消息
  148. * @param type $zoneid
  149. * @param UserGameModel $user
  150. * @param int $carbonID
  151. * */
  152. static function Carbon_Win($zoneid, $user, $carbonID, $hardLevel) {
  153. if (512001 == $carbonID) {
  154. self::pushSysMessage($zoneid, SysMessageType::Pass_carbon, array(
  155. $user->name, $carbonID, $hardLevel
  156. ));
  157. }
  158. }
  159. /**
  160. * 玩家pvp段位消息
  161. * @param type $zoneid
  162. * @param UserGameModel $user
  163. * @param int $leagueID
  164. * */
  165. static function PVP_league($zoneid, $user, $leagueID) {
  166. if ($leagueID > 10) {
  167. self::pushSysMessage($zoneid, SysMessageType::PVP_League, array(
  168. $user->name, GameConfig::pvp_leaguescore_getItem($leagueID)->leagueName
  169. ));
  170. }
  171. }
  172. /**
  173. * [6901]获取系统广播消息列表
  174. * @param Req $req
  175. */
  176. static function getSysMessage($req) {
  177. //客户端参数解析
  178. $ts = $req->paras[0]; //消息列表有效时间戳
  179. $defaultwaitcont = 60; # 暂时使用60秒作为频率,若是有压力就调大些. 若是没有问题,可以调小些.
  180. $itemDisplayTime = 7; # 7秒显示完一条消息
  181. $sysMessage = self::mem_getSysMsg_zset($req->zoneid, $ts);
  182. // 计算下次取消息的时间
  183. $count = count($sysMessage) * $itemDisplayTime;
  184. if ($count < $defaultwaitcont) { # 最低刷新时间
  185. $count = $defaultwaitcont;
  186. }
  187. $ret = array(
  188. 'sysMessage' => $sysMessage,
  189. 'nextFetchTime' => $count
  190. );
  191. //6.回送成功信息
  192. return Resp::ok($ret);
  193. }
  194. /**
  195. * [6904]玩家发送系统广播消息
  196. * @param Req $req
  197. */
  198. static function userPushSysMessage($req) {
  199. $user = $req->userInfo->game;
  200. $uid = $req->uid;
  201. // 提取参数
  202. $msg = $req->paras[0];
  203. $type = $req->paras[1]; // 消耗道具类型,1:钻石,2:xx
  204. $cost = 0; // 花费
  205. switch ($type) {
  206. case 1:
  207. $cost = glc()->SystemMessage_UserSendToMyZone_Cost;
  208. if (!$cost) {
  209. return Resp::err(ErrCode::err_msg_usersnedmsg_errorcost);
  210. }
  211. if (UserGameModel::Consume_Cash($user, $cost)) {
  212. return Resp::err(ErrCode::notenough_cash_msg, "扣费失败");
  213. }
  214. break;
  215. default : // 参数非法
  216. return Resp::err(ErrCode::paras_err);
  217. }
  218. self::pushSysMessage($req->zoneid, #
  219. SysMessageType::UserSendMessage, array($uid, $user->name, $msg));
  220. UserProc::updateUserInfo($req); // 回存账号数据
  221. return Resp::ok(array('ret' => "succeed")); # 返回值
  222. }
  223. // -----------------辅助方法---------------------
  224. //
  225. /**
  226. * 玩家升级消息
  227. * @param type $zoneid
  228. * @param UserGameModel $user
  229. * @param int $newLevel
  230. * */
  231. static function UserLevelUp($zoneid, $user, $newLevel) {
  232. if ($newLevel > 20) {
  233. self::pushSysMessage($zoneid, SysMessageType::UserLevelUp, array(
  234. $user->name, $newLevel
  235. ));
  236. }
  237. }
  238. /**
  239. * 插入英雄升阶消息
  240. * @param int $zoneid
  241. * @param string $uid
  242. * @param string $name
  243. * @param string $heroname
  244. * @param int $level
  245. */
  246. static function insertHero_StageUp($zoneid, $uid, $name, $heroname, $level) {
  247. // if ($level >= glc()->SystemMessage_HeroStage_Limit_Min) {
  248. // self::pushSysMessage($zoneid, SysMessageType::GetEquip, array(
  249. // $uid, $name, $heroname, $level
  250. // ));
  251. // }
  252. }
  253. /**
  254. * 添加购买公会钻石礼包消息
  255. * @param type $zoneid
  256. * @param UserGameModel $user
  257. * */
  258. static function BuyGuildCashPack($zoneid, $user) {
  259. self::pushSysMessage($zoneid, SysMessageType::BuyGuild_CashPack, array(
  260. $user->name
  261. ));
  262. }
  263. /**
  264. * 添加获得装备消息
  265. * @param type $zoneid
  266. * @param UserGameModel $user
  267. * @param int $equipModelId
  268. * */
  269. static function GetEquip($zoneid, $user, $equipModelId) {
  270. $equipModel = GameConfig::item_getItem($equipModelId);
  271. if ($equipModel && $equipModel->quailty > 3) { # 紫色橙色装备
  272. self::pushSysMessage($zoneid, SysMessageType::GetEquip, array(
  273. $user->name, $equipModel->name
  274. ));
  275. }
  276. }
  277. /**
  278. * 插入装备强化消息
  279. * @deprecated since version 1.0 装备强化暂不支持了
  280. * @param type $zoneid
  281. * @param type $uid
  282. * @param type $name
  283. * @param type $weaponname
  284. * @param type $level
  285. */
  286. static function insertWeapon_promoteUp($zoneid, $uid, $name, $weaponname, $level) {
  287. // if ($level >= glc()->SystemMessage_WeaponLevel_Limit_Min) {
  288. // self::pushSysMessage($zoneid, SysMessageType::Weapon_Promote, array(
  289. // $uid, $name, $weaponname, $level
  290. // ));
  291. // }
  292. }
  293. ////=================////
  294. /**
  295. * 添加获得英雄消息
  296. * @param type $zoneid
  297. * @param UserGameModel $user
  298. * @param int $heroId
  299. * @return int $err
  300. * */
  301. static function GetHero($zoneid, $user, $heroId) {
  302. $heroModel = GameConfig::hero_getItem($heroId);
  303. if ($heroModel && $heroModel->zhenxidu > 3) {
  304. self::pushSysMessage($zoneid, SysMessageType::GetHero, array(
  305. $user->name, $heroModel->name
  306. ));
  307. }
  308. }
  309. /**
  310. * 添加英雄血脉提纯消息
  311. * @param type $zoneid
  312. * @param UserGameModel $user
  313. * @param int $heroId
  314. * @return int $err
  315. * */
  316. static function Hero_purification($zoneid, $user, $heroId) {
  317. $heroModel = GameConfig::hero_getItem($heroId);
  318. if ($heroModel && $heroModel->zhenxidu > 3) {
  319. self::pushSysMessage($zoneid, SysMessageType::Hero_purification, array(
  320. $user->name, $heroModel->name
  321. ));
  322. }
  323. }
  324. //
  325. // <editor-fold defaultstate="collapsed" desc=" 读写memdb ">
  326. /**
  327. * 取数据
  328. * @param int $zoneid
  329. * @return array
  330. */
  331. private static function mem_getSysMsg_zset($zoneid, $ts) {
  332. $ret = gMem()->zrangebyscore(MemKey_GameRun::Game_SysMsgByZone_zset($zoneid), $ts, now(+1));
  333. //todo:目前是在这里手动解码的, 应该移动到CRedisUtil里面去.
  334. $arr = ArrayInit();
  335. if ($ret) {
  336. foreach ($ret as $msg) {
  337. $arr[] = JsonUtil::decode($msg);
  338. }
  339. }
  340. return $arr;
  341. }
  342. /**
  343. * 回写数据
  344. * @param int $zoneid
  345. * @param SysMessageModel $value
  346. */
  347. private static function mem_addSysMsg_zset($zoneid, $value) {
  348. $ts = $value->ts;
  349. $key = MemKey_GameRun::Game_SysMsgByZone_zset($zoneid);
  350. gMem()->zadd($key, array(json_encode($value) => $ts)); // 插入消息
  351. gMem()->zremrangebyscore($key, 0, $ts - self::SYS_MSG_OUTTS); // 清理过期数据
  352. }
  353. // </editor-fold>
  354. //
  355. /**
  356. * 推送系统消息
  357. * @param int $zoneid 分区
  358. * @param SysMessageType $type enum
  359. * @param array $datas
  360. */
  361. static function pushSysMessage($zoneid, $type, $datas) {
  362. // 添加新系统消息
  363. $newMsg = new SysMessageModel(array(
  364. 'type' => $type,
  365. 'datas' => $datas,
  366. 'ts' => now()
  367. ));
  368. self::mem_addSysMsg_zset($zoneid, $newMsg);
  369. }
  370. // <editor-fold defaultstate="collapsed" desc=" 备用 需修改">
  371. /**
  372. * 添加中奖消息
  373. * @param type $mem
  374. * @param UserModel $user
  375. * @param int $itemId
  376. * @param string $src 来源: 砸木桶,砸金蛋,公会抽奖,开宝箱,蛋蛋忧伤,...
  377. * @return int $err
  378. * */
  379. static function insertLotterySysMessage($zoneid, $mem, $user, $itemId, $src) {
  380. throw new \Exception("need reimplement");
  381. $err = ErrCode::ok;
  382. // 向系统消息区域发送中奖消息.
  383. $broadCastIDs = ConstProc::getBuildReward($mem, ConstProc::buildreward_lottery_broadcast);
  384. if ($broadCastIDs == null) {
  385. $err = ErrCode::err_msg_buildrewardnoconst;
  386. } else {
  387. $broadItemArray = JsonUtil::decode($broadCastIDs->content);
  388. // 如果是测试的话,将所有中奖物品加入到系统消息中
  389. if (!GAME_ONLINE || CommUtil::isPropertyExists($broadItemArray, $itemId)) {
  390. self::pushSysMessage($zoneid, SysMessageType::GetHero, #
  391. array($user->oid, $user->name, $itemId, $src));
  392. }
  393. }
  394. return $err;
  395. }
  396. // </editor-fold>
  397. }