#!/usr/bin/python # -*- coding: GBK -*- #------------------------------------------------------------------------------- # ##@package Player.PlayerMail # # @todo:Óʼþ # @author hxp # @date 2025-05-14 # @version 1.0 # # ÏêϸÃèÊö: Óʼþ # #------------------------------------------------------------------------------- #"""Version = 2025-05-14 12:00""" #------------------------------------------------------------------------------- import GameWorld import ItemCommon import PlayerControl import IPY_GameWorld import DataRecordPack import ChPyNetSendPack import IpyGameDataPY import ItemControler import NetPackCommon import ShareDefine import DBDataMgr import ChConfig import json import time def OnPlayerLogin(curPlayer): Sync_PlayerServerMail(curPlayer) Sync_PersonalMail(curPlayer) return def OnDayEx(): curTime = int(time.time()) DelTimeoutServerMail(curTime) DelTimeoutPersonalMail(curTime) return def DelTimeoutServerMail(curTime): ## ÇåÀí³¬Ê±È«·þÓʼþ, È«·þÓʼþ·ÖÁ½²¿´¦Àí£º1. Óʼþ½ÓÊÕµÄÓÐЧʱ¼ä£¬ºǫ́ÉèÖã¬2. Óʼþɾ³ýʱ¼äΪ½ÓÊÕÓÐЧʱ¼äÔÙÑÓ³¤30Ìì mailMgr = DBDataMgr.GetMailMgr() serverMailGuids = mailMgr.GetServerMailGuids() for guid in serverMailGuids: mailObj = mailMgr.GetServerMail(guid) if not mailObj: continue createTime = GameWorld.ChangeTimeStrToNum(mailObj.GetCreateTime()) limitTime = createTime + (mailObj.GetLimitDays() + 7) * 3600 * 24 if curTime < limitTime: #GameWorld.DebugLog("È«·þÓʼþδ³¬Ê±£¬²»É¾³ý! %s,createTime=%s,limitTime=%s" % (guid, mailObj.GetCreateTime(), GameWorld.ChangeTimeNumToStr(limitTime))) continue DelServerMail(guid, "Timeout") return def DelServerMail(guid, delEvent=""): GameWorld.Log("ɾ³ýÈ«·þÓʼþ: %s" % (guid)) mailMgr = DBDataMgr.GetMailMgr() playerStateDict = mailMgr.DelServerMail(guid) DataRecordPack.DR_ServerMail(guid, "Delete" + delEvent) if not playerStateDict: return playerMgr = GameWorld.GetPlayerManager() clientPack = __packMailStateChange({guid:ShareDefine.MailState_Del}) for playerID, mailState in playerStateDict.items(): if mailState >= ShareDefine.MailState_Del: continue curPlayer = playerMgr.FindPlayerByID(playerID) if curPlayer: NetPackCommon.SendFakePack(curPlayer, clientPack) return def DelTimeoutPersonalMail(curTime): ## ÇåÀí³¬Ê±¸öÈËÓʼþ mailMgr = DBDataMgr.GetMailMgr() personalMailDict = mailMgr.GetAllPersonalMailDict() for playerID, mailDict in personalMailDict.items(): notifyGUIDState = {} for guid, mailObj in mailDict.items(): createTime = GameWorld.ChangeTimeStrToNum(mailObj.GetCreateTime()) limitTime = createTime + (mailObj.GetLimitDays() + 0) * 3600 * 24 if curTime < limitTime: #GameWorld.DebugLog("¸öÈËÓʼþδ³¬Ê±£¬²»É¾³ý! %s,createTime=%s,limitTime=%s" % (guid, mailObj.GetCreateTime(), GameWorld.ChangeTimeNumToStr(limitTime)), playerID) continue mailState = mailObj.GetMailState() mailItemCount = mailMgr.GetMailItemCount(guid) if mailItemCount and mailState != ShareDefine.MailState_Got: #GameWorld.DebugLog("¸öÈËÓʼþÓÐÎïÆ·Î´ÁìÈ¡²»É¾³ý! %s" % guid, playerID) continue mailMgr.DelPersonalMail(playerID, guid) DataRecordPack.DR_MailDel(playerID, guid, "Timeout") notifyGUIDState[guid] = ShareDefine.MailState_Del if not notifyGUIDState: continue curPlayer = GameWorld.GetPlayerManager().FindPlayerByID(playerID) if curPlayer: Sync_PlayerMailState(curPlayer, notifyGUIDState) return def SendMailByKey(mailTypeKey, playerID, itemList, paramList=[], limitDays=7): ## ·¢Ë͸öÈËÓʼþħ°å if not mailTypeKey: mailTypeKey = ShareDefine.DefaultLackSpaceMailType title = "%s" % mailTypeKey text = "%s" % json.dumps(paramList, ensure_ascii=False) SendMail(playerID, title, text, itemList, limitDays) return def SendMail(playerID, title, text, itemList=None, limitDays=7, mailType=0): ## ·¢Ë͸öÈËÓʼþ if itemList == None: itemList = [] mailMgr = DBDataMgr.GetMailMgr() mailMax = IpyGameDataPY.GetFuncCfg("PersonalMail", 1) mailCnt = mailMgr.GetPersonalMailCount(playerID) if mailCnt >= mailMax: mailList = mailMgr.GetPersonalMails(playerID) mailList.sort(key=lambda m: (-m.GetMailState(), m.GetCreateTime())) # °´Óʼþ״̬µ¹Ðò¡¢´´½¨Ê±¼äÉýÐòÅÅ oneDelCnt = max(1, mailMax / 10) # Ò»´ÎÐÔɾ³ý×î´óÊýÁ¿µÄ1/10·âÓʼþ isStop = False delCnt = 0 notifyGUIDState = {} while delCnt < oneDelCnt and mailList and not isStop: mailObj = mailList.pop(0) # ¸ÃÁбíÊÇcopy£¬¿ÉÖ±½Ópop if not mailObj: continue guid = mailObj.GetGUID() mailState = mailObj.GetMailState() # ÒѾ­É¾µ½Î´¶Á»òδÁìÈ¡µÄÓʼþ£¬ÔòÇ¿ÖÆÍ£Ö¹£¬²»ÔÙɾ³ý if mailState == ShareDefine.MailState_UnRead or (mailState == ShareDefine.MailState_Read and mailMgr.GetMailItemCount(guid)): isStop = True if delCnt > 0: # ÒѾ­ÓÐɾ¹ýÁ˱¾·â¿É²»É¾ break #ÖÁÉÙҪɾ1·â delCnt += 1 GameWorld.DebugLog("ϵͳ×Ô¶¯É¾³ýÓʼþ: playerID=%s,guid=%s,mailState=%s,isStop=%s" % (playerID, guid, mailState, isStop)) mailMgr.DelPersonalMail(playerID, guid) DataRecordPack.DR_MailDel(playerID, guid, "MaxCountLimiit") notifyGUIDState[guid] = ShareDefine.MailState_Del if notifyGUIDState: curPlayer = GameWorld.GetPlayerManager().FindPlayerByID(playerID) if curPlayer: Sync_PlayerMailState(curPlayer, notifyGUIDState) mailObj = mailMgr.AddPersonalMail(playerID, title, text, itemList, limitDays, mailType) CreateTime = mailObj.GetCreateTime() GUID = mailObj.GetGUID() #Ìí¼ÓÁ÷Ïò addDict = {"CreateTime":CreateTime, "Title":title, "Text":text, "LimitDays":limitDays, "ItemList":itemList, "ItemListLen":len(itemList)} DataRecordPack.DR_MailSend(playerID, GUID, addDict) curPlayer = GameWorld.GetPlayerManager().FindPlayerByID(playerID) if curPlayer: Sync_PersonalMail(curPlayer, [mailObj.GetGUID()]) return def SendSeverMail(guid, title, text, itemList=None, limitDays=7, mailType=0, limitLV=0, limitLVType=0, checkState=0): '''·¢ËÍÈ«·þÓʼþ @param guid: ¿É´«Èë¿Õ£¬Ôòϵͳ×Ô¶¯Éú³Éguid @param limitLV: ÏÞÖÆ¿ÉÁìµÄ×îµÍµÈ¼¶ @param limitLVType: µÈ¼¶´ïµ½ºóÊÇ·ñ¿ÉÁ죬ĬÈϲ»¿É @param checkState: ÊÇ·ñÐèÒªÉóºË£¬Ä¬Èϲ»ÐèÒª @return: None - ·¢ËÍʧ°Ü£» mailObj - ³É¹¦·¢Ë͵ÄÓʼþʵÀý ''' mailMgr = DBDataMgr.GetMailMgr() mailObj = mailMgr.AddServerMail(guid, title, text, itemList, limitDays, mailType) if not mailObj: return mailObj GUID = mailObj.GetGUID() mailObj.SetLimitLV(limitLV) mailObj.SetLimitLVType(limitLVType) mailObj.SetCheckState(checkState) eventName = "Add" if not checkState else "AddToCheck" addDict = {"LimitDays":limitDays, "LimitLV":limitLV, "LimitLVType":limitLVType, "CheckState":checkState, "title":title, "Text":text, "ItemList":itemList} DataRecordPack.DR_ServerMail(GUID, eventName, addDict) if not checkState: Sync_ServerMail(mailObj.GetGUID()) return mailObj def CheckServerMailResult(guid, isOK): ## ÉóºËÈ«·þÓʼþ½á¹û # @param isOK: ÊÇ·ñͨ¹ýÉóºË mailMgr = DBDataMgr.GetMailMgr() mailObj = mailMgr.GetServerMail(guid) if not mailObj: return if not isOK: # ÉóºË²»Í¨¹ýµÄÖ±½Óɾ³ý DelServerMail(guid, "GMDel") return GameWorld.Log("È«·þÓʼþÉóºËͨ¹ý: %s" % guid) mailObj.SetCheckState(0) # ÉèÖÃΪ0£¬²»ÐèÒªÉóºËÁË£¬¼´Í¨¹ý DataRecordPack.DR_ServerMail(guid, "CheckOK") Sync_ServerMail(guid) return #// A5 37 ÇëÇóÓʼþ²Ù×÷ #tagCMRequestMail # #struct tagCMRequestMail #{ # tagHead Head; # char GUID[36]; //ÓʼþGUID£¬¿É´«¿Õ£¬Ä¬ÈÏÕë¶Ô¸öÈËÓʼþµÄÅúÁ¿´¦Àí£¬ÈçÅúÁ¿ÁìÈ¡¡¢ÅúÁ¿É¾³ýÒÑÁìÓʼþµÈ£»È«·þÓʼþÔÝʱÏÞÖÆÖ»Äܵ¥·âÓʼþ´¦Àí # BYTE ReqType; //0-ÉèÖÃÒѶÁ£¬1-ÁìÈ¡Óʼþ£¬2-ɾ³ýÓʼþ #}; def OnRequestMail(index, curPackData, tick): curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index) guid = curPackData.GUID reqType = curPackData.ReqType if reqType == 2: doMailDel(curPlayer, guid) elif reqType == 1: doMailGetAward(curPlayer, guid) else: doMailRead(curPlayer, guid) return def doMailRead(curPlayer, guid): ## Ö´ÐÐÓʼþÒѶÁ if not guid: return playerID = curPlayer.GetPlayerID() mailMgr = DBDataMgr.GetMailMgr() mailState = mailMgr.GetPlayerMailState(guid, playerID) if mailState == ShareDefine.MailState_UnRead: mailState = mailMgr.SetPlayerMailState(guid, playerID, ShareDefine.MailState_Read) Sync_PlayerMailState(curPlayer, {guid:mailState}) return def doMailGetAward(curPlayer, guid): ## Ö´ÐÐÓʼþÁìÈ¡£¬Ö§³ÖÅúÁ¿ playerID = curPlayer.GetPlayerID() mailMgr = DBDataMgr.GetMailMgr() # ÅúÁ¿´¦Àí£¬½öÕë¶Ô¸öÈËÓʼþ if not guid: guidList = mailMgr.GetPersonalMailGuids(playerID) else: guidList = [guid] statItemList = [] statItemDict = {} # ͳ¼ÆÀÛ¼Æ isPackSpaceEnough = True notifyGUIDState = {} for guid in guidList: mailState = mailMgr.GetPlayerMailState(guid, playerID) if mailState == ShareDefine.MailState_Unknown or mailState >= ShareDefine.MailState_Got: GameWorld.DebugLog("Óʼþ״̬ÒÑÁìÈ¡»ò²»ÄÜÁìÈ¡! mailState=%s,%s" % (mailState, guid), playerID) continue mailItemCount = mailMgr.GetMailItemCount(guid) if not mailItemCount: GameWorld.DebugLog("ÓʼþûÓÐÎïÆ·¿ÉÁìÈ¡! %s" % (guid), playerID) continue needPackSpaceDict = {} for index in range(mailItemCount): mailItem = mailMgr.GetMailItemAt(guid, index) itemID = mailItem.GetItemID() itemCount = mailItem.GetCount() isBind = mailItem.GetIsBind() userData = mailItem.GetUserData() curItemData = GameWorld.GetGameData().GetItemByTypeID(itemID) if not curItemData: continue packType = ChConfig.GetItemPackType(curItemData) if userData: statItemList.append([itemID, itemCount, isBind, userData]) needSpace = 1 else: key = (itemID, isBind) if key not in statItemDict: statItemDict[key] = 0 statItemList.append(key) statItemDict[key] = statItemDict[key] + itemCount needSpace = ItemControler.GetItemNeedPackCount(packType, curItemData, itemCount, isBind) needPackSpaceDict[packType] = needPackSpaceDict.get(packType, 0) + needSpace GameWorld.DebugLog(" guid=%s,needPackSpaceDict=%s" % (guid, needPackSpaceDict)) for packType, needSpace in needPackSpaceDict.items(): if needSpace > ItemCommon.GetItemPackSpace(curPlayer, packType, needSpace): PlayerControl.NotifyCode(curPlayer, "GeRen_chenxin_676165", [packType]) isPackSpaceEnough = False break if not isPackSpaceEnough: break notifyGUIDState[guid] = mailMgr.SetPlayerMailState(guid, playerID, ShareDefine.MailState_Got) for index in range(mailItemCount): mailItem = mailMgr.GetMailItemAt(guid, index) itemID = mailItem.GetItemID() itemCount = mailItem.GetCount() isBind = mailItem.GetIsBind() userData = mailItem.GetUserData() #setAttrDict = {} if not userData else eval(userData) Ö®ºóÀ©Õ¹ÓÐÖ¸¶¨ÊôÐԵģ¬¿É²Î¿¼¿³Ê÷°æ±¾ if not ItemControler.GivePlayerItem(curPlayer, itemID, itemCount, isBind, [IPY_GameWorld.rptItem], event=[ChConfig.ItemGive_Mail, False, {"MailGUID":guid}]): continue DataRecordPack.DR_MailGiveSuccess(playerID, guid) giveItemInfo = [] for statItem in statItemList: if len(statItem) == 2: itemID, isBind = statItem itemCount = statItemDict.get(statItem, 0) giveItemInfo.append([itemID, itemCount, isBind]) else: giveItemInfo.append(statItem) if giveItemInfo: ItemControler.NotifyGiveAwardInfo(curPlayer, giveItemInfo, "Mail") Sync_PlayerMailState(curPlayer, notifyGUIDState) return def doMailDel(curPlayer, guid, isGM=False, playerID=0): ## Ö´ÐÐÓʼþɾ³ý # @param isGM: ÊÇ·ñGMɾ³ý£¬ÎÞÊÓÎïÆ·ÊÇ·ñÒÑÁìÈ¡£¬Ç¿ÖÆÉ¾³ý if curPlayer: playerID = curPlayer.GetPlayerID() mailMgr = DBDataMgr.GetMailMgr() # ÅúÁ¿´¦Àí£¬½öÕë¶Ô¸öÈËÓʼþ if not guid: guidList = mailMgr.GetPersonalMailGuids(playerID) else: guidList = [guid] notifyGUIDState = {} for guid in guidList: mailState = mailMgr.GetPlayerMailState(guid, playerID) if mailState >= ShareDefine.MailState_Del: continue if not isGM: mailItemCount = mailMgr.GetMailItemCount(guid) if mailItemCount and mailState != ShareDefine.MailState_Got: GameWorld.DebugLog("ÓÐÎïÆ·ÓʼþδÁìÈ¡²»ÄÜɾ³ý! %s" % guid, playerID) continue if not mailItemCount and mailState != ShareDefine.MailState_Read: GameWorld.DebugLog("ÎÞÎïÆ·Óʼþδ¶Á²»ÄÜɾ³ý! %s" % guid, playerID) continue notifyGUIDState[guid] = mailMgr.SetPlayerMailState(guid, playerID, ShareDefine.MailState_Del) if isGM: DataRecordPack.DR_MailDel(playerID, guid, "GMDel") # ÕâÀïÍæ¼ÒÖ÷¶¯É¾³ýµÄ¿É²»¼Ç¼Á÷Ïò£¬ÒòΪδ¶ÁδÁìÈ¡²»ÔÊÐíÖ÷¶¯É¾³ý£¬ÒÑÁìÈ¡µÄÒÑÓÐÁìÈ¡¼Ç¼£¬ËùÒԿɲ»¼Ç¼ if curPlayer: Sync_PlayerMailState(curPlayer, notifyGUIDState) return def Sync_ServerMail(guid): ## ֪ͨȫ·þÓʼþ mailMgr = DBDataMgr.GetMailMgr() serverMail = mailMgr.GetServerMail(guid) if not serverMail: return packMail = __packMailObj(serverMail) clientPack = ChPyNetSendPack.tagMCMailList() clientPack.IsServerMail = 1 clientPack.MailList = [packMail] clientPack.Count = len(clientPack.MailList) playerManager = GameWorld.GetPlayerManager() for i in range(playerManager.OnlineCount()): curPlayer = playerManager.OnlineAt(i) if not GameWorld.IsNormalPlayer(curPlayer): continue mailState = CheckPlayerServerMailState(curPlayer, serverMail) if mailState == ShareDefine.MailState_Unknown or mailState >= ShareDefine.MailState_Del: continue packMail.MailState = mailState NetPackCommon.SendFakePack(curPlayer, clientPack) return def Sync_PlayerServerMail(curPlayer): ## Í¨ÖªÍæ¼ÒÏà¹ØµÄÈ«·þÓʼþ mailMgr = DBDataMgr.GetMailMgr() guidList = mailMgr.GetServerMailGuids() if not guidList: return mailList = [] for guid in guidList: mailObj = mailMgr.GetServerMail(guid) if not mailObj: continue mailState = CheckPlayerServerMailState(curPlayer, mailObj) if mailState == ShareDefine.MailState_Unknown or mailState >= ShareDefine.MailState_Del: continue mail = __packMailObj(mailObj) mail.MailState = mailState mailList.append(mail) if not mailList: return clientPack = ChPyNetSendPack.tagMCMailList() clientPack.IsServerMail = 1 clientPack.MailList = mailList clientPack.Count = len(clientPack.MailList) NetPackCommon.SendFakePack(curPlayer, clientPack) return def CheckPlayerServerMailState(curPlayer, serverMail): ## ¼ì²é´¦ÀíÍæ¼ÒÈ«·þÓʼþ״̬ # @return: Íæ¼Ò¸ÃÈ«·þÓʼþµÄ״̬ if not serverMail or serverMail.GetCheckState(): # ÐèÒªÉóºËµÄ£¬Ö±½Ó·µ»Ø return ShareDefine.MailState_Unknown playerID = curPlayer.GetPlayerID() guid = serverMail.GetGUID() mailMgr = DBDataMgr.GetMailMgr() mailState = mailMgr.GetPlayerMailState(guid, playerID) if mailState != ShareDefine.MailState_Unknown: return mailState mailState = ShareDefine.MailState_Unknown limitLV = serverMail.GetLimitLV() limitLVType = serverMail.GetLimitLVType() playerLV = curPlayer.GetLV() if playerLV < limitLV: if not limitLVType: return mailMgr.SetPlayerMailState(guid, playerID, ShareDefine.MailState_Limit) return ShareDefine.MailState_Unknown return mailMgr.SetPlayerMailState(guid, playerID, ShareDefine.MailState_UnRead) def Sync_PersonalMail(curPlayer, guidList=None): ## Í¨ÖªÍæ¼Ò¸öÈËÓʼþ playerID = curPlayer.GetPlayerID() mailMgr = DBDataMgr.GetMailMgr() if not guidList: guidList = mailMgr.GetPersonalMailGuids(playerID) if not guidList: return clientPack = ChPyNetSendPack.tagMCMailList() clientPack.MailList = [] for guid in guidList: mailObj = mailMgr.GetPersonalMail(playerID, guid) if not mailObj: continue mail = __packMailObj(mailObj) mail.MailState = mailObj.GetMailState() clientPack.MailList.append(mail) clientPack.Count = len(clientPack.MailList) NetPackCommon.SendFakePack(curPlayer, clientPack) return def __packMailObj(mailObj): ## ´ò°ü֪ͨµÄÓʼþ guid = mailObj.GetGUID() mail = ChPyNetSendPack.tagMCMail() mail.GUID = guid mail.Type = mailObj.GetType() mail.CreateTime = mailObj.GetCreateTime() mail.LimitDays = mailObj.GetLimitDays() mail.Title = mailObj.GetTitle() mail.TitleLen = len(mail.Title) mail.Text = mailObj.GetText() mail.TextLen = len(mail.Text) mailMgr = DBDataMgr.GetMailMgr() mailItemCount = mailMgr.GetMailItemCount(guid) for index in range(mailItemCount): mailItem = mailMgr.GetMailItemAt(guid, index) if not mailItem: continue item = ChPyNetSendPack.tagMCMailItem() item.ItemID = mailItem.GetItemID() item.Count = mailItem.GetCount() item.IsBind = mailItem.GetIsBind() item.UserData = mailItem.GetUserData() item.UserDataLen = len(item.UserData) mail.Items.append(item) mail.Count = len(mail.Items) return mail def __packMailStateChange(notifyGUIDState): clientPack = ChPyNetSendPack.tagMCMailStateChange() clientPack.MailList = [] for guid, mailState in notifyGUIDState.items(): mail = ChPyNetSendPack.tagMCMailState() mail.GUID = guid mail.MailState = mailState clientPack.MailList.append(mail) clientPack.Count = len(clientPack.MailList) return clientPack def Sync_PlayerMailState(curPlayer, notifyGUIDState): ## ֪ͨÓʼþ״̬±ä¸ü if not notifyGUIDState: return NetPackCommon.SendFakePack(curPlayer, __packMailStateChange(notifyGUIDState)) return