From 69871482099a1c7022cad6c8d8cd90d3b163f0f2 Mon Sep 17 00:00:00 2001
From: hxp <ale99527@vip.qq.com>
Date: 星期二, 25 十二月 2018 21:11:32 +0800
Subject: [PATCH] 5424 【后端】【1.4】跨服竞技场开发(增加赛季时间管理、赛区赛季榜单、玩家各种PK数据、各种奖励领取及邮件补发、王者法宝等级)

---
 ServerPython/CoreServerGroup/GameServer/Script/GameWorldLogic/CrossRealmPK.py |  784 +++++++++++++++++++++++++++++++++++++++++++++++++++++--
 1 files changed, 755 insertions(+), 29 deletions(-)

diff --git a/ServerPython/CoreServerGroup/GameServer/Script/GameWorldLogic/CrossRealmPK.py b/ServerPython/CoreServerGroup/GameServer/Script/GameWorldLogic/CrossRealmPK.py
index 9d4f853..24fca7d 100644
--- a/ServerPython/CoreServerGroup/GameServer/Script/GameWorldLogic/CrossRealmPK.py
+++ b/ServerPython/CoreServerGroup/GameServer/Script/GameWorldLogic/CrossRealmPK.py
@@ -18,19 +18,22 @@
 import GameWorld
 import PlayerControl
 import CrossRealmMsg
-import CrossRealmPlayer
 import ChPyNetSendPack
+import CrossRealmPlayer
+import PyGameDataStruct
+import PlayerDBGSEvent
+import PyDataManager
 import NetPackCommon
 import IpyGameDataPY
 import ShareDefine
 import PyGameData
+import CommFunc
 import ChConfig
 
+import datetime
 import operator
 import random
-    
-PKPlayerState_Matching = 0
-PKPlayerState_Fighting = 1
+import time
 
 class CrossPKPlayer():
     ## 跨服PK玩家类
@@ -43,6 +46,7 @@
         self.playerLV = 0
         self.maxHP = 0
         self.fightPower = 0
+        self.realmLV = 0
         self.pkScore = 0
         self.danLV = 0
         self.matchTick = 0
@@ -58,6 +62,7 @@
     
     def __init__(self):
         self.pkZoneID = 0
+        self.seasonID = 0
         self.roomID = 0
         self.mapID = 0
         self.openTick = 0 # 开房时间
@@ -68,11 +73,669 @@
         self.isMapOpen = False # 地图是否已经开启该房间,未开启的房间超时后,本次匹配视为无效,有玩家进地图才会开启副本分线
         return
     
