/** * 约定好的消息类型 */ class SysMessageType extends Enum { /** (1)XXX(玩家名称)解锁英雄XXX(紫色橙色英雄) */ const GetHero = 1; /** (2)XXX(玩家名称)的英雄XXX(紫色橙色英雄)神血升值40%+(40%都有) */ const Hero_purification = 2; /** (3)XXX 获得XXX(紫色橙色装备) */ const GetEquip = 3; /** (4)XXX(玩家名称)购买公会钻石礼包 */ const BuyGuild_CashPack = 4; /** (5)XXX(玩家名称)升到XX级别(20级以上) */ const UserLevelUp = 5; /** (6)XXX(玩家名称)达到XX段位(黄金以上) */ const PVP_League = 6; /** (7) XXX(玩家名称)打败噩梦关八岐大蛇,获得铂金宝箱,可喜可贺! * 通过副本 * */ const Pass_carbon = 7; /** (4)装备-强化 */ const Weapon_Promote = 4000; /** * (99)玩家自己购买的全服消息(本分区) */ const UserSendMessage = 99; } /** * 系统消息对象 */ class SysMessageModel extends Object_ext { /** @var SysMessageType */ public $type; /** @var array 消息数据 */ public $datas; /** @var int */ public $ts; } // // /** * 系统消息逻辑处理流程 * @author gwang */ class SystemProc { /** * 系统消息的过期时间(秒) * @var int */ const SYS_MSG_OUTTS = 3600; /** * 主逻辑分发 * @param type $req * @return type */ static function procMain($req) { switch ($req->cmd) { case CmdCode::cmd_system_userSendsysmessage: # 6904 玩家发送系统广播 return self::userPushSysMessage($req); case CmdCode::cmd_system_getsysmessage: # 6901 拉取系统消息 return self::getSysMessage($req); case CmdCode::cmd_system_logreport: # 6902 客户端上报日志 return self::logReport($req); case CmdCode::cmd_system_clienttick: # 6903 客户端心跳包 return self::clientTick($req); default : return Resp::err(ErrCode::cmd_err); } } // // // /** * 客户端心跳包 * @param Req $req */ static function clientTick($req) { $timespan = now() - $req->userInfo->game->baseInfo->lastSaveTs; if ($timespan < 300) { # 间隔超过5分钟的不算 if ($timespan < 30) { # 心跳包固定30秒1次 $timespan = 30; } $req->userInfo->game->privateState->onlineGiftts += $timespan; UserProc::updateUserInfo(); } return Resp::ok(); } /** * 客户端日志上报 * @param Req $req * @return type */ static function logReport($req) { $mem = $req->mem; //客户端参数解析 $openId = $req->oid; //fromoid $log = $req->paras[0]; //消息列表有效时间戳 $logList = $mem->get("report-log"); # 读记录 if ($logList == null) { $logList = ArrayInit(); } # 错误记录上限300条 if (StlUtil::count($logList) >= 300) { StlUtil::arrayRemoveAt($logList, 0); } $logItem = ObjectInit(); $logItem->oid = $openId; $logItem->log = $log; $logItem->ts = CommUtil::tsCurrent(); $logList[] = $logItem; $mem->set("report-log", $logList); # 回写记录 $resp = Resp::myRetResponse($req, "copy!"); return $resp; } // // // // /** * 玩家通过xx副本消息 * @param type $zoneid * @param UserGameModel $user * @param int $carbonID * */ static function Carbon_Win($zoneid, $user, $carbonID, $hardLevel) { if (512001 == $carbonID) { self::pushSysMessage($zoneid, SysMessageType::Pass_carbon, array( $user->name, $carbonID, $hardLevel )); } } /** * 玩家pvp段位消息 * @param type $zoneid * @param UserGameModel $user * @param int $leagueID * */ static function PVP_league($zoneid, $user, $leagueID) { if ($leagueID > 10) { self::pushSysMessage($zoneid, SysMessageType::PVP_League, array( $user->name, GameConfig::pvp_leaguescore_getItem($leagueID)->leagueName )); } } /** * [6901]获取系统广播消息列表 * @param Req $req */ static function getSysMessage($req) { //客户端参数解析 $ts = $req->paras[0]; # 消息列表有效时间戳 $defaultwaitcont = 60; # 暂时使用60秒作为频率,若是有压力就调大些. 若是没有问题,可以调小些. $itemDisplayTime = 7; # 7秒显示完一条消息 $sysMessage = self::mem_getSysMsg_zset($req->zoneid, $ts); $count = count($sysMessage) * $itemDisplayTime; # 计算下次取消息的时间 if ($count < $defaultwaitcont) { # 最低刷新时间 $count = $defaultwaitcont; } $ret = array( 'sysMessage' => $sysMessage, 'nextFetchTime' => $count ); return Resp::ok($ret); # 返回信息 } /** * [6904]玩家发送系统广播消息 * @param Req $req */ static function userPushSysMessage($req) { list($msg, $type) = $req->paras; # 提取参数: 消息内容, 消耗道具类型,1:钻石,2:xx $user = $req->userInfo->game; $uid = $req->uid; $cost = 0; // 花费 switch ($type) { case 1: # 钻石 $cost = glc()->SystemMessage_UserSendToMyZone_Cost; my_Assert($cost, ErrCode::err_msg_usersnedmsg_errorcost); my_Assert(UserGameModel::Consume_Cash($user, $cost), ErrCode::notenough_cash_msg); break; default : Err(ErrCode::paras_err); // 其他类型:参数非法 } self::pushSysMessage($req->zoneid, # SysMessageType::UserSendMessage, array($uid, $user->name, $msg)); UserProc::updateUserInfo(); // 回存账号数据 return Resp::ok(array('ret' => "succeed")); # 返回值 } // -----------------辅助方法--------------------- // /** * 玩家升级消息 * @param type $zoneid * @param UserGameModel $user * @param int $newLevel * */ static function UserLevelUp($zoneid, $user, $newLevel) { if ($newLevel > 20) { self::pushSysMessage($zoneid, SysMessageType::UserLevelUp, array( $user->name, $newLevel )); } } /** * 插入英雄升阶消息 * @param int $zoneid * @param string $uid * @param string $name * @param string $heroname * @param int $level */ static function insertHero_StageUp($zoneid, $uid, $name, $heroname, $level) { // if ($level >= glc()->SystemMessage_HeroStage_Limit_Min) { // self::pushSysMessage($zoneid, SysMessageType::GetEquip, array( // $uid, $name, $heroname, $level // )); // } } /** * 添加购买公会钻石礼包消息 * @param type $zoneid * @param UserGameModel $user * */ static function BuyGuildCashPack($zoneid, $user) { self::pushSysMessage($zoneid, SysMessageType::BuyGuild_CashPack, array( $user->name )); } /** * 添加获得装备消息 * @param type $zoneid * @param UserGameModel $user * @param int $equipModelId * @deprecated since version 0 待维修 --王刚2020年1月2日21:07:04 * */ static function GetEquip($zoneid, $user, $equipModelId) { $equipModel = GameConfig::item_getItem($equipModelId); if ($equipModel && $equipModel->quailty > 3) { # 紫色橙色装备 self::pushSysMessage($zoneid, SysMessageType::GetEquip, array( $user->name, $equipModel->name )); } } /** * 插入装备强化消息 * @deprecated since version 1.0 装备强化暂不支持了 * @param type $zoneid * @param type $uid * @param type $name * @param type $weaponname * @param type $level */ static function insertWeapon_promoteUp($zoneid, $uid, $name, $weaponname, $level) { // if ($level >= glc()->SystemMessage_WeaponLevel_Limit_Min) { // self::pushSysMessage($zoneid, SysMessageType::Weapon_Promote, array( // $uid, $name, $weaponname, $level // )); // } } ////=================//// /** * 添加获得英雄消息 * @param type $zoneid * @param UserGameModel $user * @param int $heroId * @return int $err * */ static function GetHero($zoneid, $user, $heroId) { $heroModel = GameConfig::hero_getItem($heroId); if ($heroModel && $heroModel->zhenxidu > 3) { self::pushSysMessage($zoneid, SysMessageType::GetHero, array( $user->name, $heroModel->name )); } } /** * 添加英雄血脉提纯消息 * @param type $zoneid * @param UserGameModel $user * @param int $heroId * @return int $err * */ static function Hero_purification($zoneid, $user, $heroId) { $heroModel = GameConfig::hero_getItem($heroId); if ($heroModel && $heroModel->zhenxidu > 3) { self::pushSysMessage($zoneid, SysMessageType::Hero_purification, array( $user->name, $heroModel->name )); } } // // /** * 取数据 * @param int $zoneid * @return array */ private static function mem_getSysMsg_zset($zoneid, $ts) { $ret = gMem()->zrangebyscore(MemKey_GameRun::Game_SysMsgByZone_zset($zoneid), $ts, now(+1)); //todo:目前是在这里手动解码的, 应该移动到CRedisUtil里面去. $arr = ArrayInit(); if ($ret) { foreach ($ret as $msg) { $arr[] = JsonUtil::decode($msg); } } return $arr; } /** * 回写数据 * @param int $zoneid * @param SysMessageModel $value */ private static function mem_addSysMsg_zset($zoneid, $value) { $ts = $value->ts; $key = MemKey_GameRun::Game_SysMsgByZone_zset($zoneid); gMem()->zadd($key, array(json_encode($value) => $ts)); # 插入消息 gMem()->zremrangebyscore($key, 0, $ts - self::SYS_MSG_OUTTS); # 清理过期数据 } // // /** * 推送系统消息 * @param int $zoneid 分区 * @param SysMessageType $type enum * @param array $datas */ static function pushSysMessage($zoneid, $type, $datas) { $newMsg = new SysMessageModel(array(# # 添加新系统消息 'type' => $type, 'datas' => $datas, 'ts' => now() )); self::mem_addSysMsg_zset($zoneid, $newMsg); # 写入mem } // /** * 添加中奖消息 * @param type $mem * @param UserModel $user * @param int $itemId * @param string $src 来源: 砸木桶,砸金蛋,公会抽奖,开宝箱,蛋蛋忧伤,... * @return int $err * */ static function insertLotterySysMessage($zoneid, $mem, $user, $itemId, $src) { throw new \Exception("need reimplement"); $err = ErrCode::ok; // 向系统消息区域发送中奖消息. $broadCastIDs = glc()->broadCastIDs; if ($broadCastIDs == null) { # 需要广播的道具ID $err = ErrCode::err_msg_buildrewardnoconst; } else { $broadItemArray = JsonUtil::decode($broadCastIDs->content); if (!GAME_ONLINE || CommUtil::isPropertyExists($broadItemArray, $itemId)) {# 如果是测试的话,将所有中奖物品加入到系统消息中 self::pushSysMessage($zoneid, SysMessageType::GetHero, # array($user->oid, $user->name, $itemId, $src)); } } return $err; } // }