cmd) {
case CmdCode::cmd_email_questEmailList: # 6701 刷新邮件列表状态
return EmailProc::RefreshEmailList($req);
case CmdCode::cmd_email_readAEmail: # 6702 读取一封邮件
return EmailProc::ReadEmail($req);
case CmdCode::cmd_email_DrawReward: # 6703 领取一封邮件附件(奖励)
return EmailProc::DrawEmailAppendix($req);
case CmdCode::cmd_email_DrawAllRewards: # 6704 领取所有邮件
return EmailProc::DrawAllEmailAppendixes($req);
case CmdCode::cmd_mail_delMailReaded: # 6705 删除已读邮件
return EmailProc::DelReadedEmail($req);
case CmdCode::cmd_mail_notReadMailNum: # 6706 请求邮件未处理的数量
return EmailProc::queryNotReadEmails($req);
default:
return Resp::err(ErrCode::cmd_err);
}
}
//
/**
* 【6706】查询未处理邮件数量
* @param req $req
*/
static function queryNotReadEmails($req) {
$uid = $req->uid;
$zoneid = $req->zoneid;
$n = 0; # 计数器
self::refreshSysMail($zoneid, $uid); # 更新下系统邮件
self::clearExpireMails($zoneid, $uid); # 清理过期邮件, 以及超过容量的邮件
$mails = self::getMailQueue($zoneid, $uid);
foreach ($mails as $m) {
// isEditor() and $m = new EmailModel();
if (!$m->readts <= 0) {
$n += 1;
}
}
return Resp::ok(array('num' => $n));
}
/**
* 【6701】拉取最新邮件列表
* @param Req $req
*/
public static function RefreshEmailList($req) {
$uid = $req->uid;
$zoneid = $req->zoneid;
self::refreshSysMail($zoneid, $uid); # 更新下系统邮件
self::clearExpireMails($zoneid, $uid); # 清理过期邮件, 以及超过容量的邮件
$mails = self::getMailQueue($zoneid, $uid); # 拉取邮件列表
var_dump($mails);
return Resp::ok(array('mailQueue' => $mails)); # 返回值
}
/**
* 【6702】读取一封邮件, 更新readts
* @param Req $req
*/
public static function ReadEmail($req) {
$uid = $req->uid;
$zoneid = $req->zoneid;
$mailId = $req->paras[0]; # 传递参数,邮件的id字符串
my_Assert($mailId, ErrCode::email_wrongid); # 普通读取一封邮件的逻辑
$mail = self::getMail($zoneid, $uid, $mailId);
$mail->readts = now();
self::updateMail($zoneid, $uid, $mail); # 更新邮件数据
self::logMailReaded(array($mailId), $uid, $zoneid); # 更新数据库中邮件的read记录
return Resp::ok(array("rewardstr" => $mail->appendix));
}
/**
* 【6703】 领取一封邮件的附件,更新drawedts
* @param req $req
* @return type
*/
public static function DrawEmailAppendix($req) {
$uid = $req->uid;
$zoneid = $req->zoneid;
$mailId = $req->paras[0]; # 传递参数,邮件的id字符串
my_Assert($mailId, ErrCode::email_wrongid); # 邮件id
$mail = self::getMail($zoneid, $uid, $mailId); # 取出对应的邮件数据
my_Assert($mail->readts > 0, ErrCode::err_innerfault); # 未打开的不可能调用领取接口
my_Assert($mail->isExistReward(), ErrCode::email_no_appendix); # 先判断邮件,是否存在有效的奖励物品
my_Assert($mail->drawedts <= 0, ErrCode::email_appendix_drawed); # 邮件不可重复领取
$err = StoreProc::AddMultiItemInStore($req, $mail->appendix, 4); # 发放奖励
my_Assert(ErrCode::ok == $err, $err); # 发奖成功
$mail->drawedts = now(); # 更新领取时间戳
self::updateMail($zoneid, $uid, $mail); # 回写邮件数据
self::logMailDrawed(array($mailId), $uid, $zoneid); # 更新数据库中邮件的领取记录
UserProc::updateUserInfo();
return Resp::ok(array(# # 同步数据
'gold' => $req->userInfo->game->baseInfo->gold,
'cash' => $req->userInfo->game->baseInfo->cash,
'store' => $req->userInfo->game->store,
'hero' => $req->userInfo->game->heros,
'num' => 1,
'reward' => $mail->appendix
));
}
/**
* 【6704】 领取所有邮件附件奖励
* @param req $req
* @return type
*/
public static function DrawAllEmailAppendixes($req) {
$uid = $req->uid;
$zoneid = $req->zoneid;
$arr = ArrayInit(); # 记录奖励字符串
$rewardEmailIds = ArrayInit(); # 记录领取邮件id
$mails = self::getMailQueue($zoneid, $uid); # 提取邮件列表
// 有奖励的邮件,全部处理,领取奖励。无奖励的邮件,不处理。因为全部领取邮件功能只限于处理有奖励的物品,无奖励的不管
foreach ($mails as $m) { # 遍历所有邮件
isEditor() and $m = new EmailModel;
if ($m->isExistReward()) { # 先判断邮件,是否存在附件
if ($m->drawedts > 0) { # 已领取邮件跳过
continue;
}
$err = StoreProc::AddMultiItemInStore($req, $m->appendix, 4);
my_Assert(ErrCode::ok == $err, $err); # 发奖成功
$m->drawedts = now(); # 更新下领取时间戳
if ($m->readts <= 0) { # 更新下读取时间戳
$m->readts = now();
}
$arr[] = $m->appendix;
$rewardEmailIds[] = $m->mailId;
} // else # 无附件的邮件不管
}
$asocMails = array();
foreach ($mails as $mm) { # 转为关联数组
// isEditor() and $mm = new EmailModel;
$asocMails[$mm->mailId] = $mm;
}
$n = count($rewardEmailIds); # 计数,领取邮件数量
if ($n > 0) {
self::updateMails($zoneid, $uid, $asocMails); # 批量更新邮件
self::logMailDrawed($rewardEmailIds, $uid, $zoneid); # 更新数据库中邮件的领取记录
}
$reward = implode(';', $arr); # 拼接下奖励字符串
UserProc::updateUserInfo();
return Resp::ok(array(# # 同步数据
'gold' => $req->userInfo->game->baseInfo->gold,
'cash' => $req->userInfo->game->baseInfo->cash,
'store' => $req->userInfo->game->store,
'hero' => $req->userInfo->game->heros,
'num' => $n,
'reward' => $reward));
}
/**
* 【6705】 删除所有已读邮件
* @param req $req
* @return type
*/
public static function DelReadedEmail($req) {
$uid = $req->uid;
$zoneid = $req->zoneid;
$mails = self::getMailQueue($zoneid, $uid); # 取邮件队列
$n = 0; # 记个数,看一共删除几封邮件
foreach ($mails as $m) {
isEditor() and $m = new EmailModel;
if ($m->readts <= 0) { # 未读邮件跳过
continue;
}
if ($m->isExistReward()) { # 包含附件,
if (!$m->isDrawed()) { # 且附件尚未领取的,不能删除,跳过
continue;
}
}
self::delMail($zoneid, $uid, $m->mailId); # 规则: 附件领取后就可以删除邮件
$n++;
}
return Resp::ok(array('num' => $n)); # 返回删除数量
}
//
//
//
/**
* 系统邮件 - 发送月卡奖励
* @param type $zoneid
* @param type $uid
* @param type $rank
*/
public static function SendMonthlyVIPDailyReward($zoneid, $uid, $cardName, $reward) {
$mail = new EmailModel(null, enum_Mail_Type::SysTemMail, "月卡奖励", #
$cardName . "每日奖励", $reward);
self::InsertMail($zoneid, $uid, $mail);
}
/**
* 系统邮件 - 发送竞技场赛季排行榜奖励
* @param type $zoneid
* @param type $uid
* @param type $rank
*/
public static function SendPvpRankReward_Season($zoneid, $uid, $rank) {
foreach (GameConfig::pvp_rankreward() as $rkrwd) {
isEditor() and $rkrwd = new \sm_pvp_rankreward();
if ($rank >= $rkrwd->minRank and $rank <= $rkrwd->maxRank) {
$arr = explode(',', $rkrwd->reward_season);
$itemid = $arr[0];
$num = $arr[1];
$mail = new EmailModel(null, enum_Mail_Type::SysTemMail, "竞技场赛季上榜奖励", #
"恭喜您在上赛季的竞技场战斗中获得总榜" . $rkrwd->rankName . "的奖励", #
"$itemid,$num");
self::InsertMail($zoneid, $uid, $mail);
break;
}
}
}
/**
* 系统邮件 - 发送竞技场每日排行榜上榜奖励
* @param type $zoneid
* @param type $uid
* @param type $rank
*/
public static function SendPvpRankReward_Lastday($zoneid, $uid, $rank) {
foreach (GameConfig::pvp_rankreward() as $rkrwd) {
isEditor() and $rkrwd = new \sm_pvp_rankreward();
if ($rank >= $rkrwd->minRank and $rank <= $rkrwd->maxRank) {
$arr = explode(',', $rkrwd->reward_day);
$itemid = $arr[0];
$num = $arr[1];
$mail = new EmailModel(null, enum_Mail_Type::SysTemMail, "竞技场每日上榜奖励", #
"恭喜您在昨天的竞技场战斗中获得总榜" . $rkrwd->rankName . "的奖励", #
"$itemid,$num");
self::InsertMail($zoneid, $uid, $mail);
break;
}
}
}
/**
* 删档内侧补偿邮件
* @param type $zoneid
* @param type $uid
* @param type $name
* @param type $content
*/
public static function SendDelTestMail($zoneid, $uid, $name, $content) {
$arr = explode(',', $content);
$itemid = $arr[0];
$num = intval($arr[1]) * 2; # 2倍返还
$mail = new EmailModel(null, enum_Mail_Type::SysTemMail, "删档内侧补偿", #
"感谢您在之前的删档内侧活动中充值购买$name.", "$itemid, $num");
self::InsertMail($zoneid, $uid, $mail);
}
//
//
//
/**
* 系统邮件 - 公会申请被拒,通知玩家
* @param type $zoneid
* @param type $uid
* @param type $rank
*/
public static function SendGuildApplyRefusedMail($zoneid, $uid, $guildName) {
$mail = new EmailModel(null, enum_Mail_Type::GuildApplyRefuseMail, "公会申请结果", #
"很遗憾" . $guildName . "公会拒绝了您的加入申请", "", "公会");
self::InsertMail($zoneid, $uid, $mail);
}
/**
* 系统邮件 - 公会捐献碎片结算
* @param type $zoneid
* @param type $uid
* @param type $rank
*/
public static function SendGuildDonateSettle($zoneid, $uid, $chipArr) {
$itemId = $chipArr[0];
$itemNum = $chipArr[1];
$content = $itemNum == null ? "请求捐献结算时间截止,没有得到捐献碎片" : "请求捐献结算时间截止,领取已获得碎片";
$mail = new EmailModel(null, enum_Mail_Type::GuildDonateSettle, "公会捐献碎片结算", #
$content, "$itemId, $itemNum", "公会");
self::InsertMail($zoneid, $uid, $mail);
}
/**
* 系统邮件 - 公会钻石礼包奖励结算
* @param type $zoneid
* @param type $uid
* @param type $rank
*/
public static function SendGuildCashGiftReward($zoneid, $uid, $itemId, $num) {
$mail = new EmailModel(null, enum_Mail_Type::GuildCashGiftReward, "公会礼包回赠", #
"系统回赠礼品", "$itemId, $num", "公会");
self::InsertMail($zoneid, $uid, $mail);
}
/**
* 公会公告邮件
* @param type $zoneid
* @param type $uid
* @param type $content
*/
public static function SendGuildNoticeMail($zoneid, $uid, $title, $content) {
$mail = new EmailModel(null, enum_Mail_Type::GuildNoticeMail, $title, #
$content, "", "公会");
self::InsertMail($zoneid, $uid, $mail);
}
//
//
//
/**
* 插入邮件
* @param int $zoneid
* @param string $uid
* @param EmailModel $mail
*/
private static function InsertMail($zoneid, $uid, $mail) {
$mem = gMem();
$key_id = MemKey_User::Mail_CurId_int($zoneid, $uid);
$key_queue = MemKey_User::Mail_Queue_hash($zoneid, $uid);
$mail->insertts = now();
$mail->mailId = $mem->increment($key_id);
if (!$mem->hsetnx($key_queue, $mail->mailId, $mail)) { # 重试下
$mail->mailId = $mem->increment($key_id);
if (!$mem->hsetnx($key_queue, $mail->mailId, $mail)) {
// todo: 重试都没能成功的话, 记录下日志, log err;
CLog::err('create sysmail failed! id:' . JsonUtil::encode($mail), "EmailProc");
}
}
self:: logMail($zoneid, $uid, $mail); # 将邮件写入Mysql中
CornerSignEventProc::OnNewMails(req());
return $mail->mailId;
}
/**
* 回写mail数据
* @param type $zoneid
* @param type $uid
* @param EmailModel $mail
*/
private static function updateMail($zoneid, $uid, $mail) {
gMem()->hset(MemKey_User::Mail_Queue_hash($zoneid, $uid), $mail->mailId, $mail);
}
/**
* 批量回写mail数据
* @param type $zoneid
* @param type $uid
* @param dic $mails
*/
private static function updateMails($zoneid, $uid, $mails) {
gMem()->hmset(MemKey_User::Mail_Queue_hash($zoneid, $uid), $mails);
}
/**
*
* @param type $zoneid
* @param type $uid
* @param EmailModel $mail
*/
private static function logMail($zoneid, $uid, $mail) {
$data = array(
'mailId' => $mail->mailId,
'zoneid' => $zoneid,
'appendix' => $mail->appendix,
'type' => $mail->type,
'sender_name' => $mail->sender_name,
'sender_uid' => $mail->sender_uid,
'to_uid' => $uid, # # this mail is send to me 啊.
'title' => $mail->title,
'content' => $mail->content,
'tag' => $mail->tag
);
daoInst()->insert('tab_mailrecord')->data($data)->exec();
}
/**
* 更新邮件的领取记录
* @version 1 这里邮件id不是唯一, 需要联合uid一起改.--晨叶反馈于2020.5.21
* 0 created at 言灵世界1.0
* @param type $ids
*/
static function logMailDrawed($ids, $uid, $zoneid) {
daoInst()->update(self::MailLog_TableName)->data(array(
'drawedts' => now()
))->where('mailId')->in($ids)->
andWhere('zoneid')->eq($zoneid)->
andWhere('to_uid')->eq($uid)->
exec();
}
/**
* 更新邮件的读取/打开记录
* @version 1 这里邮件id不是唯一, 需要联合uid一起改.--晨叶反馈于2020.5.21
* 0 created at 言灵世界1.0
* @param type $ids
*/
static function logMailReaded($ids, $uid, $zoneid) {
daoInst()->update(self::MailLog_TableName)->data(array(
'readts' => now()
))->where('mailId')->in($ids)->
andWhere('zoneid')->eq($zoneid)->
andWhere('to_uid')->eq($uid)->
exec();
}
/**
* 刷新系统派发邮件到玩家邮件列表
* @param int $zoneid
* @param string $uid
* @return void
*/
private static function refreshSysMail($zoneid, $uid) {
$mem = gMem();
$sysMailQueue = GameConfig::sysmail(); # 取系统消息列表
if (!$sysMailQueue) {
return; # 系统消息为空
}
$key = MemKey_User::Mail_SysRecord_set($zoneid, $uid); # memkey
$record = $mem->smembers($key); # 系统邮件处理记录,在数据集过大以前, 个人认为全部获取比较高效 --王刚,所以系统邮件不能太多呢(后面取已处理最大id,做优化吧)
foreach ($sysMailQueue as $sysId => $sysMail) {
isEditor() and $sysMail = new \sm_sysmail(); # 辅助方法.
if (!StlUtil::arrayContains($record, $sysId)) { # 判断尚未处理此邮件
$ts = now();
if ($ts > $sysMail->endts) { # 已经过期的系统邮件
$mem->sadd($key, $sysId); # 记录已经领取此邮件, 但不插入玩家邮件列表了.
continue; # 继续处理下一封
}
if ($ts < $sysMail->startts) {
continue; # 系统邮件尚未生效, 跳过
} # else => 有效期内,继续处理
$mail = new EmailModel($sysMail); # 创建邮件
$mail->type = enum_Mail_Type::SysTemMail; # 设置邮件类型为系统邮件
$mail->sender_uid = $mail->sender_name = "系统"; # 设置发送者昵称和uid为系统
self::InsertMail($zoneid, $uid, $mail); # 插入邮件
$mem->sadd($key, $sysId); # 记录已经领取此邮件
}
}
}
/**
* 清理过期邮件
* @param string $zoneid
* @param string $uid
* @return void
*/
private static function clearExpireMails($zoneid, $uid) {
$ts = now();
$mem = gMem();
$key = MemKey_User::Mail_Queue_hash($zoneid, $uid);
$arr = $mem->hgetall($key); # 所有邮件
$del = array_filter((array) $arr, function($v) use($ts) {
$email = new EmailModel($v);
return $email->ExpireTs() < $ts; # 选出过期邮件
});
if (count($del)) { # >0
$mem->hdel($key, array_keys($del)); # 批量清除
}
}
/**
* 获取邮件序列
* @param int $zoneid
* @param string $uid
* @return array
*/
private static function getMailQueue($zoneid, $uid) {
$key = MemKey_User::Mail_Queue_hash($zoneid, $uid); # redis-key:= 玩家邮件列表
$keys = gMem()->hkeys($key); # 拉取所有id
var_dump($keys);
sort($keys); # 排序
$mkeys = array_slice($keys, 0, self::MaxMailContent); # 取固定数量100
var_dump($mkeys);
$mails = (array) gMem()->hmget($key, $mkeys); # mget
$ret = array_map(function($v) {
return new EmailModel($v); # 装箱
}, $mails);
return array_values($ret);
}
/**
* 获取邮件
* @param int $zoneid
* @param string $uid
* @param int $mailId
* @return EmailModel
*/
private static function getMail($zoneid, $uid, $mailId) {
$m = gMem()->hget(MemKey_User::Mail_Queue_hash($zoneid, $uid), $mailId);
my_Assert($m, ErrCode::email_not_found);
return new EmailModel($m);
}
/**
* 删除邮件
* @param int $zoneid
* @param string $uid
* @param int $mailId
* @return int 删除的邮件数量, (0,1)
*/
private static function delMail($zoneid, $uid, $mailId) {
return gMem()->hdel(MemKey_User::Mail_Queue_hash($zoneid, $uid), $mailId);
}
/**
* 清空邮件列表
* @param int $zoneid
* @param string $uid
* @return int 删除邮件的条数, (0,n)
*/
private static function clearMailQueue($zoneid, $uid) {
$key = MemKey_User::Mail_Queue_hash($zoneid, $uid);
$n = gMem()->hlen($key); # 先看总共有多少邮件, Ps.返回值要用
gMem()->delete($key); # 删除邮件列表
return $n;
}
//
}