+#跨服PK排行榜管理,注意该类只处理数据逻辑,功能相关逻辑不要写在该类,不然重读脚本不会生效
+class CrossPKBillboardManager(object):
+    
+    DBKEY_CrossPKFinalBillboardData = "CrossPKFinalBillboard_%s_%s" # 是否收到赛区赛季最终榜单同步,参数(zoneID, seasonID)
+    
+    def __init__(self):
+        self.__ZoneSeasonDataList = "ZoneSeasonDataList_%s_%s" # 分区赛季排行数据列表 [tagDBCrossPKBillboard, ...]
+        self.__ZoneSeasonPlayerOrderDict = "ZoneSeasonPlayerOrderDict_%s_%s" # 分区赛季排行数据字典 {playerID:rank, ...}
+        self.__ZoneSeasonList = [] # 分区赛季列表 [(zoneID, seasonID), ...]
+        self.__UnSortZoneSeasonTimeDict = {} # 未排序的分区赛季排行 {(zoneID, seasonID):tick, ...}
+        return
+    
+    def GetCrossPKBillboardInfo(self, zoneID, seasonID, isSort=False):
+        ## 获取跨服PK排行榜信息
+        # @return: billboardList, orderDict
+        listAttrName = self.__ZoneSeasonDataList % (zoneID, seasonID)
+        orderDictAttrName = self.__ZoneSeasonPlayerOrderDict % (zoneID, seasonID)
+        if not hasattr(self, listAttrName):
+            setattr(self, listAttrName, [])
+            setattr(self, orderDictAttrName, {})
+            self.__ZoneSeasonList.append((zoneID, seasonID))
+        billboardList = getattr(self, listAttrName)
+        if isSort:
+            self.__PKBillboardSort(zoneID, seasonID, billboardList)
+        orderDict = getattr(self, orderDictAttrName)
+        return billboardList, orderDict
+    
+    def __PKBillboardSort(self, zoneID, seasonID, billboardList):
+        ## 排序
+        if (zoneID, seasonID) not in self.__UnSortZoneSeasonTimeDict:
+            return
+        self.__UnSortZoneSeasonTimeDict.pop((zoneID, seasonID))
+        billboardList.sort(key=operator.attrgetter("PKScore", "Time"), reverse=True)
+        orderDict = {}
+        for order, billboardData in enumerate(billboardList, 1):
+            orderDict[billboardData.PlayerID] = order # 缓存赛季玩家排名
+        orderDictAttrName = self.__ZoneSeasonPlayerOrderDict % (zoneID, seasonID)
+        setattr(self, orderDictAttrName, orderDict)
+        GameWorld.DebugLog("跨服PK榜单排序: zoneID=%s,seasonID=%s,orderDict=%s" % (zoneID, seasonID, orderDict))
+        return
+    
+    def PKBillboardSortByTime(self, tick):
+        ## 定时排序
+        if not self.__UnSortZoneSeasonTimeDict:
+            return
+        sortCD = 60 * 1000 # 超过1分钟强制排序
+        for key, updTick in self.__UnSortZoneSeasonTimeDict.items():
+            zoneID, seasonID = key
+            if tick - updTick < sortCD:
+                continue
+            self.GetCrossPKBillboardInfo(zoneID, seasonID, True)
+        return
+    
+    def SetNeedSort(self, zoneID, seasonID):
+        if (zoneID, seasonID) not in self.__UnSortZoneSeasonTimeDict:
+            self.__UnSortZoneSeasonTimeDict[(zoneID, seasonID)] = GameWorld.GetGameWorld().GetTick()
+        return
+    
+    ## ==================================== 子服的榜单数据管理 =====================================
+    def UpdClientServerPKBillboard(self, zoneID, seasonID, syncBillboardList, isFinalBillboardData):
+        ## 先直接清除本服数据,然后直接覆盖更新
+        billboardList = self.GetCrossPKBillboardInfo(zoneID, seasonID)[0]
+        billboardList = billboardList[:len(syncBillboardList)] # 直接用本服以后的排行数据实例clear后覆盖更新,不足的创建新实例
+        orderDict = {} # 排行信息重新更新
+        for i, syncData in enumerate(syncBillboardList):
+            playerID, playerName, job, fightPower, realmLV, pkScore, danLV, billTime, order = syncData
+            if i < len(billboardList):
+                billboardData = billboardList[i]
+                billboardData.clear()
+            else:
+                billboardData = PyGameDataStruct.tagDBCrossPKBillboard()
+                billboardList.append(billboardData)
+            billboardData.ZoneID = zoneID
+            billboardData.SeasonID = seasonID
+            billboardData.PlayerID = playerID
+            billboardData.PlayerName = playerName
+            billboardData.Job = job
+            billboardData.FightPower = fightPower
+            billboardData.RealmLV = realmLV
+            billboardData.PKScore = pkScore
+            billboardData.DanLV = danLV
+            billboardData.Time = billTime
+            orderDict[playerID] = order
+            
+        listAttrName = self.__ZoneSeasonDataList % (zoneID, seasonID)
+        orderDictAttrName = self.__ZoneSeasonPlayerOrderDict % (zoneID, seasonID)
+        setattr(self, listAttrName, billboardList)
+        setattr(self, orderDictAttrName, orderDict)
+        dbIsFinalData = PlayerDBGSEvent.GetDBGSTrig_ByKey(self.DBKEY_CrossPKFinalBillboardData % (zoneID, seasonID))
+        isFinalBillboardData = 1 if isFinalBillboardData else 0
+        if dbIsFinalData != isFinalBillboardData:
+            PlayerDBGSEvent.SetDBGSTrig_ByKey(self.DBKEY_CrossPKFinalBillboardData % (zoneID, seasonID), isFinalBillboardData)
+            GameWorld.Log("更新子服榜单数据是否是最终榜单数据!zoneID=%s,seasonID=%s,isFinalBillboardData=%s" 
+                          % (zoneID, seasonID, isFinalBillboardData))
+        return billboardList, orderDict
+    
+    def IsFinalBillboardData(self, zoneID, seasonID):
+        ## 子服的赛区赛季榜单数据是否最终榜单数据
+        return PlayerDBGSEvent.GetDBGSTrig_ByKey(self.DBKEY_CrossPKFinalBillboardData % (zoneID, seasonID))
+    
+    ## ===========================================================================================
+    
+    # 保存数据 存数据库和realtimebackup
+    def GetSaveData(self):
+        savaData = ""
+        cntData = ""
+        cnt = 0
+        for zoneID, seasonID in self.__ZoneSeasonList:
+            billboardList = self.GetCrossPKBillboardInfo(zoneID, seasonID)[0]
+            for billboardData in billboardList:
+                cnt += 1
+                savaData += billboardData.getBuffer()
+                
+        GameWorld.Log("SaveCrossPKBillboard cnt :%s" % cnt)
+        return CommFunc.WriteDWORD(cntData, cnt) + savaData
+    
+    # 从数据库载入数据
+    def LoadPyGameData(self, datas, pos, dataslen):
+        cnt, pos = CommFunc.ReadDWORD(datas, pos)
+        GameWorld.Log("LoadCrossPKBillboard cnt :%s" % cnt)
+        
+        for _ in xrange(cnt):
+            billboardData = PyGameDataStruct.tagDBCrossPKBillboard()
+            billboardData.clear()
+            pos += billboardData.readData(datas, pos, dataslen)
+            
+            zoneID = billboardData.ZoneID
+            seasonID = billboardData.SeasonID
+            billboardList = self.GetCrossPKBillboardInfo(zoneID, seasonID)[0]
+            billboardList.append(billboardData)
+            
+        # 排序
+        for zoneID, seasonID in self.__ZoneSeasonList:
+            self.SetNeedSort(zoneID, seasonID)
+            billboardList = self.GetCrossPKBillboardInfo(zoneID, seasonID, True)[0]
+            GameWorld.Log("    zoneID=%s, seasonID=%s, count=%s" % (zoneID, seasonID, len(billboardList)))
+            
+        return pos
+    
+def UpdateCrossPKBillboard(zoneID, seasonID, winner, loser):
+    ## 更新跨服PK排行榜,跨服服务器结算调用,子服不调用
+    
+    curZoneSeasonID = GameWorld.GetGameWorld().GetDictByKey(ChConfig.Def_WorldKey_CrossPKZoneSeasonID % zoneID)
+    if curZoneSeasonID != seasonID:
+        GameWorld.ErrLog("不是当前赛季,不更新排行榜! zoneID=%s,seasonID=%s,curZoneSeasonID=%s" % (zoneID, seasonID, curZoneSeasonID))
+        return
+    billboardCfg = IpyGameDataPY.GetFuncEvalCfg("CrossRealmPKCfg", 1, [])
+    if not billboardCfg or len(billboardCfg) != 2:
+        GameWorld.ErrLog("跨服竞技场排行榜配置错误!")
+        return
+    maxCount, danLVLimit = billboardCfg
+    if maxCount <= 0:
+        return
+    maxCount = min(2000, maxCount)
+    upBillboardList = []
+    if winner.danLV >= danLVLimit:
+        upBillboardList.append(winner)
+    else:
+        GameWorld.DebugLog("    段位不足,无法上榜! winnerDanLV=%s < danLVLimit=%s" % (winner.danLV, danLVLimit), winner.playerID)
+    if loser.danLV >= danLVLimit:
+        upBillboardList.append(loser)
+    else:
+        GameWorld.DebugLog("    段位不足,无法上榜! loserDanLV=%s < danLVLimit=%s" % (loser.danLV, danLVLimit), loser.playerID)
+    if not upBillboardList:
+        return
+    
+    crossPKBillboardMgr = PyDataManager.GetCrossPKBillboardManager()
+    billboardList, orderDict = crossPKBillboardMgr.GetCrossPKBillboardInfo(zoneID, seasonID)
+    
+    isUpd = False
+    curTime = int(time.time())
+    billboardTime = max(0, GameWorld.ChangeTimeStrToNum("2080-01-01 00:00:00") - curTime) # 因为先上榜排前面,所以时间记录值得反减,倒序排
+    for pkPlayer in upBillboardList:
+        playerID = pkPlayer.playerID
+        if playerID in orderDict:
+            order = orderDict[playerID]
+            billboardData = billboardList[order - 1]
+            GameWorld.DebugLog("    已经在榜单上!playerID=%s,order=%s" % (playerID, order), playerID)
+        else:
+            if len(billboardList) < maxCount:
+                newBillboardData = PyGameDataStruct.tagDBCrossPKBillboard()
+                billboardList.append(newBillboardData)
+                order = len(billboardList)
+                GameWorld.DebugLog("    添加新上榜榜单!playerID=%s,order=%s" % (playerID, order), playerID)
+            else:
+                lastBillboardData = billboardList[-1]
+                # 分数如果超过最后一个,则顶掉最后一个
+                if lastBillboardData.PKScore >= pkPlayer.pkScore:
+                    GameWorld.DebugLog("    PK积分不超过最后一名玩家,无法上榜! pkScore=%s <= lastPKScore=%s" 
+                                       % (pkPlayer.pkScore, lastBillboardData.PKScore), playerID)
+                    continue
+                order = orderDict.pop(lastBillboardData.PlayerID, len(billboardList))
+                GameWorld.DebugLog("    顶掉最后一个榜单!playerID=%s,lastPlayer=%s,lastScore=%s,order=%s" 
+                                   % (playerID, lastBillboardData.PlayerID, lastBillboardData.PKScore, order))
+                newBillboardData = PyGameDataStruct.tagDBCrossPKBillboard()
+                billboardList[-1] = newBillboardData
+            billboardData = newBillboardData
+            orderDict[playerID] = order
+            
+        isUpd = True
+        # 更新值
+        billboardData.ZoneID = zoneID
+        billboardData.SeasonID = seasonID
+        billboardData.PlayerID = playerID
+        billboardData.PlayerName = pkPlayer.playerName
+        billboardData.Job = pkPlayer.playerJob
+        billboardData.FightPower = pkPlayer.fightPower
+        billboardData.RealmLV = pkPlayer.realmLV
+        billboardData.PKScore = pkPlayer.pkScore
+        billboardData.DanLV = pkPlayer.danLV
+        billboardData.Time = billboardTime
+        GameWorld.Log("    更新PK积分排行榜: playerID=%s,pkScore=%s,order=%s" % (playerID, billboardData.PKScore, order), playerID)
+        
+    # 战斗结算更新榜单先不排序,只设置需要排序
+    if isUpd:
+        crossPKBillboardMgr.SetNeedSort(zoneID, seasonID)
+        
+    # 如果匹配已经结束,且没有战斗中的房间了,则处理本阶段匹配总结算
+    matchState = GameWorld.GetGameWorld().GetDictByKey(ShareDefine.Def_Notify_WorldKey_CrossDailyActionState % ShareDefine.DailyActionID_CrossReamPK)
+    if not matchState and not PyGameData.g_crossPKRoomDict:
+        GameWorld.Log("匹配已结束,且当前没有PK中的房间了!主动广播子服最新榜单! ")
+        zoneIpyData = IpyGameDataPY.GetIpyGameData("CrossRealmPKZone", zoneID)
+        if zoneIpyData:
+            serverGroupIDList = zoneIpyData.GetServerGroupIDList()
+            SyncPKSyncBillboardToClientServer(zoneID, seasonID, serverGroupIDList)
+            
+    return
+
+#// C0 01 查看跨服竞技场赛季排行榜 #tagCGViewCrossPKBillboard
+#
+#struct    tagCGViewCrossPKBillboard
+#{
+#    tagHead        Head;
+#    BYTE        ZoneID;    // 赛区ID    
+#    BYTE        SeasonID;    // 赛季ID    
+#};
+def OnViewCrossPKBillboard(index, clientData, tick):
+    ''' 赛区赛季榜单同步规则,这里以多台跨服服务器为考虑
+            每台跨服服务器单独管理自己关联的子服赛区榜单
+                    每日匹配结束结算时间点主动同步所有子服本台跨服服务器的所有赛区当前赛季榜单,这样能确保所有子服的赛区榜单是最新的
+                    匹配期间,子服设置同步CD,如果有玩家查询,则每1分钟可向跨服服务器同步当前赛区赛季最新榜单信息,同步后发送玩家
+                    非匹配期间,只要子服有数据则可直接发送给玩家,没有的话向跨服服务器同步后再发送玩家
+                    历史赛季,因为每日跨服服务器都有主动广播,所以历史赛季只要子服有数据则可直接发送给玩家,没有的话向跨服服务器同步后再发送玩家
+                    赛季结束 或 历史赛季 只要不是最终榜单数据的,则需主动向跨服服务器请求同步数据后再发送玩家
+                    不同跨服服务器赛区的话由跨服服务器之间自己同步数据,子服只管向自己所属跨服服务器同步数据即可
+                    
+            跨服服务器与跨服服务器之间的赛区榜单同步,同步规则类似子服与跨服服务器,相互之间做好数据同步即可
+            数据同步后再同步各自所有子服,确保子服也是最新的,可考虑匹配结算结束同步一次即可
+            这样玩家查看其它跨服服务器赛区数据可能会延迟一次匹配阶段结算的时间,比如两个小时,这个等以后需要多台跨服服务器时再讨论
+    '''
+    curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index)
+    if GameWorld.IsCrossServer():
+        return
+    playerID = curPlayer.GetPlayerID()
+    zoneID, seasonID = clientData.ZoneID, clientData.SeasonID
+    tickKey = ChConfig.Def_PlayerKey_ViewCrossPKBillboardTick % (zoneID, seasonID)
+    if tick - curPlayer.GetDictByKey(tickKey) < 60000:
+        GameWorld.DebugLog("玩家查询跨服PK排行榜CD中: zoneID=%s, seasonID=%s" % (zoneID, seasonID), playerID)
+        return
+    curPlayer.SetDict(tickKey, tick)
+    gameWorld = GameWorld.GetGameWorld()
+    serverZoneID = gameWorld.GetDictByKey(ShareDefine.Def_Notify_WorldKey_CrossPKZoneID)
+
+    crossPKBillboardMgr = PyDataManager.GetCrossPKBillboardManager()
+    billboardList = crossPKBillboardMgr.GetCrossPKBillboardInfo(zoneID, seasonID)[0]
+    isFinalBillboardData = crossPKBillboardMgr.IsFinalBillboardData(zoneID, seasonID)
+    
+    GameWorld.DebugLog("玩家请求查看跨服PK排行榜: zoneID=%s,seasonID=%s,serverZoneID=%s,isFinalBillboardData=%s" 
+                       % (zoneID, seasonID, serverZoneID, isFinalBillboardData))
+    
+    # 本服赛区
+    if zoneID == serverZoneID:
+        curSeasonID = gameWorld.GetDictByKey(ShareDefine.Def_Notify_WorldKey_CrossPKSeasonID)
+        seasonState = gameWorld.GetDictByKey(ShareDefine.Def_Notify_WorldKey_CrossPKSeasonState)
+        
+    # 其他赛区
+    else:
+        serverTime = GameWorld.GetServerTime()
+        curSeasonID = 0
+        seasonState = 0
+        seasonList = IpyGameDataPY.GetIpyGameDataList("CrossRealmPKSeason", zoneID)
+        seasonList = [] if not seasonList else seasonList
+        for seasonIpyData in seasonList:
+            startDateStr = seasonIpyData.GetStartDate()
+            endDateStr = seasonIpyData.GetEndDate()
+            endTimeStr = seasonIpyData.GetEndTime()
+            
+            startDateTime = datetime.datetime.strptime("%s 00:00:00" % (startDateStr), ChConfig.TYPE_Time_Format)
+            endDateTime = datetime.datetime.strptime("%s %s:00" % (endDateStr, endTimeStr), ChConfig.TYPE_Time_Format)
+            if serverTime < startDateTime:
+                break
+            if serverTime <= endDateTime:
+                curSeasonID = seasonIpyData.GetSeasonID()
+                seasonState = 1
+            else:
+                break
+            
+    # 查询当前进行中的赛季
+    if seasonID == curSeasonID:
+        matchState = gameWorld.GetDictByKey(ShareDefine.Def_Notify_WorldKey_CrossDailyActionState % ShareDefine.DailyActionID_CrossReamPK)
+        # 非匹配中的
+        if not matchState:
+            # 最终数据 or 赛季进行中 直接同步
+            if isFinalBillboardData or (seasonState == 1 and billboardList):
+                SyncCrossPKBillboard(curPlayer, zoneID, seasonID, billboardList)
+                return
+            
+        # 正在匹配中的,验证本服数据同步CD,暂定1分钟同步一次
+        else:
+            syncTickKey = ChConfig.Def_WorldKey_CrossPKBillboardSyncTick % (zoneID, seasonID)
+            if matchState and billboardList and tick - gameWorld.GetDictByKey(syncTickKey) < 60000:
+                SyncCrossPKBillboard(curPlayer, zoneID, seasonID, billboardList)
+                return
+            gameWorld.SetDict(syncTickKey, tick)
+            
+    # 查询历史赛季的
+    else:
+        # 如果是最终数据则直接同步
+        if isFinalBillboardData and billboardList:
+            SyncCrossPKBillboard(curPlayer, zoneID, seasonID, billboardList)
+            return
+        
+    # 请求查询跨服服务器
+    dataMsg = {"ZoneID":zoneID, "SeasonID":seasonID, "ExData":{"EventName":"View", "PlayerID":playerID}}
+    CrossRealmMsg.SendMsgToCrossServer(ShareDefine.ClientServerMsg_PKBillboard, dataMsg)
+    return
+
+def MapServer_QueryCrossPKSeasonOrder(curPlayer, msgList):
+    ## 地图服务器查询玩家赛区赛季PK榜排名
+    playerID = curPlayer.GetPlayerID()
+    zoneID, seasonID, eventName, eventData = msgList
+    crossPKBillboardMgr = PyDataManager.GetCrossPKBillboardManager()
+    billboardList, orderDict = crossPKBillboardMgr.GetCrossPKBillboardInfo(zoneID, seasonID) # 子服的数据一定是排完序同步过来的,所以这里就不需要再排序了
+    if not billboardList:
+        # 本服没榜单数据,查询跨服服务器
+        # 请求查询跨服服务器
+        dataMsg = {"ZoneID":zoneID, "SeasonID":seasonID, "ExData":{"EventName":eventName, "PlayerID":playerID, "EventData":eventData}}
+        CrossRealmMsg.SendMsgToCrossServer(ShareDefine.ClientServerMsg_PKBillboard, dataMsg)
+        return
+    
+    order = orderDict.get(playerID, 0)
+    sysMsg = str([zoneID, seasonID, eventName, eventData, order])
+    curPlayer.MapServer_QueryPlayerResult(0, 0, "CrossPKSeasonOrder", sysMsg, len(sysMsg))
+    return
+
+def ClientServerMsg_PKBillboard(serverGroupID, msgData):
+    ## 收到子服请求查询PK排行榜信息
+    zoneID = msgData["ZoneID"]
+    seasonID = msgData["SeasonID"]
+    exData = msgData.get("ExData", {}) # 原数据返回子服
+    SyncPKSyncBillboardToClientServer(zoneID, seasonID, [serverGroupID], exData)
+    return
+
+def SyncPKSyncBillboardToClientServer(zoneID, seasonID, serverGroupIDList, exData={}):
+    ## 同步赛区赛季榜单到子服
+    crossPKBillboardMgr = PyDataManager.GetCrossPKBillboardManager()
+    billboardList, orderDict  = crossPKBillboardMgr.GetCrossPKBillboardInfo(zoneID, seasonID, True) # 同步子服前需触发排序
+    isFinalBillboardData = False # 是否最终的榜单数据
+    gameWorld = GameWorld.GetGameWorld()
+    curZoneSeasonID = gameWorld.GetDictByKey(ChConfig.Def_WorldKey_CrossPKZoneSeasonID % zoneID)
+    if seasonID < curZoneSeasonID:
+        isFinalBillboardData = True # 历史赛季在跨服服务器中的一定是最终榜单数据
+    elif seasonID == curZoneSeasonID:
+        seasonState = gameWorld.GetDictByKey(ChConfig.Def_WorldKey_CrossPKZoneSeasonState % zoneID)
+        if seasonState == 2:
+            isFinalBillboardData = True # 当前赛季已经是赛季结算状态的了,代表是最终榜单数据
+            
+    syncBillboardList = []
+    for billboardData in billboardList:
+        playerID = billboardData.PlayerID
+        playerName = billboardData.PlayerName
+        job = billboardData.Job
+        fightPower = billboardData.FightPower
+        realmLV = billboardData.RealmLV
+        pkScore = billboardData.PKScore
+        danLV = billboardData.DanLV
+        billTime = billboardData.Time
+        order = orderDict.get(playerID, 0)
+        syncBillboardList.append([playerID, playerName, job, fightPower, realmLV, pkScore, danLV, billTime, order])
+        
+    syncInfo = [zoneID, seasonID, syncBillboardList, exData, isFinalBillboardData]
+    CrossRealmMsg.SendMsgToClientServer(ShareDefine.CrossServerMsg_PKSyncBillboard, syncInfo, serverGroupIDList)
+    return
+
+def CrossServerMsg_PKSyncBillboard(syncInfo):
+    ## 收到跨服服务器同步的排行榜信息
+    zoneID, seasonID, syncBillboardList, exData, isFinalBillboardData = syncInfo
+    GameWorld.Log("收到跨服服务器同步的排行榜信息: zoneID=%s,seasonID=%s,billboardDataCount=%s,exData=%s,isFinalBillboardData=%s" 
+                  % (zoneID, seasonID, len(syncBillboardList), exData, isFinalBillboardData))
+    
+    crossPKBillboardMgr = PyDataManager.GetCrossPKBillboardManager()
+    billboardList, orderDict = crossPKBillboardMgr.UpdClientServerPKBillboard(zoneID, seasonID, syncBillboardList, isFinalBillboardData)
+    if not exData:
+        return
+    eventName = exData.get("EventName")
+    eventData = exData.get("EventData")
+    queryPlayerID = exData.get("PlayerID", 0)
+    if not eventName or not queryPlayerID:
+        return
+    
+    queryPlayer = GameWorld.GetPlayerManager().FindPlayerByID(queryPlayerID)
+    if not queryPlayer:
+        return
+    
+    if eventName == "View":        
+        SyncCrossPKBillboard(queryPlayer, zoneID, seasonID, billboardList)
+    else:
+        order = orderDict.get(queryPlayerID, 0)
+        sysMsg = str([zoneID, seasonID, eventName, eventData, order])
+        queryPlayer.MapServer_QueryPlayerResult(0, 0, "CrossPKSeasonOrder", sysMsg, len(sysMsg))
+        
+    return
+
+def SyncCrossPKBillboard(curPlayer, zoneID, seasonID, billboardList):
+    ## 同步给玩家跨服PK榜单
+    billboardInfo = ChPyNetSendPack.tagGCCrossRealmPKBillboardInfo()
+    billboardInfo.ZoneID = zoneID
+    billboardInfo.SeasonID = seasonID
+    billboardInfo.PKBillboardList = []
+    for billboardData in billboardList:
+        billboardInfoData = ChPyNetSendPack.tagGCCrossRealmPKBillboardData()
+        billboardInfoData.PlayerID = billboardData.PlayerID
+        billboardInfoData.PlayerName = billboardData.PlayerName
+        billboardInfoData.NameLen = len(billboardInfoData.PlayerName)
+        billboardInfoData.Job = billboardData.Job
+        billboardInfoData.FightPower = billboardData.FightPower
+        billboardInfoData.RealmLV = billboardData.RealmLV
+        billboardInfoData.PKScore = billboardData.PKScore
+        billboardInfoData.DanLV = billboardData.DanLV
+        billboardInfo.PKBillboardList.append(billboardInfoData)
+    billboardInfo.Count = len(billboardInfo.PKBillboardList)
+    NetPackCommon.SendFakePack(curPlayer, billboardInfo)
+    return
+    
 ################################################################################
 
