/**
* 约定好的消息类型
*/
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;
}
//
}