using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using Sog; using Sog.Log; using ProtoCSStruct; namespace Game { public class MailHandler : BasePacketHandler { public override int GetServiceType() { return GameServiceType.MailHandler; } //销毁的时候置空 public override void Dispose() { } public MailHandler() { } public override void HandlerClientPacket(PlayerSession playerSession, StructPacket packet) { PlayerOnGame player = playerSession.Player; if (player == null) { TraceLog.Error("MailHandler.HandlerClientPacket can not find PlayerOnGame sessionid {0}", playerSession.SessionID); return; } switch (packet.MsgID) { case (int)CSGameMsgID.QueryMailReq: OnCliQueryMailReq(player, packet); break; case (int)CSGameMsgID.MailOpReq: OnCliMailOpReq(player, packet); break; case (int)CSGameMsgID.MailSendToPlayerReq: OnCliSendMailToPlayerReq(player, packet); break; default: break; } } public override void HandlerServerPacket(uint serverID, StructPacket packet) { switch (packet.MsgID) { case (int)SSGameMsgID.QueryMailRes: OnSvrQueryMailRes(serverID, packet); break; case (int)SSGameMsgID.MailOpRes: OnSvrMailOpRes(serverID, packet); break; case (int)CSGameMsgID.MailSendToPlayerRes: OnSvrMailSendToPlayerRes(serverID, packet); break; case (int)SSGameMsgID.OperationMailDeleteReq: OnOperationDeleteMail(serverID, packet); break; default: break; } } private void OnCliQueryMailReq(PlayerOnGame player, StructPacket packet) { if (player.DBMailDataLoadedTime != 0) { player.Trace("MailHandler.OnCliQueryMailReq uid {0} mail data already in memory", player.UserID); long nowTime = GameServerUtils.GetTimeSecond(); bool needDelMail = false; List list = new List(); ref CSQueryMailRes res = ref CSStructPool.Instance.GetObjRef(); for (int i = 0; i < player.MailInfo.Count; i++) { ref var mail = ref player.MailInfo[i]; if (mail.ExpirationTime > 0 && mail.ExpirationTime <= nowTime) { //删除过期的邮件(缓存) list.Add(mail.MailID); needDelMail = true; continue; } if (mail.DeleteTime > 0) { continue; } res.MailList.Add(ref mail); } SendToPlayer(player, (int)CSGameMsgID.QueryMailRes, ref res); //删除过期邮件 if (needDelMail) { DBMail mail = new DBMail(); mail.Uid = player.UserID; MailSender.SendMailOpReqToDB(0, MailOpType.AllDelete, ref mail, list); } return; } player.Trace("MailHandler.OnCliQueryMailReq uid {0} no mail data already in memory, query from db", player.UserID); MailSvc.QueryRoleMail(player); } private void OnSvrQueryMailRes(uint serverID, StructPacket packet) { ref SSQueryMailRes ssres = ref packet.GetMessage(); PlayerOnGame player = GameServerUtils.GetPlayerTableOp().GetPlayerByUid(ssres.Uid); if (player == null) { player.Error("MailHandler.OnSvrQueryMailRes no player object uid {0}", ssres.Uid); return; } bool loadMailDataFirst = false; if (player.DBMailDataLoadedTime == 0) { player.DBMailDataLoadedTime = GameServerUtils.GetTimeSecond(); loadMailDataFirst = true; } player.MailInfo.Clear(); player.MailInfo.CopyFrom(ref ssres.MailList); player.Trace("MailHandler.OnSvrQueryMailRes player uid {0} have mail count {1}, LastVersionUpdateCompensate {2}" , player.UserID, player.MailInfo.Count, player.RoleData.OtherData.LastVersionUpdateCompensate); MailSvc.ProcessSpecialMailOnQueryRes(player); //通知一下客户端 ref CSQueryMailRes res = ref CSStructPool.Instance.GetObjRef(); res.MailList.CopyFrom(ref player.MailInfo); SendToPlayer(player, (int)CSGameMsgID.QueryMailRes, ref res); if (loadMailDataFirst) { //上次领取操作未完成 if (player.RoleData.MailOp.GetItemMailID != 0) { player.Error("MailHandler.OnSvrQueryMailRes last getItem op no finished, mailid {0} uid {1} check it ..." , player.RoleData.MailOp.GetItemMailID, player.UserID); int mailIndex = MailSvc.GetMailIndexFromPlayer(player, player.RoleData.MailOp.GetItemMailID); if (mailIndex != -1) { ref DBMail mail = ref MailSvc.GetMailByIndex(player, mailIndex); if (mail.GetItemTime != 0) { player.Error("MailHandler.OnSvrQueryMailRes mail getitem success in db, so get item to palyer now."); OnGetMailItemSuccessAddItemToPlayer(player, ref mail,MailOpType.GetItem); } else { player.Error("MailHandler.OnSvrQueryMailRes mail getitem not finish in db, so resend request"); MailSender.SendMailOpReqToDB(player.UserID, MailOpType.GetItem, ref mail); } } else { player.Error("MailHandler.OnSvrQueryMailRes mail getitem not finish in db, but mail not exist now !skip"); player.RoleData.MailOp.GetItemMailID = 0; //算了 player.MakeDirty(); } } //放到tick里去,这样发不停服版本可以支持 //VersionUpdateCompensateSvc.TryCompensatePlayerAfterGetMailData(player); } //MailSvc.ProcessSpecialMailOnQueryRes(player); } private void OnCliMailOpReq(PlayerOnGame player, StructPacket packet) { ref CSMailOpReq req = ref packet.GetMessage(); //if (req.Mail.MailID == 0 || player.DBMailDataLoadedTime == 0) //{ // //外挂 // player.Error("OnCliMailOpReq uid {0} no maildata", player.UserID); // return; //} //领取附件 if (req.OpType == (int)MailOpType.GetItem) { if (req.MailID == 0) { player.Error("OnCliMailOpReq uid {0} mailid = 0, invalid", player.UserID); return; } int mailIndex = MailSvc.GetMailIndexFromPlayer(player, req.MailID); if (mailIndex == -1) { AckPlayerMailOpError(player, ref req, (int)CSErrCode.MailNotExist); return; } ref DBMail mail = ref MailSvc.GetMailByIndex(player, mailIndex); if ( mail.AddGoods.Count == 0) { //外挂?没附件领个毛 player.Error("OnCliMailOpReq uid {0} no item in mail", player.UserID); return; } //已经领取过了 if (mail.GetItemTime != 0) { AckPlayerMailOpError(player, ref req, (int)CSErrCode.MailAlreadyGot); return; } //上次领取操作未完成 if (player.RoleData.MailOp.GetItemMailID != 0) { AckPlayerMailOpError(player, ref req, (int)CSErrCode.MailOpNotFinish); return; } //未达到领取版本条件 if (AppVersion.ToIntVersion(mail.ApkVersion.GetString()) > AppVersion.ToIntVersion(player.apkVersion)) { AckPlayerMailOpError(player, ref req, (int)CSErrCode.MailConditionNotFinish); return; } //检测邮件是否有领取限制 UnifyOp bagOp = new UnifyOp(player, BillChangeItemReason.GetItemMail, mail.MailType.ToString()); bagOp.InitGoodTypeLimit(player); //初始化类型限制 for (int i = 0; i < mail.AddGoods.Count; i++) { if (mail.AddGoods[i].Type > 0 && !string.IsNullOrEmpty(mail.AddGoods[i].Id.ToString()) && mail.AddGoods[i].Value > 0) { bagOp.AddGoods(mail.AddGoods[i].Type, mail.AddGoods[i].Id.ToString(), mail.AddGoods[i].Value); bagOp.ChgGoodTypeLimit(mail.AddGoods[i].Type, mail.AddGoods[i].Value); //增加类型限制 } } CSErrCode code = bagOp.CheckOp(); if (code != CSErrCode.None) { AckPlayerMailOpError(player, ref req, (int)code); return; } code = bagOp.CheckGoodTypeLimit(player);//进行类型限制检测 if (code != CSErrCode.None) { AckPlayerMailOpError(player, ref req, (int)code); return; } //开始领取操作,先设置标记 player.RoleData.MailOp.GetItemMailID = mail.MailID; player.MakeDirty(); player.Trace("MailHandler.OnCliMailOpReq begin get item from mail {0} uid {1}", mail.MailID, player.UserID); MailSender.SendMailOpReqToDB(player.UserID, MailOpType.GetItem, ref mail); } else if (req.OpType == (int)MailOpType.Delete) { if (req.MailID == 0) { player.Error("OnCliMailOpReq uid {0} mailid = 0, invalid", player.UserID); return; } int mailIndex = MailSvc.GetMailIndexFromPlayer(player, req.MailID); if (mailIndex == -1) { AckPlayerMailOpError(player, ref req, (int)CSErrCode.MailNotExist); return; } ref DBMail mail = ref MailSvc.GetMailByIndex(player, mailIndex); player.Trace("MailHandler.OnCliMailOpReq begin delete mail {0} uid {1}", mail.MailID, player.UserID); MailSender.SendMailOpReqToDB(player.UserID, MailOpType.Delete, ref mail); } else if (req.OpType == (int)MailOpType.GetItemDel) { if (req.MailID == 0) { player.Error("OnCliMailOpReq uid {0} mailid = 0 optype {1}, invalid", player.UserID, req.OpType); return; } int mailIndex = MailSvc.GetMailIndexFromPlayer(player, req.MailID); if (mailIndex == -1) { AckPlayerMailOpError(player, ref req, (int)CSErrCode.MailNotExist); return; } ref DBMail mail = ref MailSvc.GetMailByIndex(player, mailIndex); if (mail.AddGoods.Count == 0) { //外挂?没附件领个毛 player.Error("OnCliMailOpReq uid {0} optype {1} no item in mail", player.UserID, req.OpType); return; } //已经领取过了 if (mail.GetItemTime != 0) { AckPlayerMailOpError(player, ref req, (int)CSErrCode.MailAlreadyGot); return; } //上次领取操作未完成 if (player.RoleData.MailOp.GetItemMailID != 0) { AckPlayerMailOpError(player, ref req, (int)CSErrCode.MailOpNotFinish); return; } //未达到领取版本条件 if (AppVersion.ToIntVersion(mail.ApkVersion.GetString()) > AppVersion.ToIntVersion(player.apkVersion)) { AckPlayerMailOpError(player, ref req, (int)CSErrCode.MailConditionNotFinish); return; } //开始领取操作,先设置标记 player.RoleData.MailOp.GetItemMailID = mail.MailID; player.MakeDirty(); player.Trace("MailHandler.OnCliMailOpReq begin get item & del from mail {0} uid {1}", mail.MailID, player.UserID); MailSender.SendMailOpReqToDB(player.UserID, MailOpType.GetItemDel, ref mail); } else if (req.OpType == (int)MailOpType.Read) { if (req.MailID == 0) { player.Error("OnCliMailOpReq uid {0} mailid = 0, invalid", player.UserID); return; } int mailIndex = MailSvc.GetMailIndexFromPlayer(player, req.MailID); if (mailIndex == -1) { AckPlayerMailOpError(player, ref req, (int)CSErrCode.MailNotExist); return; } ref DBMail mail = ref MailSvc.GetMailByIndex(player, mailIndex); //已经读了 if (mail.Status != 0) { AckPlayerMailOp(player, (int) MailOpType.Read, ref mail); return; } player.Trace("MailHandler.OnCliMailOpReq begin Read mail {0} uid {1}", mail.MailID, player.UserID); MailSender.SendMailOpReqToDB(player.UserID, MailOpType.Read, ref mail); } else if (req.OpType == (int)MailOpType.AllDelete) { List list = new List(); for (int i = 0; i < player.MailInfo.Count; i++) { int AddGoodsCount = 0; ref var one = ref player.MailInfo[i]; for (int k = 0; k < one.AddGoods.Count; k++) { if ((one.AddGoods[k].Type > 0 && !string.IsNullOrEmpty(one.AddGoods[k].Id.GetString())) && one.AddGoods[k].Value > 0) { AddGoodsCount++; } } if (one.Status > 0 || one.GetItemTime > 0) { if (one.GetItemTime > 0) { list.Add(one.MailID); } } } DBMail mail = new DBMail(); mail.Uid = player.UserID; //player.MakeDirty(); //player.Trace("MailHandler.OnCliMailOpReq begin Read mail {0} uid {1}", mail.MailID, player.UserID); MailSender.SendMailOpReqToDB(player.UserID, MailOpType.AllDelete, ref mail, list); } else if (req.OpType == (int)MailOpType.AllGetItem) { UnifyOp bagAllOp = new UnifyOp(player, BillChangeItemReason.GetItemMail, ""); bagAllOp.InitGoodTypeLimit(player); List list = new List(); for (int i = 0; i < player.MailInfo.Count; i++) { int AddCurrencyCount = 0; int AddGoodsCount = 0; ref var one = ref player.MailInfo[i]; if(one.GetItemTime > 0) { continue; } //未达到领取版本条件 if (AppVersion.ToIntVersion(one.ApkVersion.GetString()) > AppVersion.ToIntVersion(player.apkVersion)) { continue; } //检测邮件是否有领取限制 UnifyOp bagOp = new UnifyOp(player, BillChangeItemReason.GetItemMail, one.MailType.ToString()); for (int k = 0; k < one.AddGoods.Count; k++) { if ((one.AddGoods[k].Type > 0 || !string.IsNullOrEmpty(one.AddGoods[k].Id.GetString())) && one.AddGoods[k].Value > 0) { bagOp.AddGoods(one.AddGoods[k].Type, one.AddGoods[k].Id.ToString(), one.AddGoods[k].Value); bagAllOp.ChgGoodTypeLimit(one.AddGoods[k].Type, one.AddGoods[k].Value); //增加类型限制 AddGoodsCount++; } } if (one.GetItemTime == 0 && (AddCurrencyCount != 0 || AddGoodsCount != 0)) { if(AddGoodsCount != 0) { CSErrCode code = bagOp.CheckOp(); if (code != CSErrCode.None) { continue; } code = bagAllOp.CheckGoodTypeLimit(player);//进行类型限制检测 if (code != CSErrCode.None) { for (int k = 0; k < one.AddGoods.Count; k++) //将本次的限制退回 { if ((one.AddGoods[k].Type > 0 || !string.IsNullOrEmpty(one.AddGoods[k].Id.GetString())) && one.AddGoods[k].Value > 0) { bagAllOp.ChgGoodTypeLimit(one.AddGoods[k].Type, one.AddGoods[k].Value * -1); //减少类型限制 } } continue; } } list.Add(one.MailID); } } DBMail mail = new DBMail(); mail.Uid = player.UserID; //player.MakeDirty(); //player.Trace("MailHandler.OnCliMailOpReq begin Read mail {0} uid {1}", mail.MailID, player.UserID); MailSender.SendMailOpReqToDB(player.UserID, MailOpType.AllGetItem, ref mail, list); } else { player.Error("OnCliMailOpReq uid {0} unsupport op type {1}", player.UserID, req.OpType); return; } } private void AckPlayerMailOpError(PlayerOnGame player, ref CSMailOpReq req, int iErrorCode) { player.Trace("MailHandler.AckPlayerMailOpError uid {0} opType {1} error {2}" , player.UserID, req.OpType, iErrorCode); CSMailOpRes res = new CSMailOpRes(); res.Ret = iErrorCode; res.OpType = req.OpType; res.Mail.MailID = req.MailID; SendToPlayer(player, (int)CSGameMsgID.MailOpRes, ref res); } private void AckPlayerMailOpError(PlayerOnGame player, ref SSMailOpRes ssres, int iErrorCode, List list = null) { player.Trace("MailHandler.AckPlayerMailOpError uid {0} opType {1} error {2}" , player.UserID, ssres.OpType, iErrorCode); if(ssres.ClientOpUid == 0 ) {//只有客户端发送的才返回给客户端 return; } CSMailOpRes res = new CSMailOpRes(); res.Ret = iErrorCode; res.OpType = ssres.OpType; res.Mail = ssres.Mail; // 目前只有AllDelete会传入list, 即一键删除才会填ListMId if(list != null && list.Count > 0) { for(int i = 0; i < list.Count; i++) { res.ListMId.Add(list[i]); } } // if(res.OpType == (int)MailOpType.AllDelete || res.OpType == (int)MailOpType.AllGetItem) // { // if(list == null && list.Count == 0) // { // // } // } SendToPlayer(player, (int)CSGameMsgID.MailOpRes, ref res); } private void AckPlayerMailOp(PlayerOnGame player, int opType, ref DBMail mail) { player.Trace("MailHandler.AckPlayerMailOp uid {0} opType {1} mailId {2}" , player.UserID, opType, mail.MailID); var res = new CSMailOpRes(); res.OpType = opType; res.Mail = mail; SendToPlayer(player, (int)CSGameMsgID.MailOpRes, ref res); } private void OnSvrMailOpRes(uint serverID, StructPacket packet) { ref SSMailOpRes ssres = ref packet.GetMessage(); //最开始一定要设置这个,删除超时重发 if (ssres.UniqueID != 0) { WaitAckStructRequestSender.Instance.OnReceiveSuccess(ssres.UniqueID); CommBillLogUtils.LogMailOpRet(ssres.ClientOpUid, ref ssres.Mail, ssres.OpType, ssres.Ret); } if (ssres.ClientOpUid == 0) { TraceLog.Debug("MailHandler.OnSvrMailOpRes no clientOpUid, skip"); return; } //如果2个不相等,不往下处理了 if (ssres.ClientOpUid != ssres.Mail.Uid) { TraceLog.Debug("MailHandler.OnSvrMailOpRes clientOpUid {0} != mail.uid {1}, skip" , ssres.ClientOpUid, ssres.Mail.Uid); return; } //不在线也正常 PlayerOnGame player = GameServerUtils.GetPlayerTableOp().GetPlayerByUid(ssres.Mail.Uid); if (player == null) { TraceLog.Debug("MailHandler.OnSvrMailOpRes no player object uid {0}" , ssres.Mail.Uid); return; } if (player.DBMailDataLoadedTime == 0) { player.Error("MailHandler.OnSvrMailOpRes no player mailinfo uid {0}" , ssres.Mail.Uid); return; } if (ssres.DelFirst.Count > 0) { CSMailChgNotify chgNotify = new CSMailChgNotify(); for (int i = 0; i < ssres.DelFirst.Count; i++) { MailSvc.DeleteMailMemory(player, ssres.DelFirst[i]); chgNotify.DelMailId.Add(ssres.DelFirst[i]); } if (chgNotify.DelMailId.Count > 0) { player.SendToClient((int)CSGameMsgID.MailChgNotify, ref chgNotify); } } //删除邮件只要回包一定成功,数据库不存在也算删除成功 if (ssres.OpType == (int)MailOpType.Delete) { if (ssres.Ret != 0) { AckPlayerMailOpError(player, ref ssres, -1); return; } MailSvc.DeleteMailMemory(player, ssres.Mail.MailID); //成功 AckPlayerMailOpError(player, ref ssres, 0); return; } else if(ssres.OpType == (int)MailOpType.AllDelete) { if (ssres.Ret != 0) { AckPlayerMailOpError(player, ref ssres, -1); return; } List list = new List(); for (int i = 0; i < player.MailInfo.Count; i++) { ref var one = ref player.MailInfo[i]; if (!ssres.ListMId.Contains(one.MailID)) { continue; } int AddGoodsCount = 0; for (int k = 0; k < one.AddGoods.Count; k++) { if ((one.AddGoods[k].Type > 0 || !string.IsNullOrEmpty(one.AddGoods[k].Id.GetString())) && one.AddGoods[k].Value > 0) { AddGoodsCount++; } } if (one.Status > 0 || one.GetItemTime > 0) { if (one.GetItemTime > 0) { list.Add(one.MailID); } else if ( AddGoodsCount == 0) { list.Add(one.MailID); } } } MailSvc.DeleteAllMailMemory(player, list); //成功 AckPlayerMailOpError(player, ref ssres, 0, list); return; } else if (ssres.OpType == (int)MailOpType.GetItem) { //已经取过了也算成功,重复性保证在player if (ssres.Ret == 220202 || ssres.Ret == 0) { int mailIndex = MailSvc.GetMailIndexFromPlayer(player, ssres.Mail.MailID); if (mailIndex == -1) { player.Error("MailHandler.OnSvrMailOpRes getitem mail uid {0}, mail {1} no mail in memory!", ssres.ClientOpUid, ssres.Mail.MailID); return; } ref DBMail mail = ref MailSvc.GetMailByIndex(player, mailIndex); if (mail.GetItemTime != 0) { player.Error("MailHandler.OnSvrMailOpRes getitem mail uid {0}, mail {1} mail in memory already getitem at time {2}!" , ssres.ClientOpUid, ssres.Mail.MailID, mail.GetItemTime); AckPlayerMailOpError(player, ref ssres, (int)CSErrCode.MailAlreadyGot); return; } //设置玩家身上的mail数据的领取时间 mail.GetItemTime = GameServerUtils.GetTimeSecond(); //回档了,怎么办呢,这个需要在玩家第一次拉取角色数据的时候处理完成,这里我们不处理了,请再次发起请求 if (player.RoleData.MailOp.GetItemMailID != mail.MailID && player.RoleData.MailOp.GetItemMailID != 0) { player.Error("MailHandler.OnSvrMailOpRes getitem mail uid {0}, mail {1} != role.GetItemMailID {2}!" , ssres.ClientOpUid, ssres.Mail.MailID, mail.GetItemTime); return; } //已经领过了,亲 if (player.RoleData.MailOp.GetItemMailID == 0) { player.Error("MailHandler.OnSvrMailOpRes getitem mail uid {0}, mail {1} mail in memory already getitem at time {2}!" , ssres.ClientOpUid, ssres.Mail.MailID, mail.GetItemTime); AckPlayerMailOpError(player, ref ssres, (int)CSErrCode.MailAlreadyGot); return; } OnGetMailItemSuccessAddItemToPlayer(player, ref mail, (MailOpType)ssres.OpType); return; } } else if (ssres.OpType == (int)MailOpType.Read) { //已经取过了也算成功,重复性保证在player if (ssres.Ret == 220202 || ssres.Ret == 0) { int mailIndex = MailSvc.GetMailIndexFromPlayer(player, ssres.Mail.MailID); if (mailIndex == -1) { player.Error("MailHandler.OnSvrMailOpRes getitem mail uid {0}, mail {1} no mail in memory!", ssres.ClientOpUid, ssres.Mail.MailID); return; } ref DBMail mail = ref MailSvc.GetMailByIndex(player, mailIndex); if (mail.Status != 0) { player.Error("MailHandler.OnSvrMailOpRes read mail uid {0}, mail {1} mail in memory already read!" , ssres.ClientOpUid, ssres.Mail.MailID); AckPlayerMailOpError(player, ref ssres, (int)CSErrCode.MailAlreadyGot); return; } //设置玩家身上的mail数据的领取时间 mail.Status = 1; if(ssres.Mail.GetItemTime > 0 && mail.GetItemTime == 0) { mail.GetItemTime = ssres.Mail.GetItemTime; } //成功 AckPlayerMailOpError(player, ref ssres, 0); return; } } else if (ssres.OpType == (int)MailOpType.Insert) { //已经存在 if (ssres.Ret == 220201 || ssres.Ret == 0) { MailSvc.InsertMailMemory(player, ref ssres.Mail); //处理一下特殊邮件 MailSvc.ProcessSpecialMailOnQueryRes(player); ////成功 //if (ssres.Mail.MailType == (int)MailType.ArenaDefence)//竞技场攻击邮件就不通知客户端了 //{ // return; //} ////成功 //if (ssres.Mail.MailType == (int)MailType.ArenaPeakPromotion) //{ // return; //} AckPlayerMailOpError(player, ref ssres, 0); return; } //这种情况呢 if (ssres.Ret != 0) { player.Error("MailHandler.OnSvrMailOpRes insert mail failed uid {0}, mail {1}" , ssres.ClientOpUid, ssres.Mail.MailID); return; } } else if (ssres.OpType == (int)MailOpType.GetItemDel) { //已经取过了也算成功,重复性保证在player if (ssres.Ret == 220202 || ssres.Ret == 0) { int mailIndex = MailSvc.GetMailIndexFromPlayer(player, ssres.Mail.MailID); if (mailIndex == -1) { player.Error("MailHandler.OnSvrMailOpRes getitem mail uid {0}, mail {1} no mail in memory!", ssres.ClientOpUid, ssres.Mail.MailID); return; } ref DBMail mail = ref MailSvc.GetMailByIndex(player, mailIndex); if (mail.GetItemTime != 0) { player.Error("MailHandler.OnSvrMailOpRes getitem mail uid {0}, mail {1} mail in memory already getitem at time {2}!" , ssres.ClientOpUid, ssres.Mail.MailID, mail.GetItemTime); AckPlayerMailOpError(player, ref ssres, (int)CSErrCode.MailAlreadyGot); return; } if (mail.DeleteTime != 0) { player.Error("MailHandler.OnSvrMailOpRes getitem mail uid {0}, mail {1} mail in memory already getitem at time {2}!" , ssres.ClientOpUid, ssres.Mail.MailID, mail.GetItemTime); AckPlayerMailOpError(player, ref ssres, (int)CSErrCode.MailAlreadyGot); return; } //设置玩家身上的mail数据的领取时间 mail.GetItemTime = GameServerUtils.GetTimeSecond(); //回档了,怎么办呢,这个需要在玩家第一次拉取角色数据的时候处理完成,这里我们不处理了,请再次发起请求 if (player.RoleData.MailOp.GetItemMailID != mail.MailID && player.RoleData.MailOp.GetItemMailID != 0) { player.Error("MailHandler.OnSvrMailOpRes getitem mail uid {0}, mail {1} != role.GetItemMailID {2}!" , ssres.ClientOpUid, ssres.Mail.MailID, mail.GetItemTime); return; } //已经领过了,亲 if (player.RoleData.MailOp.GetItemMailID == 0) { player.Error("MailHandler.OnSvrMailOpRes getitem mail uid {0}, mail {1} mail in memory already getitem at time {2}!" , ssres.ClientOpUid, ssres.Mail.MailID, mail.GetItemTime); AckPlayerMailOpError(player, ref ssres, (int)CSErrCode.MailAlreadyGot); return; } OnGetMailItemSuccessAddItemToPlayer(player, ref mail, (MailOpType)ssres.OpType); MailSvc.DeleteMailMemory(player, ssres.Mail.MailID); return; } } else if (ssres.OpType == (int)MailOpType.AllGetItem) { //已经取过了也算成功,重复性保证在player if (ssres.Ret == 220202 || ssres.Ret == 0) { List list = new List(); for (int i = 0; i < ssres.ListMId.Count; i++) { int mailIndex = MailSvc.GetMailIndexFromPlayer(player, ssres.ListMId[i]); if (mailIndex == -1) { player.Error("MailHandler.OnSvrMailOpRes getitem mail uid {0}, mail {1} no mail in memory!", ssres.ClientOpUid, ssres.Mail.MailID); return; } ref DBMail mail = ref MailSvc.GetMailByIndex(player, mailIndex); if (mail.GetItemTime != 0) { player.Error("MailHandler.OnSvrMailOpRes getitem mail uid {0}, mail {1} mail in memory already getitem at time {2}!" , ssres.ClientOpUid, ssres.Mail.MailID, mail.GetItemTime); AckPlayerMailOpError(player, ref ssres, (int)CSErrCode.MailAlreadyGot); return; } //设置玩家身上的mail数据的领取时间 mail.GetItemTime = GameServerUtils.GetTimeSecond(); if(mail.AddGoods.Count > 0) { mail.Status = 1; } list.Add(ssres.ListMId[i]); } OnGetAllMailItemSuccessAddItemToPlayer(player, ref ssres.Mail, (MailOpType)ssres.OpType, list); return; } else if (ssres.OpType == (int)MailOpType.Update) { // } else { AckPlayerMailOpError(player, ref ssres, (int)CSErrCode.MailAlreadyGot); } } } private void OnGetAllMailItemSuccessAddItemToPlayer(PlayerOnGame player, ref DBMail one, MailOpType opType = MailOpType.None, List list = null) { if (list == null || list.Count == 0) { return; } player.MakeDirty(); CSMailOpRes res = new CSMailOpRes(); res.Ret = 0; res.OpType = (int)opType; res.Mail = one; int vipExp = 0; //领取物品 UnifyOp bagOp = new UnifyOp(player, BillChangeItemReason.GetItemMail, one.MailType.ToString()); List titleList = new List(); for (int k = 0; k < list.Count; k++) { int mailIndex = MailSvc.GetMailIndexFromPlayer(player, list[k]); if (mailIndex == -1) { TraceLog.Error("OnGetAllMailItemSuccessAddItemToPlayer error,no Mail {0}", list[k]); return; } ref DBMail mail = ref MailSvc.GetMailByIndex(player, mailIndex); res.ListMId.Add(mail.MailID); for (int i = 0; i < mail.AddGoods.Count; i++) { if (mail.AddGoods[i].Type > 0 && !string.IsNullOrEmpty(mail.AddGoods[i].Id.GetString()) && mail.AddGoods[i].Value > 0) { { bagOp.AddGoods(mail.AddGoods[i].Type, mail.AddGoods[i].Id.ToString(), mail.AddGoods[i].Value); } } } if ((k + 1) % 30 == 0 && list.Count > (k + 1)) { CSErrCode tempRet = bagOp.DoOp(); if (tempRet != CSErrCode.None) { player.Error("MailHandler.OnGetMailItemSuccessAddItemToPlayer getitem uid {0} bagOp.DoOp failed ret {1}", player.UserID, tempRet); } bagOp = new UnifyOp(player, BillChangeItemReason.GetItemMail, one.MailType.ToString()); } } CSErrCode iRet = bagOp.DoOp(true, true, true); if (iRet != 0) { player.Error("MailHandler.OnGetMailItemSuccessAddItemToPlayer getitem uid {0} bagOp.DoOp failed ret {1}" , player.UserID, iRet); return; } player.Trace("MailHandler.OnGetMailItemSuccessAddItemToPlayer uid {0} get Allitem success" , player.UserID); SendToPlayer(player, (int)CSGameMsgID.MailOpRes, ref res); } private void OnGetMailItemSuccessAddItemToPlayer(PlayerOnGame player, ref DBMail mail, MailOpType opType = MailOpType.None) { player.RoleData.MailOp.GetItemMailID = 0; player.MakeDirty(); int vipExp = 0; //领取物品 UnifyOp bagOp = new UnifyOp(player, BillChangeItemReason.GetItemMail, mail.MailType.ToString()); for (int i = 0; i < mail.AddGoods.Count; i++) { if (mail.AddGoods[i].Type > 0 && !string.IsNullOrEmpty(mail.AddGoods[i].Id.GetString()) && mail.AddGoods[i].Value > 0) { bagOp.AddGoods(mail.AddGoods[i].Type, mail.AddGoods[i].Id.ToString(), mail.AddGoods[i].Value); //if (mail.AddGoods[i].Type == (int)CurrencyType.VipExp) //{ // vipExp += mail.AddGoods[i].Value; //} } } CSErrCode iRet = bagOp.DoOp(true, true, true); if (iRet != 0) { player.Error("MailHandler.OnGetMailItemSuccessAddItemToPlayer getitem uid {0} mail {1} bagOp.DoOp failed ret {2}" , player.UserID, mail.MailID, iRet); return; } player.Trace("MailHandler.OnGetMailItemSuccessAddItemToPlayer uid {0} mail {1} get item success" , player.UserID, mail.MailID); CSMailOpRes res = new CSMailOpRes(); res.Ret = 0; res.OpType = (int)opType; res.Mail = mail; SendToPlayer(player, (int)CSGameMsgID.MailOpRes, ref res); } private int CheckCliCanSendMailToPlayer(PlayerOnGame player, long sendChip, int shopItemId,out long costChip, out long tax, out int costDiamond ,out string sendItemId) { costChip = 0; tax = 0; costDiamond = 0; sendItemId = ""; if(sendChip == 0 && shopItemId == 0) { player.Error("MailHandler.CheckCliCanSendMailToPlayer uid {0} chip {1} shopItemId {2}" , player.UserID, sendChip, shopItemId); return -1; } if (sendChip > 0) { int minChip = 0; // CommParamDescUtils.GetCommParam().sendMailToPlayerMinChip; if (sendChip < minChip) { player.Error("MailHandler.CheckCliCanSendMailToPlayer uid {0} chip {1} invalid minChip {2}" , player.UserID, sendChip, minChip); return -1; } } //税率写死了10% tax = sendChip * 0; //CommParamDescUtils.GetCommParam().sendMailToPlayerChipTax / 100; if (tax < 1) { tax = 1; } //校验钱够不够 costChip = sendChip + tax; if (shopItemId > 0) { } //如果送钱的话送完钱后需要有剩余 long checkNeedChip = costChip; if (sendChip > 0) { checkNeedChip += 0; // CommParamDescUtils.GetCommParam().sendMailToPlayerMinChipLeft; } if (checkNeedChip > player.GetGold()) { player.Error("MailHandler.CheckCliCanSendMailToPlayer uid {0} not enought chip, cost {1} need {2}" , player.UserID, costChip, checkNeedChip); return -5; } if (costDiamond > player.GetDiamond()) { player.Error("MailHandler.CheckCliCanSendMailToPlayer uid {0} not enought diamond, cost {1}" , player.UserID, costDiamond); return -6; } return 0; } private void OnCliSendMailToPlayerReq(PlayerOnGame player, StructPacket packet) { ref CSMailSendToPlayerReq req = ref packet.GetMessage(); if (req.TargetUid == 0 || req.TargetUid == player.UserID) { player.Error("MailHandler.OnCliSendMailToPlayerReq uid {0} invalid targetuid {1}", player.UserID, req.TargetUid); return; } CSMailSendToPlayerRes res = new CSMailSendToPlayerRes(); res.TargetUid = req.TargetUid; res.Chip = req.Chip; res.ShopItemId = req.ShopItemId; long costChip; long tax; int costDiamond; string sendItemId; int ret = CheckCliCanSendMailToPlayer(player , req.Chip , req.ShopItemId , out costChip , out tax , out costDiamond , out sendItemId); if (ret != 0) { player.Error("MailHandler.OnCliSendMailToPlayerReq uid {0} CheckCliCanSendMailToPlayer failed ret {1}" , player.UserID, ret); res.Ret = ret; player.SendToClient((int)CSGameMsgID.MailSendToPlayerRes, ref res); return; } player.Debug("MailHandler.OnCliSendMailToPlayerReq uid {0} send to world check,send chip {1}" , player.UserID, req.Chip); //发给world转去friend校验一下target是否是好友 GameServerUtils.GetPacketSender().SendToWorldServer(packet, player.UserID); return; } private void OnSvrMailSendToPlayerRes(uint serverID, StructPacket packet) { PlayerOnGame player = GameServerUtils.GetPlayerTableOp().GetPlayerByUid(packet.ObjectID); if (player == null) { player.Error("MailHandler.OnSvrMailSendToPlayerRes no player object uid {0}", packet.ObjectID); return; } ref CSMailSendToPlayerRes res = ref packet.GetMessage(); if(res.Ret != 0) { player.Error("MailHandler.OnSvrMailSendToPlayerRes uid {0} world ack ret {1}", player.UserID, res.Ret); player.SendToClient(packet); return; } long costChip; long tax; int costDiamond; string sendItemId; int ret = CheckCliCanSendMailToPlayer(player, res.Chip, res.ShopItemId , out costChip , out tax , out costDiamond , out sendItemId); if (ret != 0) { player.Error("MailHandler.OnSvrMailSendToPlayerRes uid {0} CheckCliCanSendMailToPlayer failed ret {1}", player.UserID, ret); res.Ret = ret; player.SendToClient((int)CSGameMsgID.MailSendToPlayerRes, ref res); return; } //扣chip UnifyOp bagOp = new UnifyOp(player, BillChangeItemReason.SendMailToPlayer); bagOp.CostGold(costChip); bagOp.CostDiamond(costDiamond); CSErrCode iRet = bagOp.DoOp(); if (iRet != 0) { player.Error("MailHandler.OnSvrMailSendToPlayerRes uid {0} bagOp.DoOp failed ret {1}", player.UserID, iRet); return; } //发邮件 DBMail mail = new DBMail(); mail.Uid = res.TargetUid; mail.MailType = (int)MailType.SendToPlayer; // var currency = new IDValue64() {Id = (long) CurrencyType.Chip, Value = res.Chip}; //mail.AddCurrency.Add(ref currency); mail.SendTime = GameServerUtils.GetTimeSecond(); mail.SenderUid = player.UserID; mail.SenderName.SetString(player.GetNick()); mail.SenderIcon.SetString(player.GetIcon()); mail.Title = res.Title; mail.Content = res.Content; //送物品 if(string.IsNullOrEmpty(sendItemId)) { var typeIdValue = new TypeIDValueString(){Type = (int)GoodsType.Items, Id = new FixedStructString64(sendItemId), Value = 1 }; mail.AddGoods.Add(ref typeIdValue); } MailSender.SendNewMailToPlayer(player.UserID, ref mail); GameBillLogUtils.LogSendMailToPlayer(player.UserID, res.TargetUid, player.GetVipLevel(), res.Chip, tax); /*这个不算,因为这个送钱是收税的,随便送 //统计数据变化操作 RoleStatChgOp statChgOp = new RoleStatChgOp(player); statChgOp.AddIDDaily((int)CSRoleStatisticsID.GiveFriendChipCount, 1); //可以不通知 statChgOp.NotifyClient(); */ res.Ret = 0; player.SendToClient((int)CSGameMsgID.MailSendToPlayerRes, ref res); //通知好友聊天,好友送你钱了 SSFriendSomeOpNotifyChat notify = new SSFriendSomeOpNotifyChat(); notify.ChatType = (int)ChatType.FriendSendChip; notify.Uid = res.TargetUid; notify.FriendUid = player.UserID; notify.Param1.SetString( res.Chip.ToString()); if (!string.IsNullOrEmpty(sendItemId) ) { notify.Param2.SetString(sendItemId.ToString()); } //ChatSvc.NotifyFriendSomeOpToChat(ref notify); NotifyFriendSomeOpToChat(ref notify); player.Debug("MailHandler.OnSvrMailSendToPlayerRes uid {0} send mail to targetuid {1} success with chip {2} tax {3}" , player.UserID, res.TargetUid, res.Chip, tax); } public static void NotifyFriendSomeOpToChat(ref SSFriendSomeOpNotifyChat notify) { TraceLog.Trace("MailHandler.NotifyFriendSomeOpToChat player uid {0} friend uid {1} chatType {2} " , notify.Uid, notify.FriendUid, notify.ChatType); GameServerUtils.GetPacketSender().SendToWorldServer((int)SSGameMsgID.FriendSomeOpNotifyChat, ref notify, 0); } public static void OnOperationDeleteMail(uint serverID, StructPacket packet) { SSOperationDeleteMailReq sreq = packet.GetMessage(); SSOperationDeleteMailRes res = new SSOperationDeleteMailRes(); res.Id = sreq.Id; res.Uid = sreq.Uid; res.Ret = 0; PlayerOnGame player = GameServerUtils.GetPlayerTableOp().GetPlayerByUid(sreq.Uid); DBMail mail = new DBMail(); mail.Uid = sreq.Uid; mail.MailID = (uint)sreq.MailId; if (player == null) { //离线处理 MailSender.SendMailOpReqToDB(0, MailOpType.Delete, ref mail); TraceLog.Debug("MailHandler.OnOperationDeleteMail no player object uid {0}", sreq.Uid); GameServerUtils.GetPacketSender().SendToWorldServer((int)SSGameMsgID.OperationMailDeleteRes, ref res, packet.ObjectID); return; } int index = -1; for (int i = 0; i < player.MailInfo.Count; i++) { ref var mailInfo = ref player.MailInfo[i]; if (mailInfo.MailID == sreq.MailId) { index = i; break; } } if (index < 0) { res.Ret = -1;//mail not found GameServerUtils.GetPacketSender().SendToWorldServer((int)SSGameMsgID.OperationMailDeleteRes, ref res, packet.ObjectID); return; } MailSender.SendMailOpReqToDB(sreq.Uid, MailOpType.Delete, ref mail); GameServerUtils.GetPacketSender().SendToWorldServer((int)SSGameMsgID.OperationMailDeleteRes, ref res, packet.ObjectID); } } }