-def OnPlayerLogin(curPlayer):
+def __GetCrossPKZoneSeasonTimeInfo():
+    key = "CrossPKZoneSeasonTimeInfo"
+    openServerDay = PlayerDBGSEvent.GetDBGSTrig_ByKey(PlayerDBGSEvent.Def_ServerDay) + 1
+    ZoneSeasonTimeInfo = IpyGameDataPY.GetConfigEx(key)
+    
+    if ZoneSeasonTimeInfo and ZoneSeasonTimeInfo[0] == openServerDay:
+        #GameWorld.DebugLog("已经加载过本日跨服PK赛季处理信息!openServerDay=%s" % openServerDay)
+        return ZoneSeasonTimeInfo[1]
+    
+    GameWorld.Log("加载跨服PK赛季时间信息: openServerDay=%s" % (openServerDay))
+    
+    zoneSeasonTimeDict = {}
+    serverTime = GameWorld.GetServerTime()
+    ipyDataMgr = IpyGameDataPY.IPY_Data()
+    for index in xrange(ipyDataMgr.GetCrossRealmPKZoneCount()):
+        zoneIpyData = ipyDataMgr.GetCrossRealmPKZoneByIndex(index)
+        zoneID = zoneIpyData.GetZoneID()
+        
+        # 规定每个赛区的赛季时间需按顺序配置
+        seasonIpyDataList = []
+        for sIndex in xrange(ipyDataMgr.GetCrossRealmPKSeasonCount()):
+            seasonIpyData = ipyDataMgr.GetCrossRealmPKSeasonByIndex(sIndex)
+            if zoneID == seasonIpyData.GetZoneID():
+                seasonIpyDataList.append(seasonIpyData)
+                
+        for i, seasonIpyData in enumerate(seasonIpyDataList):
+            seasonID = seasonIpyData.GetSeasonID()
+            startDateStr = seasonIpyData.GetStartDate()
+            endDateStr = seasonIpyData.GetEndDate()
+            endTimeStr = seasonIpyData.GetEndTime()
+            
+            startDateTime = datetime.datetime.strptime("%s 00:00:00" % (startDateStr), ChConfig.TYPE_Time_Format)
+            endDateTime = datetime.datetime.strptime("%s %s:00" % (endDateStr, endTimeStr), ChConfig.TYPE_Time_Format)
+            
+            # 最后一个赛季
+            if i == len(seasonIpyDataList) - 1:
+                nextSeasonIpyData = None
+            else:
+                nextSeasonIpyData = seasonIpyDataList[i + 1]
+                
+            if serverTime < startDateTime:
+                GameWorld.Log("    赛季未开始! zoneID=%s,seasonID=%s,startDateStr=%s,endDateStr=%s" % (zoneID, seasonID, startDateStr, endDateStr))
+                break
+            
+            elif startDateTime <= serverTime <= endDateTime:
+                pass
+            
+            elif endDateTime < serverTime:
+                if nextSeasonIpyData:
+                    nestStartDateStr = nextSeasonIpyData.GetStartDate()
+                    nextStartDateTime = datetime.datetime.strptime("%s 00:00:00" % (nestStartDateStr), ChConfig.TYPE_Time_Format)
+                    if serverTime >= nextStartDateTime:
+                        GameWorld.Log("    赛季已过期! zoneID=%s,seasonID=%s,startDateStr=%s,endDateStr=%s" % (zoneID, seasonID, startDateStr, endDateStr))
+                        continue
+                else:
+                    pass
+                
+            else:
+                continue
+            
+            nextSeasonID = 0 if not nextSeasonIpyData else nextSeasonIpyData.GetSeasonID()
+            zoneSeasonTimeDict[zoneID] = [seasonIpyData]
+            GameWorld.Log("    赛季活动中! zoneID=%s,seasonID=%s,startDateStr=%s,endDateStr=%s,nextSeasonID=%s" % (zoneID, seasonID, startDateStr, endDateStr, nextSeasonID))
+            break
+        
+    ZoneSeasonTimeInfo = IpyGameDataPY.SetConfigEx(key, [openServerDay, zoneSeasonTimeDict])
+    GameWorld.Log("跨服PK赛季时间信息加载完毕!")
+    GameWorld.Log("=============================================================")
+    return ZoneSeasonTimeInfo[1]
+
+def OnMinuteProcess():
+    ## 每分钟处理
+    
     if not GameWorld.IsCrossServer():
