From e9ec5c336b25726e16385e290227e2e8677cebb7 Mon Sep 17 00:00:00 2001 From: hxp <ale99527@vip.qq.com> Date: 星期五, 23 四月 2021 18:13:23 +0800 Subject: [PATCH] 8901 【BT2】【后端】全服红包(优化红包系统 1.全服红包去除总上限个数,改为限制下发数量,并在领取红包后补充相应的红包数量; 2.全服未开放可领的红包仅个人可见; 3.红包超时间隔改为5分钟检查一次 4.修改封包) --- ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerFamilyRedPacket.py | 1355 ++++++++++++++++++++++++++++++++++++---------------------- 1 files changed, 843 insertions(+), 512 deletions(-) diff --git a/ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerFamilyRedPacket.py b/ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerFamilyRedPacket.py index 7c07e9a..ad6da7b 100644 --- a/ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerFamilyRedPacket.py +++ b/ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerFamilyRedPacket.py @@ -18,50 +18,27 @@ #--------------------------------------------------------------------- import GameWorld -import ChPyNetSendPack -import NetPackCommon import ShareDefine +import NetPackCommon import IpyGameDataPY -import PlayerDBGSEvent -import PlayerUniversalGameRec -import PlayerControl -import ChConfig +import ChPyNetSendPack import PlayerCompensation +import PlayerDBGSEvent +import PlayerControl import PlayerFamily +import PyGameData +import ChConfig -import time -import random import datetime - -''' -红包暂定有效期24小时,过天清除过期的红包,如果是玩家发放的返还未领取的货币 -上线同步所有红包信息,红包变化实时广播全服在线玩家 -''' -#Def_UniversalGameRecType_FamilyRedPacketAllRecord -#Time 创建红包时间,非红包实际开放领取时间,如果红包表有配置系统发放时间,则该时间存配表时间,没有的话存创建时的服务器时间 -#value1 红包唯一ID,该ID为实例ID,非配表的红包ID -#value2 家族ID,0代表全服红包 -#value3 总额度*10+金钱类型 -#value4 状态 -#value5 时间,用来判断是否过期删除的,实际开放该红包领取的时间 -#strValue1 创建者ID|创建者名字|创建者职业|获得途径(红包类型) -#strValue2 可抢总个数|是否匿名(默认不匿名兼容老数据) -#strValue3 祝福语,玩家自己编辑的内容 - -#Def_UniversalGameRecType_FamilyRedPacketGrabRecord -#value1 红包唯一ID -#value2 playerID -#value3 job -#value4 moneyType -#value5 getMoney -#strValue1 名字 +import random +import time ( -State_NoSend, #未发 -State_NoGot, #未领取 -State_HasGot, #已领取 -State_HasAllGot,#全部领完 -)=range(4) +State_NoSend, #未发 +State_NoGot, #未领取 +State_HasGot, #已领取 +State_HasAllGot, #全部领完 +) = range(4) g_allRecordDict = {} #{红包ID:recData, ...} g_grabDataDict = {} #{红包ID:{playerid:[抢到的钱,名字,job]}, ...} @@ -70,21 +47,663 @@ DBKey_RedPacketSend = "RedPacketSend_%s" # 系统定时红包是否已发放, 参数红包ID DBKey_RedPacketSystemDayCount = "RedPacketSystemDayCount" # 全服系统红包已发放个数 -## 玩家登录 -# @param None -# @return None -def OnPlayerLogin(curPlayer): - NotifyRedPacketInfo(curPlayer) +def __SaveRedpacketRecData(recData, redPacketObj): + ''' 红包暂定有效期24小时,过天清除过期的红包,如果是玩家发放的返还未领取的货币 + 上线同步所有红包信息,红包变化实时广播全服在线玩家 + ''' + #红包数据 Def_UniversalGameRecType_FamilyRedPacketAllRecord + #Time 创建红包时间,非红包实际开放领取时间,如果红包表有配置系统发放时间,则该时间存配表时间,没有的话存创建时的服务器时间 + #value1 红包唯一ID,该ID为实例ID,非配表的红包ID + #value2 家族ID,0代表全服红包 + #value3 总额度*10+金钱类型 + #value4 状态 + #value5 时间,用来判断是否过期删除的,实际开放该红包领取的时间 + #strValue1 创建者ID|创建者名字|创建者职业|获得途径(红包类型) + #strValue2 可抢总个数|是否匿名(默认不匿名兼容老数据) + #strValue3 祝福语,玩家自己编辑的内容 + + recData.SetTime(redPacketObj.createTime) + recData.SetValue1(redPacketObj.redPacketID) + recData.SetValue2(redPacketObj.familyID) + recData.SetValue3(redPacketObj.moneyType + redPacketObj.moneyValue * 10) + recData.SetValue4(redPacketObj.state) + recData.SetValue5(redPacketObj.calcTime) + strValue1 = '%s|%s|%s|%s' % (redPacketObj.playerID, redPacketObj.playerName, redPacketObj.playerJob, redPacketObj.getWay) + recData.SetStrValue1(strValue1) + recData.SetStrValue2('%s|%s' % (redPacketObj.packetCnt, int(redPacketObj.isAnonymous))) + recData.SetStrValue3(redPacketObj.wish) return +def __SaveRedpacketRecGrabData(recData, grabObj): + #抢红包记录 Def_UniversalGameRecType_FamilyRedPacketGrabRecord + #value1 红包唯一ID + #value2 playerID + #value3 job + #value4 moneyType + #value5 getMoney + #strValue1 名字 + + recData.SetValue1(grabObj.redPacketID) + recData.SetValue2(grabObj.playerID) + recData.SetValue3(grabObj.playerJob) + recData.SetValue4(grabObj.moneyType) + recData.SetValue5(grabObj.getMoney) + recData.SetStrValue1(grabObj.playerName) + return +class RedPacketGrab(): + ## 红包抢记录数据 + + def __init__(self, redPacketID, playerID): + self.redPacketID = redPacketID + self.playerID = playerID + self.playerJob = 0 + self.playerName = "" + self.moneyType = 0 + self.getMoney = 0 + return + +class RedPacketData(): + ## 红包数据 + + def __init__(self, redPacketID): + self.redPacketID = redPacketID + self.familyID = 0 + self.moneyType = 0 + self.moneyValue = 0 + self.state = 0 + self.createTime = 0 + self.calcTime = 0 + self.playerID = 0 + self.playerName = "" + self.playerJob = 0 + self.getWay = 0 + self.packetCnt = 0 + self.isAnonymous = 0 # 是否匿名 + self.wish = "" + + self.grabDict = {} # 抢红包记录 {playerID:RedPacketGrab, ...} + return + +class RedPacketMgr(): + ''' 红包缓存管理等 + 通知玩家红包逻辑: + 由于刚开服时红包大概率会比较多,红包的交互及交叉通知也相对比较密集,所以做些优化,不对所有红包处理 + 将红包分为红包总库及通知给玩家的部分红包,假设当前所有红包总数为500个,标记为 T 个 + 可配置限制通知给玩家可操作的红包个数如只通知20个,标记为 M 个,可视为热红包,当 M 消化完后可附加通知 N 个 + + 通知玩家的红包组成: + 非仙盟红包: 归属玩家的未开放红包A + 不限制通知个数的红包B + 限制通知个数的红包C; 不包含其他玩家未开放的 + 仙盟红包: 所有玩家未领取过的且未全部领完的红包,包含其他玩家未开放的 + + 如果 (A + B) >= M 了,则不需要再附加通知 C + ''' + def __init__(self): + self.allRedPacketDict = {} # 所有红包信息 {红包ID:RedPacketData, ...} + + self.familyRedPacketDict = {} # 仙盟红包信息,全部同步 {familyID:[红包ID, ...], ...} + + # --- 以下仅针对非仙盟红包 --- + # 针对红包量比较大的红包类型,有限制同步个数,按类型分组,每组按规则独立同步;如 开服成就红包、节日成就红包、全服红包 + # 同步规则: + # 比如先同步20个,然后减一个则再从已开放的库中补充; + # 新增一个开放领取的红包时,如果玩家有可领取的则不需要同步,没有可领取的则需要同步给他 + # 注: 全服红包中,未开放的红包仅玩家自己可见 + self.playerNosendRedPacketIDInfo = {} # 玩家未开放的红包ID信息,针对有同步个数限制的类型 {playerID:{红包类型:[红包ID, ...], ...}, ...} + + # playerCanGetRedPacketIDInfo 的playerID包含所有在线玩家,不含脱机挂 + self.playerCanGetRedPacketIDInfo = {} # 玩家可领取的红包ID信息,针对有同步个数限制的类型 {playerID:{红包类型:[红包ID, ...], ...}, ...} + self.activeRedPacketIDInfo = {} # 已开放领取的红包ID列表,针对有同步个数限制的类型 {红包类型:[红包ID, ...], ...} + + # 其他全服红包,一般量比较少的,相对固定的,全部同步,如节日定时发送的红包 + self.notifyAllServerRedPacketIDList = [] # 其他没有限制下发同步个数的全服红包ID [红包ID, ...] + return + + def PrintData(self, sign=""): + if sign: + GameWorld.DebugLog(" === %s ===" % sign) + GameWorld.DebugLog(" 所有红包=%s" % self.allRedPacketDict.keys()) + GameWorld.DebugLog(" 仙盟红包=%s" % self.familyRedPacketDict) + GameWorld.DebugLog(" 全服同步全部红包=%s" % self.notifyAllServerRedPacketIDList) + GameWorld.DebugLog(" 全服同步活跃红包=%s" % self.activeRedPacketIDInfo) + GameWorld.DebugLog(" 全服个人未开放红包=%s" % self.playerNosendRedPacketIDInfo) + GameWorld.DebugLog(" 全服个人可领取红包=%s" % self.playerCanGetRedPacketIDInfo) + return + + def GetRedPacketObj(self, redPacketID, createNew): + ## 获取红包实例 + redPacketObj = None + if redPacketID in self.allRedPacketDict: + redPacketObj = self.allRedPacketDict[redPacketID] + elif createNew: + redPacketObj = RedPacketData(redPacketID) + self.allRedPacketDict[redPacketID] = redPacketObj + return redPacketObj + + def AddFamilyRedPacketID(self, familyID, redPacketID): + ## 添加红包ID进入仙盟红包ID缓存 + if familyID not in self.familyRedPacketDict: + self.familyRedPacketDict[familyID] = [] + familyRedpacketIDList = self.familyRedPacketDict[familyID] + if redPacketID not in familyRedpacketIDList: + familyRedpacketIDList.append(redPacketID) + return + + def DelFamilyRedPacketID(self, familyID, redPacketID): + ## 删除仙盟红包ID缓存 + if familyID not in self.familyRedPacketDict: + return + familyRedpacketIDList = self.familyRedPacketDict[familyID] + if redPacketID not in familyRedpacketIDList: + return + familyRedpacketIDList.remove(redPacketID) + return True + + def AddPlayerNosendRedPacketID(self, playerID, getWay, redPacketID): + ## 添加玩家未开放的红包ID缓存 + if playerID not in self.playerNosendRedPacketIDInfo: + self.playerNosendRedPacketIDInfo[playerID] = {} + playerNosendRedPacketTypeIDInfo = self.playerNosendRedPacketIDInfo[playerID] + if getWay not in playerNosendRedPacketTypeIDInfo: + playerNosendRedPacketTypeIDInfo[getWay] = [] + playerNosendRedPacketTypeIDList = playerNosendRedPacketTypeIDInfo[getWay] + if redPacketID not in playerNosendRedPacketTypeIDList: + playerNosendRedPacketTypeIDList.append(redPacketID) + return + + def DelPlayerNosendRedPacketID(self, playerID, getWay, redPacketID): + ## 删除玩家未开放的红包ID缓存 + if playerID not in self.playerNosendRedPacketIDInfo: + return + playerNosendRedPacketTypeIDInfo = self.playerNosendRedPacketIDInfo[playerID] + if getWay not in playerNosendRedPacketTypeIDInfo: + return + playerNosendRedPacketTypeIDList = playerNosendRedPacketTypeIDInfo[getWay] + if redPacketID not in playerNosendRedPacketTypeIDList: + return + playerNosendRedPacketTypeIDList.remove(redPacketID) + return True + + def AddActiveRedPacketID(self, getWay, redPacketID): + ## 添加已开放的全服红包ID缓存 + if getWay not in self.activeRedPacketIDInfo: + self.activeRedPacketIDInfo[getWay] = [] + redPacketIDList = self.activeRedPacketIDInfo[getWay] + if redPacketID not in redPacketIDList: + redPacketIDList.append(redPacketID) + return + + def DelActiveRedPacketID(self, getWay, redPacketID): + ## 删除已开放的全服红包ID缓存 + if getWay not in self.activeRedPacketIDInfo: + return + redPacketIDList = self.activeRedPacketIDInfo[getWay] + if redPacketID not in redPacketIDList: + return + redPacketIDList.remove(redPacketID) + return True + + def AddPlayerCanGetRedPacketID(self, playerID, getWay, redPacketID): + ## 添加玩家可领取的红包ID缓存 + if playerID not in self.playerCanGetRedPacketIDInfo: + self.playerCanGetRedPacketIDInfo[playerID] = {} + redPacketTypeIDInfo = self.playerCanGetRedPacketIDInfo[playerID] + if getWay not in redPacketTypeIDInfo: + redPacketTypeIDInfo[getWay] = [] + redPacketIDList = redPacketTypeIDInfo[getWay] + if redPacketID not in redPacketIDList: + redPacketIDList.append(redPacketID) + return + + def DelPlayerCanGetRedPacketID(self, playerID, getWay, redPacketID): + ## 删除玩家可领取的红包ID缓存 + if playerID not in self.playerCanGetRedPacketIDInfo: + return + redPacketTypeIDInfo = self.playerCanGetRedPacketIDInfo[playerID] + if getWay not in redPacketTypeIDInfo: + return + redPacketIDList = redPacketTypeIDInfo[getWay] + if redPacketID not in redPacketIDList: + return + redPacketIDList.remove(redPacketID) + # 返回当前类型可用红包ID列表 + return redPacketIDList + +def GetRedpacketMgr(): + redPacketMgr = PyGameData.g_redPacketMgr + if redPacketMgr == None: + redPacketMgr = RedPacketMgr() + PyGameData.g_redPacketMgr = redPacketMgr + return redPacketMgr + +def OnServerStart(): + redPacketMgr = GetRedpacketMgr() + + universalRecMgr = GameWorld.GetUniversalRecMgr() + + # 红包数据 + notifyLimitTypeList = IpyGameDataPY.GetFuncEvalCfg("RedPacketSys", 1) + recordList = universalRecMgr.GetTypeList(ShareDefine.Def_UniversalGameRecType_FamilyRedPacketAllRecord) + GameWorld.Log("加载红包信息通用记录: count=%s" % recordList.Count()) + for index in xrange(recordList.Count()): + recData = recordList.At(index) + state = recData.GetValue4() + if state == State_HasAllGot: + # 已全部领完的不处理 + continue + redPacketID = recData.GetValue1() + familyID = recData.GetValue2() + + redPacketObj = redPacketMgr.GetRedPacketObj(redPacketID, True) + redPacketObj.familyID = familyID + redPacketObj.createTime = recData.GetTime() + redPacketObj.moneyType = recData.GetValue3() % 10 + redPacketObj.moneyValue = recData.GetValue3() / 10 + redPacketObj.state = recData.GetValue4() + redPacketObj.calcTime = recData.GetValue5() + + strValue1List = recData.GetStrValue1().split('|') + playerID, playerName, job, getWay = strValue1List + redPacketObj.playerID = GameWorld.ToIntDef(playerID) + redPacketObj.playerName = playerName + redPacketObj.playerJob = GameWorld.ToIntDef(job) + redPacketObj.getWay = GameWorld.ToIntDef(getWay) + + strValue2List = recData.GetStrValue2().split('|') + redPacketObj.packetCnt = GameWorld.ToIntDef(strValue2List[0]) + redPacketObj.isAnonymous = GameWorld.ToIntDef(strValue2List[1]) if len(strValue2List) > 1 else 0 + + redPacketObj.wish = recData.GetStrValue3() + + playerID = redPacketObj.playerID + getWay = redPacketObj.getWay + + # 1. 仙盟的红包 + if familyID: + redPacketMgr.AddFamilyRedPacketID(familyID, redPacketID) + continue + + # 以下是面向全服的红包 + # 2. 全服未开放红包 + if state == State_NoSend: + # 未发放的添加进ID缓存 + redPacketMgr.AddPlayerNosendRedPacketID(playerID, getWay, redPacketID) + continue + + # 3. 全服不限制下发个数的 + if getWay not in notifyLimitTypeList: + redPacketMgr.notifyAllServerRedPacketIDList.append(redPacketID) + continue + + # 4. 有限制通知个数的 + if state == State_NoGot: + redPacketMgr.AddActiveRedPacketID(getWay, redPacketID) + + # 抢红包记录 + grabRecordList = universalRecMgr.GetTypeList(ShareDefine.Def_UniversalGameRecType_FamilyRedPacketGrabRecord) + GameWorld.Log("加载红包抢记录信息通用记录: count=%s" % grabRecordList.Count()) + for index in xrange(grabRecordList.Count()): + recData = grabRecordList.At(index) + redPacketID = recData.GetValue1() + playerID = recData.GetValue2() + redPacketObj = redPacketMgr.GetRedPacketObj(redPacketID, False) + if not redPacketObj: + continue + + grabObj = RedPacketGrab(redPacketID, playerID) + grabObj.playerJob = recData.GetValue3() + grabObj.playerName = recData.GetStrValue1() + grabObj.moneyType = recData.GetValue4() + grabObj.getMoney = recData.GetValue5() + + redPacketObj.grabDict[playerID] = grabObj + + redPacketMgr.PrintData("OnServerStart") + return + +def OnServerClose(): + + redPacketMgr = GetRedpacketMgr() + + recMgr = GameWorld.GetUniversalRecMgr() + recMgr.Delete(ShareDefine.Def_UniversalGameRecType_FamilyRedPacketAllRecord) + recDataList = recMgr.GetTypeList(ShareDefine.Def_UniversalGameRecType_FamilyRedPacketAllRecord) + + recMgr.Delete(ShareDefine.Def_UniversalGameRecType_FamilyRedPacketGrabRecord) + grabRecDataList = recMgr.GetTypeList(ShareDefine.Def_UniversalGameRecType_FamilyRedPacketGrabRecord) + + redPacketCount = 0 + grabRecCount = 0 + for redPacketObj in redPacketMgr.allRedPacketDict.values(): + if redPacketObj.state == State_HasAllGot: + # 已全部抢完的不保存 + continue + recData = recDataList.AddRec() + __SaveRedpacketRecData(recData, redPacketObj) + redPacketCount += 1 + + for grabObj in redPacketObj.grabDict.values(): + grabRecData = grabRecDataList.AddRec() + __SaveRedpacketRecGrabData(grabRecData, grabObj) + grabRecCount += 1 + + GameWorld.Log("保存红包信息通用记录: count=%s" % redPacketCount) + GameWorld.Log("保存红包抢记录信息通用记录: count=%s" % grabRecCount) + return + +def OnPlayerLogin(curPlayer): + + if not PlayerControl.GetIsTJG(curPlayer): + + redPacketMgr = GetRedpacketMgr() + playerID = curPlayer.GetPlayerID() + redPacketMgr.playerCanGetRedPacketIDInfo[playerID] = {} + redPacketMgr.PrintData("OnPlayerLogin %s" % playerID) + + notifyLimitTypeList = IpyGameDataPY.GetFuncEvalCfg("RedPacketSys", 1) + maxNotifyCount = IpyGameDataPY.GetFuncCfg("RedPacketSys", 2) + + for getWay in notifyLimitTypeList: + redPacketMgr.playerCanGetRedPacketIDInfo[playerID][getWay] = [] # 确保 getWay key 一定存在 + + nowActiveRedPacketIDList = redPacketMgr.activeRedPacketIDInfo.get(getWay, []) # 当前此类型还可用的公共已开放红包列表 + if not nowActiveRedPacketIDList: + continue + nosendIDList = redPacketMgr.playerNosendRedPacketIDInfo.get(playerID, {}).get(getWay, []) + addCount = maxNotifyCount - len(nosendIDList) + if addCount <= 0: + continue + + playerCanGetIDList = [] + for redPacketID in nowActiveRedPacketIDList: + redPacketObj = redPacketMgr.GetRedPacketObj(redPacketID, False) + if playerID in redPacketObj.grabDict: + continue + playerCanGetIDList.append(redPacketID) + addCount -= 1 + if addCount <= 0: + break + redPacketMgr.playerCanGetRedPacketIDInfo[playerID][getWay] = playerCanGetIDList + + redPacketMgr.PrintData("loginOK") + + NotifyRedPacketInfo(curPlayer, isLogin=True) + return + +def OnLeaveServer(curPlayer): + playerID = curPlayer.GetPlayerID() + redPacketMgr = GetRedpacketMgr() + redPacketMgr.playerCanGetRedPacketIDInfo.pop(playerID, None) + return + ## 隔天更新 -# @param None -# @return None def DoOnDay(): - __CheckGrabRecData() PlayerDBGSEvent.SetDBGSTrig_ByKey(DBKey_RedPacketSystemDayCount, 0) # 重置每日全服系统红包发放个数 RandTodayServerSystemRedPacketSendTime() + return + +def CheckDelRedpacketData(): + ## 检查红包删除红包,5分钟一次: 1-删除过期红包,2-删除已全部抢完的红包 + + curTimeNum = int(time.time()) + rangeTime = IpyGameDataPY.GetFuncCfg("RedPacketSys", 3) * 3600 + + backMoneyDict = {} + delRedPacketIDList = [] # 删除的全服红包 [红包ID, ...] + delFamilyRedPacketInfo = {} # 删除的仙盟红包 {familyID:[红包ID, ...], ...} + delNosendRedPacketInfo = {} # 要通知给玩家删除的红包 {playerID:[红包ID, ...], ...} + + redPacketMgr = GetRedpacketMgr() + + for redPacketObj in redPacketMgr.allRedPacketDict.values(): + + state = redPacketObj.state + if state == State_HasAllGot: + pass + elif curTimeNum - redPacketObj.calcTime < rangeTime: + continue + + redPacketID = redPacketObj.redPacketID + playerID = redPacketObj.playerID + familyID = redPacketObj.familyID + getWay = redPacketObj.getWay + + if redPacketID in redPacketMgr.allRedPacketDict: + redPacketMgr.allRedPacketDict.pop(redPacketID) + + # 返还未领完的玩家主动发放的仙玉红包 + if state != State_HasAllGot and playerID and getWay == ShareDefine.RedPackType_GoldPacket: + outNum = sum([grabObj.getMoney for grabObj in redPacketObj.grabDict.values()]) #已被抢的钱 + moneyType = redPacketObj.moneyType + totalMoney = redPacketObj.moneyValue + remainMoney = totalMoney - outNum #剩余的钱 + if moneyType == 1 and remainMoney: + backMoneyDict[playerID] = backMoneyDict.get(playerID, 0) + remainMoney + + # 1. 仙盟红包 + if familyID: + redPacketMgr.DelFamilyRedPacketID(familyID, redPacketID) + + if familyID not in delFamilyRedPacketInfo: + delFamilyRedPacketInfo[familyID] = [] + defFamilyRedPacketIDList = delFamilyRedPacketInfo[familyID] + defFamilyRedPacketIDList.append(redPacketID) + continue + + # 2. 全服红包 + + # 2.1 是否玩家私有未开放的全服红包 + if state == State_NoSend: + redPacketMgr.DelPlayerNosendRedPacketID(playerID, getWay, redPacketID) + + if playerID not in delNosendRedPacketInfo: + delNosendRedPacketInfo[playerID] = [] + playerNosendRedPacketIDList = delNosendRedPacketInfo[playerID] + playerNosendRedPacketIDList.append(redPacketID) + continue + + # 2.2 已开放的全服红包 + redPacketMgr.DelActiveRedPacketID(getWay, redPacketID) + + if redPacketID in redPacketMgr.notifyAllServerRedPacketIDList: + redPacketMgr.notifyAllServerRedPacketIDList.remove(redPacketID) + + # 这个玩家可领取的可能包含非玩家自己发的红包 + for typeIDDict in redPacketMgr.playerCanGetRedPacketIDInfo.values(): + if getWay not in typeIDDict: + continue + redpacketIDList = typeIDDict[getWay] + if redPacketID not in redpacketIDList: + continue + redpacketIDList.remove(redPacketID) + + delRedPacketIDList.append(redPacketID) + + #返回玩家未被领取的仙玉 + if backMoneyDict: + for playerID, moneyNum in backMoneyDict.items(): + PlayerCompensation.SendMailByKey('RedPackBack', [playerID], [], [], moneyNum) + + playerManager = GameWorld.GetPlayerManager() + + # 同步删除的仙盟红包 + GameWorld.DebugLog("同步删除的仙盟红包: %s" % delFamilyRedPacketInfo) + for familyID, delIDList in delFamilyRedPacketInfo.items(): + family = GameWorld.GetFamilyManager().FindFamily(familyID) + if not family: + return + + sendPack = ChPyNetSendPack.tagGCRedPacketDel() + sendPack.DelRedPacketID = delIDList + sendPack.Cnt = len(delIDList) + + for i in xrange(family.GetCount()): + notifyMember = family.GetAt(i) + curPlayer = playerManager.FindPlayerByID(notifyMember.GetPlayerID()) + if curPlayer == None or not curPlayer.GetInitOK() or PlayerControl.GetIsTJG(curPlayer): + continue + NetPackCommon.SendFakePack(curPlayer, sendPack) + + # 同步删除个人未开放的全服红包 + GameWorld.DebugLog("同步删除个人未开放的全服红包: %s" % delNosendRedPacketInfo) + for playerID, nosendIDList in delNosendRedPacketInfo.items(): + curPlayer = playerManager.FindPlayerByID(playerID) + if curPlayer == None or not curPlayer.GetInitOK() or PlayerControl.GetIsTJG(curPlayer): + continue + sendPack = ChPyNetSendPack.tagGCRedPacketDel() + sendPack.DelRedPacketID = nosendIDList + sendPack.Cnt = len(nosendIDList) + NetPackCommon.SendFakePack(curPlayer, sendPack) + + # 同步删除已开放的全服红包 + GameWorld.DebugLog("同步删除已开放的全服红包: %s" % delRedPacketIDList) + if delRedPacketIDList: + sendPack = ChPyNetSendPack.tagGCRedPacketDel() + sendPack.Clear() + sendPack.DelRedPacketID = delRedPacketIDList + sendPack.Cnt = len(delRedPacketIDList) + for i in xrange(playerManager.GetActivePlayerCount()): + curPlayer = playerManager.GetActivePlayerAt(i) + if curPlayer == None or not curPlayer.GetInitOK() or PlayerControl.GetIsTJG(curPlayer): + continue + NetPackCommon.SendFakePack(curPlayer, sendPack) + + return + +def OnChangeRedPacketState(family, redPacketObj, beforeState=None): + ## 红包状态变更处理 + state = redPacketObj.state + if state == beforeState: + return + + redPacketMgr = GetRedpacketMgr() + redPacketID = redPacketObj.redPacketID + familyID = redPacketObj.familyID + ownerID = redPacketObj.playerID + getWay = redPacketObj.getWay + + GameWorld.DebugLog("红包状态变更处理: redPacketID=%s,ownerID=%s,familyID=%s,beforeState=%s,state=%s" + % (redPacketID, ownerID, familyID, beforeState, state)) + redPacketMgr.PrintData("a") + + notifyPlayerDict = {ownerID:[redPacketID]} # 通知给指定玩家的信息,每个玩家可能不一样 + + # 1. 仙盟红包直接通知该仙盟所有成员 + if family: + if state in [State_NoSend, State_NoGot]: + redPacketMgr.AddFamilyRedPacketID(family.GetID(), redPacketID) + + # 2. 全服未开放红包默认只发给个人 + elif state == State_NoSend: + if not ownerID: + return + if beforeState == None: + redPacketMgr.AddPlayerNosendRedPacketID(ownerID, getWay, redPacketID) + + # 3. 全服不限制下发个数的同步全服玩家 + elif getWay not in IpyGameDataPY.GetFuncEvalCfg("RedPacketSys", 1): + notifyPlayerDict = None + if state == State_HasAllGot: + if redPacketID in redPacketMgr.notifyAllServerRedPacketIDList: + redPacketMgr.notifyAllServerRedPacketIDList.remove(redPacketID) + else: + if redPacketID not in redPacketMgr.notifyAllServerRedPacketIDList: + redPacketMgr.notifyAllServerRedPacketIDList.append(redPacketID) + + # 4. 其他的要限制下发个数的检查需要同步的玩家即可 + # 4.1 变为 开放领取状态 + elif state == State_NoGot: + if beforeState != State_NoGot: + redPacketMgr.DelPlayerNosendRedPacketID(ownerID, getWay, redPacketID) # 移出拥有者私有未开放红包队列 + redPacketMgr.AddPlayerCanGetRedPacketID(ownerID, getWay, redPacketID) # 添加拥有者私有已开放红包队列 + redPacketMgr.AddActiveRedPacketID(getWay, redPacketID) # 添加公共已开放红包队列 + + maxNotifyCount = IpyGameDataPY.GetFuncCfg("RedPacketSys", 2) + # 检查追加该红包记录的玩家 + for playerID, typeRedIDDict in redPacketMgr.playerCanGetRedPacketIDInfo.items(): + if playerID == ownerID: + continue + redIDList = typeRedIDDict.get(getWay, []) + if redPacketID in redIDList: + continue + nosendTypeRedIDDict = redPacketMgr.playerNosendRedPacketIDInfo.get(playerID, {}) + nosendRedIDList = nosendTypeRedIDDict.get(getWay, []) + totalCount = len(nosendRedIDList) + len(redIDList) # 玩家当前还可操作领取的红包数 + if totalCount >= maxNotifyCount: + continue + redPacketMgr.AddPlayerCanGetRedPacketID(playerID, getWay, redPacketID) # 添加目标玩家私有已开放红包队列 + notifyPlayerDict[playerID] = [redPacketID] + + # 4.1 变为 全部领取完毕 + elif state == State_HasAllGot: + if beforeState != State_HasAllGot: + redPacketMgr.DelActiveRedPacketID(getWay, redPacketID) # 移除公共已开放红包队列 + + nowActiveRedPacketIDList = redPacketMgr.activeRedPacketIDInfo.get(getWay, []) # 当前此类型还可用的公共已开放红包列表 + + # 检查需要补充红包记录的玩家,采用 减去1 补充1 的模式 + for playerID, typeRedIDDict in redPacketMgr.playerCanGetRedPacketIDInfo.items(): + + canGetIDList = redPacketMgr.DelPlayerCanGetRedPacketID(playerID, getWay, redPacketID) # 移出私有已开放红包队列 + if canGetIDList == None: + continue + + lastCanGetID = 0 if not canGetIDList else canGetIDList[-1] + checkIndex = nowActiveRedPacketIDList.index(lastCanGetID) if lastCanGetID in nowActiveRedPacketIDList else 0 + for i in xrange(checkIndex, len(nowActiveRedPacketIDList)): + newCanGetRedID = nowActiveRedPacketIDList[i] + if newCanGetRedID not in canGetIDList: + if redPacketMgr.AddPlayerCanGetRedPacketID(playerID, getWay, newCanGetRedID): # 添加目标玩家私有已开放红包队列 + notifyPlayerDict[playerID] = [redPacketID, newCanGetRedID] + break + else: + return + + redPacketMgr.PrintData("b") + + syncRedPacketList = [redPacketID] + playerManager = GameWorld.GetPlayerManager() + + # 仙盟的直接同步该仙盟所有玩家 + if family: + for i in xrange(family.GetCount()): + notifyMember = family.GetAt(i) + player = playerManager.FindPlayerByID(notifyMember.GetPlayerID()) + if player == None or not player.GetInitOK() or PlayerControl.GetIsTJG(player): + continue + NotifyRedPacketInfo(player, syncRedPacketList) + + # 没有指定玩家,则通知全服玩家 + elif notifyPlayerDict == None: + for i in xrange(playerManager.GetActivePlayerCount()): + player = playerManager.GetActivePlayerAt(i) + if player == None or not player.GetInitOK() or PlayerControl.GetIsTJG(player): + continue + NotifyRedPacketInfo(player, syncRedPacketList) + + # 通知指定玩家 + else: + for playerID, syncRedPacketList in notifyPlayerDict.items(): + player = playerManager.FindPlayerByID(playerID) + if player == None or not player.GetInitOK() or PlayerControl.GetIsTJG(player): + continue + NotifyRedPacketInfo(player, syncRedPacketList) + return + +def DelRedPackByFamilyID(delfamilyID): + ## 删除仙盟的时候才需要删除红包,所以这里不做通知,重新加入仙盟时会重新同步一次 isAll 的情况 + + familyID = delfamilyID + redPacketMgr = GetRedpacketMgr() + if familyID not in redPacketMgr.familyRedPacketDict: + return + familyRedpacketIDList = redPacketMgr.familyRedPacketDict.pop(familyID) + + for redPacketID in familyRedpacketIDList: + if redPacketID in redPacketMgr.allRedPacketDict: + redPacketMgr.allRedPacketDict.pop(redPacketID) + + GameWorld.DebugLog("解散仙盟删除仙盟红包! familyID=%s, %s" % (familyID, familyRedpacketIDList)) return ##---------------------------------------- 节日红包 ----------------------------------------------- @@ -138,7 +757,7 @@ endDateTime = None validMinutes = ipyData.GetValidMinutes() if validMinutes: - endDateTime = openDateTime + + datetime.timedelta(minutes=validMinutes) + endDateTime = openDateTime + +datetime.timedelta(minutes=validMinutes) redPacketByTimeList.append([redPackID, openDateTime, endDateTime]) @@ -211,12 +830,13 @@ def RandTodayServerSystemRedPacketSendTime(): ## 随机生成今日全服系统红包发放时间点 - sendTimeList = [] sysRedPackketSendCountToday = PlayerDBGSEvent.GetDBGSTrig_ByKey(DBKey_RedPacketSystemDayCount) maxCount = IpyGameDataPY.GetFuncCfg("ServerSysRedPacket", 1) + if maxCount: + return needSendCount = max(0, maxCount - sysRedPackketSendCountToday) - + GameWorld.Log("随机生成发放全服系统红包时间! maxCount=%s,sysRedPackketSendCountToday=%s,needSendCount=%s" % (maxCount, sysRedPackketSendCountToday, needSendCount)) if needSendCount > 0: @@ -374,23 +994,7 @@ return ## 记录新红包数据 -def __SaveNewRedRecord(family, ownerid, playerName, job, jobRank, getType, moneyType, outputNum, packetCnt,state=State_NoSend, wishStr='', sysCreateTime=None, data=0, isAnonymous=0): - global g_allRecordDict - global g_redPackCountDict - recordType = ShareDefine.Def_UniversalGameRecType_FamilyRedPacketAllRecord - universalRecMgr = GameWorld.GetUniversalRecMgr() - recordList = universalRecMgr.GetTypeList(recordType) - for maxCountKeyNum, getTypeList in ShareDefine.RedPackMaxCountDict.items(): - if getType in getTypeList: - if not __CheckOSRedPacketCnt(recordList, maxCountKeyNum, getTypeList): - return - g_redPackCountDict[maxCountKeyNum] = g_redPackCountDict.get(maxCountKeyNum, 0) + 1 - GameWorld.DebugLog("当前红包数: g_redPackCountDict=%s" % g_redPackCountDict) - break - - familyID = family.GetID() if family else 0 - recData = recordList.AddRec() - +def __SaveNewRedRecord(family, ownerID, playerName, job, jobRank, getType, moneyType, outputNum, packetCnt, state=State_NoSend, wishStr='', sysCreateTime=None, data=0, isAnonymous=0): #红包唯一ID 从1开始累计 超过20亿则重新开始 # 红包唯一ID @@ -400,21 +1004,33 @@ redPacketID = 1 PlayerDBGSEvent.SetDBGSTrig_ByKey(DB_RedPacketID, redPacketID) + familyID = family.GetID() if family else 0 + curTimeNum = int(time.time()) - recData.SetTime(sysCreateTime if sysCreateTime else curTimeNum) # 为方便前端对比配表设置的发放红包时间,如果有配置的时间,则创建时间默认取配表的 - recData.SetValue1(redPacketID) #红包唯一ID - recData.SetValue2(familyID) #家族ID - recData.SetValue3(moneyType + outputNum * 10) #总额度*10+金钱类型 - recData.SetValue4(state) #是否已发 - recData.SetValue5(curTimeNum) #该时间为开放领取的时间,不一定等于创建时间 - recData.SetStrValue1('%s|%s|%s|%s'%(ownerid,playerName,job,getType)) #创建者ID|创建者名字|创建者职业|途径 - recData.SetStrValue2('%s|%s' % (packetCnt, int(isAnonymous)))#可抢总个数|是否匿名 - recData.SetStrValue3(wishStr)#祝福语 - g_allRecordDict[redPacketID] = recData - GameWorld.Log("生成新的红包: familyID=%s,redPacketID=%s,ownerid=%s,ownername=%s,getType=%s,moneyType=%s,outputNum=%s,packetCnt=%s" % (familyID, redPacketID, ownerid, playerName, getType, moneyType, outputNum, packetCnt)) + + redPacketMgr = GetRedpacketMgr() + redPacketObj = redPacketMgr.GetRedPacketObj(redPacketID, True) + redPacketObj.redPacketID = redPacketID + redPacketObj.familyID = familyID + redPacketObj.moneyType = moneyType + redPacketObj.moneyValue = outputNum + redPacketObj.state = state + redPacketObj.createTime = sysCreateTime if sysCreateTime else curTimeNum + redPacketObj.calcTime = curTimeNum + redPacketObj.playerID = ownerID + redPacketObj.playerName = playerName + redPacketObj.playerJob = job + redPacketObj.getWay = getType + redPacketObj.packetCnt = packetCnt + redPacketObj.isAnonymous = isAnonymous # 是否匿名 + redPacketObj.wish = wishStr + redPacketObj.grabDict = {} + + GameWorld.Log("生成新的红包: familyID=%s,redPacketID=%s,ownerID=%s,getType=%s,moneyType=%s,outputNum=%s,packetCnt=%s,state=%s,isAnonymous=%s" + % (familyID, redPacketID, ownerID, getType, moneyType, outputNum, packetCnt, state, isAnonymous)) #通知 - __NotifyFamilyRedPacketInfo(family, recData, []) + OnChangeRedPacketState(family, redPacketObj, None) if getType == ShareDefine.RedPackType_OpenServer: if not PlayerDBGSEvent.GetDBGSTrig_ByKey(PlayerDBGSEvent.Def_OSRedPacket): PlayerControl.WorldNotify(0, 'OpenRedBag2', [playerName, data, outputNum]) @@ -431,100 +1047,7 @@ and getType not in [ShareDefine.RedPackType_Server]: PlayerControl.WorldNotify(0, 'OSRedpackSfx', [getType]) - return recData - - -def __CheckOSRedPacketCnt(recordList, maxCountKeyNum, getTypeList): - global g_grabDataDict - global g_allRecordDict - global g_redPackCountDict - ##开服红包个数是否达上限 - curRedCnt = g_redPackCountDict.get(maxCountKeyNum, 0) - openServerRedPacketCnt = IpyGameDataPY.GetFuncCfg('OpenServerRedPacketCnt', 1) # 直接用开服红包这个配置作为通用配置 - if curRedCnt and curRedCnt < openServerRedPacketCnt + 10: - return True - allCnt = recordList.Count() - - curCnt = 0 - delRedPacketIDList = [] - for index in xrange(allCnt): - universalRecData = recordList.At(index) - strValue1 = universalRecData.GetStrValue1() - strValue1List = strValue1.split('|') - getWay = int(strValue1List[3]) - if getWay not in getTypeList: - continue - redPacketID = universalRecData.GetValue1() - curCnt += 1 - if len(delRedPacketIDList) < 10: - delRedPacketIDList.append(redPacketID) - elif curRedCnt: - break - if not delRedPacketIDList: - return True - if not curRedCnt: - curRedCnt = curCnt - - if curRedCnt < openServerRedPacketCnt + 10: - return True - - delCnt = 0 - for index in xrange(recordList.Count()): - dataIndex = index - delCnt - universalRecData = recordList.At(dataIndex) - delRedPacketID = universalRecData.GetValue1() - if delRedPacketID in delRedPacketIDList: - recordList.Delete(dataIndex) - delCnt +=1 - g_grabDataDict.pop(delRedPacketID, 0) - g_allRecordDict.pop(delRedPacketID, 0) - curRedCnt -= delCnt - - - recordType = ShareDefine.Def_UniversalGameRecType_FamilyRedPacketGrabRecord - universalRecMgr = GameWorld.GetUniversalRecMgr() - recordList = universalRecMgr.GetTypeList(recordType) - delCnt = 0 - for index in xrange(recordList.Count()): - dataIndex = index - delCnt - universalRecData = recordList.At(dataIndex) - if universalRecData.GetValue1() in delRedPacketIDList: - recordList.Delete(dataIndex) - delCnt +=1 - - #通知 - NotifyDelRedPacketInfo(delRedPacketIDList) - return True - -def __DelGrabRecord(): - #删除多余抢信息 - universalRecMgr = GameWorld.GetUniversalRecMgr() - allRecordList = universalRecMgr.GetTypeList(ShareDefine.Def_UniversalGameRecType_FamilyRedPacketAllRecord) - allCnt = allRecordList.Count() - redPacketIDList = [] - for index in xrange(allCnt): - universalRecData = allRecordList.At(index) - redPacketID = universalRecData.GetValue1() - redPacketIDList.append(redPacketID) - - recordType = ShareDefine.Def_UniversalGameRecType_FamilyRedPacketGrabRecord - recordList = universalRecMgr.GetTypeList(recordType) - delCnt = 0 - for index in xrange(recordList.Count()): - dataIndex = index - delCnt - universalRecData = recordList.At(dataIndex) - if universalRecData.GetValue1() not in redPacketIDList: - recordList.Delete(dataIndex) - delCnt +=1 - GameWorld.Log(' 删除多余抢红包信息 delCnt=%s'%delCnt) - return - -isdel = False -if not isdel: - __DelGrabRecord() - isdel = True - - + return redPacketObj def SendFamilyRedPacket(msgList): '''发系统赠送的红包,该红包已存在,只是状态未发放,由归属玩家自由选择发放时机''' @@ -533,15 +1056,13 @@ if not curPlayer: return - recDataList = __FindGrabRecData(ShareDefine.Def_UniversalGameRecType_FamilyRedPacketAllRecord,redPacketID) - - if not recDataList: + redPacketMgr = GetRedpacketMgr() + redPacketObj = redPacketMgr.GetRedPacketObj(redPacketID, False) + if not redPacketObj: return - recData=recDataList[0] - strValue1 = recData.GetStrValue1() - strValue1List = strValue1.split('|') - ownID = int(strValue1List[0]) - getWay = int(strValue1List[3]) + + ownID = redPacketObj.playerID + getWay = redPacketObj.getWay ipyData = IpyGameDataPY.GetIpyGameDataByCondition('FamilyRedPack', {'GetType':getWay}) if not ipyData: @@ -551,88 +1072,81 @@ GameWorld.DebugLog(' 发系统赠送的红包 权限不足!', playerID) return if playerID != ownID: - strValue1List[0] = str(playerID) - StrValue1 = '|'.join(strValue1List) - recData.SetStrValue1(StrValue1) + redPacketObj.playerID = playerID elif playerID != ownID: GameWorld.DebugLog(' 发系统赠送的红包 不是本人!', playerID) return - recData.SetValue4(State_NoGot) - recData.SetStrValue2('%s|%s' % (packetCnt, int(isAnonymous))) - #更新时间 - curTimeNum = int(time.time()) - recData.SetValue5(curTimeNum) - if recData.GetValue2() == 0: + beforeState = redPacketObj.state + redPacketObj.state = State_NoGot + redPacketObj.packetCnt = packetCnt + redPacketObj.isAnonymous = int(isAnonymous) + redPacketObj.calcTime = int(time.time()) + + if redPacketObj.familyID == 0: family = None else: family = curPlayer.GetFamily() if family == None: return - __NotifyFamilyRedPacketInfo(family, recData, []) + + OnChangeRedPacketState(family, redPacketObj, beforeState) return - -## 抢红包 def DoGrabFamilyRedPacket(curPlayer, msgList): - global g_grabDataDict + ## 抢红包 redPacketID, reqGetWay, canGrabCnt = msgList - playerID= curPlayer.GetPlayerID() - job = curPlayer.GetJob() - playerName = curPlayer.GetName() - - - recDataList = __FindGrabRecData(ShareDefine.Def_UniversalGameRecType_FamilyRedPacketAllRecord, redPacketID) - if not recDataList: - GameWorld.Log(' 未找到该仙盟红包记录redPacketID=%s'%redPacketID) + redPacketMgr = GetRedpacketMgr() + redPacketObj = redPacketMgr.GetRedPacketObj(redPacketID, False) + if not redPacketObj: + PlayerControl.NotifyCode(curPlayer, "该红包不存在!") return - redPacketRecData = recDataList[0] - state = redPacketRecData.GetValue4() + + playerID = curPlayer.GetPlayerID() + + state = redPacketObj.state + beforeState = state if state in [State_NoSend]: - GameWorld.DebugLog(" 该仙盟红包还未发送!",playerID) + GameWorld.DebugLog(" 该红包还未发送!", playerID) return - familyID = redPacketRecData.GetValue2() + + familyID = redPacketObj.familyID if familyID: curFamily = curPlayer.GetFamily() if curFamily == None: return else: curFamily = None - - value3 = redPacketRecData.GetValue3() - moneyType, totalMoney =value3%10, value3/10 - strValue2 = redPacketRecData.GetStrValue2() - strValue2List = strValue2.split('|') - packetCnt = int(strValue2List[0]) + + moneyType = redPacketObj.moneyType + totalMoney = redPacketObj.moneyValue + packetCnt = redPacketObj.packetCnt #找该红包的抢信息 - grabRecordDict = __GetGrabRecord(redPacketID) + grabRecordDict = redPacketObj.grabDict if playerID in grabRecordDict: GameWorld.DebugLog(" 该玩家已抢过此红包!", playerID) __NotifyGrabRedPacketInfo(curPlayer, redPacketID, grabRecordDict) return - if len(grabRecordDict) >= packetCnt: + outNum = sum([grabObj.getMoney for grabObj in grabRecordDict.values()]) #已被抢的钱 + remainNum = totalMoney - outNum #剩余的钱 + + if len(grabRecordDict) >= packetCnt or remainNum <= 0: GameWorld.DebugLog(" 红包已被抢完!", playerID) if state != State_HasAllGot: - redPacketRecData.SetValue4(State_HasAllGot) + redPacketObj.state = State_HasAllGot #GameWorld.DebugLog(" 纠正红包已抢完状态! state=%s,updState=%s" % (state, State_HasAllGot)) - __NotifyFamilyRedPacketInfo(curFamily, redPacketRecData, grabRecordDict.keys()) + OnChangeRedPacketState(curFamily, redPacketObj, beforeState) __NotifyGrabRedPacketInfo(curPlayer, redPacketID, grabRecordDict) return - outNum = sum([a[0] for a in grabRecordDict.values()]) #已被抢的钱 - remainNum = totalMoney - outNum #剩余的钱 - remainPacketCnt = packetCnt-len(grabRecordDict) - if remainNum < remainPacketCnt: - GameWorld.Log(' 该红包剩余的钱不够发 packetCnt =%s,totalMoney=%s,outNum=%s,remainMoney=%s,grabRecordDict=%s'%(packetCnt, totalMoney,outNum,remainNum, grabRecordDict)) - return - strValue1 = redPacketRecData.GetStrValue1() - strValue1List = strValue1.split('|') - getWay = int(strValue1List[3]) - owerID = int(strValue1List[0]) + remainPacketCnt = packetCnt - len(grabRecordDict) + + getWay = redPacketObj.getWay + owerID = redPacketObj.playerID isSelf = owerID == playerID if not isSelf and canGrabCnt != -1 and canGrabCnt <= 0: GameWorld.DebugLog(' 抢开服红包,次数不足!!') @@ -640,6 +1154,7 @@ if reqGetWay != getWay: GameWorld.ErrLog("领取的红包类型不一致,无法领取! reqGetWay=%s,getWay=%s" % (reqGetWay, getWay)) return + if getWay in [ShareDefine.RedPackType_OpenServer, ShareDefine.RedPackType_Server]: getNumformula = IpyGameDataPY.GetFuncCompileCfg('OpenRedRacketOutNum') elif getWay in ShareDefine.FeastRedPackType: @@ -648,23 +1163,25 @@ getNumformula = IpyGameDataPY.GetFuncCompileCfg('FamilyRedRacketOutNum') getMoney = eval(getNumformula) if remainPacketCnt > 1 else remainNum - GameWorld.DebugLog(" 该玩家抢到红包=%s!"%getMoney, playerID) - grabRecordDict[playerID] = [getMoney, playerName, job] - #新增一条抢的记录 - recType = ShareDefine.Def_UniversalGameRecType_FamilyRedPacketGrabRecord - valueList = [redPacketID, playerID, job, moneyType, getMoney] - strValueList = [playerName] - PlayerUniversalGameRec.MapServer_UniversalGameRec(None, recType, valueList, strValueList) - #{playerid:[抢到的钱,名字,job]} - g_grabDataDict[redPacketID] = grabRecordDict + getMoney = min(getMoney, remainNum) + remainNum -= getMoney + GameWorld.DebugLog(" 该玩家抢到红包=%s!" % getMoney, playerID) - if len(grabRecordDict) >= packetCnt: - redPacketRecData.SetValue4(State_HasAllGot) - - #通知该玩家红包抢结果 - __NotifyFamilyRedPacketInfo(curFamily, redPacketRecData, grabRecordDict.keys()) + # 新增抢的记录 + grabObj = RedPacketGrab(redPacketID, playerID) + grabObj.playerJob = curPlayer.GetJob() + grabObj.playerName = curPlayer.GetName() + grabObj.moneyType = moneyType + grabObj.getMoney = getMoney + grabRecordDict[playerID] = grabObj + + if len(grabRecordDict) >= packetCnt or remainNum <= 0: + redPacketObj.state = State_HasAllGot + OnChangeRedPacketState(curFamily, redPacketObj, beforeState) else: - NotifyRedPacketInfo(curPlayer, [redPacketRecData, grabRecordDict.keys()]) + if getWay in IpyGameDataPY.GetFuncEvalCfg("RedPacketSys", 1): + redPacketMgr.DelPlayerCanGetRedPacketID(playerID, getWay, redPacketID) + NotifyRedPacketInfo(curPlayer, [redPacketID]) __NotifyGrabRedPacketInfo(curPlayer, redPacketID, grabRecordDict) @@ -673,289 +1190,103 @@ curPlayer.MapServer_QueryPlayerResult(0, 0, "GrabFamilyRedPacketResult", result, len(result)) return getMoney - - -## 获取抢红包记录 -def __GetGrabRecord(redPacketID): - if redPacketID in g_grabDataDict: - return g_grabDataDict[redPacketID] - - recDataList = __FindGrabRecData(ShareDefine.Def_UniversalGameRecType_FamilyRedPacketGrabRecord, redPacketID) - if not recDataList: - return {} - grabRecordDict = {} - for recData in recDataList: #{playerid:[抢到的钱,名字,job]} - grabRecordDict[recData.GetValue2()] = [recData.GetValue5(), recData.GetStrValue1(), recData.GetValue3()] - - return grabRecordDict - -def __FindGrabRecData(recordType, redPacketID): - global g_allRecordDict - if recordType == ShareDefine.Def_UniversalGameRecType_FamilyRedPacketAllRecord: - if redPacketID in g_allRecordDict: - frecData = g_allRecordDict[redPacketID] - if frecData: - return [frecData] - - - recDataList = [] - universalRecMgr = GameWorld.GetUniversalRecMgr() - allRecordList = universalRecMgr.GetTypeList(recordType) - allCnt = allRecordList.Count() - for index in xrange(allCnt): - recData = allRecordList.At(index) - if recData.GetValue1() == redPacketID: - recDataList.append(recData) - if recordType == ShareDefine.Def_UniversalGameRecType_FamilyRedPacketAllRecord: - g_allRecordDict[redPacketID] = recData - break - return recDataList - -## 检查红包是否过期 -def __CheckGrabRecData(): - global g_grabDataDict - global g_allRecordDict - global g_redPackCountDict - g_redPackCountDict = {} - universalRecMgr = GameWorld.GetUniversalRecMgr() - allRecordList = universalRecMgr.GetTypeList(ShareDefine.Def_UniversalGameRecType_FamilyRedPacketAllRecord) - allCnt = allRecordList.Count() - curTimeNum = int(time.time()) - - rangeTime = 24*60*60 - backMoneyDict = {} - delRedPacketIDList = [] - familyIDList = [] - delCnt = 0 - for index in xrange(allCnt): - dataIndex = index - delCnt - universalRecData = allRecordList.At(dataIndex) - saveTime = universalRecData.GetValue5() - GameWorld.DebugLog(" 检查红包是否过期 curTime=%s,saveTime=%s,rangeTime=%s,redPacketID=%s"%(curTimeNum, saveTime, curTimeNum -saveTime,universalRecData.GetValue1())) - if curTimeNum -saveTime > rangeTime:#过期 - redPacketID = universalRecData.GetValue1() - - strValue1 = universalRecData.GetStrValue1() - strValue1List = strValue1.split('|') - playerID = strValue1List[0] - getWay = int(strValue1List[3]) - if playerID and getWay is ShareDefine.RedPackType_GoldPacket: - playerID = int(playerID) - grabRecordDict = __GetGrabRecord(redPacketID) - outNum = sum([a[0] for a in grabRecordDict.values()]) #已被抢的钱 - value3 = universalRecData.GetValue3() - moneyType, totalMoney =value3%10, value3/10 - remainMoney = totalMoney - outNum #剩余的钱 - #GameWorld.DebugLog(' outNum=%s,remainMoney=%s,moneyType=%s'%(outNum,remainMoney,moneyType)) - if moneyType ==1 and remainMoney: - backMoneyDict[playerID] = backMoneyDict.get(playerID, 0) + remainMoney - - delRedPacketIDList.append(redPacketID) - familyID=universalRecData.GetValue2() - if familyID not in familyIDList: - familyIDList.append(familyID) - - allRecordList.Delete(dataIndex) - delCnt +=1 - - if not delRedPacketIDList: - return - for redID in delRedPacketIDList: - g_grabDataDict.pop(redID, 0) - g_allRecordDict.pop(redID, 0) - recordType = ShareDefine.Def_UniversalGameRecType_FamilyRedPacketGrabRecord - recordList = universalRecMgr.GetTypeList(recordType) - - delCnt = 0 - for index in xrange(recordList.Count()): - dataIndex = index - delCnt - universalRecData = recordList.At(dataIndex) - if universalRecData.GetValue1() in delRedPacketIDList: - recordList.Delete(dataIndex) - delCnt +=1 - - - NotifyDelRedPacketInfo(delRedPacketIDList) - - - #返回玩家未被领取的仙玉 - if backMoneyDict: - for playerID, moneyNum in backMoneyDict.items(): - PlayerCompensation.SendMailByKey('RedPackBack', [playerID], [], [], moneyNum) - - return -def DelRedPackByFamilyID(delfamilyID): - global g_grabDataDict - global g_allRecordDict - #删除某个家族的红包记录 - universalRecMgr = GameWorld.GetUniversalRecMgr() - allRecordList = universalRecMgr.GetTypeList(ShareDefine.Def_UniversalGameRecType_FamilyRedPacketAllRecord) - allCnt = allRecordList.Count() - delRedPacketIDList = [] - delCnt = 0 - for index in xrange(allCnt): - dataIndex = index - delCnt - universalRecData = allRecordList.At(dataIndex) - familyID=universalRecData.GetValue2() - if delfamilyID != familyID: - continue - redPacketID = universalRecData.GetValue1() - delRedPacketIDList.append(redPacketID) - allRecordList.Delete(dataIndex) - delCnt +=1 - if not delRedPacketIDList: - return - for redID in delRedPacketIDList: - g_grabDataDict.pop(redID, 0) - g_allRecordDict.pop(redID, 0) - recordList = universalRecMgr.GetTypeList(ShareDefine.Def_UniversalGameRecType_FamilyRedPacketGrabRecord) - delCnt = 0 - for index in xrange(recordList.Count()): - dataIndex = index - delCnt - universalRecData = recordList.At(dataIndex) - if universalRecData.GetValue1() in delRedPacketIDList: - recordList.Delete(dataIndex) - delCnt +=1 - #NotifyDelRedPacketInfo(delRedPacketIDList) - return - -## 红包变更通知单个红包给对应战盟所有成员 -def __NotifyFamilyRedPacketInfo(family, redPacketRecData, grabHeroIDList): - syncPacketDataList = [redPacketRecData, grabHeroIDList] -# recordType = ShareDefine.Def_UniversalGameRecType_FamilyRedPacketAllRecord -# universalRecMgr = GameWorld.GetUniversalRecMgr() -# recordList = universalRecMgr.GetTypeList(recordType) -# for index in xrange(recordList.Count()): -# recData = recordList.At(index) -# familyID = recData.GetValue2() -# if familyID and family and family.GetID() != familyID: -# continue -# if redPacketID: -# if recData.GetValue1() == redPacketID: -# syncPacketDataList = [recData, grabHeroIDList] -# break -# else: -# syncPacketDataList.append(recData) - if not syncPacketDataList: - return - playerManager = GameWorld.GetPlayerManager() - if not family: - for i in xrange(0, playerManager.GetActivePlayerCount()): - curPlayer = playerManager.GetActivePlayerAt(i) - if curPlayer == None or not curPlayer.GetInitOK(): - continue - NotifyRedPacketInfo(curPlayer, syncPacketDataList) - else: - for i in xrange(0, family.GetCount()): - notifyMember = family.GetAt(i) - notifyPlayer = playerManager.FindPlayerByID(notifyMember.GetPlayerID()) - if notifyPlayer == None: - continue - NotifyRedPacketInfo(notifyPlayer, syncPacketDataList) - return - -## 通知红包信息 -# 通知玩家本战盟所有红包或单个红包 -def NotifyRedPacketInfo(curPlayer, packetDataList=[]): - if PlayerControl.GetIsTJG(curPlayer): - return - if not packetDataList: - syncPacketDataList = [] - recordType = ShareDefine.Def_UniversalGameRecType_FamilyRedPacketAllRecord - universalRecMgr = GameWorld.GetUniversalRecMgr() - recordList = universalRecMgr.GetTypeList(recordType) - for index in xrange(recordList.Count()): - recData = recordList.At(index) - familyID = recData.GetValue2() - if familyID and curPlayer.GetFamilyID() != familyID: - continue - grabRecordDict = __GetGrabRecord(recData.GetValue1()) - syncPacketDataList.append([recData, grabRecordDict.keys()]) - else: - syncPacketDataList = [packetDataList] - if not syncPacketDataList: - return - joinFamilyTime = PlayerFamily.GetPlayerJoinFamilyTime(curPlayer) - sendPack = ChPyNetSendPack.tagGCFamilyRedPacketInfo() - sendPack.Clear() - sendPack.IsAll = int(packetDataList==[]) - sendPack.RedPacketInfo = [] - - for packetData, grabHeroIDList in syncPacketDataList: - #仙盟红包只通知玩家进入仙盟后生成的红包 - #GameWorld.Log('1111packetData.GetValue2()=%s,joinFamilyTime=%s,packetData.GetValue5()=%s'%(packetData.GetValue2(),joinFamilyTime,packetData.GetValue5())) - if packetData.GetValue2() and joinFamilyTime and packetData.GetValue5() < joinFamilyTime: - continue - - packetInfo = ChPyNetSendPack.tagFRedPacketInfo() - packetInfo.Clear() - packetInfo.RedPacketID = packetData.GetValue1() - strValue1 = packetData.GetStrValue1() - strValue1List = strValue1.split('|') - if len(strValue1List) != 4: - return - playerID, playerName, job, getWay = strValue1List - packetInfo.PlayerID = int(playerID) - packetInfo.Name = playerName - packetInfo.Time = packetData.GetTime() - packetInfo.PlayeJob = int(job) - value3 = packetData.GetValue3() - packetInfo.MoneyType = value3 % 10 - packetInfo.MoneyNum = value3 / 10 - packetInfo.GetWay = int(getWay) - state = packetData.GetValue4() - - if curPlayer.GetPlayerID() in grabHeroIDList: - state = State_HasGot - if sendPack.IsAll and state in [State_HasGot, State_HasAllGot]: - #GameWorld.DebugLog("已抢或抢完的不发: RedPacketID=%s,state=%s" % (packetInfo.RedPacketID, state)) - continue - packetInfo.State = state - strValue2 = packetData.GetStrValue2() - strValue2List = strValue2.split('|') - packetInfo.PacketCnt = int(strValue2List[0]) - packetInfo.IsAnonymous = int(strValue2List[1]) if len(strValue2List) > 1 else 0 - - packetInfo.Wish = packetData.GetStrValue3() - sendPack.RedPacketInfo.append(packetInfo) - if len(sendPack.RedPacketInfo) > 250: - #GameWorld.DebugLog("红包太多了!") - break - - sendPack.Count = len(sendPack.RedPacketInfo) - NetPackCommon.SendFakePack(curPlayer, sendPack) - #GameWorld.Log('仙盟红包通知 IsAll=%s,Count=%s,syncPacketDataList=%s,redPacketID=%s'%(sendPack.IsAll,sendPack.Count,syncPacketDataList,redPacketID)) - return - - def __NotifyGrabRedPacketInfo(curPlayer, redPacketID, grabRecordDict): '''通知抢红包信息''' sendPack = ChPyNetSendPack.tagGCFamilyRedPacketGrabInfo() sendPack.Clear() sendPack.RedPacketID = redPacketID - #grabRecordDict = __GetGrabRecord(redPacketID) #{playerid:[抢到的钱,名字,job]} - sendPack.Count = len(grabRecordDict) sendPack.GrabInfo = [] - for playerID, info in grabRecordDict.items(): - money, name, job = info + for grabObj in grabRecordDict.values(): grabInfo = ChPyNetSendPack.tagFGrabRedPacketInfo() - grabInfo.Name = name - grabInfo.PlayeJob = job - grabInfo.MoneyNum = money + grabInfo.Name = grabObj.playerName + grabInfo.NameLen = len(grabInfo.Name) + grabInfo.PlayeJob = grabObj.playerJob + grabInfo.MoneyNum = grabObj.getMoney sendPack.GrabInfo.append(grabInfo) + sendPack.Count = len(sendPack.GrabInfo) NetPackCommon.SendFakePack(curPlayer, sendPack) return -def NotifyDelRedPacketInfo(delRedPacketIDList): - ##通知红包删除信息 - sendPack = ChPyNetSendPack.tagGCRedPacketDel() - sendPack.Clear() - sendPack.DelRedPacketID = delRedPacketIDList - sendPack.Cnt = len(delRedPacketIDList) - playerManager = GameWorld.GetPlayerManager() - for i in xrange(0, playerManager.GetActivePlayerCount()): - curPlayer = playerManager.GetActivePlayerAt(i) - if curPlayer == None or not curPlayer.GetInitOK(): +def NotifyRedPacketInfo(curPlayer, syncRedPacketIDList=None, isLogin=False): + ## 通知红包信息 + if PlayerControl.GetIsTJG(curPlayer): + return + + redPacketMgr = GetRedpacketMgr() + isAll = int(syncRedPacketIDList == None) + if syncRedPacketIDList == None: + syncRedPacketIDList = [] + + playerID = curPlayer.GetPlayerID() + family = curPlayer.GetFamily() + familyID = family.GetID() if family else 0 + + syncRedPacketIDList += redPacketMgr.familyRedPacketDict.get(familyID, []) # 1. 仙盟所有(含未开放的) + + syncRedPacketIDList += redPacketMgr.notifyAllServerRedPacketIDList # 2. 全服不限制下发个数 + + # 3. 全服私有未开放 + for redIDList in redPacketMgr.playerNosendRedPacketIDInfo.get(playerID, {}).values(): + syncRedPacketIDList += redIDList + + # 4. 全服限制下发个数分配给个人可领取的红包 + for redIDList in redPacketMgr.playerCanGetRedPacketIDInfo.get(playerID, {}).values(): + syncRedPacketIDList += redIDList + + if not syncRedPacketIDList and isLogin: + return + + redPacketInfo = [] + playerID = curPlayer.GetPlayerID() + joinFamilyTime = PlayerFamily.GetPlayerJoinFamilyTime(curPlayer) + GameWorld.DebugLog("通知红包信息: isLogin=%s,isAll=%s,syncRedPacketIDList=%s" % (isLogin, isAll, syncRedPacketIDList), playerID) + + for redPacketID in syncRedPacketIDList: + redPacketObj = redPacketMgr.GetRedPacketObj(redPacketID, False) + if not redPacketObj: continue - NetPackCommon.SendFakePack(curPlayer, sendPack) - return \ No newline at end of file + + #仙盟红包只通知玩家进入仙盟后生成的红包 + if redPacketObj.familyID: + if joinFamilyTime and redPacketObj.calcTime < joinFamilyTime: + GameWorld.DebugLog(" 加入仙盟之前的红包不发: redPacketID=%s,joinFamilyTime=%s > %s" % (redPacketID, joinFamilyTime, redPacketObj.calcTime)) + continue + + state = redPacketObj.state + if playerID in redPacketObj.grabDict: + state = State_HasGot + if isAll and state in [State_HasGot, State_HasAllGot]: + GameWorld.DebugLog(" 已抢或抢完的不发: redPacketID=%s,state=%s" % (redPacketID, state)) + continue + + packetInfo = ChPyNetSendPack.tagFRedPacketInfo() + packetInfo.Clear() + packetInfo.RedPacketID = redPacketObj.redPacketID + packetInfo.PlayerID = redPacketObj.playerID + packetInfo.Name = "" if redPacketObj.isAnonymous else redPacketObj.playerName + packetInfo.NameLen = len(packetInfo.Name) + packetInfo.Time = redPacketObj.createTime + packetInfo.PlayeJob = redPacketObj.playerJob + packetInfo.MoneyType = redPacketObj.moneyType + packetInfo.MoneyNum = redPacketObj.moneyValue + packetInfo.GetWay = redPacketObj.getWay + packetInfo.State = state + packetInfo.PacketCnt = redPacketObj.packetCnt + packetInfo.IsAnonymous = int(redPacketObj.isAnonymous) + packetInfo.Wish = redPacketObj.wish + packetInfo.WishLen = len(packetInfo.Wish) + redPacketInfo.append(packetInfo) + if len(redPacketInfo) > 250: + #GameWorld.DebugLog("红包太多了!") + break + + if not redPacketInfo: + return + + sendPack = ChPyNetSendPack.tagGCFamilyRedPacketInfo() + sendPack.Clear() + sendPack.IsAll = isAll + sendPack.RedPacketInfo = redPacketInfo + sendPack.Count = len(sendPack.RedPacketInfo) + NetPackCommon.SendFakePack(curPlayer, sendPack) + return -- Gitblit v1.8.0