#!/usr/bin/python # -*- coding: GBK -*- #------------------------------------------------------------------------------- # ##@package DB.StructData.DBMail # # @todo:DBÓʼþ # @author hxp # @date 2025-05-14 # @version 1.0 # # ÏêϸÃèÊö: DBÓʼþ # #------------------------------------------------------------------------------- #"""Version = 2025-05-14 12:00""" #------------------------------------------------------------------------------- import DBStruct import CommFunc import ShareDefine import GameWorld class MailItem(): ## ÓʼþÎïÆ· - ¸öÈË¡¢È«·þÓʼþͨÓà def __init__(self, dbData=None): self.__dbData = DBStruct.tagDBMailItem() if not dbData else dbData return def GetGUID(self): return self.__dbData.GUID def GetItemID(self): return self.__dbData.ItemID def GetCount(self): return self.__dbData.Count def GetIsBind(self): return self.__dbData.IsBind def GetUserData(self): return self.__dbData.UserData def GetBuffer(self): return self.__dbData.getBuffer() class ServerMail(): ## È«·þÓʼþ def __init__(self, dbData=None): self.__dbData = DBStruct.tagDBMailServer() if not dbData else dbData return def GetGUID(self): return self.__dbData.GUID def GetType(self): return self.__dbData.Type def GetCreateTime(self): return self.__dbData.CreateTime def GetLimitDays(self): return self.__dbData.LimitDays def GetTitle(self): return self.__dbData.Title def GetText(self): return self.__dbData.Text def GetLimitLV(self): return self.__dbData.LimitLV # ÏÞÖÆ¿ÉÁìµÄ×îµÍÍæ¼ÒµÈ¼¶ def SetLimitLV(self, limitLV): self.__dbData.LimitLV = limitLV def GetLimitLVType(self): return self.__dbData.LimitLVType # Éý¼¶´ïµ½µÈ¼¶Ìõ¼þºóÊÇ·ñ¿ÉÁ죻0-²»¿É£¬1-¿ÉÒÔ def SetLimitLVType(self, limitLVType): self.__dbData.LimitLVType = limitLVType def GetCheckState(self): return self.__dbData.CheckState # ÐèÒªÉóºË״̬£º0-ÒÑÉóºË£»1-δÉóºË def SetCheckState(self, checkState): self.__dbData.CheckState = checkState def GetBuffer(self): return self.__dbData.getBuffer() class PersonalMail(): ## ¸öÈËÓʼþ def __init__(self, dbData=None): self.__dbData = DBStruct.tagDBMailPersonal() if not dbData else dbData return def GetPlayerID(self): return self.__dbData.PlayerID def GetGUID(self): return self.__dbData.GUID def GetType(self): return self.__dbData.Type def GetCreateTime(self): return self.__dbData.CreateTime def GetLimitDays(self): return self.__dbData.LimitDays def GetTitle(self): return self.__dbData.Title def GetText(self): return self.__dbData.Text def GetMailState(self): return self.__dbData.MailState def SetMailState(self, mailState): self.__dbData.MailState = mailState def GetBuffer(self): return self.__dbData.getBuffer() class MailMgr(): def __init__(self): self.__personalMailDict = {} # ¸öÈËÓʼþ {playerID:{GUID:PersonalMail, ...}, ...} self.__mailItemDict = {} # ÓʼþÎïÆ· {GUID:[MailItem, ...], ...} self.__serverMailDict = {} # È«·þÓʼþ {GUID:ServerMail, ...} self.__serverMailPlayerStateDict = {} # È«·þÓʼþÍæ¼Ò״̬ {GUID:{playerID:mailState, ...}, ...} return def __InitPersonalMailInstance(self, dbData): '''³õʼ»¯¹¦ÄÜÊý¾ÝʵÀý£¬´´½¨»ò¼ÓÔØÊý¾ÝʱͨÓ㬹¦ÄÜÒ»°ã²»µ÷Óà @param dbData: ʵÀý¶ÔÓ¦°ó¶¨µÄdbData @return: ³É¹¦·µ»ØÊµÀý¶ÔÏó£¬Ê§°Ü·µ»ØNone ''' mailObj = PersonalMail(dbData) playerID = mailObj.GetPlayerID() if playerID not in self.__personalMailDict: self.__personalMailDict[playerID] = {} mailDict = self.__personalMailDict[playerID] mailDict[mailObj.GetGUID()] = mailObj return mailObj def __InitServerMailInstance(self, dbData): '''³õʼ»¯¹¦ÄÜÊý¾ÝʵÀý£¬´´½¨»ò¼ÓÔØÊý¾ÝʱͨÓ㬹¦ÄÜÒ»°ã²»µ÷Óà @param dbData: ʵÀý¶ÔÓ¦°ó¶¨µÄdbData @return: ³É¹¦·µ»ØÊµÀý¶ÔÏó£¬Ê§°Ü·µ»ØNone ''' mailObj = ServerMail(dbData) guid = mailObj.GetGUID() self.__serverMailDict[guid] = mailObj return mailObj def __InitMailItemInstance(self, dbData): '''³õʼ»¯¹¦ÄÜÊý¾ÝʵÀý£¬´´½¨»ò¼ÓÔØÊý¾ÝʱͨÓ㬹¦ÄÜÒ»°ã²»µ÷Óà @param dbData: ʵÀý¶ÔÓ¦°ó¶¨µÄdbData @return: ³É¹¦·µ»ØÊµÀý¶ÔÏó£¬Ê§°Ü·µ»ØNone ''' mailItem = MailItem(dbData) guid = mailItem.GetGUID() if guid not in self.__mailItemDict: self.__mailItemDict[guid] = [] mailItemList = self.__mailItemDict[guid] mailItemList.append(mailItem) return mailItem def __AddMailItem(self, guid, itemList): '''Ìí¼ÓÓʼþÎïÆ·£¬È«·þ¡¢¸öÈËÓʼþͨÓã¬ÓʼþÎïÆ·Ö»¹ØÁªguid£¬¹¦ÄÜʹÓò㼶µ¥·âÓʼþÎïÆ·ÉÏÏÞ²»ÏÞ£¬µ«ÊÇÓʼþϵͳµ¥·âÓÐÄÚÖÃÉÏÏÞ @param itemList: ÔªËØÖ§³Ö×Öµä{k:v, ...} »òÁбí [itemID, itemCount, ¿ÉÑ¡ÊÇ·ñÅÄÆ·, ÎïÆ·UserData] ''' if not itemList: return self.__mailItemDict.pop(guid, None) # ·ÀÖ¹ÖØ¸´Ìí¼ÓÓʼþÎïÆ·£¬ÏÈÒÆ³ý # ¼ì²éÕûºÏºÏ²¢ÎïÆ·£¬²¢È·±£ÎïÆ·Ë³Ðò itemRankList = [] itemDict = {} for itemInfo in itemList: if isinstance(itemInfo, dict): itemID = itemInfo.get("ItemID", 0) itemCount = itemInfo.get("Count", 0) isBind = itemInfo.get("IsBind", 0) userData = itemInfo.get("UserData", "") elif (isinstance(itemInfo, list) or isinstance(itemInfo, tuple)) and len(itemInfo) >= 2: itemID, itemCount = itemInfo[:2] isBind = itemInfo[2] if len(itemInfo) > 2 else 0 userData = itemInfo[3] if len(itemInfo) > 3 else "" else: continue itemID = min(GameWorld.ToIntDef(itemID, 0), ShareDefine.Def_UpperLimit_DWord) itemCount = min(GameWorld.ToIntDef(itemCount, 0), ShareDefine.Def_UpperLimit_DWord) isBind = 1 if isBind else 0 if not itemID or not itemCount: continue if userData: itemRankList.append([itemID, itemCount, isBind, userData]) else: key = (itemID, isBind) if key not in itemDict: itemDict[key] = 0 itemRankList.append(key) itemDict[key] = itemDict[key] + itemCount giveItemList = [] for itemInfo in itemRankList: if len(itemInfo) == 4: itemID, itemCount, isBind, userData = itemInfo else: userData = "" itemID, isBind = itemInfo itemCount = itemDict.get(itemInfo, 0) giveItemList.append([itemID, itemCount, isBind, userData]) Max_MailItem = 20 if len(giveItemList) > Max_MailItem: GameWorld.SendGameErrorEx("MailItemMultiError", "%s|%s|%s|%s" % (guid, len(giveItemList), itemList, giveItemList)) #giveItemList = giveItemList[:Max_MailItem] ÔÝʱ»¹ÊÇÈ÷¢£¬ÏÈ×öϺǫ́Óʼþ¾¯¸æ¼´¿É for itemID, itemCount, isBind, userData in giveItemList: dbData = DBStruct.tagDBMailItem() dbData.GUID = guid dbData.ItemID = itemID dbData.Count = itemCount dbData.IsBind = isBind dbData.UserData = userData dbData.UserDataLen = len(dbData.UserData) self.__InitMailItemInstance(dbData) return def AddPersonalMail(self, playerID, title, text, itemList, limitDays=7, mailType=0): '''Ìí¼Ó¸öÈËÓʼþ @param itemList: ÔªËØÖ§³Ö×Öµä{k:v, ...} »òÁбí [itemID, itemCount, ¿ÉÑ¡ÊÇ·ñÅÄÆ·, ÎïÆ·UserData] ''' guid = GameWorld.GetGUID() dbData = DBStruct.tagDBMailPersonal() dbData.PlayerID = playerID dbData.GUID = guid dbData.Type = mailType dbData.CreateTime = GameWorld.GetCurrentDataTimeStr() dbData.LimitDays = limitDays dbData.Title = title dbData.TitleLen = len(dbData.Title) dbData.Text = text dbData.TextLen = len(dbData.Text) dbData.MailState = ShareDefine.MailState_UnRead # ¸öÈËÓʼþĬÈÏδ¶Á self.__AddMailItem(guid, itemList) mailObj = self.__InitPersonalMailInstance(dbData) return mailObj def GetAllPersonalMailDict(self): return self.__personalMailDict def GetPersonalMailCount(self, playerID): ## »ñÈ¡Íæ¼Ò¸öÈËÓʼþ×ÜÊý if playerID not in self.__personalMailDict: return 0 return len(self.__personalMailDict[playerID]) def GetPersonalMailGuids(self, playerID): ## »ñÈ¡Íæ¼ÒËùÓиöÈËÓʼþguidÁбí if playerID not in self.__personalMailDict: return [] mailDict = self.__personalMailDict[playerID] return mailDict.keys() def GetPersonalMails(self, playerID): ## »ñÈ¡Íæ¼ÒËùÓиöÈËÓʼþʵÀýÁбí if playerID not in self.__personalMailDict: return [] mailDict = self.__personalMailDict[playerID] return mailDict.values() def GetPersonalMail(self, playerID, guid): ## »ñÈ¡Íæ¼Ò¸öÈËÓʼþ mailObj = None if playerID not in self.__personalMailDict: self.__personalMailDict[playerID] = {} mailDict = self.__personalMailDict[playerID] if guid in mailDict: mailObj = mailDict[guid] elif False: mailObj = PersonalMail() return mailObj def GetMailItemCount(self, guid): ## »ñÈ¡ÓʼþÎïÆ·¸öÊý£¬È«·þÓʼþ¡¢¸öÈËÓʼþͨÓà if guid not in self.__mailItemDict: return 0 return len(self.__mailItemDict[guid]) def GetMailItemAt(self, guid, index): ## »ñÈ¡Óʼþij¸öÎïÆ· itemObj = None if guid in self.__mailItemDict: itemObjList = self.__mailItemDict[guid] if 0 <= index < len(itemObjList): itemObj = itemObjList[index] if not itemObj and False: itemObj = MailItem() return itemObj def GetMailItemList(self, guid): if guid not in self.__mailItemDict: return [] itemList = [] for mailItem in self.__mailItemDict[guid]: itemID = mailItem.GetItemID() itemCount = mailItem.GetCount() isBind = mailItem.GetIsBind() userData = mailItem.GetUserData() itemInfo = [itemID, itemCount, isBind] if userData: itemInfo.append(userData) itemList.append(itemInfo) return itemList def AddServerMail(self, guid, title, text, itemList, limitDays=7, mailType=0): '''Ìí¼Ó¸öÈËÓʼþ @param guid: Ö¸¶¨µÄÓʼþguid£¬Îª¿Õʱ×Ô¶¯Éú³ÉÐÂguid @param itemList: ÔªËØÖ§³Ö×Öµä{k:v, ...} »òÁбí [itemID, itemCount, ¿ÉÑ¡ÊÇ·ñÅÄÆ·, ÎïÆ·UserData] ''' mailObj = None if not guid: guid = GameWorld.GetGUID() if guid in self.__serverMailDict: # ÒѾ­´æÔÚµÄguid²»ÔÊÐíÖØ¸´²åÈëÈ«·þÓʼþ£¬·ÀÖ¹¶àÁìÈ¡£¬ºǫ́·¢ËÍÈ«·þÓʼþʱÈç¹ûÖØ¸´ÍÆË͵½Ä³¸ö·þÎñÆ÷¾Í¿ÉÄÜ´æÔÚÖØ¸´Çé¿ö return mailObj dbData = DBStruct.tagDBMailServer() dbData.GUID = guid dbData.Type = mailType dbData.CreateTime = GameWorld.GetCurrentDataTimeStr() dbData.LimitDays = limitDays dbData.Title = title dbData.TitleLen = len(dbData.Title) dbData.Text = text dbData.TextLen = len(dbData.Text) self.__AddMailItem(guid, itemList) mailObj = self.__InitServerMailInstance(dbData) return mailObj def GetServerMail(self, guid): ## »ñȡȫ·þÓʼþ mailObj = None if guid in self.__serverMailDict: mailObj = self.__serverMailDict[guid] elif False: mailObj = ServerMail() return mailObj def GetServerMailGuids(self): ## »ñÈ¡ËùÓÐÈ«·þÓʼþguidÁбí return self.__serverMailDict.keys() def GetPlayerMailState(self, guid, playerID): ## »ñÈ¡Íæ¼Òij¸öÓʼþ״̬£¬¸öÈË¡¢È«·þÓʼþͨÓà personalMail = self.GetPersonalMail(playerID, guid) if personalMail: return personalMail.GetMailState() if guid not in self.__serverMailPlayerStateDict: return ShareDefine.MailState_Unknown playerStateDict = self.__serverMailPlayerStateDict[guid] if playerID not in playerStateDict: return ShareDefine.MailState_Unknown return playerStateDict[playerID] def SetPlayerMailState(self, guid, playerID, mailState): ## ÉèÖÃÍæ¼Òij¸öÓʼþ״̬£¬¸öÈË¡¢È«·þÓʼþͨÓà # @return: ·µ»ØÉèÖõÄÓʼþ״̬ personalMail = self.GetPersonalMail(playerID, guid) if personalMail: if mailState >= ShareDefine.MailState_Del: self.DelPersonalMail(playerID, guid) return ShareDefine.MailState_Del personalMail.SetMailState(mailState) return mailState if guid not in self.__serverMailPlayerStateDict: self.__serverMailPlayerStateDict[guid] = {} playerStateDict = self.__serverMailPlayerStateDict[guid] playerStateDict[playerID] = mailState return mailState def DelPersonalMail(self, playerID, guid): ## ɾ³ý¸öÈËÓʼþ self.__mailItemDict.pop(guid, None) if playerID in self.__personalMailDict: mailDict = self.__personalMailDict[playerID] mailDict.pop(guid, None) return def DelServerMail(self, guid): ## ɾ³ýij¸öÈ«·þÓʼþ self.__mailItemDict.pop(guid, None) self.__serverMailDict.pop(guid, None) playerStateDict = self.__serverMailPlayerStateDict.pop(guid, {}) return playerStateDict def DelAllMail(self): self.__personalMailDict = {} self.__mailItemDict = {} self.__serverMailDict = {} self.__serverMailPlayerStateDict = {} return # ±£´æÊý¾Ý ´æÊý¾Ý¿âºÍrealtimebackup def GetSaveData(self): saveData = "" # È«·þÓʼþ serverMailCnt, serverMailSavaData = 0, "" for mailObj in self.__serverMailDict.values(): serverMailCnt += 1 serverMailSavaData += mailObj.GetBuffer() saveData += CommFunc.WriteDWORD("", serverMailCnt) + serverMailSavaData GameWorld.Log("Save DBMailServer count :%s len=%s" % (serverMailCnt, len(serverMailSavaData))) # È«·þÓʼþÍæ¼Ò״̬ dbData = DBStruct.tagDBMailPlayerRec() playerStateCnt, playerStateSaveData = 0, "" for guid, playerStateDict in self.__serverMailPlayerStateDict.items(): for playerID, mailState in playerStateDict.items(): dbData.clear() dbData.GUID = guid dbData.PlayerID = playerID dbData.MailState = mailState playerStateCnt += 1 playerStateSaveData += dbData.getBuffer() saveData += CommFunc.WriteDWORD("", playerStateCnt) + playerStateSaveData GameWorld.Log("Save DBMailPlayerRec count :%s len=%s" % (playerStateCnt, len(playerStateSaveData))) # ¸öÈËÓʼþ personalMailCnt, personalMailSavaData = 0, "" for mailDict in self.__personalMailDict.values(): for mailObj in mailDict.values(): personalMailCnt += 1 personalMailSavaData += mailObj.GetBuffer() saveData += CommFunc.WriteDWORD("", personalMailCnt) + personalMailSavaData GameWorld.Log("Save DBMailPersonal count :%s len=%s" % (personalMailCnt, len(personalMailSavaData))) # ÓʼþÎïÆ· mailItemCnt, mailItemSavaData = 0, "" for itemList in self.__mailItemDict.values(): for itemObj in itemList: mailItemCnt += 1 mailItemSavaData += itemObj.GetBuffer() saveData += CommFunc.WriteDWORD("", mailItemCnt) + mailItemSavaData GameWorld.Log("Save DBMailItem count :%s len=%s" % (mailItemCnt, len(mailItemSavaData))) return saveData # ´ÓÊý¾Ý¿âÔØÈëÊý¾Ý def LoadPyGameData(self, datas, pos, dataslen): if pos >= dataslen: return # È«·þÓʼþ cnt, pos = CommFunc.ReadDWORD(datas, pos) GameWorld.Log("Load DBMailServer count :%s" % cnt) for _ in xrange(cnt): dbData = DBStruct.tagDBMailServer() pos += dbData.readData(datas, pos, dataslen) self.__InitServerMailInstance(dbData) # È«·þÓʼþÍæ¼Ò״̬ cnt, pos = CommFunc.ReadDWORD(datas, pos) GameWorld.Log("Load DBMailPlayerRec count :%s" % cnt) dbData = DBStruct.tagDBMailPlayerRec() for _ in xrange(cnt): dbData.clear() pos += dbData.readData(datas, pos, dataslen) self.SetPlayerMailState(dbData.GUID, dbData.PlayerID, dbData.MailState) # ¸öÈËÓʼþ cnt, pos = CommFunc.ReadDWORD(datas, pos) GameWorld.Log("Load DBMailPersonal count :%s" % cnt) for _ in xrange(cnt): dbData = DBStruct.tagDBMailPersonal() pos += dbData.readData(datas, pos, dataslen) self.__InitPersonalMailInstance(dbData) # ÓʼþÎïÆ· cnt, pos = CommFunc.ReadDWORD(datas, pos) GameWorld.Log("Load DBMailItem count :%s" % cnt) for _ in xrange(cnt): dbData = DBStruct.tagDBMailItem() pos += dbData.readData(datas, pos, dataslen) self.__InitMailItemInstance(dbData) return pos