+        return
+    
+    zoneSeasonTimeDict = __GetCrossPKZoneSeasonTimeInfo()
+    if not zoneSeasonTimeDict:
+        return
+    
+    gameWorld = GameWorld.GetGameWorld()
+    serverTime = GameWorld.GetServerTime()
+    for zoneID, seasonTimeInfo in zoneSeasonTimeDict.items():
+        zoneIpyData = IpyGameDataPY.GetIpyGameData("CrossRealmPKZone", zoneID)
+        if not zoneIpyData:
+            continue
+        
+        curSeasonIpyData = seasonTimeInfo[0]
+        if not curSeasonIpyData:
+            continue
+        
+        seasonID = curSeasonIpyData.GetSeasonID()
+        startDateStr = curSeasonIpyData.GetStartDate()
+        endDateStr = curSeasonIpyData.GetEndDate()
+        endTimeStr = curSeasonIpyData.GetEndTime()
+        
+        startDateTime = datetime.datetime.strptime("%s 00:00:00" % (startDateStr), ChConfig.TYPE_Time_Format)
+        endDateTime = datetime.datetime.strptime("%s %s:00" % (endDateStr, endTimeStr), ChConfig.TYPE_Time_Format)
+        
+        seasonState = 0
+        if startDateTime <= serverTime < endDateTime:
+            seasonState = 1
+        elif serverTime >= endDateTime:
+            seasonState = 2
+            
+        zoneSeasonIDDictName = ChConfig.Def_WorldKey_CrossPKZoneSeasonID % zoneID
+        seasonStateDictName = ChConfig.Def_WorldKey_CrossPKZoneSeasonState % zoneID
+        dictSeasonID = gameWorld.GetDictByKey(zoneSeasonIDDictName)
+        curSeasonState = gameWorld.GetDictByKey(seasonStateDictName)
+        if curSeasonState == seasonState and dictSeasonID == seasonID:
+            #已经是这个状态了
+            continue
+        gameWorld.SetDict(zoneSeasonIDDictName, seasonID)
+        gameWorld.SetDict(seasonStateDictName, seasonState)
+        GameWorld.Log("跨服PK赛季状态变更: zoneID=%s,seasonID=%s,seasonState=%s" % (zoneID, seasonID, seasonState))
+        
+        serverGroupIDList = zoneIpyData.GetServerGroupIDList()
+        # 赛季总结算,为确保子服榜单的实时性,这里需再同步子服最终榜单信息,需在同步赛季状态之前同步
+        if seasonState == 2:
+            SyncPKSyncBillboardToClientServer(zoneID, seasonID, serverGroupIDList)
+            
+        # 广播当前赛区的所有子服跨服PK赛季状态变更
+        matchState = gameWorld.GetDictByKey(ShareDefine.Def_Notify_WorldKey_CrossDailyActionState % ShareDefine.DailyActionID_CrossReamPK)
+        seasonInfo = {"ZoneID":zoneID, "SeasonID":seasonID, "SeasonState":seasonState, "MatchState":matchState}
+        CrossRealmMsg.SendMsgToClientServer(ShareDefine.CrossServerMsg_PKSeasonInfo, seasonInfo, serverGroupIDList)
+        
+    return
+
+def OnCrossRealmPKDailyActionStateChange(isOpen):
+    ## 跨服PK每日活动匹配状态变更
+    
+    if not GameWorld.IsCrossServer():
+        return
+    
+    gameWorld = GameWorld.GetGameWorld()
+    gameWorld.SetDict(ShareDefine.Def_Notify_WorldKey_CrossDailyActionState % ShareDefine.DailyActionID_CrossReamPK, isOpen)
+    
+    ipyDataMgr = IpyGameDataPY.IPY_Data()
+    for index in xrange(ipyDataMgr.GetCrossRealmPKZoneCount()):
+        zoneIpyData = ipyDataMgr.GetCrossRealmPKZoneByIndex(index)
+        zoneID = zoneIpyData.GetZoneID()
+        
+        # 广播当前赛区的所有子服跨服PK赛季状态变更
+        serverGroupIDList = zoneIpyData.GetServerGroupIDList()
+        seasonID = gameWorld.GetDictByKey(ChConfig.Def_WorldKey_CrossPKZoneSeasonID % zoneID)
+        seasonState = gameWorld.GetDictByKey(ChConfig.Def_WorldKey_CrossPKZoneSeasonState % zoneID)
+        seasonInfo = {"ZoneID":zoneID, "SeasonID":seasonID, "SeasonState":seasonState, "MatchState":isOpen}
+        GameWorld.Log("跨服PK匹配状态变更: zoneID=%s,seasonID=%s,seasonState=%s,matchState=%s" % (zoneID, seasonID, seasonState, isOpen))
+        CrossRealmMsg.SendMsgToClientServer(ShareDefine.CrossServerMsg_PKSeasonInfo, seasonInfo, serverGroupIDList)
+        
+    return
+
+def ClientServerMsg_ServerInitOK(serverGroupID, tick):
+    ## 子服启动成功
+    GameWorld.Log("子服启动成功,同步给子服对应的赛季信息: serverGroupID=%s" % (serverGroupID))
+    zoneID = GetCrossPKServerGroupZoneID(serverGroupID)
+    if not zoneID:
+        GameWorld.Log("    该子服没有分配赛区,不同步!")
+        return
+    gameWorld = GameWorld.GetGameWorld()
+    seasonID = gameWorld.GetDictByKey(ChConfig.Def_WorldKey_CrossPKZoneSeasonID % zoneID)
+    seasonState = gameWorld.GetDictByKey(ChConfig.Def_WorldKey_CrossPKZoneSeasonState % zoneID)
+    matchState = gameWorld.GetDictByKey(ShareDefine.Def_Notify_WorldKey_CrossDailyActionState % ShareDefine.DailyActionID_CrossReamPK)
+    seasonInfo = {"ZoneID":zoneID, "SeasonID":seasonID, "SeasonState":seasonState, "MatchState":matchState}
+    CrossRealmMsg.SendMsgToClientServer(ShareDefine.CrossServerMsg_PKSeasonInfo, seasonInfo, [serverGroupID])
+    return
+
+def GetCrossPKServerGroupZoneID(serverGroupID):
+    ## 获取服务器组ID对应的跨服PK所属赛区,返回0代表该服务器没有分配赛区
+    ipyDataMgr = IpyGameDataPY.IPY_Data()
+    for index in xrange(ipyDataMgr.GetCrossRealmPKZoneCount()):
+        zoneIpyData = ipyDataMgr.GetCrossRealmPKZoneByIndex(index)
+        for groupInfo in zoneIpyData.GetServerGroupIDList():
+            if (isinstance(groupInfo, int) and serverGroupID == groupInfo) \
+                or (isinstance(groupInfo, tuple) and len(groupInfo) == 2 and groupInfo[0] <= serverGroupID <= groupInfo[1]):
+                return zoneIpyData.GetZoneID()
+    return 0
+
+def OnPlayerLogin(curPlayer):
+    
+    # 本服登录处理
+    if not GameWorld.IsCrossServer():
+        # 本服没有分配赛区不处理
+        if not GameWorld.GetGameWorld().GetDictByKey(ShareDefine.Def_Notify_WorldKey_CrossPKZoneID):
+            return
         __OnLoginNotifyPKOverInfo(curPlayer)
