ServerPython/CoreServerGroup/GameServer/Script/GameWorldLogic/CrossLuckyCloudBuy.py
@@ -21,10 +21,10 @@
import PlayerControl
import DataRecordPack
import PlayerCompensation
import CrossActionControl
import ChPyNetSendPack
import IpyGameDataPY
import NetPackCommon
import CrossRealmPK
import PyGameData
import ChConfig
@@ -53,7 +53,7 @@
幸运云购开奖记录
ShareDefine.Def_UniversalGameRecType_LuckyCloudBuyLottery
time:idTime                创建时间(也作为本轮唯一标识ID,用生成时间time值作为唯一ID)
value1:zoneID            分区ID
value1:cfgID*100+zoneID        配置ID*100 + 分区ID
value2:roundNum          今日第几轮
value3:luckyPlayerID     中奖玩家ID
value4:lotteryNum         开奖号码
@@ -92,6 +92,7 @@
    '''
    def __init__(self):
        self.idTime = 0
        self.cfgID = 0
        self.zoneID = 0
        self.roundNum = 0
        self.luckyPlayerID = 0
@@ -99,15 +100,15 @@
        self.lotteryTime = 0
        
        self.luckyPlayerName = ""
        self.serverGroupIDList = [] # 分区信息
        self.serverIDRangeList = [] # 分区信息
        self.superItemInfo = [] # 大奖信息
        self.luckyPlayerAccID = "" # 中奖玩家账号
        return
    
    def GetString(self):
        return {"idTime":self.idTime, "zoneID":self.zoneID, "roundNum":self.roundNum, "luckyPlayerID":self.luckyPlayerID,
        return {"idTime":self.idTime, "cfgID":self.cfgID, "zoneID":self.zoneID, "roundNum":self.roundNum, "luckyPlayerID":self.luckyPlayerID,
                "lotteryNum":self.lotteryNum, "lotteryTime":self.lotteryTime, "luckyPlayerName":self.luckyPlayerName, 
                "serverGroupIDList":self.serverGroupIDList, "superItemInfo":self.superItemInfo, "luckyPlayerAccID":self.luckyPlayerAccID}
                "serverIDRangeList":self.serverIDRangeList, "superItemInfo":self.superItemInfo, "luckyPlayerAccID":self.luckyPlayerAccID}
        
    def SetAttrByDict(self, attrDict):
        for k, v in attrDict.items():
@@ -155,10 +156,11 @@
    
    for index in xrange(recDataList.Count()):
        recData = recDataList.At(index)
        zoneID = recData.GetValue1()
        value1 = recData.GetValue1()
        cfgID, zoneID = value1 / 100, value1 % 100
        lotteryRec = LuckyCloudBuyLottery()
        lotteryRec.idTime = int(recData.GetTime())
        lotteryRec.cfgID = cfgID
        lotteryRec.zoneID = zoneID
        lotteryRec.roundNum = recData.GetValue2()
        lotteryRec.luckyPlayerID = recData.GetValue3()
@@ -167,10 +169,10 @@
        
        lotteryRec.luckyPlayerName = recData.GetStrValue1()
        strValue3 = recData.GetStrValue3()
        lotteryRec.serverGroupIDList, lotteryRec.superItemInfo, lotteryRec.luckyPlayerAccID = [], [], ""
        lotteryRec.serverIDRangeList, lotteryRec.superItemInfo, lotteryRec.luckyPlayerAccID = [], [], ""
        if strValue3:
            groupIDStr, superItemStr, accID = strValue3.split("|")
            lotteryRec.serverGroupIDList = eval(groupIDStr) if (groupIDStr.startswith("[") and groupIDStr.endswith("]")) else []
            serverIDStr, superItemStr, accID = strValue3.split("|")
            lotteryRec.serverIDRangeList = eval(serverIDStr) if (serverIDStr.startswith("[") and serverIDStr.endswith("]")) else []
            lotteryRec.superItemInfo = eval(superItemStr) if (superItemStr.startswith("[") and superItemStr.endswith("]")) else []
            lotteryRec.luckyPlayerAccID = accID
            
@@ -183,7 +185,6 @@
        lotteryRecList.sort(key=operator.attrgetter("idTime"))
        GameWorld.Log("    幸运云购分区开奖记录! zoneID=%s, count=%s" % (zoneID, len(lotteryRecList)))
        
    CheckLuckyCloudBuyZoneInfoChange()
    return
def OnServerClose():
@@ -219,14 +220,14 @@
        for lotteryRec in lotteryRecList:
            recData = recDataList.AddRec()
            recData.SetTime(lotteryRec.idTime)
            recData.SetValue1(lotteryRec.zoneID)
            recData.SetValue1(lotteryRec.cfgID * 100 + lotteryRec.zoneID)
            recData.SetValue2(lotteryRec.roundNum)
            recData.SetValue3(lotteryRec.luckyPlayerID)
            recData.SetValue4(lotteryRec.lotteryNum)
            recData.SetValue5(lotteryRec.lotteryTime)
            
            recData.SetStrValue1(lotteryRec.luckyPlayerName)
            recData.SetStrValue3("%s|%s|%s" % (str(lotteryRec.serverGroupIDList).replace(" ", ""),
            recData.SetStrValue3("%s|%s|%s" % (str(lotteryRec.serverIDRangeList).replace(" ", ""),
                                               str(lotteryRec.superItemInfo).replace(" ", ""), 
                                               lotteryRec.luckyPlayerAccID))
            
@@ -247,7 +248,7 @@
    MaxTime = 3 * 24 * 3600 # 最大保留近3天记录
    for zoneID, lotteryRecList in PyGameData.g_luckyCloudBuyLotteryDict.items():
        doCount = len(lotteryRecList)
        GameWorld.DebugLog("检查幸运云购分区开奖记录是否超时! zoneID=%s,count=%s" % (zoneID, doCount))
        GameWorld.DebugLog("检查幸运云购分区开奖记录是否超时! zoneID=%s,doCount=%s" % (zoneID, doCount))
        while lotteryRecList and doCount > 0:
            doCount -= 1
            lotteryRec = lotteryRecList[0]
@@ -269,99 +270,47 @@
    doLotteryBuyCountPer = IpyGameDataPY.GetFuncCfg("LuckyCloudBuySet", 3)
    doLotteryBuyCount = int(math.ceil(maxBuyCount * doLotteryBuyCountPer / 100.0))
    
    zoneLotteryInfo = {}
    for zoneID, lotteryRecList in PyGameData.g_luckyCloudBuyLotteryDict.items():
        if not lotteryRecList:
            continue
        lastLotteryRec = lotteryRecList[-1] # 取最后一个为最新一期
        cfgID = lastLotteryRec.cfgID
        if lastLotteryRec.lotteryNum:
            GameWorld.Log("OnDay已开奖进入新一天第一轮! zoneID=%s" % zoneID)
            DoStartNewRoundLuckyCloudBuy(zoneID, 1)
            GameWorld.Log("OnDay已开奖进入新一天第一轮! cfgID=%s,zoneID=%s" % (cfgID, zoneID))
            DoStartNewRoundLuckyCloudBuy(cfgID, 1)
            continue
        buyRecList = PyGameData.g_luckyCloudBuyNumDict.get(zoneID, [])
        buyCount = len(buyRecList)
        if len(buyRecList) >= doLotteryBuyCount:
            GameWorld.Log("OnDay未开奖但购买份数超过开奖保底份数! zoneID=%s,buyCount=%s >= %s" % (zoneID, buyCount, doLotteryBuyCount))
            GameWorld.Log("OnDay未开奖但购买份数超过开奖保底份数! cfgID=%s,zoneID=%s,buyCount=%s >= %s" % (cfgID, zoneID, buyCount, doLotteryBuyCount))
            DoLuckyCloudBuyLottery(lastLotteryRec, True, "OnDay")
            continue
        
        GameWorld.Log("已购买份数不足开奖保底份数,重置为新一天的第一轮! zoneID=%s,buyCount=%s < %s" % (zoneID, buyCount, doLotteryBuyCount))
        GameWorld.Log("已购买份数不足开奖保底份数,重置为新一天的第一轮! cfgID=%s,zoneID=%s,buyCount=%s < %s" % (cfgID, zoneID, buyCount, doLotteryBuyCount))
        lastLotteryRec.roundNum = 1
        dataDict = {"Type":"ResetRound"}
        dataDict.update(lastLotteryRec.GetString())
        DataRecordPack.SendEventPack("LuckyCloudBuyLottery", dataDict)
        zoneLotteryInfo[zoneID] = [lastLotteryRec.GetString()]
        
        # 广播子服轮次信息变更
        crossZoneName = GameWorld.GetCrossZoneName()
        zoneIpyData = IpyGameDataPY.GetIpyGameData("CrossZonePK", crossZoneName, zoneID)
        if zoneIpyData:
            serverGroupIDList = zoneIpyData.GetServerGroupIDList()
            zoneLotteryInfo = {zoneID:[lastLotteryRec.GetString()]}
            dataMsg = {"syncType":"Update", "zoneLotteryInfo":zoneLotteryInfo}
            CrossRealmMsg.SendMsgToClientServer(ShareDefine.CrossServerMsg_LuckyCloudBuyLottery, dataMsg, serverGroupIDList)
    return
def CheckLuckyCloudBuyZoneInfoChange():
    ## 检查云购分区配置变更
    if not GameWorld.IsCrossServer():
        return
    crossZoneName = GameWorld.GetCrossZoneName()
    crossZoneList = IpyGameDataPY.GetIpyGameDataByCondition("CrossZonePK", {"CrossZoneName":crossZoneName}, True)
    if not crossZoneList:
        return
    checkZoneInfo = {} # 分区调整可能变多、变少、或只调整范围,所以检查的分区要取配置及活动分区数据的所有分区汇总
    for zoneIpyData in crossZoneList:
        zoneID = zoneIpyData.GetZoneID()
        checkZoneInfo[zoneID] = zoneIpyData.GetServerGroupIDList()
    for zoneID in PyGameData.g_luckyCloudBuyLotteryDict.keys():
        if zoneID not in checkZoneInfo:
            checkZoneInfo[zoneID] = None
    haveChange = False
    for zoneID, serverGroupIDList in checkZoneInfo.items():
        lotteryRecList = PyGameData.g_luckyCloudBuyLotteryDict.get(zoneID, [])
        if lotteryRecList:
            lastLotteryRec = lotteryRecList[-1] # 取最后一个为最新一期
            if lastLotteryRec.lotteryNum:
                GameWorld.DebugLog("已开奖,不处理! zoneID=%s" % zoneID)
                continue
            if lastLotteryRec.serverGroupIDList != serverGroupIDList:
                GameWorld.Log("分区信息变更,强制开奖! zoneID=%s,recGroupIDList=%s,serverGroupIDList=%s"
                              % (zoneID, lastLotteryRec.serverGroupIDList, serverGroupIDList))
                DoLuckyCloudBuyLottery(lastLotteryRec, True, "ServerGroupIDChange")
                haveChange = True
            else:
                GameWorld.DebugLog("分区信息不变,不处理! zoneID=%s" % zoneID)
        else:
            GameWorld.Log("配置了新分区,开启新云购! zoneID=%s,serverGroupIDList=%s" % (zoneID, serverGroupIDList))
            DoStartNewRoundLuckyCloudBuy(zoneID, 1)
            haveChange = True
        if serverGroupIDList == None:
            GameWorld.Log("分区被删除! zoneID=%s" % zoneID)
            PyGameData.g_luckyCloudBuyLotteryDict.pop(zoneID, None)
            PyGameData.g_luckyCloudBuyNumDict.pop(zoneID, None)
    if haveChange:
        Sync_LuckyCloudBuyDataToClientServer(GameWorld.GetGameWorld().GetTick())
    # 广播子服轮次信息变更
    if zoneLotteryInfo:
        dataMsg = {"syncType":"Update", "zoneLotteryInfo":zoneLotteryInfo}
        CrossRealmMsg.SendMsgToClientServer(ShareDefine.CrossServerMsg_LuckyCloudBuyLottery, dataMsg)
    return
def DoLuckyCloudBuyLottery(lotteryRec, resetRound=False, sign=""):
    ## 云购开奖
    
    idTime = lotteryRec.idTime
    cfgID = lotteryRec.cfgID
    zoneID = lotteryRec.zoneID
    roundNum = lotteryRec.roundNum
    
    lotteryDateStr = GameWorld.ChangeTimeNumToStr(idTime, ChConfig.TYPE_Time_YmdFormat)
    GameWorld.Log("幸运云购开奖: idTime=%s(%s),zoneID=%s,roundNum=%s,resetRound=%s,sign=%s"
                  % (idTime, lotteryDateStr, zoneID, roundNum, resetRound, sign))
    GameWorld.Log("幸运云购开奖: idTime=%s(%s),cfgID=%s,zoneID=%s,roundNum=%s,resetRound=%s,sign=%s"
                  % (idTime, lotteryDateStr, cfgID, zoneID, roundNum, resetRound, sign))
    
    todayLuckyPlayerCountInfo = {} # 当日中奖玩家中奖次数信息 {playerID:count, ...}
    lotteryRecList = PyGameData.g_luckyCloudBuyLotteryDict.get(zoneID, [])
@@ -400,7 +349,6 @@
        playerNumList.append(buyRec.buyNum)
        
    GameWorld.Log("    本轮开奖饼图列表信息: buyCount=%s,randListLen=%s,maxRate=%s" % (len(buyRecList), len(randList), maxRate))
    luckyBuyRec = GameWorld.GetResultByRandomList(randList)
    if luckyBuyRec:
        GameWorld.Log("    幸运中奖号码记录: lotteryNum=%s, %s" % (luckyBuyRec.buyNum, luckyBuyRec.GetString()))
@@ -408,43 +356,47 @@
        lotteryRec.luckyPlayerName = luckyBuyRec.playerName
        lotteryRec.luckyPlayerAccID = luckyBuyRec.accID
        lotteryRec.lotteryNum = luckyBuyRec.buyNum
        lotteryRec.lotteryTime = int(time.time())
        
        dataDict = {"Type":"Lottery"}
        dataDict.update(lotteryRec.GetString())
        DataRecordPack.SendEventPack("LuckyCloudBuyLottery", dataDict)
        # 广播子服开奖信息
        crossZoneName = GameWorld.GetCrossZoneName()
        zoneIpyData = IpyGameDataPY.GetIpyGameData("CrossZonePK", crossZoneName, zoneID)
        if zoneIpyData:
            serverGroupIDList = zoneIpyData.GetServerGroupIDList()
            zoneLotteryInfo = {zoneID:[lotteryRec.GetString()]}
            dataMsg = {"syncType":"Update", "zoneLotteryInfo":zoneLotteryInfo}
            CrossRealmMsg.SendMsgToClientServer(ShareDefine.CrossServerMsg_LuckyCloudBuyLottery, dataMsg, serverGroupIDList)
        # 发邮件
        for playerID, buyNumList in playerNumListDict.items():
            if playerID == lotteryRec.luckyPlayerID:
                addItemList = [lotteryRec.superItemInfo[:3]] if len(lotteryRec.superItemInfo) >= 3 else []
                PlayerCompensation.SendMailByKey("LuckyCloudBuyWin", [playerID], addItemList, [lotteryRec.lotteryNum], crossMail=True)
            else:
                buyNums = GetMailBuyNums(buyNumList)
                PlayerCompensation.SendMailByKey("LuckyCloudBuyFail", [playerID], [], [lotteryRec.lotteryNum, buyNums], crossMail=True)
    else:
        GameWorld.ErrLog("    云购开奖异常! zoneID=%s" % zoneID)
        GameWorld.ErrLog("    云购无人购买或开奖异常! cfgID=%s,zoneID=%s" % (cfgID, zoneID))
        maxBuyCount = IpyGameDataPY.GetFuncCfg("LuckyCloudBuySet", 2)
        lotteryRec.lotteryNum = random.randint(1, maxBuyCount)
        GameWorld.Log("    随机中奖号码! lotteryNum=%s" % lotteryRec.lotteryNum)
    lotteryRec.lotteryTime = int(time.time())
    # 发邮件
    for playerID, buyNumList in playerNumListDict.items():
        if playerID == lotteryRec.luckyPlayerID:
            addItemList = [lotteryRec.superItemInfo[:3]] if len(lotteryRec.superItemInfo) >= 3 else []
            PlayerCompensation.SendMailByKey("LuckyCloudBuyWin", [playerID], addItemList, [lotteryRec.lotteryNum], crossMail=True)
        else:
            buyNums = GetMailBuyNums(buyNumList)
            PlayerCompensation.SendMailByKey("LuckyCloudBuyFail", [playerID], [], [lotteryRec.lotteryNum, buyNums], crossMail=True)
    dataDict = {"Type":"Lottery"}
    dataDict.update(lotteryRec.GetString())
    DataRecordPack.SendEventPack("LuckyCloudBuyLottery", dataDict)
    # 广播子服开奖信息
    zoneLotteryInfo = {zoneID:[lotteryRec.GetString()]}
    dataMsg = {"syncType":"Update", "zoneLotteryInfo":zoneLotteryInfo}
    CrossRealmMsg.SendMsgToClientServer(ShareDefine.CrossServerMsg_LuckyCloudBuyLottery, dataMsg)
    actInfoDict = CrossActionControl.GetCrossActInfoByCfgID(ShareDefine.CrossActName_LuckyCloudBuy, cfgID)
    if not actInfoDict or not actInfoDict[ShareDefine.ActKey_State]:
        GameWorld.Log("    不在活动中了,不开下一轮! cfgID=%s" % cfgID)
        return
        
    if roundNum >= IpyGameDataPY.GetFuncCfg("LuckyCloudBuySet", 1):
        GameWorld.Log("    当日已达每日云购轮数上限,不开下一轮! roundNum=%s" % roundNum)
        return
    
    nextRoundNum = 1 if resetRound else (roundNum + 1)
    GameWorld.Log("幸运云购开启下一轮! zoneID=%s,roundNum=%s,resetRound=%s,nextRoundNum=%s"
                  % (zoneID, roundNum, resetRound, nextRoundNum))
    GameWorld.Log("幸运云购开启下一轮! cfgID=%s,zoneID=%s,roundNum=%s,resetRound=%s,nextRoundNum=%s"
                  % (cfgID, zoneID, roundNum, resetRound, nextRoundNum))
    # 开始下一轮
    DoStartNewRoundLuckyCloudBuy(zoneID, nextRoundNum)
    return
    return DoStartNewRoundLuckyCloudBuy(cfgID, nextRoundNum)
def GetMailBuyNums(buyNumList):
    buyNumList.sort()
@@ -474,26 +426,60 @@
        
    return buyNums
def DoStartNewRoundLuckyCloudBuy(zoneID, roundNum):
def OnLuckyCloudBuyReset(ipyData, state):
    ## 云购重置
    cfgID = ipyData.GetCfgID()
    zoneID = ipyData.GetZoneID()
    startNewLottery = False
    lotteryRecList = PyGameData.g_luckyCloudBuyLotteryDict.get(zoneID, [])
    lastLotteryRec = None if not lotteryRecList else lotteryRecList[-1]
    if lastLotteryRec and not lastLotteryRec.lotteryNum:
        GameWorld.Log("幸运云购重置,当前轮次未开奖,直接开奖! cfgID=%s,zoneID=%s" % (lastLotteryRec.cfgID, zoneID))
        startNewLottery = DoLuckyCloudBuyLottery(lastLotteryRec, True, "Reset")
    if state and not startNewLottery:
        GameWorld.Log("幸运云购重置,当前没有未开奖的轮次,直接开启新一轮! cfgID=%s,zoneID=%s" % (cfgID, zoneID))
        DoStartNewRoundLuckyCloudBuy(cfgID, 1)
    return
def DoStartNewRoundLuckyCloudBuy(cfgID, roundNum):
    # 开启新一轮云购
    
    crossZoneName = GameWorld.GetCrossZoneName()
    zoneIpyData = IpyGameDataPY.GetIpyGameData("CrossZonePK", crossZoneName, zoneID)
    if not zoneIpyData:
    actInfoDict = CrossActionControl.GetCrossActInfoByCfgID(ShareDefine.CrossActName_LuckyCloudBuy, cfgID)
    if not actInfoDict or not actInfoDict[ShareDefine.ActKey_State]:
        GameWorld.ErrLog("幸运云购非活动中,无法开启! cfgID=%s, roundNum=%s" % (cfgID, roundNum))
        return
    serverGroupIDList = zoneIpyData.GetServerGroupIDList()
    
    superItemInfo = GameWorld.GetResultByRandomList(IpyGameDataPY.GetFuncEvalCfg("LuckyCloudBuyAward", 3), [])
    actIpyData = IpyGameDataPY.GetIpyGameData("CrossActLuckyCloudBuy", cfgID)
    if not actIpyData:
        return
    zoneID = actIpyData.GetZoneID()
    serverIDRangeList = actIpyData.GetServerIDRangeList()
    templateIDList = actIpyData.GetTemplateIDList()
    if not templateIDList:
        return
    dayIndex = actInfoDict.get(ShareDefine.ActKey_DayIndex, 0)
    templateID = templateIDList[dayIndex] if len(templateIDList) > dayIndex else templateIDList[-1]
    templateIpyData = IpyGameDataPY.GetIpyGameData("CrossActLuckyCloudBuyTemplate", templateID)
    if not templateIpyData:
        return
    superItemWeightInfo = templateIpyData.GetSuperItemWeightInfo()
    superItemInfo = GameWorld.GetResultByWeightList(superItemWeightInfo)
    if not superItemInfo or len(superItemInfo) < 3:
        GameWorld.ErrLog("幸运云购生成大奖失败! zoneID=%s,roundNum=%s,superItemInfo=%s" % (zoneID, roundNum, superItemInfo))
        return
    
    lotteryRec = LuckyCloudBuyLottery()
    lotteryRec.idTime = int(time.time())
    lotteryRec.cfgID = cfgID
    lotteryRec.zoneID = zoneID
    lotteryRec.roundNum = roundNum
    
    lotteryRec.serverGroupIDList = serverGroupIDList
    lotteryRec.serverIDRangeList = serverIDRangeList
    lotteryRec.superItemInfo = superItemInfo
    
    if zoneID not in PyGameData.g_luckyCloudBuyLotteryDict:
@@ -510,24 +496,11 @@
    # 广播子服开奖信息
    zoneLotteryInfo = {zoneID:[lotteryRec.GetString()]}
    dataMsg = {"syncType":"New", "zoneLotteryInfo":zoneLotteryInfo}
    CrossRealmMsg.SendMsgToClientServer(ShareDefine.CrossServerMsg_LuckyCloudBuyLottery, dataMsg, serverGroupIDList)
    return
    CrossRealmMsg.SendMsgToClientServer(ShareDefine.CrossServerMsg_LuckyCloudBuyLottery, dataMsg)
    return True
def Sync_LuckyCloudBuyDataToClientServer(tick, serverGroupID=0):
    GameWorld.Log("同步给子服对应的幸运云购信息: syncServerGroupID=%s" % (serverGroupID))
    if serverGroupID:
        ipyData = CrossRealmPK.GetCrossPKServerGroupZone(serverGroupID)
        if not ipyData:
            return
        crossZoneList = [ipyData]
    else:
        crossZoneName = GameWorld.GetCrossZoneName()
        crossZoneList = IpyGameDataPY.GetIpyGameDataByCondition("CrossZonePK", {"CrossZoneName":crossZoneName}, True)
    if not crossZoneList:
        return
    #注: 开奖记录同步所有分区的开奖内容;购买记录仅同步自己分区的记录即可
    
    # 开奖记录
    zoneLotteryInfo = {}
@@ -537,22 +510,18 @@
            zoneLotteryList.append(lotteryRec.GetString())
        zoneLotteryInfo[zoneID] = zoneLotteryList
        
    for zoneIpyData in crossZoneList:
        zoneID = zoneIpyData.GetZoneID()
        serverGroupIDList = [serverGroupID] if serverGroupID else zoneIpyData.GetServerGroupIDList()
        dataMsg = {"syncType":"All", "zoneLotteryInfo":zoneLotteryInfo}
        CrossRealmMsg.SendMsgToClientServer(ShareDefine.CrossServerMsg_LuckyCloudBuyLottery, dataMsg, serverGroupIDList)
        # 购买记录
    dataMsg = {"syncType":"All", "zoneLotteryInfo":zoneLotteryInfo}
    CrossRealmMsg.SendMsgToClientServer(ShareDefine.CrossServerMsg_LuckyCloudBuyLottery, dataMsg)
    # 购买记录
    for zoneID in PyGameData.g_luckyCloudBuyLotteryDict.keys():
        zoneBuyNumList = []
        buyRecList = PyGameData.g_luckyCloudBuyNumDict.get(zoneID, [])
        for buyRec in buyRecList:
            zoneBuyNumList.append(buyRec.GetString())
            
        dataMsg = {"syncType":"All", "zoneID":zoneID, "zoneBuyNumList":zoneBuyNumList}
        CrossRealmMsg.SendMsgToClientServer(ShareDefine.CrossServerMsg_LuckyCloudBuyNum, dataMsg, serverGroupIDList)
        CrossRealmMsg.SendMsgToClientServer(ShareDefine.CrossServerMsg_LuckyCloudBuyNum, dataMsg)
        
    return
@@ -563,12 +532,9 @@
    zoneLotteryInfo = msgData["zoneLotteryInfo"]
    
    serverGroupID = GameWorld.GetServerGroupID()
    zoneIpyData = CrossRealmPK.GetCrossPKServerGroupZone(serverGroupID)
    if not zoneIpyData:
        return
    serverZoneID = zoneIpyData.GetZoneID()
    serverZoneID = CrossActionControl.GetCrossActZoneID(ShareDefine.CrossActName_LuckyCloudBuy, serverGroupID)
    syncMapLotteryRec = None # 有需要同步地图的,即有本分区的数据同步
    GameWorld.Log("收到分区云购开奖记录同步信息: syncType=%s,serverZoneID=%s,zoneCount=%s" % (syncType, serverZoneID, len(zoneLotteryInfo)))
    
    if syncType == "All":
        PyGameData.g_luckyCloudBuyLotteryDict = {}
@@ -577,7 +543,7 @@
        if zoneID not in PyGameData.g_luckyCloudBuyLotteryDict:
            PyGameData.g_luckyCloudBuyLotteryDict[zoneID] = []
        lotteryRecList = PyGameData.g_luckyCloudBuyLotteryDict[zoneID]
        GameWorld.Log("收到分区云购开奖记录同步信息: syncType=%s,zoneID=%s,count=%s" % (syncType, zoneID, zoneLotteryList))
        GameWorld.Log("    分区云购开奖记录同步信息: syncType=%s,zoneID=%s,count=%s" % (syncType, zoneID, zoneLotteryList))
        for attrDict in zoneLotteryList:
            if syncType in ["All", "New"]:
                lotteryRec = LuckyCloudBuyLottery()
@@ -588,7 +554,7 @@
                    
                # 本分区新轮次
                if syncType == "New" and zoneID == serverZoneID:
                    GameWorld.Log("    新增云购开奖记录信息: idTime=%s" % lotteryRec.idTime)
                    GameWorld.Log("        本服分区新增云购开奖记录信息: idTime=%s" % lotteryRec.idTime)
                    PyGameData.g_luckyCloudBuyNumDict[zoneID] = []
                    if len(lotteryRec.superItemInfo) >= 2:
                        superItemID, superItemCount = lotteryRec.superItemInfo[0], lotteryRec.superItemInfo[1]
@@ -607,6 +573,7 @@
                        
                        # 本分区开奖记录同步
                        if lotteryRec.lotteryNum:
                            GameWorld.Log("        本服分区更新云购开奖记录信息: idTime=%s" % lotteryRec.idTime)
                            if len(lotteryRec.superItemInfo) >= 2:
                                superItemID, superItemCount = lotteryRec.superItemInfo[0], lotteryRec.superItemInfo[1]
                                PlayerControl.WorldNotify(0, "LuckyCloudBuyClose", [lotteryRec.lotteryNum, lotteryRec.luckyPlayerName, superItemID, superItemCount])
@@ -627,10 +594,9 @@
        return
    
    serverGroupID = GameWorld.GetServerGroupID()
    zoneIpyData = CrossRealmPK.GetCrossPKServerGroupZone(serverGroupID)
    if not zoneIpyData:
    zoneID = CrossActionControl.GetCrossActZoneID(ShareDefine.CrossActName_LuckyCloudBuy, serverGroupID)
    if not zoneID:
        return
    zoneID = zoneIpyData.GetZoneID()
    
    lotteryRecList = PyGameData.g_luckyCloudBuyLotteryDict.get(zoneID, [])
    lastLotteryRec = None if not lotteryRecList else lotteryRecList[-1]
@@ -642,10 +608,9 @@
def ClientServerMsg_LuckyCloudBuy(serverGroupID, msgData):
    ## 收到子服请求幸运云购购买
    
    zoneIpyData = CrossRealmPK.GetCrossPKServerGroupZone(serverGroupID)
    if not zoneIpyData:
    zoneID = CrossActionControl.GetCrossActZoneID(ShareDefine.CrossActName_LuckyCloudBuy, serverGroupID)
    if not zoneID:
        return
    zoneID = zoneIpyData.GetZoneID()
    
    accID = msgData["accID"]
    playerID = msgData["playerID"]
@@ -709,8 +674,7 @@
    
    # 通知子服
    dataMsg = {"syncType":"New", "zoneID":zoneID, "zoneBuyNumList":zoneBuyNumList, "buyPlayer":[serverGroupID, playerID, roundID, buyCount]}
    serverGroupIDList = zoneIpyData.GetServerGroupIDList()
    CrossRealmMsg.SendMsgToClientServer(ShareDefine.CrossServerMsg_LuckyCloudBuyNum, dataMsg, serverGroupIDList)
    CrossRealmMsg.SendMsgToClientServer(ShareDefine.CrossServerMsg_LuckyCloudBuyNum, dataMsg)
    
    # 结算开奖
    if remainCount == buyCount:
@@ -720,11 +684,10 @@
def DoGMLuckyCloudBuy(serverGroupID, buyCount):
    GameWorld.Log("GM添加云购记录! serverGroupID=%s,buyCount=%s" % (serverGroupID, buyCount))
    zoneIpyData = CrossRealmPK.GetCrossPKServerGroupZone(serverGroupID)
    if not zoneIpyData:
    zoneID = CrossActionControl.GetCrossActZoneID(ShareDefine.CrossActName_LuckyCloudBuy, serverGroupID)
    if not zoneID:
        return
    zoneID = zoneIpyData.GetZoneID()
    
    lotteryRecList = PyGameData.g_luckyCloudBuyLotteryDict.get(zoneID, [])
    if not lotteryRecList:
@@ -736,7 +699,7 @@
    remainCount = max(0, maxBuyCount - len(buyRecList))
    buyCount = min(buyCount, remainCount)
    if buyCount <= 0:
        GameWorld.ErrLog("GM幸运云购购买异常!剩余可购买的份数不足!buyCount=%s" % buyCount)
        GameWorld.ErrLog("GM幸运云购购买异常!剩余可购买的份数不足!zoneID=%s,buyCount=%s" % (zoneID, buyCount))
        return
    
    preBuyRec = None if not buyRecList else buyRecList[-1]
@@ -766,8 +729,7 @@
        
    # 通知子服
    dataMsg = {"syncType":"New", "zoneID":zoneID, "zoneBuyNumList":zoneBuyNumList}
    serverGroupIDList = zoneIpyData.GetServerGroupIDList()
    CrossRealmMsg.SendMsgToClientServer(ShareDefine.CrossServerMsg_LuckyCloudBuyNum, dataMsg, serverGroupIDList)
    CrossRealmMsg.SendMsgToClientServer(ShareDefine.CrossServerMsg_LuckyCloudBuyNum, dataMsg)
    
    # 结算开奖
    if remainCount == buyCount:
@@ -780,6 +742,20 @@
    syncType = msgData["syncType"] # All New
    zoneID = msgData["zoneID"]
    zoneBuyNumList = msgData["zoneBuyNumList"]
    curServerGroupID = GameWorld.GetServerGroupID()
    actInfo = CrossActionControl.GetCrossActInfoByServerGroupID(ShareDefine.CrossActName_LuckyCloudBuy, curServerGroupID)
    if not actInfo:
        return
    state = actInfo.get(ShareDefine.ActKey_State)
    ipyDataInfo = actInfo.get(ShareDefine.ActKey_IpyDataInfo)
    if not state or not ipyDataInfo:
        return
    serverZoneID = ipyDataInfo.get("ZoneID")
    if zoneID != serverZoneID:
        GameWorld.DebugLog("不是本服务器分区的云购记录不处理! curServerGroupID=%s,serverZoneID(%s) != zoneID(%s)"
                           % (curServerGroupID, serverZoneID, zoneID))
        return
    
    if syncType == "All":
        PyGameData.g_luckyCloudBuyNumDict = {}
@@ -795,9 +771,7 @@
        buyRecList.append(buyRec)
        if syncType == "New":
            syncRecList.append(buyRec)
    if syncType == "New":
        Sync_LuckyCloudBuyRoundInfo(None)
    if syncRecList:
        Sync_LuckyCloudBuyNumRecInfo(None, syncRecList)
        
@@ -805,21 +779,49 @@
    if not buyPlayer:
        return
    serverGroupID, playerID, roundID, buyCount = buyPlayer
    curServerGroupID = GameWorld.GetServerGroupID()
    if curServerGroupID != serverGroupID:
        #GameWorld.DebugLog("非本服玩家购买云购,不通知地图玩家处理!curServerGroupID=%s,buyPlayerServerGroupID=%s"
        #                   % (curServerGroupID, serverGroupID), playerID)
    if serverGroupID != curServerGroupID:
        return
    
    templateIDList = ipyDataInfo.get("TemplateIDList")
    if not templateIDList:
        return
    dayIndex = actInfo.get(ShareDefine.ActKey_DayIndex, 0)
    templateID = templateIDList[dayIndex] if len(templateIDList) > dayIndex else templateIDList[-1]
    templateIpyData = IpyGameDataPY.GetIpyGameData("CrossActLuckyCloudBuyTemplate", templateID)
    if not templateIpyData:
        return
    baseAwardInfo = templateIpyData.GetBaseAwardInfo()
    randAwardWeightInfo = templateIpyData.GetRandAwardWeightInfo()
    awardItemDict = {}
    for _ in xrange(buyCount):
        awardItemInfo = []
        awardItemInfo += baseAwardInfo
        randItemInfo = GameWorld.GetResultByWeightList(randAwardWeightInfo)
        if randItemInfo:
            awardItemInfo += [randItemInfo]
        for itemID, itemCount, isBind in awardItemInfo:
            if itemID not in awardItemDict:
                awardItemDict[itemID] = [itemCount, isBind]
            else:
                awardItemDict[itemID] = [awardItemDict[itemID][0] + itemCount, isBind]
    awardItemList = []
    for itemID in awardItemDict.keys():
        itemCount, isBind = awardItemDict[itemID]
        awardItemList.append([itemID, itemCount, isBind])
    player = GameWorld.GetPlayerManager().FindPlayerByID(playerID)
    if not player:
        GameWorld.Log("玩家不在线先缓存,玩家上线后再同步云购! roundID=%s,buyCount=%s" % (roundID, buyCount), playerID)
        PyGameData.g_unNotifyCloudBuyNumDict[playerID] = [roundID, buyCount]
        GameWorld.Log("玩家不在线先缓存,玩家上线后再同步云购! roundID=%s,buyCount=%s,awardItemList=%s"
                      % (roundID, buyCount, awardItemList), playerID)
        PyGameData.g_unNotifyCloudBuyNumDict[playerID] = [roundID, buyCount, awardItemList]
        return
    
    mapID = player.GetRealMapID()
    sysMsg = str(["LuckyCloudBuyNum", roundID, buyCount])
    sysMsg = str(["LuckyCloudBuyNum", roundID, buyCount, awardItemList])
    player.MapServer_QueryPlayerResult(0, 0, "LuckyCloudBuy", sysMsg, len(sysMsg))
    GameWorld.Log("通知地图跨服云购购买结算: roundID=%s,buyCount=%s,mapID=%s" % (roundID, buyCount, mapID), playerID)
    return
@@ -828,10 +830,10 @@
    playerID = curPlayer.GetPlayerID()
    if playerID not in PyGameData.g_unNotifyCloudBuyNumDict:
        return
    roundID, buyCount = PyGameData.g_unNotifyCloudBuyNumDict.pop(playerID)
    roundID, buyCount, awardItemList = PyGameData.g_unNotifyCloudBuyNumDict.pop(playerID)
    
    mapID = curPlayer.GetRealMapID()
    sysMsg = str(["LuckyCloudBuyNum", roundID, buyCount])
    sysMsg = str(["LuckyCloudBuyNum", roundID, buyCount, awardItemList])
    curPlayer.MapServer_QueryPlayerResult(0, 0, "LuckyCloudBuy", sysMsg, len(sysMsg))
    GameWorld.Log("上线补通知地图跨服云购购买结算: roundID=%s,buyCount=%s,mapID=%s" % (roundID, buyCount, mapID), playerID)
    return
@@ -854,7 +856,7 @@
#struct    tagCGQueryLuckyCloudBuyLotteryRec
#{
#    tagHead        Head;
#    BYTE        ZoneID;    //查询分区ID,分区同跨服PK分区
#    BYTE        ZoneID;    //查询分区ID
#};
def OnQueryLuckyCloudBuyLotteryRec(index, clientData, tick):
    curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index)
@@ -865,30 +867,65 @@
    return
def Sync_LuckyCloudBuyRoundInfo(curPlayer):
    ## 通知活动中的云购活动信息
    serverGroupID = GameWorld.GetServerGroupID()
    zoneIpyData = CrossRealmPK.GetCrossPKServerGroupZone(serverGroupID)
    if not zoneIpyData:
    actInfo = CrossActionControl.GetCrossActInfoByServerGroupID(ShareDefine.CrossActName_LuckyCloudBuy, serverGroupID)
    if not actInfo:
        return
    zoneID = zoneIpyData.GetZoneID()
    state = actInfo.get(ShareDefine.ActKey_State)
    ipyDataInfo = actInfo.get(ShareDefine.ActKey_IpyDataInfo)
    if not state or not ipyDataInfo:
        return
    zoneID = ipyDataInfo.get("ZoneID")
    if not zoneID:
        return
    templateIDList = ipyDataInfo.get("TemplateIDList")
    if not templateIDList:
        return
    dayIndex = actInfo.get(ShareDefine.ActKey_DayIndex, 0)
    templateID = templateIDList[dayIndex] if len(templateIDList) > dayIndex else templateIDList[-1]
    templateIpyData = IpyGameDataPY.GetIpyGameData("CrossActLuckyCloudBuyTemplate", templateID)
    if not templateIpyData:
        return
    baseAwardInfo = templateIpyData.GetBaseAwardInfo()
    randAwardWeightInfo = templateIpyData.GetRandAwardWeightInfo()
    
    lotteryRecList = PyGameData.g_luckyCloudBuyLotteryDict.get(zoneID, [])
    lotteryRec = None if not lotteryRecList else lotteryRecList[-1] # 取最新一期的
    if not lotteryRec:
        return
    
    buyRecList = PyGameData.g_luckyCloudBuyNumDict.get(zoneID, [])
    maxBuyCount = IpyGameDataPY.GetFuncCfg("LuckyCloudBuySet", 2)
    superItemInfo = lotteryRec.superItemInfo + [0, 0, 0, 0, 0]
    superItemID, superItemCount, _, moneyType, moneyValue = superItemInfo[:5]
    clientPack = ChPyNetSendPack.tagGCLuckyCloudBuyRoundInfo()
    clientPack.ZoneID = zoneID
    clientPack.StartDate = ipyDataInfo.get("StartDate", "")
    clientPack.EndtDate = ipyDataInfo.get("EndDate", "")
    clientPack.RoundID = lotteryRec.idTime
    clientPack.RoundNum = lotteryRec.roundNum
    clientPack.SuperItemID = superItemID
    clientPack.SuperItemCount = superItemCount
    clientPack.SuperItemMoneyType = moneyType
    clientPack.SuperItemMoneyValue = moneyValue
    clientPack.RemainCount = max(0, maxBuyCount - len(buyRecList))
    clientPack.BaseItemList = []
    for itemID, itemCount, isBind in baseAwardInfo:
        item = ChPyNetSendPack.tagGCLuckyCloudBuyRoundItem()
        item.ItemID = itemID
        item.ItemCount = itemCount
        item.IsBind = isBind
        clientPack.BaseItemList.append(item)
    clientPack.BaseItemCount = len(clientPack.BaseItemList)
    clientPack.RandItemList = []
    for _, itemID, itemCount, isBind in randAwardWeightInfo:
        item = ChPyNetSendPack.tagGCLuckyCloudBuyRoundItem()
        item.ItemID = itemID
        item.ItemCount = itemCount
        item.IsBind = isBind
        clientPack.RandItemList.append(item)
    clientPack.RandItemCount = len(clientPack.RandItemList)
    
    if not curPlayer:
        playerManager = GameWorld.GetPlayerManager()
@@ -907,23 +944,23 @@
    return
def Sync_LuckyCloudBuyNumRecInfo(curPlayer, syncRecList=None):
    ## 通知活动中的云购活动购买记录信息
    
    if syncRecList == None:
        serverGroupID = GameWorld.GetServerGroupID()
        zoneIpyData = CrossRealmPK.GetCrossPKServerGroupZone(serverGroupID)
        if not zoneIpyData:
            return
        zoneID = zoneIpyData.GetZoneID()
    serverGroupID = GameWorld.GetServerGroupID()
    zoneID = CrossActionControl.GetCrossActZoneID(ShareDefine.CrossActName_LuckyCloudBuy, serverGroupID)
    buyRecList = PyGameData.g_luckyCloudBuyNumDict.get(zoneID, [])
        
    if syncRecList == None:
        lotteryRecList = PyGameData.g_luckyCloudBuyLotteryDict.get(zoneID, [])
        lotteryRec = None if not lotteryRecList else lotteryRecList[-1] # 取最新一期的
        if not lotteryRec:
            return
        buyRecList = PyGameData.g_luckyCloudBuyNumDict.get(zoneID, [])
        syncRecList = buyRecList[-50:]
        
    maxBuyCount = IpyGameDataPY.GetFuncCfg("LuckyCloudBuySet", 2)
    clientPack = ChPyNetSendPack.tagGCLuckyCloudBuyNumRecInfo()
    clientPack.RemainCount = max(0, maxBuyCount - len(buyRecList))
    clientPack.BuyNumRecList = []
    for buyRec in syncRecList:
        buyNumInfo = ChPyNetSendPack.tagGCLuckyCloudBuyNumRec()
@@ -933,7 +970,7 @@
        clientPack.BuyNumRecList.append(buyNumInfo)
        
    clientPack.Count = len(clientPack.BuyNumRecList)
    if not curPlayer:
        playerManager = GameWorld.GetPlayerManager()
        for i in xrange(playerManager.GetActivePlayerCount()):
@@ -950,6 +987,7 @@
    return
def Sync_LuckyCloudBuyLotteryRecInfo(curPlayer, zoneID, syncRec=None):
    ## 通知云购活动分区历史开奖信息
    
    if syncRec == None:        
        lotteryRecList = PyGameData.g_luckyCloudBuyLotteryDict.get(zoneID, [])
@@ -957,6 +995,8 @@
        lotteryRecList = [syncRec]
        
    clientPack = ChPyNetSendPack.tagGCLuckyCloudBuyLotteryRecInfo()
    clientPack.ZoneIDList = PyGameData.g_luckyCloudBuyLotteryDict.keys()
    clientPack.ZoneCount = len(clientPack.ZoneIDList)
    clientPack.ZoneID = zoneID
    clientPack.LotteryRecList = []
    for lotteryRec in lotteryRecList: