SystemProc.php 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404
  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();
  63. case CmdCode::cmd_system_getsysmessage: # 6901 拉取系统消息
  64. return self::getSysMessage();
  65. case CmdCode::cmd_system_logreport: # 6902 客户端上报日志
  66. return self::logReport();
  67. case CmdCode::cmd_system_clienttick: # 6903 客户端心跳包
  68. return self::clientTick();
  69. default :
  70. return Resp::err(ErrCode::cmd_err);
  71. }
  72. }
  73. //
  74. // <editor-fold defaultstate="collapsed" desc=" 暂时不管 ">
  75. //
  76. /**
  77. * [6903] 客户端心跳包
  78. */
  79. static function clientTick() {
  80. $timespan = now() - req()->userInfo->game->baseInfo->lastSaveTs;
  81. if ($timespan < 300) { # 间隔超过5分钟的不算
  82. if ($timespan < 30) { # 心跳包固定30秒1次
  83. $timespan = 30;
  84. }
  85. req()->userInfo->game->privateState->onlineGiftts += $timespan;
  86. UserProc::updateUserInfo();
  87. }
  88. return Resp::ok();
  89. }
  90. /**
  91. * [6902] 客户端日志上报
  92. */
  93. static function logReport() {
  94. $max = 300;
  95. $once = 30;
  96. $key = "report-log";
  97. $log = req()->paras[0]; # 客户端参数解析: 本地日志
  98. $logItem = array(# # 组装对象
  99. 'uid' => req()->uid,
  100. 'log' => $log,
  101. 'ts' => TimeUtil::dtCurrent()
  102. );
  103. gMem()->lpush($key, array($logItem)); # 推送日志
  104. if (gMem()->llen($key) > $max + $once) { # 达到清理条件
  105. gMem()->ltrim($key, 0, -$once); # 缩减记录
  106. }
  107. return Resp::ok("copy!");
  108. }
  109. //
  110. //
  111. // </editor-fold>
  112. //
  113. /**
  114. * 玩家通过xx副本消息
  115. * @param type $zoneid
  116. * @param Data_UserGame $user
  117. * @param int $carbonID
  118. * */
  119. static function Carbon_Win($zoneid, $user, $carbonID, $hardLevel) {
  120. if (512001 == $carbonID) {
  121. self::pushSysMessage($zoneid, SysMessageType::Pass_carbon, array(
  122. $user->name, $carbonID, $hardLevel
  123. ));
  124. }
  125. }
  126. /**
  127. * 玩家pvp段位消息
  128. * @param type $zoneid
  129. * @param Data_UserGame $user
  130. * @param int $leagueID
  131. * */
  132. static function PVP_league($zoneid, $user, $leagueID) {
  133. if ($leagueID > 10) {
  134. self::pushSysMessage($zoneid, SysMessageType::PVP_League, array(
  135. $user->name, GameConfig::pvp_leaguescore_getItem($leagueID)->leagueName
  136. ));
  137. }
  138. }
  139. /**
  140. * [6901]获取系统广播消息列表
  141. */
  142. static function getSysMessage() {
  143. //客户端参数解析
  144. $ts = req()->paras[0]; # 消息列表有效时间戳
  145. $defaultwaitcont = 60; # 暂时使用60秒作为频率,若是有压力就调大些. 若是没有问题,可以调小些.
  146. $itemDisplayTime = 7; # 7秒显示完一条消息
  147. $sysMessage = self::mem_getSysMsg_zset(req()->zoneid, $ts);
  148. $count = count($sysMessage) * $itemDisplayTime; # 计算下次取消息的时间
  149. if ($count < $defaultwaitcont) { # 最低刷新时间
  150. $count = $defaultwaitcont;
  151. }
  152. $ret = array(
  153. 'sysMessage' => $sysMessage,
  154. 'nextFetchTime' => $count
  155. );
  156. return Resp::ok($ret); # 返回信息
  157. }
  158. /**
  159. * [6904]玩家发送系统广播消息
  160. */
  161. static function userPushSysMessage() {
  162. list($msg, $type) = req()->paras; # 提取参数: 消息内容, 消耗道具类型,1:钻石,2:xx
  163. $uid = req()->uid;
  164. $user = req()->userInfo->game;
  165. $cost = 0; // 花费
  166. switch ($type) {
  167. case 1: # 钻石
  168. $cost = glc()->SystemMessage_UserSendToMyZone_Cost;
  169. my_Assert($cost, ErrCode::err_msg_usersnedmsg_errorcost);
  170. my_Assert($user->base()->Consume_Cash($cost), ErrCode::notenough_cash_msg);
  171. break;
  172. default :
  173. Err(ErrCode::paras_err); // 其他类型:参数非法
  174. }
  175. self::pushSysMessage(req()->zoneid, #
  176. SysMessageType::UserSendMessage, array($uid, $user->name, $msg));
  177. UserProc::updateUserInfo(); // 回存账号数据
  178. return Resp::ok(array('ret' => "succeed")); # 返回值
  179. }
  180. // -----------------辅助方法---------------------
  181. //
  182. /**
  183. * 玩家升级消息
  184. * @param type $zoneid
  185. * @param Data_UserGame $user
  186. * @param int $newLevel
  187. * */
  188. static function UserLevelUp($zoneid, $user, $newLevel) {
  189. if ($newLevel > 20) {
  190. self::pushSysMessage($zoneid, SysMessageType::UserLevelUp, array(
  191. $user->name, $newLevel
  192. ));
  193. }
  194. }
  195. /**
  196. * 插入英雄升阶消息
  197. * @param int $zoneid
  198. * @param string $uid
  199. * @param string $name
  200. * @param string $heroname
  201. * @param int $level
  202. */
  203. static function insertHero_StageUp($zoneid, $uid, $name, $heroname, $level) {
  204. // if ($level >= glc()->SystemMessage_HeroStage_Limit_Min) {
  205. // self::pushSysMessage($zoneid, SysMessageType::GetEquip, array(
  206. // $uid, $name, $heroname, $level
  207. // ));
  208. // }
  209. }
  210. /**
  211. * 添加购买公会钻石礼包消息
  212. * @param type $zoneid
  213. * @param Data_UserGame $user
  214. * */
  215. static function BuyGuildCashPack($zoneid, $user) {
  216. self::pushSysMessage($zoneid, SysMessageType::BuyGuild_CashPack, array(
  217. $user->name
  218. ));
  219. }
  220. /**
  221. * 添加获得装备消息
  222. * @param type $zoneid
  223. * @param Data_UserGame $user
  224. * @param int $equipModelId
  225. * @deprecated since version 0 待维修 --王刚2020年1月2日21:07:04
  226. * */
  227. static function GetEquip($zoneid, $user, $equipModelId) {
  228. $equipModel = GameConfig::item_getItem($equipModelId);
  229. if ($equipModel && $equipModel->quailty > 3) { # 紫色橙色装备
  230. self::pushSysMessage($zoneid, SysMessageType::GetEquip, array(
  231. $user->name, $equipModel->name
  232. ));
  233. }
  234. }
  235. /**
  236. * 插入装备强化消息
  237. * @deprecated since version 1.0 装备强化暂不支持了
  238. * @param type $zoneid
  239. * @param type $uid
  240. * @param type $name
  241. * @param type $weaponname
  242. * @param type $level
  243. */
  244. static function insertWeapon_promoteUp($zoneid, $uid, $name, $weaponname, $level) {
  245. // if ($level >= glc()->SystemMessage_WeaponLevel_Limit_Min) {
  246. // self::pushSysMessage($zoneid, SysMessageType::Weapon_Promote, array(
  247. // $uid, $name, $weaponname, $level
  248. // ));
  249. // }
  250. }
  251. ////=================////
  252. /**
  253. * 添加获得英雄消息
  254. * @param type $zoneid
  255. * @param Data_UserGame $user
  256. * @param int $heroId
  257. * @return int $err
  258. * */
  259. static function GetHero($zoneid, $user, $heroId) {
  260. $heroModel = GameConfig::hero_getItem($heroId);
  261. if ($heroModel && $heroModel->zhenxidu > 3) {
  262. self::pushSysMessage($zoneid, SysMessageType::GetHero, array(
  263. $user->name, $heroModel->name
  264. ));
  265. }
  266. }
  267. /**
  268. * 添加英雄血脉提纯消息
  269. * @param type $zoneid
  270. * @param Data_UserGame $user
  271. * @param int $heroId
  272. * @return int $err
  273. * */
  274. static function Hero_purification($zoneid, $user, $heroId) {
  275. $heroModel = GameConfig::hero_getItem($heroId);
  276. if ($heroModel && $heroModel->zhenxidu > 3) {
  277. self::pushSysMessage($zoneid, SysMessageType::Hero_purification, array(
  278. $user->name, $heroModel->name
  279. ));
  280. }
  281. }
  282. //
  283. // <editor-fold defaultstate="collapsed" desc=" 读写memdb ">
  284. /**
  285. * 取数据
  286. * @param int $zoneid
  287. * @return array
  288. */
  289. private static function mem_getSysMsg_zset($zoneid, $ts) {
  290. $ret = gMem()->zrangebyscore(MemKey_GameRun::Game_SysMsgByZone_zset($zoneid), $ts, now(+1));
  291. //todo:目前是在这里手动解码的, 应该移动到CRedisUtil里面去.
  292. $arr = ArrayInit();
  293. if ($ret) {
  294. foreach ($ret as $msg) {
  295. $arr[] = JsonUtil::decode($msg);
  296. }
  297. }
  298. return $arr;
  299. }
  300. /**
  301. * 回写数据
  302. * @param int $zoneid
  303. * @param SysMessageModel $value
  304. */
  305. private static function mem_addSysMsg_zset($zoneid, $value) {
  306. $ts = $value->ts;
  307. $key = MemKey_GameRun::Game_SysMsgByZone_zset($zoneid);
  308. gMem()->zadd($key, array(json_encode($value) => $ts)); # 插入消息
  309. gMem()->zremrangebyscore($key, 0, $ts - self::SYS_MSG_OUTTS); # 清理过期数据
  310. }
  311. // </editor-fold>
  312. //
  313. /**
  314. * 推送系统消息
  315. * @param int $zoneid 分区
  316. * @param SysMessageType $type enum
  317. * @param array $datas
  318. */
  319. static function pushSysMessage($zoneid, $type, $datas) {
  320. $newMsg = new SysMessageModel(array(# # 添加新系统消息
  321. 'type' => $type,
  322. 'datas' => $datas,
  323. 'ts' => now()
  324. ));
  325. self::mem_addSysMsg_zset($zoneid, $newMsg); # 写入mem
  326. }
  327. // <editor-fold defaultstate="collapsed" desc=" 备用 需修改">
  328. /**
  329. * 添加中奖消息
  330. * @param type $mem
  331. * @param UserModel $user
  332. * @param int $itemId
  333. * @param string $src 来源: 砸木桶,砸金蛋,公会抽奖,开宝箱,蛋蛋忧伤,...
  334. * @return int $err
  335. * */
  336. static function insertLotterySysMessage($zoneid, $mem, $user, $itemId, $src) {
  337. throw new \Exception("need reimplement");
  338. $err = ErrCode::ok;
  339. // 向系统消息区域发送中奖消息.
  340. $broadCastIDs = glc()->broadCastIDs;
  341. if ($broadCastIDs == null) { # 需要广播的道具ID
  342. $err = ErrCode::err_msg_buildrewardnoconst;
  343. } else {
  344. $broadItemArray = JsonUtil::decode($broadCastIDs->content);
  345. if (!GAME_ONLINE || CommUtil::isPropertyExists($broadItemArray, $itemId)) {# 如果是测试的话,将所有中奖物品加入到系统消息中
  346. self::pushSysMessage($zoneid, SysMessageType::GetHero, #
  347. array($user->oid, $user->name, $itemId, $src));
  348. }
  349. }
  350. return $err;
  351. }
  352. // </editor-fold>
  353. }