+        
+        # 同步所有赛区赛季信息
+        zoneSeasonInfo = ChPyNetSendPack.tagGCCrossRealmPKSeasonInfo()
+        zoneSeasonInfo.ZoneList = []
+        ipyDataMgr = IpyGameDataPY.IPY_Data()
+        for index in xrange(ipyDataMgr.GetCrossRealmPKZoneCount()):
+            zoneIpyData = ipyDataMgr.GetCrossRealmPKZoneByIndex(index)
+            zoneID = zoneIpyData.GetZoneID()
+            zoneInfo = ChPyNetSendPack.tagGCCrossRealmPKZone()
+            zoneInfo.ZoneID = zoneID
+            zoneInfo.ZoneName = zoneIpyData.GetZoneName().decode(ShareDefine.Def_Game_Character_Encoding).encode(GameWorld.GetCharacterEncoding())
+            zoneInfo.ZoneNameLen = len(zoneInfo.ZoneName)
+            zoneInfo.SeasonList = []
+            seasonList = IpyGameDataPY.GetIpyGameDataList("CrossRealmPKSeason", zoneID)
+            seasonList = [] if not seasonList else seasonList
+            for seasonIpyData in seasonList:
+                seasonInfo = ChPyNetSendPack.tagGCCrossRealmPKSeason()
+                seasonInfo.SeasonID = seasonIpyData.GetSeasonID()
+                seasonInfo.StartDate = seasonIpyData.GetStartDate()
+                seasonInfo.EndDate = seasonIpyData.GetEndDate()
+                seasonInfo.EndTime = seasonIpyData.GetEndTime()
+                zoneInfo.SeasonList.append(seasonInfo)
+            zoneInfo.SeasonCount = len(zoneInfo.SeasonList)
+            zoneSeasonInfo.ZoneList.append(zoneInfo)
+        zoneSeasonInfo.ZoneCount = len(zoneSeasonInfo.ZoneList)
+        NetPackCommon.SendFakePack(curPlayer, zoneSeasonInfo)
+        
+        # 同步本服赛季状态
+        gameWorld = GameWorld.GetGameWorld()
+        seasonStatePack = ChPyNetSendPack.tagGCCrossRealmPKSeasonState()
+        seasonStatePack.ZoneID = gameWorld.GetDictByKey(ShareDefine.Def_Notify_WorldKey_CrossPKZoneID)
+        seasonStatePack.SeasonID = gameWorld.GetDictByKey(ShareDefine.Def_Notify_WorldKey_CrossPKSeasonID)
+        seasonStatePack.SeasonState = gameWorld.GetDictByKey(ShareDefine.Def_Notify_WorldKey_CrossPKSeasonState)
+        seasonStatePack.MatchState = gameWorld.GetDictByKey(ShareDefine.Def_Notify_WorldKey_CrossDailyActionState % ShareDefine.DailyActionID_CrossReamPK)
+        NetPackCommon.SendFakePack(curPlayer, seasonStatePack)
+        
+    # 跨服登录处理
+    else:
+        # 比如验证房间ID是否合法
+        pass
+    
     return
 
 ## 玩家离线处理
