using System; using System.Collections.Generic; using Sog; using ProtoCSStruct; namespace Mail { public static class MailOp { public static int MaxMailCount = 149; //上限150 private static uint DeleteFirstTypeMail(ref DBMailBlob blob, int type) { uint delId = 0; for (int i = 0; i < blob.MailList.Count; i++) { ref DBMail mail = ref blob.MailList[i]; if (mail.MailType == type) { TraceLog.Debug("MailOp.DeleteFirstTypeMail delete mail {0} type {1} for uid {2}" , mail.MailID, mail.MailType, mail.Uid); delId = blob.MailList[i].MailID; blob.MailList.RemoveAt(i); break; } } return delId; } /// /// 邮件满了的话删除一些邮件 /// /// /// /// 是否有变化 private static bool DeleteSomeMailWhenFull(ref DBMailBlob blob, long uid, out List mailIds) { mailIds = new List(); long nowSecond = MailServerUtils.GetApp().GetTimeSecond(); bool changed = false; //删除超过14天的过期邮件,不管邮件有没有领取 //var delDay = 14; for (int i = blob.MailList.Count - 1; i >= 0; i--) { var mail = blob.MailList[i]; if (mail.ExpirationTime > 0 && nowSecond > mail.ExpirationTime /*|| nowSecond - mail.SendTime > delDay * 24 * 3600*/) { TraceLog.Debug("MailOp.DeleteSomeMailWhenFull delete timeout mail {0} for uid {1}", mail.MailID, uid); mailIds.Add(mail.MailID); blob.MailList.RemoveAt(i); changed = true; continue; } if (mail.Status > 0 || mail.GetItemTime > 0) { if (mail.GetItemTime > 0 && nowSecond > mail.GetItemTime + AppTime.SECONDS_ADAY) { TraceLog.Debug("MailOp.DeleteSomeMailWhenFull delete timeout mail {0} for uid {1}", mail.MailID, uid); mailIds.Add(mail.MailID); blob.MailList.RemoveAt(i); changed = true; continue; } } } //删除已经删除的邮件 for (int i = blob.MailList.Count - 1; i >= 0; i--) { var mail = blob.MailList[i]; if (mail.DeleteTime != 0) { TraceLog.Debug("MailOp.DeleteSomeMailWhenFull delete timeout DeleteTime mail {0} for uid {1}", mail.MailID, uid); mailIds.Add(mail.MailID); blob.MailList.RemoveAt(i); changed = true; } } //如果还超过100封邮件,尝试删除一些好友送筹码邮件,因为这个不是很重要,最多删除MaxMailCount封邮件 //for (int i = 0; i < MaxMailCount; i++) //{ // if (blob.MailList.Count > MaxMailCount) // { // uint delId = DeleteFirstTypeMail(ref blob, (int)MailType.FriendGiftDaily); // if (delId > 0) // { // mailIds.Add(delId); // } // changed = true; // } // else // { // break; // } //} ////删除已经领取完的邮件 //if (blob.MailList.Count >= MaxMailCount) //{ // for (int i = blob.MailList.Count - 1; i >= 0; i--) // { // var mail = blob.MailList[i]; // if (mail.GetItemTime != 0) // { // TraceLog.Debug("MailOp.DeleteSomeMailWhenFull delete timeout DeleteTime mail {0} for uid {1}", mail.MailID, uid); // mailIds.Add(mail.MailID); // blob.MailList.RemoveAt(i); // changed = true; // } // } //} ////删除没有附件的已读邮件 //if (blob.MailList.Count >= MaxMailCount) //{ // for (int i = blob.MailList.Count - 1; i >= 0; i--) // { // var mail = blob.MailList[i]; // if (mail.Status != 0 // && mail.AddGoods.Count == 0) // { // TraceLog.Debug("MailOp.DeleteSomeMailWhenFull delete timeout DeleteTime mail {0} for uid {1}", mail.MailID, uid); // mailIds.Add(mail.MailID); // blob.MailList.RemoveAt(i); // changed = true; // } // } //} ////删除没有附件的邮件 //if (blob.MailList.Count >= MaxMailCount) //{ // for (int i = blob.MailList.Count - 1; i >= 0; i--) // { // var mail = blob.MailList[i]; // if ( mail.AddGoods.Count == 0) // { // TraceLog.Debug("MailOp.DeleteSomeMailWhenFull delete timeout DeleteTime mail {0} for uid {1}", mail.MailID, uid); // mailIds.Add(mail.MailID); // blob.MailList.RemoveAt(i); // changed = true; // } // } //} //如果还超过MaxMailCount封邮件,则删除最老的 while (blob.MailList.Count >= MaxMailCount) { var mail = blob.MailList[0]; TraceLog.Debug("MailOp.DeleteSomeMailWhenFull delete to much mail {0} for uid {1}", mail.MailID, uid); mailIds.Add(mail.MailID); blob.MailList.RemoveAt(0); changed = true; } return changed; } //有些邮件每日限制 public static bool MailTypeDailyLimited(ref DBMailBlob blob, int newMailType, out bool bChange) { bChange = false; long nowSecond = MailServerUtils.GetTimeSecond(); //reset if (AppTime.IsSameDay(nowSecond, blob.TodayResetTime) == false) { bChange = true; blob.TodayResetTime = nowSecond; blob.InviteeSuccessMailCount = 0; blob.FriendDailyChipMailCount = 0; } //好友每天送钱有限制 if (newMailType == (int)MailType.FriendGiftDaily && blob.FriendDailyChipMailCount >= 20) { return true; } return false; } public static void OnQueryMailReq(uint remoteAppID, StructPacket packet, MailDBOperator dbOperator) { ref SSQueryMailReq req = ref packet.GetMessage(); SSQueryMailRes res = new SSQueryMailRes(); DBMailBlob blob = new DBMailBlob(); int ret = dbOperator.QueryMail(req.Uid, ref blob); if (ret == -1) { TraceLog.Error("MailOp.OnQueryMailReq failed uid {0}", req.Uid); return; } //没有记录则创建,其他人有可能立即会往我这里发送邮件 if (ret == 1) { blob = new DBMailBlob(); blob.LastSeq = 0; bool bSuccess = dbOperator.InsertMail(req.Uid, ref blob); if (bSuccess == false) { //系统严重错误,不应该 TraceLog.Error("MailOp.OnQueryMailReq insert mail failed uid {0}", req.Uid); return; } } else { bool changed = DeleteSomeMailWhenFull(ref blob, req.Uid, out List delIds); if (changed) { bool bSuccess = dbOperator.UpdateMail(req.Uid, ref blob); if (bSuccess == false) { TraceLog.Error("MailOp.OnQueryMailReq update mail failed uid {0}", req.Uid); return; } } } res.Uid = req.Uid; long nowTime = MailServerUtils.GetApp().GetTimeSecond(); bool needUpdateMail = false; //过滤已经删除的邮件或者过期的邮件 for (int i = 0; i < blob.MailList.Count; i++) { ref var mail = ref blob.MailList[i]; if (mail.DeleteTime == 0) { if (mail.ExpirationTime > 0 && mail.ExpirationTime <= nowTime) { //删除过期但是未删除的邮件 mail.DeleteTime = nowTime; needUpdateMail = true; continue; } res.MailList.Add(ref mail); } } if (needUpdateMail) { bool bSuccess = dbOperator.UpdateMail(req.Uid, ref blob); if (bSuccess == false) { TraceLog.Error("MailOp.OnQueryMailReq delete Expiration mail failed uid {0}", req.Uid); } } //SSQueryMailVersionRes verRes = new SSQueryMailVersionRes //{ // Uid = req.Uid, // Version = blob.LastVer, //}; //MailServerUtils.SendMsgToSelf(remoteAppID, // (int)SSGameMsgID.QueryMailVersionRes, ref verRes, packet.ObjectID); MailServerUtils.GetPacketSender().SendToServerByID(remoteAppID, (int)SSGameMsgID.QueryMailRes, ref res, packet.ObjectID); } public static void OnOperationQueryMailReq(uint remoteAppID, StructPacket packet, MailDBOperator dbOperator) { ref SSOperationSearchMailReq req = ref packet.GetMessage(); SSOperationSearchMailRes res = new SSOperationSearchMailRes(); res.Id = req.Id; DBMailBlob blob = new DBMailBlob(); int ret = dbOperator.QueryMail(req.Uid, ref blob); if (ret == -1) { res.Ret = ret; MailServerUtils.GetPacketSender().SendToServerByID(remoteAppID, (int)SSGameMsgID.OperationMailSearchRes, ref res, packet.ObjectID); TraceLog.Error("MailOp.OnQueryMailReq failed uid {0}", req.Uid); return; } res.Uid = req.Uid; long nowTime = MailServerUtils.GetApp().GetTimeSecond(); for (int i = 0; i < blob.MailList.Count; i++) { var mail = blob.MailList[i]; if (mail.DeleteTime == 0) { if (mail.ExpirationTime > 0 && mail.ExpirationTime <= nowTime) { continue; } if(res.Mails.Count>=res.Mails.GetMaxCount()){ break; } res.Mails.Add(ref mail); } } MailServerUtils.GetPacketSender().SendToServerByID(remoteAppID, (int)SSGameMsgID.OperationMailSearchRes, ref res, packet.ObjectID); } public static void OnQueryMailVersionReq(uint remoteAppID, StructPacket packet, MailDBOperator dbOperator) { ref SSQueryMailVersionReq req = ref packet.GetMessage(); SSQueryMailVersionRes res = new SSQueryMailVersionRes(); DBMailBlob blob = new DBMailBlob(); int ret = dbOperator.QueryMail(req.Uid, ref blob); if (ret == -1) { TraceLog.Error("MailOp.OnQueryMailVersionReq failed uid {0} ret {1}", req.Uid, ret); return; } res.Uid = req.Uid; res.Version = blob.LastVer; MailServerUtils.SendMsgToSelf(remoteAppID, (int)SSGameMsgID.QueryMailVersionRes, ref res, packet.ObjectID); } public static void OnMailOpReq(uint remoteAppID, StructPacket packet, MailDBOperator dbOperator) { ref SSMailOpReq req = ref packet.GetMessage(); long uid = req.Mail.Uid; long mailID = req.Mail.MailID; SSMailOpRes res = new SSMailOpRes(); res.AckGameServerID = req.AckGameServerID; res.ClientOpUid = req.ClientOpUid; res.Mail = req.Mail; res.OpType = req.OpType; res.UniqueID = req.UniqueID; res.Ret = -1; res.Seq = req.Seq; DBMailBlob blob = new DBMailBlob(); int ret = dbOperator.QueryMail(uid, ref blob); if (ret == -1) { TraceLog.Error("MailOp.OnMailOpReq failed uid {0}", uid); MailServerUtils.GetPacketSender().SendToServerByID(remoteAppID, (int)SSGameMsgID.MailOpRes, ref res, packet.ObjectID); return; } if (req.OpType == (int)MailOpType.Delete) { DoMailDeleteOp(uid, mailID, ref blob, dbOperator, ref res); } //新邮件 else if (req.OpType == (int)MailOpType.Insert) { //新邮件的话先校验这个类型的邮件能不能再发,某些邮件有数量限制 bool changed = false; if (MailTypeDailyLimited(ref blob, req.Mail.MailType, out changed)) { TraceLog.Error("MailOp.OnMailOpReq MailTypeDailyLimited check failed uid {0}, mailType {1}" , uid, req.Mail.MailType); if (changed) { bool bSuccess = dbOperator.UpdateMail(uid, ref blob); if (bSuccess == false) { TraceLog.Error("MailOp.OnMailOpReq update mail failed uid {0}", uid); return; } } } else { //添加邮件前先尝试删除一些无用邮件 changed = DeleteSomeMailWhenFull(ref blob, uid, out List delIds); if (changed) { bool bSuccess = dbOperator.UpdateMail(uid, ref blob); if (bSuccess == false) { TraceLog.Error("MailOp.OnMailOpReq update mail failed uid {0}", uid); return; } } if (delIds.Count > 0) { //这里应该是直接返回querymailres,哪个服务器来的回哪个服务器, //但是不知道其他人怎么处理的,有没有bug,先保证game不出问题吧 //毕竟现在出问题的只有game for(int i=0;i 0 && res.Ret == 0 && req.OpType == (int)MailOpType.Insert) //{ // PlayerMailVerSeqSvc.OnPlayerVerChange(uid, req.MailVerSeq); //} } private static void DoMailDeleteOp(long uid, long mailID, ref DBMailBlob blob, MailDBOperator dbOperator, ref SSMailOpRes res) { for (int i = 0; i < blob.MailList.Count; i++) { ref DBMail mail = ref blob.MailList[i]; if (mail.MailID == mailID) { if (mail.DeleteTime == 0) { mail.DeleteTime = AppTime.GetNowSysMs() / 1000; bool bSuccess = dbOperator.UpdateMail(uid, ref blob); if (bSuccess == false) { TraceLog.Error("MailOp.DoMailDeleteOp update mail failed uid {0}", uid); return; } } else { TraceLog.Error("MailOp.DoMailDeleteOp delete mail {0} for uid {1},already delete at time {2}" , mailID, uid, mail.DeleteTime); } res.Ret = 0; return; } } //没有也算成功 res.Ret = 0; TraceLog.Debug("MailOp.DoMailDeleteOp delete mail {0} for uid {1} success, no mail in maillist already", mailID, uid); return; } private static void DoMailInsertOp(long uid, ref DBMailBlob blob, MailDBOperator dbOperator, ref SSMailOpRes res, long mailVer) { //避免重复 for (int i = 0; i < blob.MailList.Count; i++) { ref DBMail mail = ref blob.MailList[i]; if (mail.InsertUniqueID != 0 && mail.InsertUniqueID == res.Mail.InsertUniqueID) { //也算成功吧 TraceLog.Error("MailOp.DoMailInsertOp insert mail {0} for uid {1},already insert at time {2} InsertUniqueID {3}" , mail.MailID, uid, mail.SendTime, mail.InsertUniqueID); res.Ret = 220201; res.Mail = mail; return; } } //邀请成功一个新玩家,有每天限制 if (res.Mail.MailType == (int)MailType.InviteeSuccessReward) { blob.InviteeSuccessMailCount++; } //好友每天送钱有限制 if (res.Mail.MailType == (int)MailType.FriendGiftDaily) { blob.FriendDailyChipMailCount++; } blob.LastSeq++; //if(blob.LastVer < mailVer) //{ // blob.LastVer = mailVer; //} res.Mail.MailID = blob.LastSeq; res.Mail.DeleteTime = 0; res.Mail.GetItemTime = 0; //如果创建时间没有的话设置一下 if (res.Mail.SendTime == 0) { res.Mail.SendTime = AppTime.GetNowSysSecond(); } blob.MailList.Add(ref res.Mail); bool bSuccess = dbOperator.UpdateMail(uid, ref blob); if (bSuccess == false) { TraceLog.Error("MailOp.DoMailInsertOp update mail failed uid {0}", uid); //这里应该返回错误吧?? return; } TraceLog.Debug("MailOp.DoMailInsertOp update mail success uid {0} mailid {1} lastSeq {2} InviteeSuccessMailCount {3} FriendDailyChipMailCount {4}" , uid, res.Mail.MailID, blob.LastSeq, blob.InviteeSuccessMailCount, blob.FriendDailyChipMailCount); res.Ret = 0; return; } private static void DoMailReadOp(long uid, ref DBMail getItemMail, ref DBMailBlob blob, MailDBOperator dbOperator, ref SSMailOpRes res) { for (int i = 0; i < blob.MailList.Count; i++) { ref DBMail mail = ref blob.MailList[i]; if (mail.MailID == getItemMail.MailID) { if (mail.Status == 1) { TraceLog.Error("MailOp.DoMailReadOp status = 1 mail {0} for uid {1} " , mail.MailID, uid); } mail.Status = 1; if(mail.AddGoods.Count == 0) { mail.GetItemTime = AppTime.GetNowSysSecond(); } bool bSuccess = dbOperator.UpdateMail(uid, ref blob); if (bSuccess == false) { TraceLog.Error("MailOp.DoMailGetItemOp update mail failed uid {0}", uid); return; } res.Mail = mail; res.Ret = 0; TraceLog.Debug("MailOp.DoMailGetItemOp mail {0} for uid {1}" , mail.MailID, uid); return; } } res.Ret = 220202; TraceLog.Error("MailOp.DoMailGetItemOp get mail item {0} for uid {1} failed, no mail exist" , getItemMail.MailID, uid); } private static void DoMailUpdate(long uid, ref DBMail getItemMail, ref DBMailBlob blob, MailDBOperator dbOperator, ref SSMailOpRes res) { for (int i = 0; i < blob.MailList.Count; i++) { ref DBMail mail = ref blob.MailList[i]; if (mail.MailID == getItemMail.MailID) { //只能更新从addReward到addGoods if(!mail.AddReward.IsEmpty() && getItemMail.AddReward.IsEmpty() && mail.AddGoods.GetCount() ==0 && getItemMail.AddGoods.GetCount() > 0) { mail.AddGoods.CopyFrom(ref getItemMail.AddGoods); mail.AddReward.CopyFrom(ref getItemMail.AddReward); bool bSuccess = dbOperator.UpdateMail(uid, ref blob); if (bSuccess == false) { TraceLog.Error("MailOp.DoMailUpdate update mail failed uid {0}", uid); return; } res.Mail = mail; res.Ret = 0; TraceLog.Debug("MailOp.DoMailUpdate mail {0} for uid {1}" , mail.MailID, uid); } return; } } res.Ret = 220202; TraceLog.Error("MailOp.DoMailUpdate get mail item {0} for uid {1} failed, no mail exist" , getItemMail.MailID, uid); } private static void DoMailGetItemOp(long uid, ref DBMail getItemMail, ref DBMailBlob blob, MailDBOperator dbOperator, ref SSMailOpRes res) { for (int i = 0; i < blob.MailList.Count; i++) { ref DBMail mail = ref blob.MailList[i]; if (mail.MailID == getItemMail.MailID) { //已经领取过了 if (mail.GetItemTime != 0) { TraceLog.Error("MailOp.DoMailGetItemOp get item mail {0} for uid {1},already get at time {2} " , mail.MailID, uid, mail.GetItemTime); getItemMail = mail; res.Ret = 0; return; } mail.GetItemTime = AppTime.GetNowSysMs() / 1000; getItemMail.GetItemTime = mail.GetItemTime; bool bSuccess = dbOperator.UpdateMail(uid, ref blob); if (bSuccess == false) { TraceLog.Error("MailOp.DoMailGetItemOp update mail failed uid {0}", uid); return; } getItemMail = mail; res.Mail = getItemMail; res.Ret = 0; TraceLog.Debug("MailOp.DoMailGetItemOp get mail item {0} for uid {1} at time {2}" , mail.MailID, uid, mail.GetItemTime); return; } } res.Ret = 220202; TraceLog.Error("MailOp.DoMailGetItemOp get mail item {0} for uid {1} failed, no mail exist" , getItemMail.MailID, uid); } private static void DoMailAllDelOp(long uid, ref SSMailOpReq req, ref DBMailBlob blob, MailDBOperator dbOperator, ref SSMailOpRes res) { // 一键删除回包都是成功, 实际上根据规则处理 res.Ret = 0; bool change = false; long timeNow = AppTime.GetNowSysMs() / 1000; for (int i = 0; i < blob.MailList.Count; i++) { int AddGoodsCount = 0; ref DBMail mail = ref blob.MailList[i]; for (int k = 0; k < mail.AddGoods.Count; k++) { if ((!string.IsNullOrEmpty(mail.AddGoods[k].Id.GetString()) || mail.AddGoods[k].Type > 0) && mail.AddGoods[k].Value > 0) { AddGoodsCount++; } } if (req.ListMId.Contains(mail.MailID)) { if (mail.Status > 0 || mail.GetItemTime > 0) { if (mail.GetItemTime > 0) { mail.DeleteTime = timeNow; res.ListMId.Add(mail.MailID); change = true; } else if ( AddGoodsCount == 0) { mail.DeleteTime = timeNow; res.ListMId.Add(mail.MailID); change = true; } } } } if (change) { bool bSuccess = dbOperator.UpdateMail(uid, ref blob); if (bSuccess == false) { TraceLog.Error("MailOp.DoMailAllDelOp update mail failed uid {0}", uid); return; } } } private static void DoMailAllGetItemOp(long uid, ref SSMailOpReq req, ref DBMailBlob blob, MailDBOperator dbOperator, ref SSMailOpRes res) { bool change = false; long getItemTime = AppTime.GetNowSysMs() / 1000; for (int i = 0; i < blob.MailList.Count; i++) { int AddGoodsCount = 0; ref DBMail mail = ref blob.MailList[i]; for (int k = 0; k < mail.AddGoods.Count; k++) { if ((!string.IsNullOrEmpty(mail.AddGoods[k].Id.GetString()) || mail.AddGoods[k].Type > 0) && mail.AddGoods[k].Value > 0 ) { AddGoodsCount++; } } if (req.ListMId.Contains(mail.MailID)) { if (mail.GetItemTime == 0 && ( AddGoodsCount != 0)) { mail.Status = 1; mail.GetItemTime = getItemTime; res.ListMId.Add(mail.MailID); change = true; } } } if (change) { bool bSuccess = dbOperator.UpdateMail(uid, ref blob); if (bSuccess == false) { TraceLog.Error("MailOp.DoMailAllGetItemOp update mail failed uid {0}", uid); return; } res.Mail.GetItemTime = getItemTime; res.Ret = 0; } else { TraceLog.Error("MailOp.DoMailAllGetItemOp update mail failed !!"); res.Ret = -1; } } private static void DoMailGetItemDelOp(long uid, ref DBMail getItemMail, ref DBMailBlob blob, MailDBOperator dbOperator, ref SSMailOpRes res) { for (int i = 0; i < blob.MailList.Count; i++) { ref DBMail mail = ref blob.MailList[i]; if (mail.MailID == getItemMail.MailID) { //已经领取过了 if (mail.GetItemTime != 0 || mail.DeleteTime != 0) { TraceLog.Error("MailOp.DoMailGetItemDelOp get item mail & del {0} for uid {1},already get at time {2} {3}" , mail.MailID, uid, mail.GetItemTime, mail.DeleteTime); getItemMail = mail; res.Ret = 0; return; } mail.GetItemTime = AppTime.GetNowSysMs() / 1000; getItemMail.GetItemTime = mail.GetItemTime; mail.DeleteTime = mail.GetItemTime; getItemMail.DeleteTime = getItemMail.GetItemTime; bool bSuccess = dbOperator.UpdateMail(uid, ref blob); if (bSuccess == false) { TraceLog.Error("MailOp.DoMailGetItemOp update mail failed uid {0}", uid); return; } getItemMail = mail; res.Mail = getItemMail; res.Ret = 0; TraceLog.Debug("MailOp.DoMailGetItemOp get mail item {0} for uid {1} at time {2}" , mail.MailID, uid, mail.GetItemTime); return; } } res.Ret = 220202; TraceLog.Error("MailOp.DoMailGetItemOp get mail item {0} for uid {1} failed, no mail exist" , getItemMail.MailID, uid); } private static void DoMailVerChangeOp(long uid, ref SSMailOpReq req, ref DBMailBlob blob, MailDBOperator dbOperator, ref SSMailOpRes res) { if(blob.LastVer > req.MailVerSeq) { TraceLog.Error("MailOp.DoMailVerChangeOp err uid {0} blob Ver {1} change {2}", uid, blob, req.MailVerSeq); return; } blob.LastVer = req.MailVerSeq; bool bSuccess = dbOperator.UpdateMail(uid, ref blob); if (bSuccess == false) { TraceLog.Error("MailOp.DoMailVerChangeOp update mail failed uid {0}", uid); return; } res.Ret = 0; } } }