@@ -81,17 +744,10 @@
     SendCancelCrossRealmPKMatch(curPlayer, "PlayerDisconnect")
     return
 
-def IsCrossRealmPKOpen():
+def IsCrossRealmPKMatchState():
     ## 跨服PK匹配赛是否开启
-    return 1
-    return GameWorld.GetGameWorld().GetDictByKey(ShareDefine.Def_Notify_WorldKey_MergePKState) == ChConfig.Def_Action_Open
-
-def ClientServerMsg_ServerInitOK(serverGroupID, tick):
-    ## 子服启动成功
-    GameWorld.Log("同步跨服PK赛季信息及状态到子服: serverGroupID=%s" % (serverGroupID))
-    seasonInfo = {"SeasonID":1, "SeasonState":1, "MatchState":1}
-    CrossRealmMsg.SendMsgToClientServer(ShareDefine.CrossServerMsg_PKSeasonInfo, seasonInfo, [serverGroupID])
-    return
+    return GameWorld.GetGameWorld().GetDictByKey(ShareDefine.Def_Notify_WorldKey_CrossDailyActionState \
+                                                 % ShareDefine.DailyActionID_CrossReamPK) == ChConfig.Def_Action_Open
 
 def SendCancelCrossRealmPKMatch(curPlayer, reason):   
     ## 发送取消匹配
@@ -101,7 +757,7 @@
         return
     
     # 非活动中不处理
-    if not IsCrossRealmPKOpen():
+    if not IsCrossRealmPKMatchState():
         return
     
 #    # 如果是要登陆到跨服服务器的,不发送取消
@@ -133,7 +789,7 @@
         GameWorld.ErrLog("非跨服服务器不处理跨服PK匹配请求!")
         return
     
-    if not IsCrossRealmPKOpen():
+    if not IsCrossRealmPKMatchState():
         GameWorld.Log("跨服匹配PK活动未开启,不允许请求匹配!")
         return
     
@@ -146,6 +802,7 @@
     playerLV = playerInfoDict["playerLV"] # 职业
     maxHP = playerInfoDict["maxHP"] # 职业
     fightPower = playerInfoDict["fightPower"] # 战斗力
+    realmLV = playerInfoDict["realmLV"] # 境界
     pkScore = playerInfoDict["pkScore"] # 当前积分
     danLV = playerInfoDict["danLV"] # 当前段位
     cWinCount = playerInfoDict["cWinCount"] # 连胜次数
@@ -171,6 +828,7 @@
     pkPlayer.pkScore = pkScore
     pkPlayer.danLV = danLV
     pkPlayer.fightPower = fightPower
+    pkPlayer.realmLV = realmLV
     pkPlayer.matchTick = tick
     pkPlayer.cWinCount = cWinCount
     pkPlayer.ondayScore = ondayScore
@@ -197,7 +855,7 @@
         return
     
     # 非活动中不处理
-    if not IsCrossRealmPKOpen():
+    if not IsCrossRealmPKMatchState():
         return
     
     accID = playerInfoDict["accID"] # 角色账号
@@ -327,11 +985,12 @@
     if not GameWorld.IsCrossServer():
         return
     
-    if not IsCrossRealmPKOpen():
+    if not IsCrossRealmPKMatchState():
         return
     
-    # 同步子服排行榜
-    #__SyncBillboardToClientServer(False, tick)
+    # 定时更新排行榜
+    crossPKBillboardMgr = PyDataManager.GetCrossPKBillboardManager()
+    crossPKBillboardMgr.PKBillboardSortByTime(tick)
     
     processTick = IpyGameDataPY.GetFuncCfg("CrossRealmPKMatch", 1) * 1000
     processTickKey = "PKMatchLastTick"
@@ -528,6 +1187,7 @@
         
         newRoom = CrossPKRoom()
         newRoom.pkZoneID = pkZoneID
+        newRoom.seasonID = aPlayer.seasonID # 因为匹在一起的玩家一定是同一赛区同一赛季的,所以随便取一个玩家的赛季ID信息即可
         newRoom.roomID = roomID
         newRoom.mapID = mapID
         newRoom.openTick = tick
@@ -570,8 +1230,7 @@
     
     timeoutRoomDict = {}
     serverGroupIDList = []
-    #roomTimeout = IpyGameDataPY.GetFuncCfg("CheckRoomTimeout", 1) * 1000 # 这个时间尽量长点,目前暂时不确定玩家从准备好到进入到地图的时长
-    roomTimeout = 180 * 1000 # 这个时间尽量长点,目前暂时不确定玩家从准备到进入到地图的时长
+    roomTimeout = IpyGameDataPY.GetFuncCfg("CrossRealmPKCfg", 2) * 1000 # 这个时间尽量长点,目前暂时不确定玩家从准备到进入到地图的时长
     for roomID, pkRoom in PyGameData.g_crossPKRoomDict.items():
         if pkRoom.isMapOpen or not pkRoom.readyTick:
             continue
@@ -647,7 +1306,8 @@
     loser = PyGameData.g_crossPKPlayerDict.pop(loserID)
     #winner = PyGameData.g_crossPKPlayerDict[winnerID]
     #loser = PyGameData.g_crossPKPlayerDict[loserID]
-    seasonID = winner.seasonID
+    zoneID = vsRoom.pkZoneID
+    seasonID = vsRoom.seasonID
     
     cWinCount = winner.cWinCount
     winnerScore, loserScore = winner.pkScore, loser.pkScore
@@ -693,6 +1353,9 @@
     GameWorld.Log("wBaseScore=%s,wExScore=%s,winnerAddScore=%s,updScore=%s,updDanLV=%s,updCWinCount=%s" % (wBaseScore, wExScore, winnerAddScore, winner.pkScore, winner.danLV, winner.cWinCount))
     GameWorld.Log("lBaseScore=%s,lExScore=%s,loserAddScore=%s,updScore=%s,updDanLV=%s,updCWinCount=%s" % (lBaseScore, lExScore, loserAddScore, loser.pkScore, loser.danLV, loser.cWinCount))
     
+    # 更新排行榜
+    UpdateCrossPKBillboard(zoneID, seasonID, winner, loser)
+    
     timeStr = GameWorld.GetCurrentDataTimeStr()
     playerOverDict = {}
     # 通知客户端战斗结果
@@ -707,7 +1370,7 @@
         player = GameWorld.GetPlayerManager().FindPlayerByID(playerID)
         notifyState = True if player else False
         
-        playerOverDict[playerID] = [roomID, seasonID, timeStr, overType, winnerID, roundWinnerIDList] \
+        playerOverDict[playerID] = [roomID, zoneID, seasonID, timeStr, overType, winnerID, roundWinnerIDList] \
                                     + [serverGroupID, pkScore, danLV, cWinCount, addScore, tagPlayerID, tagPlayerName, notifyState]
         if not player:
             continue
@@ -737,6 +1400,69 @@
     return
 
 ##================================== 以下是子服逻辑 ==========================================
+
+def OnMapServerInitOK():
+    # 通知地图服务器状态
+    
+    if GameWorld.IsCrossServer():
+        return
+    
+    gameWorld = GameWorld.GetGameWorld()
+    zoneID = gameWorld.GetDictByKey(ShareDefine.Def_Notify_WorldKey_CrossPKZoneID)
+    seasonID = gameWorld.GetDictByKey(ShareDefine.Def_Notify_WorldKey_CrossPKSeasonID)
+    seasonState = gameWorld.GetDictByKey(ShareDefine.Def_Notify_WorldKey_CrossPKSeasonState)
+    matchState = GameWorld.GetGameWorld().GetDictByKey(ShareDefine.Def_Notify_WorldKey_CrossDailyActionState % ShareDefine.DailyActionID_CrossReamPK)
+    
+    GameWorld.SendMapServerMsgEx(ShareDefine.Def_Notify_WorldKey_CrossPKZoneID, zoneID)
+    GameWorld.SendMapServerMsgEx(ShareDefine.Def_Notify_WorldKey_CrossPKSeasonID, seasonID)
+    GameWorld.SendMapServerMsgEx(ShareDefine.Def_Notify_WorldKey_CrossPKSeasonState, seasonState)
+    GameWorld.SendMapServerMsgEx(ShareDefine.Def_Notify_WorldKey_CrossDailyActionState % ShareDefine.DailyActionID_CrossReamPK, matchState)
+    return
+
+def CrossServerMsg_PKSeasonInfo(seasonInfo):
+    ## 收到跨服服务器同步的赛季信息
+    #seasonInfo = {"ZoneID":zoneID, "SeasonID":seasonID, "SeasonState":seasonState, "MatchState":matchState}
+    GameWorld.Log("收到跨服服务器同步的赛季信息...")
+    if not seasonInfo:
+        return
+    zoneID = seasonInfo.get("ZoneID", 0)
+    seasonID = seasonInfo.get("SeasonID", 0)
+    seasonState = seasonInfo.get("SeasonState", 0)
+    matchState = seasonInfo.get("MatchState", 0)
+    GameWorld.Log("    zoneID=%s,seasonID=%s,seasonState=%s,matchState=%s" % (zoneID, seasonID, seasonState, matchState))
+    if not zoneID:
+        return
+    
+    gameWorld = GameWorld.GetGameWorld()
+    curSeasonState = gameWorld.GetDictByKey(ShareDefine.Def_Notify_WorldKey_CrossPKSeasonState)
+    
+    gameWorld.SetDict(ShareDefine.Def_Notify_WorldKey_CrossPKZoneID, zoneID)
+    gameWorld.SetDict(ShareDefine.Def_Notify_WorldKey_CrossPKSeasonID, seasonID)
+    gameWorld.SetDict(ShareDefine.Def_Notify_WorldKey_CrossPKSeasonState, seasonState)
+    gameWorld.SetDict(ShareDefine.Def_Notify_WorldKey_CrossDailyActionState % ShareDefine.DailyActionID_CrossReamPK, matchState)
+    
+    if curSeasonState == 1 and seasonState == 2:
+        PlayerControl.WorldNotify(0, "NotifySeasonOver")
+        
+    # 通知地图服务器状态
+    GameWorld.SendMapServerMsgEx(ShareDefine.Def_Notify_WorldKey_CrossPKZoneID, zoneID)
+    GameWorld.SendMapServerMsgEx(ShareDefine.Def_Notify_WorldKey_CrossPKSeasonID, seasonID)
+    GameWorld.SendMapServerMsgEx(ShareDefine.Def_Notify_WorldKey_CrossPKSeasonState, seasonState)
+    GameWorld.SendMapServerMsgEx(ShareDefine.Def_Notify_WorldKey_CrossDailyActionState % ShareDefine.DailyActionID_CrossReamPK, matchState)
+    
+    # 广播玩家赛季相关状态变更
+    seasonStatePack = ChPyNetSendPack.tagGCCrossRealmPKSeasonState()
+    seasonStatePack.ZoneID = zoneID
+    seasonStatePack.SeasonID = seasonID
+    seasonStatePack.SeasonState = seasonState
+    seasonStatePack.MatchState = matchState
+    playerManager = GameWorld.GetPlayerManager()
+    for i in xrange(playerManager.GetPlayerCount()):
+        curPlayer = playerManager.GetPlayerByIndex(i)
+        if curPlayer == None or not curPlayer.GetInitOK():
+            continue
+        NetPackCommon.SendFakePack(curPlayer, seasonStatePack)
+    return
 
 def CrossServerMsg_PKMatchReqRet(retInfo):
     ## 跨服PK匹配请求结果
@@ -876,13 +1602,13 @@
     GameWorld.Log("===收到跨服服务器同步的跨服PK结果=== curServerGroupID=%s" % curServerGroupID)
     
     for playerID, overInfo in playerOverDict.items():
-        roomID, seasonID, timeStr, overType, winnerID, roundWinnerIDList, \
+        roomID, zoneID, seasonID, timeStr, overType, winnerID, roundWinnerIDList, \
             serverGroupID, pkScore, danLV, cWinCount, addScore, tagPlayerID, tagPlayerName, notifyState = overInfo
         if serverGroupID != curServerGroupID:
             GameWorld.DebugLog("    不是本服玩家,不处理!playerID=%s,serverGroupID=%s" % (playerID, serverGroupID))
             continue
         
-        sendMapOverInfo = [roomID, seasonID, timeStr, overType, winnerID, roundWinnerIDList, pkScore, danLV, cWinCount, addScore, tagPlayerID, tagPlayerName, notifyState]
+        sendMapOverInfo = [roomID, zoneID, seasonID, timeStr, overType, winnerID, roundWinnerIDList, pkScore, danLV, cWinCount, addScore, tagPlayerID, tagPlayerName, notifyState]
         player = GameWorld.GetPlayerManager().FindPlayerByID(playerID)
         if not player or PlayerControl.GetIsTJG(player):
             GameWorld.Log("    玩家不在线 或脱机中,先缓存,玩家上线后再同步,playerID=%s" % (playerID))
@@ -891,8 +1617,8 @@
         
         sysMsg = str(sendMapOverInfo)
         player.MapServer_QueryPlayerResult(0, 0, "CrossPKOverInfo", sysMsg, len(sysMsg))
-        GameWorld.Log("通知地图跨服PK结算: roomID=%s,seasonID=%s,timeStr=%s,overType=%s,winnerID=%s,roundWinnerIDList=%s, pkScore=%s,danLV=%s,cWinCount=%s,addScore=%s,tagPlayerID=%s,notifyState=%s,mapID=%s" 
-                      % (roomID, seasonID, timeStr, overType, winnerID, roundWinnerIDList, pkScore, danLV, cWinCount, addScore, tagPlayerID, notifyState, player.GetMapID()), playerID)
+        GameWorld.Log("通知地图跨服PK结算: roomID=%s,zoneID=%s,seasonID=%s,timeStr=%s,overType=%s,winnerID=%s,roundWinnerIDList=%s, pkScore=%s,danLV=%s,cWinCount=%s,addScore=%s,tagPlayerID=%s,notifyState=%s,mapID=%s" 
+                      % (roomID, zoneID, seasonID, timeStr, overType, winnerID, roundWinnerIDList, pkScore, danLV, cWinCount, addScore, tagPlayerID, notifyState, player.GetMapID()), playerID)
     return
 
 def __OnLoginNotifyPKOverInfo(curPlayer):

--
Gitblit v1.8.0