5424 【后端】【1.4】跨服竞技场开发(增加赛季时间管理、赛区赛季榜单、玩家各种PK数据、各种奖励领取及邮件补发、王者法宝等级)
15个文件已修改
2个文件已添加
1710 ■■■■■ 已修改文件
ServerPython/CoreServerGroup/GameServer/PyNetPack.ini 22 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/CoreServerGroup/GameServer/Script/ChConfig.py 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/CoreServerGroup/GameServer/Script/GameWorldLogic/CrossRealmMsg.py 24 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/CoreServerGroup/GameServer/Script/GameWorldLogic/CrossRealmPK.py 784 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/CoreServerGroup/GameServer/Script/GameWorldLogic/GameWorldActionControl.py 5 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/CoreServerGroup/GameServer/Script/GameWorldLogic/GameWorldProcess.py 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/CoreServerGroup/GameServer/Script/Player/CrossRealmPlayer.py 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerControl.py 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerQuery.py 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/CoreServerGroup/GameServer/Script/PyDataManager.py 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/CoreServerGroup/GameServer/Script/PyGameDataStruct.py 80 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChConfig.py 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GM/Commands/SetCrossPK.py 122 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/ChPlayer.py 12 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerCrossRealmPK.py 518 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerEventCounter.py 30 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/RemoteQuery/GY_Query_CrossPKSeasonOrder.py 49 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/CoreServerGroup/GameServer/PyNetPack.ini
@@ -345,6 +345,28 @@
PacketSubCMD_4=0x04
PacketCallFunc_4=OnQueryBossInfo
[CrossRealmPK]
ScriptName = GameWorldLogic\CrossRealmPK.py
Writer = hxp
Releaser = hxp
RegType = 0
RegisterPackCount = 1
PacketCMD_1=0xC0
PacketSubCMD_1=0x01
PacketCallFunc_1=OnViewCrossPKBillboard
[CrossRealmPlayer]
ScriptName = Player\CrossRealmPlayer.py
Writer = hxp
Releaser = hxp
RegType = 0
RegisterPackCount = 1
PacketCMD_1=0xC0
PacketSubCMD_1=0x02
PacketCallFunc_1=OnViewCrossPlayerInfo
[PlayerXMZZ]
ScriptName = Player\PlayerXMZZ.py
Writer = xdh
ServerPython/CoreServerGroup/GameServer/Script/ChConfig.py
@@ -373,6 +373,9 @@
Def_WorldKey_BossRebornNeedPoint = "BossRebornNeedPoint"     #boss复活需要总点数
Def_WorldKey_BossIsAlive = 'BossIsAlive_%s'                  #boss是否活着
Def_WorldKey_IsGameWorldInit = 'IsGameWorldInit'             #GameWold是否初始化完成
Def_WorldKey_CrossPKZoneSeasonID = "CrossPKZoneSeasonID_%s"  #跨服PK赛区对应赛季,跨服服务器控制,参数(zoneID)
Def_WorldKey_CrossPKZoneSeasonState = "CrossPKZoneSeasonState_%s" #跨服PK赛区赛季状态,跨服服务器控制,参数(zoneID)0-未开启,1-开启中,2-已结束
Def_WorldKey_CrossPKBillboardSyncTick = "CrossPKBillboardSyncTick_%s_%s" #跨服PK本赛季排行榜同步tick,参数(zoneID, seasonID)
#---------------------------------------------------------------------
#个人时间间隔
TYPE_Player_Tick_Requestkey = 0                       # 玩家请求处理间隔
@@ -656,6 +659,8 @@
Def_PDict_GeTuiSet = "GetuiSet"     # 推送提醒的设置
Def_PDict_NoGeTuiTime = "NoGetuiTime"     # 推送提醒免打扰时间,将字符串组合数字
Def_PlayerKey_ViewCrossPKBillboardTick = "ViewCrossPKBillboardTick_%s_%s"  #查询PK排行榜tick,参数(zoneID, seasonID)
#跨服服务器广播类型
(
Def_PreeSetPlayer,                  #添加跨服预选赛参赛人员 0
ServerPython/CoreServerGroup/GameServer/Script/GameWorldLogic/CrossRealmMsg.py
@@ -55,6 +55,9 @@
            
        elif msgType == ShareDefine.ClientServerMsg_PKPrepareOK:
            CrossRealmPK.ClientServerMsg_PKPrepareOK(msgData, tick)
        elif msgType == ShareDefine.ClientServerMsg_PKBillboard:
            CrossRealmPK.ClientServerMsg_PKBillboard(serverGroupID, msgData)
                        
        elif msgType == ShareDefine.ClientServerMsg_GMCMD:
            GMShell.ClientServerMsg_GMCMD(msgData, tick)
@@ -134,6 +137,12 @@
        elif msgType == ShareDefine.CrossServerMsg_PKOverInfo:
            CrossRealmPK.CrossServerMsg_PKOverInfo(msgData)
            
        elif msgType == ShareDefine.CrossServerMsg_PKSeasonInfo:
            CrossRealmPK.CrossServerMsg_PKSeasonInfo(msgData)
        elif msgType == ShareDefine.CrossServerMsg_PKSyncBillboard:
            CrossRealmPK.CrossServerMsg_PKSyncBillboard(msgData)
        else:
            GameWorld.ErrLog("没有该信息类型逻辑处理!")
            
@@ -151,8 +160,17 @@
    ## 子服收到跨服服务器信息
    dataPack = IPY_GameServer.IPY_LGCrossLoginResult()
    result = dataPack.GetResult()
    if result == 1:
        GameWorld.Log("OnConnCorossServer conn success!!!")
    else:
    if result != 1:
        GameWorld.Log("--OnClientServerReceiveMsg  disconn")
        return
    GameWorld.Log("OnConnCorossServer conn success!!!")
    serverGroupID = GameWorld.GetServerGroupID()
    if GameWorld.IsCrossRealmOpen() and not GameWorld.IsCrossServer():
        GameWorld.Log("通知跨服主服务器链接成功, 可接收最新跨服活动状态及数据...")
        dataMsg = {"ServerGroupID":serverGroupID}
        SendMsgToCrossServer(ShareDefine.ClientServerMsg_ServerInitOK, dataMsg)
    return
    
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):
ServerPython/CoreServerGroup/GameServer/Script/GameWorldLogic/GameWorldActionControl.py
@@ -32,7 +32,7 @@
import GameWorldAverageLv
#import GameWorldMergeBoss
#import GameWorldMergeKing
#import GameWorldMergePK
import CrossRealmPK
import GameWorldFamilyWar
import PlayerFamilyParty
import IpyGameDataPY
@@ -1240,6 +1240,9 @@
    #骑宠争夺
    elif dictName == ShareDefine.Def_Notify_WorldKey_DailyActionState % ShareDefine.DailyActionID_FamilyRobBoss:
        GameWorldBoss.OnHorsePetRobBossActionChange(isOpen)
    #跨服PK
    elif dictName == ShareDefine.Def_Notify_WorldKey_DailyActionState % ShareDefine.DailyActionID_CrossReamPK:
        CrossRealmPK.OnCrossRealmPKDailyActionStateChange(isOpen)
    return
#------------------------------------------------------------------------------ 
ServerPython/CoreServerGroup/GameServer/Script/GameWorldLogic/GameWorldProcess.py
@@ -352,7 +352,8 @@
    GameWorldActionControl.Dispose_OperationActionState()
    GameWorldActionControl.Dispose_DailyActionState()
    GameWorldActionControl.Dispose_FBStateTime()
    #跨服PK
    CrossRealmPK.OnMinuteProcess()
    #处理重开服务器后, 活动继续开启逻辑根据天数
    #GameWorldActionControl.Dispose_Action_GoOn_ByDay(tick)
    #触发世界等级
@@ -1252,11 +1253,6 @@
    #GameWorldActionTeHui.OnGameServerInitOK() # 特惠活动初始化
    #子服启动成功告知跨服主服
    serverGroupID = GameWorld.GetServerGroupID()
    if GameWorld.IsCrossRealmOpen() and not GameWorld.IsCrossServer():
        GameWorld.Log("通知跨服主服务器启动成功, 可接收最新跨服活动状态及数据...")
        dataMsg = {"ServerGroupID":serverGroupID}
        CrossRealmMsg.SendMsgToCrossServer(ShareDefine.ClientServerMsg_ServerInitOK, dataMsg)
    GameWorld.Log("服务器启动成功: ServerGroupID=%s" % serverGroupID)
    return
@@ -1418,7 +1414,7 @@
    #GameWorldShopItem.OnMapServerInitOK()
    
    # 跨服PK
    #GameWorldMergePK.OnMapServerInitOK()
    CrossRealmPK.OnMapServerInitOK()
    #GameWorldMergeKing.OnMapServerInitOK()
    
    SendAllMapGlobalDropInfo() # 全局掉落控制
ServerPython/CoreServerGroup/GameServer/Script/Player/CrossRealmPlayer.py
@@ -112,4 +112,17 @@
#    NetPackCommon.SendFakePack(curPlayer, canEnterMServer)
    return
#// C0 02 查看跨服玩家信息 #tagCGViewCrossPlayerInfo
#
#struct    tagCGViewCrossPlayerInfo
#{
#    tagHead        Head;
#    DWORD        PlayerID;    // 跨服玩家ID
#};
def OnViewCrossPlayerInfo(index, clientData, tick):
    curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index)
    return
ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerControl.py
@@ -53,9 +53,9 @@
    curPlayer.NotifyCode(msgMark, __GetNotifyCodeList(msgParamList))
    return
def NotifyCodeToClientServer(serverGroupID, playerID, msgMark, msgParamList=[]):
def NotifyCodeToClientServer(serverGroupIDList, playerID, msgMark, msgParamList=[]):
    dataMsg = {"Type":"Player", "ID":playerID, "Mark":msgMark, "Param":msgParamList}
    CrossRealmMsg.SendMsgToClientServer(ShareDefine.CrossServerMsg_Notify, dataMsg, [serverGroupID])
    CrossRealmMsg.SendMsgToClientServer(ShareDefine.CrossServerMsg_Notify, dataMsg, serverGroupIDList)
    return
def CrossServerMsg_Notify(notifyInfoDict):
ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerQuery.py
@@ -566,6 +566,14 @@
        CrossRealmPK.SendCancelCrossRealmPKMatch(curPlayer, resultName)
        return
    
    #跨服PK请求玩家当前排名
    if callName == "CrossPKSeasonOrder":
        curPlayer = GameWorld.GetPlayerManager().FindPlayerByID(srcPlayerID)
        if not curPlayer:
            return
        CrossRealmPK.MapServer_QueryCrossPKSeasonOrder(curPlayer, eval(resultName))
        return
    #跨服注册结果
    if callName == "CrossRealmReg":
        CrossRealmPlayer.OnCrossRealmRegOK(srcPlayerID, eval(resultName), tick)
ServerPython/CoreServerGroup/GameServer/Script/PyDataManager.py
@@ -21,6 +21,7 @@
import PlayerXMZZ
import binascii
import PyGameData
import CrossRealmPK
def GetSavePyData():
    result = PyGameData.g_pyGameDataManager.GetSaveData()
@@ -43,6 +44,7 @@
class PyGameDataManager(object):
    def __init__(self):
        self.crossPKBillboard = CrossRealmPK.CrossPKBillboardManager()
        self.XMZZManager = PlayerXMZZ.XMZZManager()
        self.sealDemonManager = PlayerSealDemon.SealDemonManager()
        self.bossAttentionManager = GameWorldBoss.BossAttentionManager()
@@ -58,6 +60,7 @@
    def GetSaveData(self):
        buff = ""
        buff += self.crossPKBillboard.GetSaveData()
        buff += self.XMZZManager.GetSaveData()
        buff += self.sealDemonManager.GetSaveData()
        buff += self.bossAttentionManager.GetSaveData()
@@ -72,6 +75,7 @@
        return buff
    
    def LoadGameData(self, gameBuffer, pos):
        pos = self.crossPKBillboard.LoadPyGameData(gameBuffer, pos, len(gameBuffer))
        pos = self.XMZZManager.LoadPyGameData(gameBuffer, pos, len(gameBuffer))
        pos = self.sealDemonManager.LoadPyGameData(gameBuffer, pos, len(gameBuffer))
        pos = self.bossAttentionManager.LoadPyGameData(gameBuffer, pos, len(gameBuffer))
@@ -85,6 +89,10 @@
        pos = self.socialInfoManager.LoadPyGameData(gameBuffer, pos, len(gameBuffer))
        return pos
# 跨服竞技场排行榜管理
def GetCrossPKBillboardManager():
    return PyGameData.g_pyGameDataManager.crossPKBillboard
# 仙魔之争管理
def GetXMZZManager():
    return PyGameData.g_pyGameDataManager.XMZZManager
ServerPython/CoreServerGroup/GameServer/Script/PyGameDataStruct.py
@@ -15,6 +15,86 @@
from ctypes import (Structure, memset, memmove, sizeof, addressof, create_string_buffer, string_at)
import CommFunc
# 跨服竞技场PK排行榜 #tagDBCrossPKBillboard
class tagDBCrossPKBillboard(Structure):
    _pack_ = 1
    _fields_ = [
        ('ZoneID', ctypes.c_ubyte),
        ('SeasonID', ctypes.c_ubyte),
        ('PlayerID', ctypes.c_ulong),
        ('PlayerName', ctypes.c_char * 33),
        ('Job', ctypes.c_ubyte),
        ('FightPower', ctypes.c_ulong),
        ('RealmLV', ctypes.c_ushort),
        ('PKScore', ctypes.c_ulong),
        ('DanLV', ctypes.c_ubyte),
        ('Time', ctypes.c_ulong),
        ('ADOResult', ctypes.c_ulong),
    ]
    def __init__(self):
        Structure.__init__(self)
        self.clear()
    def clear(self):
        memset(addressof(self), 0, self.getLength())
    def readData(self, buf, pos = 0, length = 0):
        if not pos <= length:
            return -1
        if len(buf) < pos + self.getLength():
            return -1
        self.clear()
        memmove(addressof(self), buf[pos:], self.getLength())
        return self.getLength()
    def getBuffer(self):
        buf = create_string_buffer(self.getLength())
        memmove(addressof(buf), addressof(self), self.getLength())
        return string_at(addressof(buf), self.getLength())
    def getLength(self):
        return sizeof(tagDBCrossPKBillboard)
    def outputString(self):
        output = '''// 跨服竞技场PK排行榜 #tagDBCrossPKBillboard:
            ZoneID = %s,
            SeasonID = %s,
            PlayerID = %s,
            PlayerName = %s,
            Job = %s,
            FightPower = %s,
            RealmLV = %s,
            PKScore = %s,
            DanLV = %s,
            Time = %s,
            ADOResult = %s,
            '''%(
                self.ZoneID,
                self.SeasonID,
                self.PlayerID,
                self.PlayerName,
                self.Job,
                self.FightPower,
                self.RealmLV,
                self.PKScore,
                self.DanLV,
                self.Time,
                self.ADOResult,
            )
        return output
    #Char数组类型Set接口,使用该接口对此类型数据赋值,防止赋值的数据过长报错
    def SetPlayerName(self,Str):
        if len(Str)<=33:
            self.PlayerName = Str
        else:
            self.PlayerName = Str[:33]
#仙魔之争记录表#tagDBPyXMZZ
class tagDBPyXMZZ(Structure):
    _pack_ = 1
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChConfig.py
@@ -3850,7 +3850,17 @@
Def_PDict_CrossPK_WinCount = "CrossPK_WinCount" # 当前胜利次数
Def_PDict_CrossPK_CWinCount = "CrossPK_CWinCount" # 跨当前连胜次数
Def_PDict_CrossPK_TodayPKCount = "CrossPK_TodayPKCount" # 今日已PK次数
Def_PDict_CrossPK_TodayWinCount = "CrossPK_TodayWinCount" # 今日已胜利次数
Def_PDict_CrossPK_TodayBuyCount = "CrossPK_TodayBuyCount" # 今日已购买PK次数
Def_PDict_CrossPK_DayPKCountAwardState = "CrossPK_DayPKCountAwardState" # 每日匹配次数奖励记录,二进制位存储是否已领取,按匹配次数升序排序索引代表奖励位
Def_PDict_CrossPK_DayWinCountAwardState = "CrossPK_DayWinCountAwardState" # 每日胜利次数奖励记录,二进制位存储是否已领取,按胜利次数升序排序索引代表奖励位
Def_PDict_CrossPK_DanLVAwardState = "CrossPK_DanLVAwardState" # 段位达标奖励记录,二进制位存储是否已领取,按段位代表奖励位
Def_PDict_CrossPK_SeasonAwardState = "CrossPK_SeasonAwardState" # 赛季结算奖励是否已领取,优先排名奖励,未上榜可领段位奖励
Def_PDict_CrossPK_ZoneID = "CrossPK_ZoneID" # 玩家上次参与的赛区ID
Def_PDict_CrossPK_SeasonID = "CrossPK_SeasonID" # 玩家上次参与的赛季ID
Def_PDict_CrossPK_SeasonDanLV = "CrossPK_SeasonDanLV_%s" # 历史赛季段位,参数,赛季ID
Def_PDict_CrossPK_SeasonOrder = "CrossPK_SeasonOrder_%s" # 历史赛季名次,参数,赛季ID
Def_PDict_CrossPK_SeasonAwardLV = "CrossPK_SeasonAwardLV_%s" # 历史赛季奖励等级(一般是段位等级,排行奖励的在最高段位等级基础上增加),参数,赛季ID
#自动战斗设置记录
Def_PDict_AutoFightSetting = "AFSetting_%s_%s"
@@ -4603,6 +4613,7 @@
Def_Cost_GodWeapon, # 神兵
Def_Cost_FBHelpBattle, # 副本助战
Def_Cost_FBGatherSoulBoss, # 聚魂副本BOSS召唤 40
Def_Cost_CrossRealmPK, # 跨服PK
#-----------以下为暂时没用的,先不删除,如有新增消费点则放在这些之前------------
Def_Cost_RefreshArrestTask, # 刷新悬赏任务
Def_Cost_OffLineExp, # 兑换离线经验
@@ -4623,7 +4634,7 @@
Def_Cost_Trade, # 交易
Def_Cost_Rename, # 改名
Def_Cost_SkillLvUp, # 技能升级
) = range(2000, 2000 + 60)
) = range(2000, 2000 + 61)
Def_Cost_Reason_SonKey = "reason_name_son" # 消费点原因子类说明key
@@ -4711,6 +4722,7 @@
Def_Cost_GodWeapon:"GodWeapon",
Def_Cost_FBHelpBattle:"FBHelpBattle",
Def_Cost_FBGatherSoulBoss:"FBGatherSoulBoss",
Def_Cost_CrossRealmPK:"CrossRealmPK",
}
## -----------------------------------------------------
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GM/Commands/SetCrossPK.py
New file
@@ -0,0 +1,122 @@
#!/usr/bin/python
# -*- coding: GBK -*-
#-------------------------------------------------------------------------------
#
##@package GM.Commands.SetCrossPK
#
# @todo:设置玩家跨服PK活动数据
# @author hxp
# @date 2018-12-25
# @version 1.0
#
# 详细描述: 设置玩家跨服PK活动数据
#
#-------------------------------------------------------------------------------
#"""Version = 2018-12-25 21:30"""
#-------------------------------------------------------------------------------
import GameWorld
import PlayerControl
import PlayerCrossRealmPK
import ShareDefine
import ChConfig
#---------------------------------------------------------------------
#逻辑实现
## GM命令执行入口
#  @param curPlayer 当前玩家
#  @param list 参数列表 [npcID]
#  @return None
#  @remarks 函数详细说明.
def OnExec(curPlayer, msgList):
    if not msgList:
        __PrintHelp(curPlayer)
        return
    if len(msgList) == 1:
        if msgList[0] != 0:
            __PrintHelp(curPlayer)
            return
        # 重置数据
        PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_CrossPK_TotalScore, 0)
        PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_CrossPK_OnDayScore, 0)
        PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_CrossPK_DanLV, 0)
        PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_CrossPK_PKCount, 0)
        PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_CrossPK_WinCount, 0)
        PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_CrossPK_CWinCount, 0)
        PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_CrossPK_TodayPKCount, 0)
        PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_CrossPK_TodayWinCount, 0)
        PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_CrossPK_TodayBuyCount, 0)
        PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_CrossPK_DayPKCountAwardState, 0)
        PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_CrossPK_DayWinCountAwardState, 0)
        PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_CrossPK_DanLVAwardState, 0)
        PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_CrossPK_SeasonAwardState, 0)
        PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_CrossPK_ZoneID, 0)
        PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_CrossPK_SeasonID, 0)
        for i in xrange(1, 20):
            PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_CrossPK_SeasonDanLV % i, 0)
            PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_CrossPK_SeasonOrder % i, 0)
            PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_CrossPK_SeasonAwardLV % i, 0)
        GameWorld.DebugAnswer(curPlayer, "重置跨服PK数据OK!")
        PlayerCrossRealmPK.SyncCrossRealmPKPlayerInfo(curPlayer)
        PlayerCrossRealmPK.SyncCrossRealmPKAwardState(curPlayer)
        PlayerCrossRealmPK.SyncCrossRealmPKHisSeasonInfo(curPlayer)
        return
    if len(msgList) == 2 or len(msgList) % 2 == 0:
        setTypeDict = {0:[ChConfig.Def_PDict_CrossPK_TotalScore, "积分"],
                       1:[ChConfig.Def_PDict_CrossPK_OnDayScore, "过天积分"],
                       2:[ChConfig.Def_PDict_CrossPK_DanLV, "段位"],
                       3:[ChConfig.Def_PDict_CrossPK_PKCount, "PK次数"],
                       4:[ChConfig.Def_PDict_CrossPK_WinCount, "胜利次数"],
                       5:[ChConfig.Def_PDict_CrossPK_CWinCount, "连胜次数"],
                       6:[ChConfig.Def_PDict_CrossPK_TodayPKCount, "今日PK次数"],
                       7:[ChConfig.Def_PDict_CrossPK_TodayWinCount, "今日胜利次数"],
                       8:[ChConfig.Def_PDict_CrossPK_TodayBuyCount, "今日购买次数"],
                       }
        indexList = range(len(msgList))
        for i in indexList[::2]:
            setType, value = msgList[i:i+2]
            if setType not in setTypeDict:
                continue
            dictName, chName = setTypeDict[setType]
            PlayerControl.NomalDictSetProperty(curPlayer, dictName, value)
            GameWorld.DebugAnswer(curPlayer, "设置%s: %s" % (chName, value))
        mapZoneID = GameWorld.GetGameWorld().GetGameWorldDictByKey(ShareDefine.Def_Notify_WorldKey_CrossPKZoneID)
        mapSeasonID = GameWorld.GetGameWorld().GetGameWorldDictByKey(ShareDefine.Def_Notify_WorldKey_CrossPKSeasonID)
        PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_CrossPK_ZoneID, mapZoneID)
        PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_CrossPK_SeasonID, mapSeasonID)
        PlayerCrossRealmPK.SyncCrossRealmPKPlayerInfo(curPlayer)
        return
    if len(msgList) == 3:
        seasonID, setType, value = msgList
        setTypeDict = {0:[ChConfig.Def_PDict_CrossPK_SeasonDanLV, "段位"],
                       1:[ChConfig.Def_PDict_CrossPK_SeasonOrder, "名次"],
                       2:[ChConfig.Def_PDict_CrossPK_SeasonAwardLV, "奖励等级"],
                       }
        if setType not in setTypeDict:
            __PrintHelp(curPlayer)
            return
        dictName, chName = setTypeDict[setType]
        PlayerControl.NomalDictSetProperty(curPlayer, dictName % seasonID, value)
        GameWorld.DebugAnswer(curPlayer, "设置赛季%s%s: %s" % (seasonID, chName, value))
        return
    __PrintHelp(curPlayer)
    return
def __PrintHelp(curPlayer):
    GameWorld.DebugAnswer(curPlayer, "重置数据: SetCrossPK 0")
    GameWorld.DebugAnswer(curPlayer, "设置数据: SetCrossPK 类型  值")
    GameWorld.DebugAnswer(curPlayer, "类型:0-积分,1-过天积分,2-段位,3-PK次数,4-胜利次数,5-连胜次数")
    GameWorld.DebugAnswer(curPlayer, "6-今日PK次数,7-今日胜利次数,8-今日购买次数")
    GameWorld.DebugAnswer(curPlayer, "设置历史记录: SetCrossPK 赛季ID 类型 数值")
    GameWorld.DebugAnswer(curPlayer, "类型:0-段位,1-名次,2-奖励等级")
    return
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/ChPlayer.py
@@ -18,7 +18,6 @@
import GameMap
import ChConfig
import EventShell
import SkillShell
import BuffSkill
import PlayerEventCounter
import PlayerTeam
@@ -57,10 +56,8 @@
import PlayerLoginDayAward
import PlayerGodWeapon
import PlayerWorldAverageLv
import GameLogic_ManorWar
import PlayerGoldInvest
import PlayerActivity
import PlayerTeHui
import FBCommon
import PlayerBindJadeWheel
import BossHurtMng
@@ -70,15 +67,12 @@
import PlayerDienstgrad
import PlayerMixLoginDayAward
import PlayerFreeGoods
import ShopItemManage
import PlayerRecover
import GameLogic_IceLode
import PlayerEquipDecompose
import PlayerCoat
import PlayerGreatMaster
import PlayerGatherSoul
import PlayerMergeKing
import PlayerMergePK
import PlayerCrossRealmPK
import GameFuncComm
import PlayerMagicWeapon
import GameLogic_TrialTower
@@ -101,14 +95,12 @@
import QuestCommon
import PlayerTJG
import GameLogic_XMZZ
import GameLogic_SealDemon
import PlayerFlashSale
import PlayerFlashGiftbag
import PlayerCostRebate
import PlayerActTotalRecharge
import PlayerSpringSale
import PlayerFairyCeremony
import CrossRealmPlayer
import ChNetSendPack
import FamilyRobBoss
import FBHelpBattle
@@ -490,6 +482,8 @@
#    # 跨服匹配
#    PlayerMergePK.MergePKOnLogin(curPlayer)
#    PlayerMergeKing.MergePKOnLogin(curPlayer)
    # 跨服PK
    PlayerCrossRealmPK.DoPlayerLogin(curPlayer)
    
    # 自定义货币值同步
    PlayerControl.NotifyPlayerAllCurrency(curPlayer)
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerCrossRealmPK.py
@@ -17,33 +17,156 @@
import ShareDefine
import PlayerControl
import CrossRealmPlayer
import ChPyNetSendPack
import NetPackCommon
import IpyGameDataPY
import ChPyNetSendPack
import CrossRealmPlayer
import DataRecordPack
import IPY_GameWorld
import ItemControler
import ItemCommon
import GameWorld
import ChConfig
def DoPlayerOnDay(curPlayer):
    if GameWorld.IsCrossServer():
        return
    totalScore = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_CrossPK_TotalScore)
    if not totalScore:
        return
    PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_CrossPK_OnDayScore, totalScore)
    zoneID = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_CrossPK_ZoneID)
    seasonID = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_CrossPK_SeasonID)
    # 邮件发放未领取的每日PK次数奖励
    dayPKCountAwardDict = IpyGameDataPY.GetFuncEvalCfg("CrossRealmPKAward", 1, {})
    dayPKCount = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_CrossPK_TodayPKCount)
    dayPKCountAwardState = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_CrossPK_DayPKCountAwardState)
    SendDayPKAwardByMail(curPlayer, zoneID, seasonID, "PKCount", dayPKCount, dayPKCountAwardState, dayPKCountAwardDict, "CrossServer1")
    # 邮件发放未领取的每日胜利次数奖励
    dayWinCountAwardDict = IpyGameDataPY.GetFuncEvalCfg("CrossRealmPKAward", 2, {})
    dayWinCount = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_CrossPK_TodayWinCount)
    dayWinCountAwardState = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_CrossPK_DayWinCountAwardState)
    SendDayPKAwardByMail(curPlayer, zoneID, seasonID, "WinCount", dayWinCount, dayWinCountAwardState, dayWinCountAwardDict, "CrossServer2")
    # 重置每日奖励状态
    PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_CrossPK_TodayPKCount, 0)
    PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_CrossPK_TodayWinCount, 0)
    PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_CrossPK_TodayBuyCount, 0)
    PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_CrossPK_DayPKCountAwardState, 0)
    PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_CrossPK_DayWinCountAwardState, 0)
    SyncCrossRealmPKPlayerInfo(curPlayer)
    SyncCrossRealmPKAwardState(curPlayer)
    return
def IsCrossRealmPKOpen():
def DoPlayerLogin(curPlayer):
    if GameWorld.IsCrossServer():
        return
    mapZoneID = GameWorld.GetGameWorld().GetGameWorldDictByKey(ShareDefine.Def_Notify_WorldKey_CrossPKZoneID)
    mapSeasonID = GameWorld.GetGameWorld().GetGameWorldDictByKey(ShareDefine.Def_Notify_WorldKey_CrossPKSeasonID)
    if not mapZoneID or not mapSeasonID:
        return
    if not __CheckResetPlayerCrossPKData(curPlayer, mapZoneID, mapSeasonID):
        SyncCrossRealmPKPlayerInfo(curPlayer)
        SyncCrossRealmPKAwardState(curPlayer)
        SyncCrossRealmPKHisSeasonInfo(curPlayer)
    return
def IsCrossRealmPKMatchState():
    ## 跨服PK匹配赛是否开启
    return 1
    return GameWorld.GetGameWorld().GetGameWorldDictByKey(ShareDefine.Def_Notify_WorldKey_MergePKState) == ChConfig.Def_Action_Open
    return GameWorld.GetGameWorld().GetGameWorldDictByKey(ShareDefine.Def_Notify_WorldKey_CrossDailyActionState \
                                                          % ShareDefine.DailyActionID_CrossReamPK) == ChConfig.Def_Action_Open
def GetCrossPKZoneID():
    ## 获取本服跨服PK所属赛区
    return 1
def OnCrossRealmPKSeasonChange(value):
    ## 赛区赛季状态变更,规定所有赛区的赛季ID都一样,且赛季ID一定是自增的,所以这里只判断赛季ID变更即可
    if GameWorld.IsCrossServer():
        return
    mapZoneID = GameWorld.GetGameWorld().GetGameWorldDictByKey(ShareDefine.Def_Notify_WorldKey_CrossPKZoneID)
    mapSeasonID = GameWorld.GetGameWorld().GetGameWorldDictByKey(ShareDefine.Def_Notify_WorldKey_CrossPKSeasonID)
    if mapSeasonID == value:
        GameWorld.DebugLog("跨服PK赛季信息与地图当前值相同,不处理!")
        return
    GameWorld.Log("跨服PK赛季信息变更: mapSeasonID=%s,value=%s" % (mapSeasonID, value))
    mapSeasonID = value
    playerManager = GameWorld.GetPlayerManager()
    for i in xrange(playerManager.OnlineCount()):
        curPlayer = playerManager.OnlineAt(i)
        if not curPlayer or curPlayer.IsEmpty():
            continue
        #检查重置玩家信息
        __CheckResetPlayerCrossPKData(curPlayer, mapZoneID, mapSeasonID)
    return
def GetSeasonID():
    ## 获取当前赛季ID
    return 1
def __CheckResetPlayerCrossPKData(curPlayer, mapZoneID, mapSeasonID):
    ## 检查玩家赛区赛季状态数据
    playerID = curPlayer.GetPlayerID()
    zoneID = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_CrossPK_ZoneID)
    seasonID = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_CrossPK_SeasonID)
    if mapSeasonID == seasonID:
        GameWorld.DebugLog("玩家跨服PK赛季信息相同,不处理! mapSeasonID=%s,seasonID=%s" % (mapSeasonID, seasonID), playerID)
        return
    GameWorld.Log("玩家跨服PK赛区赛季信息不同! 处理相关数据! mapSeasonID=%s,seasonID=%s" % (mapSeasonID, seasonID), playerID)
    PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_CrossPK_SeasonID, mapSeasonID)
    playerDanLV = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_CrossPK_DanLV)
    danLVAwardState = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_CrossPK_DanLVAwardState)
def IsCrossRealmPKSeasonOpen():
    GameWorld.Log("开始新赛季,发放上赛季未领取的奖励,重置赛季数据! zoneID=%s,seasonID=%s,newSeasonID=%s,playerDanLV=%s,danLVAwardState=%s"
                  % (zoneID, seasonID, mapSeasonID, playerDanLV, danLVAwardState), playerID)
    # 邮件发放上赛季未领取的段位奖励、赛季奖励(排名或段位)
    for awardDanLV in xrange(playerDanLV + 1):
        danLVIpyData = IpyGameDataPY.GetIpyGameData("CrossRealmPKDan", awardDanLV)
        if not danLVIpyData:
            continue
        awardItemList = danLVIpyData.GetDanLVAwardList()
        if not awardItemList:
            continue
        if pow(2, awardDanLV) & danLVAwardState:
            GameWorld.DebugLog("    已经领取过该段位达标奖励!awardDanLV=%s,danLVAwardState=%s" % (awardDanLV, danLVAwardState), playerID)
            continue
        eventName = "DanLV"
        GameWorld.Log("    邮件补发未领取的段位达标奖励!awardDanLV=%s,danLVAwardState=%s,awardItemList=%s"
                      % (awardDanLV, danLVAwardState, awardItemList), playerID)
        mailDetail = {"EventName":eventName, "zoneID":zoneID, "seasonID":seasonID, "awardDanLV":awardDanLV,
                      "danLVAwardState":danLVAwardState, "mapSeasonID":mapSeasonID}
        PlayerControl.SendMailByKey("CrossServer3", [playerID], awardItemList, [seasonID, awardDanLV], detail=mailDetail)
        DR_GetCrossPKAward(curPlayer, zoneID, seasonID, eventName, True, mailDetail)
    # 查询 GameServer 玩家赛季排名
    if not curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_CrossPK_SeasonAwardState):
        OnQueryCrossPKSeasonOrderAward(curPlayer, zoneID, seasonID, True)
    # 重置状态
    PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_CrossPK_TotalScore, 0)
    PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_CrossPK_OnDayScore, 0)
    PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_CrossPK_DanLV, 0)
    PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_CrossPK_PKCount, 0)
    PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_CrossPK_WinCount, 0)
    PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_CrossPK_CWinCount, 0)
    PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_CrossPK_TodayPKCount, 0)
    PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_CrossPK_TodayWinCount, 0)
    PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_CrossPK_TodayBuyCount, 0)
    PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_CrossPK_DayPKCountAwardState, 0)
    PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_CrossPK_DayWinCountAwardState, 0)
    PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_CrossPK_DanLVAwardState, 0)
    PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_CrossPK_SeasonAwardState, 0)
    PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_CrossPK_ZoneID, mapZoneID)
    PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_CrossPK_SeasonID, mapSeasonID)
    SyncCrossRealmPKPlayerInfo(curPlayer)
    SyncCrossRealmPKAwardState(curPlayer)
    return True
#// C1 01 跨服PK匹配 #tagCMCrossRealmPKMatch
@@ -62,45 +185,33 @@
    if GameWorld.IsCrossServer():
        GameWorld.DebugLog("跨服服务器无法发起匹配!")
        return
    if not IsCrossRealmPKOpen():
        GameWorld.Log("OnRequestMergePK 跨服活动未开启,不可进行匹配!", playerID)
        PlayerControl.NotifyCode(curPlayer, "GeRen_hgg_21675")
    if GameWorld.GetGameWorld().GetGameWorldDictByKey(ShareDefine.Def_Notify_WorldKey_CrossPKSeasonState) != 1:
        GameWorld.DebugLog("OnRequestMergePK 跨服赛季未开启,不可进行匹配!", playerID)
        PlayerControl.NotifyCode(curPlayer, "SeasonIsNotOpen")
        return
    if not IsCrossRealmPKMatchState():
        GameWorld.DebugLog("OnRequestMergePK 跨服匹配未开启,不可进行匹配!", playerID)
        PlayerControl.NotifyCode(curPlayer, "MatchIsNotOpen")
        return
    
    GameWorld.Log("收到跨服PK匹配: type=%s,accID=%s" % (requestType, accID), playerID)
    
    # 进行匹配
    if requestType == 1:
#        pkCnt = __GetMergePKPDictValue(curPlayer, ChConfig.Def_PDict_MergePK_Cnt)
#        buyCnt = __GetMergePKPDictValue(curPlayer, ChConfig.Def_PDict_MergePK_BuyCnt)
#        unUsedBuyCnt = __GetMergePKPDictValue(curPlayer, ChConfig.Def_PDict_MergePK_UnUsedBuyCnt)
#        freeCnt, maxBuyCnt, moneyType, buyCostFormat = ReadChConfig.GetEvalChConfig("MergePK_BuyCost")
#
#        # 超出免费次数 且 无可用的已购买次数  则需购买次数
#        if pkCnt >= freeCnt and unUsedBuyCnt <= 0:
#
#            if buyCnt >= maxBuyCnt:
#                GameWorld.Log("    已达到最大可购买PK次数,不可再买!:buyCnt=%s,maxBuyCnt=%s,pkCnt=%s,unUsedBuyCnt=%s"
#                              % (buyCnt, maxBuyCnt, pkCnt, unUsedBuyCnt), playerID)
#                return
#
#            buyCost = eval(buyCostFormat)
#            infoDict = {"pkCnt":pkCnt, "freeCnt":freeCnt, "buyCnt":buyCnt, "buyCost":buyCost}
#            if not PlayerControl.PayMoney(curPlayer, moneyType, buyCost, ChConfig.Def_Cost_BuyMergePKCnt, infoDict):
#                return
#
#            # 增加购买次数 及 未使用的购买次数
#            __SetMergePKPDictValue(curPlayer, ChConfig.Def_PDict_MergePK_BuyCnt, buyCnt + 1)
#            __SetMergePKPDictValue(curPlayer, ChConfig.Def_PDict_MergePK_UnUsedBuyCnt, unUsedBuyCnt + 1)
#            Sync_MergePKCnt(curPlayer)
#
#            GameWorld.Log("    购买PK次数消耗: pkCnt=%s,freeCnt=%s,buyCnt=%s,moneyType=%s,buyCost=%s"
#                              % (pkCnt, freeCnt, buyCnt, moneyType, buyCost), playerID)
        dayFreeMatchCountMax = IpyGameDataPY.GetFuncCfg("CrossRealmPKMatchCount", 1)
        if dayFreeMatchCountMax:
            todayPKCount  = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_CrossPK_TodayPKCount)
            todayBuyCount  = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_CrossPK_TodayBuyCount)
            if todayPKCount >= (dayFreeMatchCountMax + todayBuyCount):
                GameWorld.DebugLog("PK次数不足,无法发起匹配! todayPKCount=%s >= (dayFreeMatchCountMax=%s + todayBuyCount=%s)"
                                   % (todayPKCount, dayFreeMatchCountMax, todayBuyCount), playerID)
                return
        dataMsg = {
                   "seasonID":GetSeasonID(), # 赛季ID
                   "pkZoneID":GetCrossPKZoneID(), # PK赛区
                   "seasonID":GameWorld.GetGameWorld().GetGameWorldDictByKey(ShareDefine.Def_Notify_WorldKey_CrossPKSeasonID), # 赛季ID
                   "pkZoneID":GameWorld.GetGameWorld().GetGameWorldDictByKey(ShareDefine.Def_Notify_WorldKey_CrossPKZoneID), # PK赛区
                   "accID":accID,
                   "playerID":playerID,
                   "playerName":CrossRealmPlayer.GetCrossPlayerName(curPlayer),
@@ -108,8 +219,9 @@
                   "playerLV":curPlayer.GetLV(),
                   "maxHP":curPlayer.GetMaxHP(),
                   "fightPower":curPlayer.GetFightPower(),
                   "realmLV":curPlayer.GetOfficialRank(),
                   "pkScore":curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_CrossPK_TotalScore), # 当前积分
                   "danLV":1, #curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_CrossPK_DanLV), # 当前段位
                   "danLV":curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_CrossPK_DanLV), # 当前段位
                   "cWinCount":curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_CrossPK_CWinCount), # 连胜次数
                   "ondayScore":curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_CrossPK_OnDayScore), # 过天时的积分
                   }
@@ -127,19 +239,23 @@
def CrossServerMsg_PKOverInfo(curPlayer, overInfo):
    ## 收到跨服服务器的PK结算信息
    playerID = curPlayer.GetPlayerID()
    roomID, seasonID, timeStr, overType, winnerID, roundWinnerIDList, pkScore, danLV, cWinCount, addScore, tagPlayerID, tagPlayerName, notifyState = overInfo
    roomID, zoneID, seasonID, timeStr, overType, winnerID, roundWinnerIDList, pkScore, danLV, cWinCount, addScore, tagPlayerID, tagPlayerName, notifyState = overInfo
    isWinner = winnerID == playerID
    GameWorld.Log("地图收到跨服PK结算: isWinner=%s,roomID=%s,seasonID=%s,timeStr=%s,overType=%s,winnerID=%s,roundWinnerIDList=%s,pkScore=%s,danLV=%s,cWinCount=%s,addScore=%s,tagPlayerID=%s,notifyState=%s"
                  % (isWinner, roomID, seasonID, timeStr, overType, winnerID, roundWinnerIDList, pkScore, danLV, cWinCount, addScore, tagPlayerID, notifyState), playerID)
    curSeasonID = GetSeasonID()
    GameWorld.Log("地图收到跨服PK结算: isWinner=%s,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"
                  % (isWinner, roomID, zoneID, seasonID, timeStr, overType, winnerID, roundWinnerIDList, pkScore, danLV, cWinCount, addScore, tagPlayerID, notifyState), playerID)
    curSeasonID = GameWorld.GetGameWorld().GetGameWorldDictByKey(ShareDefine.Def_Notify_WorldKey_CrossPKSeasonID)
    if curSeasonID != seasonID:
        GameWorld.Log("    非本赛季的结算信息,不处理!curSeasonID=%s,seasonID=%s" % (curSeasonID, seasonID), playerID)
        return
    
    # 赛季是否已结算
    if not IsCrossRealmPKSeasonOpen():
        GameWorld.Log("    赛季已经结算过了,不处理!seasonID=%s" % (seasonID), playerID)
    # 赛季已关闭
    if GameWorld.GetGameWorld().GetGameWorldDictByKey(ShareDefine.Def_Notify_WorldKey_CrossPKSeasonState) != 1:
        GameWorld.Log("    赛季已关闭,不处理!seasonID=%s" % (seasonID), playerID)
        return
    PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_CrossPK_ZoneID, zoneID)
    PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_CrossPK_SeasonID, seasonID)
    PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_CrossPK_SeasonDanLV % seasonID, danLV)
    
    PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_CrossPK_TotalScore, pkScore)
    PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_CrossPK_DanLV, danLV)
@@ -157,7 +273,12 @@
    if GameWorld.CheckTimeIsSameServerDayEx(GameWorld.ChangeTimeStrToNum(timeStr)):
        todayPKCount = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_CrossPK_TodayPKCount) + 1
        PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_CrossPK_TodayPKCount, todayPKCount)
        if isWinner:
            todayWinCount = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_CrossPK_TodayWinCount) + 1
            PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_CrossPK_TodayWinCount, todayWinCount)
    SyncCrossRealmPKPlayerInfo(curPlayer)
    ## 跨服已经通知过了,证明还在跨服服务器,不做以下的处理
    if notifyState:
        return
@@ -186,7 +307,30 @@
#};
def OnCrossRealmPKBuy(index, clientData, tick):
    curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index)
    playerID = curPlayer.GetPlayerID()
    dayFreeMatchCountMax = IpyGameDataPY.GetFuncCfg("CrossRealmPKMatchCount", 1)
    if not dayFreeMatchCountMax:
        GameWorld.DebugLog("每日匹配次数没有限制,不需要购买次数!", playerID)
        return
    dayBuyCountMax = IpyGameDataPY.GetFuncCfg("CrossRealmPKMatchCount", 2)
    todayBuyCount  = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_CrossPK_TodayBuyCount)
    if dayBuyCountMax and todayBuyCount >= dayBuyCountMax:
        GameWorld.DebugLog("今日购买次数已满,无法购买!todayBuyCount=%s" % (todayBuyCount), playerID)
        return
    
    costGold = eval(IpyGameDataPY.GetFuncCompileCfg("CrossRealmPKMatchCount", 3))
    costMoneyList = PlayerControl.HaveMoneyEx(curPlayer, ShareDefine.TYPE_Price_Gold_Paper_Money, costGold)
    if not costMoneyList:
        GameWorld.DebugLog("仙玉绑玉不足: todayBuyCount=%s,costGold=%s" % (todayBuyCount, costGold), playerID)
        return
    infoDict = {"Event":"BuyPKCount", "todayBuyCount":todayBuyCount}
    for moneyType, moneyNum in costMoneyList:
        PlayerControl.PayMoney(curPlayer, moneyType, moneyNum, ChConfig.Def_Cost_CrossRealmPK, infoDict)
    PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_CrossPK_TodayBuyCount, todayBuyCount + 1)
    GameWorld.DebugLog("购买跨服PK次数: todayBuyCount=%s" % (todayBuyCount), playerID)
    SyncCrossRealmPKPlayerInfo(curPlayer)
    return
@@ -200,31 +344,269 @@
#};
def OnCrossRealmPKGetAward(index, clientData, tick):
    curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index)
    if not curPlayer:
        return
    playerID = curPlayer.GetPlayerID()
    awardType = clientData.AwardType
    awardData = clientData.AwardData
    zoneID = GameWorld.GetGameWorld().GetGameWorldDictByKey(ShareDefine.Def_Notify_WorldKey_CrossPKZoneID)
    seasonID = GameWorld.GetGameWorld().GetGameWorldDictByKey(ShareDefine.Def_Notify_WorldKey_CrossPKSeasonID)
    if not zoneID or not seasonID:
        GameWorld.DebugLog("当前没有跨服PK赛季, 无法领取奖励! zoneID=%s,seasonID=%s" % (zoneID, seasonID))
        return
    
    if awardType == 1:
        awardPKCount = awardData
        playerTodayPKCount = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_CrossPK_TodayPKCount)
        GameWorld.DebugLog("玩家领取每日匹配次数奖励! awardPKCount=%s,playerTodayPKCount=%s" % (awardPKCount, playerTodayPKCount), playerID)
        if playerTodayPKCount < awardPKCount:
            GameWorld.DebugLog("    PK次数不足,无法领取!", playerID)
            return
        dayPKCountAwardDict = IpyGameDataPY.GetFuncEvalCfg("CrossRealmPKAward", 1, {}) # {"次数":[[物品ID,个数,是否绑定], ...], ...}
        awardPKCountList = dayPKCountAwardDict.keys()
        awardPKCountList.sort()
        awardPKCountStr = str(awardPKCount)
        if awardPKCountStr not in awardPKCountList:
            GameWorld.DebugLog("    没有该PK次数奖励!")
            return
        awardIndex = awardPKCountList.index(awardPKCountStr)
        awardStateDictName = ChConfig.Def_PDict_CrossPK_DayPKCountAwardState
        awardItemList = dayPKCountAwardDict[awardPKCountStr]
        eventName = "PKCount"
        drDataDict = {"awardPKCount":awardPKCount}
    elif awardType == 2:
        awardWinCount = awardData
        playerTodayWinCount = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_CrossPK_TodayWinCount)
        GameWorld.DebugLog("玩家领取每日胜利次数奖励! awardWinCount=%s,playerTodayWinCount=%s" % (awardWinCount, playerTodayWinCount), playerID)
        if playerTodayWinCount < awardWinCount:
            GameWorld.DebugLog("    胜利次数不足,无法领取!", playerID)
            return
        dayWinCountAwardDict = IpyGameDataPY.GetFuncEvalCfg("CrossRealmPKAward", 2, {}) # {"次数":[[物品ID,个数,是否绑定], ...], ...}
        awardWinCountList = dayWinCountAwardDict.keys()
        awardWinCountList.sort()
        awardWinCountStr = str(awardWinCount)
        if awardWinCountStr not in awardWinCountList:
            GameWorld.DebugLog("    没有该胜利次数奖励!", playerID)
            return
        awardIndex = awardWinCountList.index(awardWinCountStr)
        awardStateDictName = ChConfig.Def_PDict_CrossPK_DayWinCountAwardState
        awardItemList = dayWinCountAwardDict[awardWinCountStr]
        eventName = "WinCount"
        drDataDict = {"awardWinCount":awardWinCount}
    elif awardType == 3:
        awardDanLV = awardData
        playerDanLV = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_CrossPK_DanLV)
        GameWorld.DebugLog("玩家领取段位达标奖励! awardDanLV=%s,playerDanLV=%s" % (awardDanLV, playerDanLV), playerID)
        if playerDanLV < awardDanLV:
            GameWorld.DebugLog("    段位未达标,无法领取!", playerID)
            return
        danLVIpyData = IpyGameDataPY.GetIpyGameData("CrossRealmPKDan", awardDanLV)
        if not danLVIpyData:
            return
        awardIndex = awardDanLV
        awardStateDictName = ChConfig.Def_PDict_CrossPK_DanLVAwardState
        awardItemList = danLVIpyData.GetDanLVAwardList()
        eventName = "DanLV"
        drDataDict = {"awardDanLV":awardDanLV}
    elif awardType == 4:
        GameWorld.DebugLog("玩家领取赛季结算奖励!", playerID)
        if GameWorld.GetGameWorld().GetGameWorldDictByKey(ShareDefine.Def_Notify_WorldKey_CrossPKSeasonState) != 2:
            GameWorld.DebugLog("非赛季结算阶段,不可领取!", playerID)
            return
        if curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_CrossPK_SeasonAwardState):
            GameWorld.DebugLog("已经领取过该奖励,不可领取!", playerID)
            return
        # 查询 GameServer 玩家赛季排名
        OnQueryCrossPKSeasonOrderAward(curPlayer, zoneID, seasonID, False)
        return
    else:
        return
    if not awardItemList:
        GameWorld.DebugLog("该奖励没有配置奖励物品!", playerID)
        return
    awardState = curPlayer.NomalDictGetProperty(awardStateDictName)
    if pow(2, awardIndex) & awardState:
        GameWorld.DebugLog("    已经领取过该奖励!awardIndex=%s,awardState=%s" % (awardIndex, awardState), playerID)
        return
    needSpace = len(awardItemList)
    # 背包空间
    packSpace = ItemCommon.GetItemPackSpace(curPlayer, IPY_GameWorld.rptItem, needSpace)
    if packSpace < needSpace:
        PlayerControl.NotifyCode(curPlayer, "GeRen_lhs_202580")
        return
    awardState |= pow(2, awardIndex)
    PlayerControl.NomalDictSetProperty(curPlayer, awardStateDictName, awardState)
    SyncCrossRealmPKAwardState(curPlayer)
    GameWorld.DebugLog("玩家领取跨服PK奖励! awardType=%s,awardData=%s,awardIndex=%s,awardState=%s,awardItemList=%s"
                       % (awardType, awardData, awardIndex, awardState, awardItemList), playerID)
    drDataDict.update({"awardIndex":awardIndex, "awardState":awardState, "awardItemList":awardItemList})
    for itemID, itemCnt, isBind in awardItemList:
        ItemControler.GivePlayerItem(curPlayer, itemID, itemCnt, isBind, [IPY_GameWorld.rptItem])
    DR_GetCrossPKAward(curPlayer, zoneID, seasonID, eventName, False, drDataDict)
    return
def SendDayPKAwardByMail(curPlayer, zoneID, seasonID, eventName, dataCount, awardState, awardItemDict, mailTypeKey):
    ## 邮件发放未领取的每日奖励
    playerID = curPlayer.GetPlayerID()
    awardCountList = awardItemDict.keys()
    awardCountList.sort()
    for i, awardCountStr in enumerate(awardCountList):
        awardCount = int(awardCountStr)
        if dataCount < awardCount:
            GameWorld.DebugLog("跨服PK每日奖励次数不足: eventName=%s,i=%s,awardCount=%s > dataCount=%s" % (eventName, i, awardCount, dataCount), playerID)
            break
        if pow(2, i) & awardState:
            GameWorld.DebugLog("已领取该跨服PK每日奖励: eventName=%s,i=%s,awardCount=%s" % (eventName, i, awardCount), playerID)
            continue
        awardItemList = awardItemDict[awardCountStr]
        GameWorld.Log("邮件发放跨服PK未领取的每日奖励: zoneID=%s,seasonID=%s,eventName=%s,i=%s,awardCount=%s,dataCount=%s,awardState=%s,awardItemList=%s"
                      % (zoneID, seasonID, eventName, i, awardCount, dataCount, awardState, awardItemList), playerID)
        mailDetail = {"EventName":eventName, "zoneID":zoneID, "seasonID":seasonID, "awardCount":awardCount, "awardState":awardState}
        PlayerControl.SendMailByKey(mailTypeKey, [playerID], awardItemList, [awardCount], detail=mailDetail)
        DR_GetCrossPKAward(curPlayer, zoneID, seasonID, eventName, True, mailDetail)
    return
def OnQueryCrossPKSeasonOrderAward(curPlayer, zoneID, seasonID, isMail):
    # 查询 GameServer 玩家赛季排名
    playerID = curPlayer.GetPlayerID()
    danLV = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_CrossPK_DanLV)
    eventName, eventData = "SeasonAward", [danLV, isMail]
    sendMsg = str([zoneID, seasonID, eventName, eventData])
    GameWorld.GetPlayerManager().GameServer_QueryPlayerResult(playerID, 0, 0, "CrossPKSeasonOrder", sendMsg, len(sendMsg))
    GameWorld.Log("查询GameServer玩家赛区赛季排名: zoneID=%s, seasonID=%s, sendMsg=%s" % (zoneID, seasonID, sendMsg), playerID)
    return
def GameServer_CrossPKSeasonOrder(curPlayer, msgList):
    zoneID, seasonID, eventName, eventData, order = msgList
    # 领取赛季奖励
    if eventName == "SeasonAward":
        danLV, isMail = eventData
        DoGetPKSeasonAward(curPlayer, eventName, zoneID, seasonID, order, danLV, isMail)
    return
def DoGetPKSeasonAward(curPlayer, eventName, zoneID, seasonID, order, danLV, isMail):
    ## 执行发放赛季结算奖励,名次奖励与最高段位奖励互斥,优先名次奖励
    awardItemList = []
    seasonAwardLV = danLV
    playerID = curPlayer.GetPlayerID()
    mapSeasonID = GameWorld.GetGameWorld().GetGameWorldDictByKey(ShareDefine.Def_Notify_WorldKey_CrossPKSeasonID)
    GameWorld.Log("发放玩家跨服PK赛季结算奖励! zoneID=%s,seasonID=%s,order=%s,danLV=%s,isMail=%s,seasonAwardLV=%s,mapSeasonID=%s"
                  % (zoneID, seasonID, order, danLV, isMail, seasonAwardLV, mapSeasonID), playerID)
    mailTypeKey, mailParamList, mailDetail = "", [], {"EventName":eventName, "zoneID":zoneID, "seasonID":seasonID,
                                                      "order":order, "danLV":danLV, "mapSeasonID":mapSeasonID}
    if order > 0:
        PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_CrossPK_SeasonOrder % seasonID, order)
        seasonOrderAwardDict = IpyGameDataPY.GetFuncEvalCfg("CrossRealmPKAward", 3, {}) # {"名次":[[物品ID,个数,是否绑定], ...], ...}
        fromOrder, toOrder = 1, 1
        awardOrderList = sorted(seasonOrderAwardDict.keys())
        for i, awardOrderStr in enumerate(awardOrderList):
            awardOrder = int(awardOrderStr)
            if order <= awardOrder:
                toOrder = awardOrder
                awardItemList = seasonOrderAwardDict[awardOrderStr]
                maxDanLV = IpyGameDataPY.IPY_Data().GetCrossRealmPKDanCount() - 1 # 因为段位等级从0开始,所以最大段位等级要减1
                seasonAwardLV = maxDanLV + (len(awardOrderList) - i)
                GameWorld.Log("获得排名奖励, 更新奖励等级: awardOrderList=%s,i=%s,maxDanLV=%s,seasonAwardLV=%s" % (awardOrderList, i, maxDanLV, seasonAwardLV), playerID)
                mailTypeKey = "CrossServer4"
                mailParamList = [seasonID, fromOrder, toOrder]
                break
            fromOrder = awardOrder + 1
    # 没有奖励的话取段位奖励
    if not awardItemList:
        danLVIpyData = IpyGameDataPY.GetIpyGameData("CrossRealmPKDan", danLV)
        if not danLVIpyData:
            return
        awardItemList = danLVIpyData.GetSeasonDanLVAwardList()
        mailTypeKey = "CrossServer5"
        mailParamList = [seasonID, danLV]
    if not awardItemList:
        GameWorld.Log("没有玩家对应的赛季结算奖励!", playerID)
        return
    ## 发奖励之前需再判断一次,防止重复发包重复领取
    if curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_CrossPK_SeasonAwardState):
        GameWorld.Log("已经发放过赛季结算奖励!", playerID)
        return
    if seasonID == mapSeasonID:
        PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_CrossPK_SeasonAwardState, 1)
        SyncCrossRealmPKAwardState(curPlayer)
        GameWorld.Log("还是同一个赛季,设置赛季奖励已领取!")
    PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_CrossPK_SeasonAwardLV % seasonID, seasonAwardLV)
    if not isMail:
        needSpace = len(awardItemList)
        packSpace = ItemCommon.GetItemPackSpace(curPlayer, IPY_GameWorld.rptItem, needSpace)
        if packSpace < needSpace:
            isMail = True
    if isMail:
        PlayerControl.SendMailByKey(mailTypeKey, [playerID], awardItemList, mailParamList, detail=mailDetail)
    else:
        for itemID, itemCnt, isBind in awardItemList:
            ItemControler.GivePlayerItem(curPlayer, itemID, itemCnt, isBind, [IPY_GameWorld.rptItem])
    GameWorld.Log("领取成功! awardItemList=%s" % (awardItemList), playerID)
    drDataDict = {"awardItemList":awardItemList, "order":order, "danLV":danLV, "seasonAwardLV":seasonAwardLV, "isMail":isMail}
    DR_GetCrossPKAward(curPlayer, zoneID, seasonID, eventName, isMail, drDataDict)
    return
def SyncCrossRealmPKPlayerInfo(curPlayer):
#    DWORD        Score;    // 当前积分
#    BYTE        DanLV;    // 当前段位
#    WORD        PKCount;    // PK次数
#    WORD        WinCount;    // 胜利次数
#    WORD        CWinCount;    // 连胜次数
#    BYTE        DayPKCount;    // 当日已PK次数
#    BYTE        DayWinCount;    // 当日已胜利次数
#    BYTE        DayBuyCount; // 当日已购买次数
    ## 同步玩家跨服PK玩家相关信息,积分、段位、相关次数等信息
    pkPlayerInfo = ChPyNetSendPack.tagMCCrossRealmPKPlayerInfo()
    pkPlayerInfo.Score = 0
    pkPlayerInfo.DanLV = 0
    pkPlayerInfo.Score = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_CrossPK_TotalScore)
    pkPlayerInfo.DanLV = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_CrossPK_DanLV)
    pkPlayerInfo.PKCount = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_CrossPK_PKCount)
    pkPlayerInfo.WinCount = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_CrossPK_WinCount)
    pkPlayerInfo.CWinCount = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_CrossPK_CWinCount)
    pkPlayerInfo.DayPKCount = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_CrossPK_TodayPKCount)
    pkPlayerInfo.DayWinCount = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_CrossPK_TodayWinCount)
    pkPlayerInfo.DayBuyCount = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_CrossPK_TodayBuyCount)
    NetPackCommon.SendFakePack(curPlayer, pkPlayerInfo)
    return
    
def SyncCrossRealmPKAwardState(curPlayer):
#    DWORD        DayPKCountAwardState;    // 每日匹配次数奖励记录,二进制位存储是否已领取,按匹配次数升序排序索引代表奖励位
#    DWORD        DayWinCountAwardState;    // 每日胜利次数奖励记录,二进制位存储是否已领取,按胜利次数升序排序索引代表奖励位
#    DWORD        DanLVAwardState;        // 段位达标奖励记录,二进制位存储是否已领取,按段位代表奖励位
#    BYTE        SeasonAwardState;    // 赛季结算奖励是否已领取
    ## 同步玩家跨服PK相关奖励状态
    pkAwardPack = ChPyNetSendPack.tagMCCrossRealmPKAwardState()
    pkAwardPack.DayPKCountAwardState = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_CrossPK_DayPKCountAwardState)
    pkAwardPack.DayWinCountAwardState = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_CrossPK_DayWinCountAwardState)
    pkAwardPack.DanLVAwardState = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_CrossPK_DanLVAwardState)
    pkAwardPack.SeasonAwardState = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_CrossPK_SeasonAwardState)
    NetPackCommon.SendFakePack(curPlayer, pkAwardPack)
    return
def SyncCrossRealmPKHisSeasonInfo(curPlayer):
    mapSeasonID = GameWorld.GetGameWorld().GetGameWorldDictByKey(ShareDefine.Def_Notify_WorldKey_CrossPKSeasonID)
    hisSeasonInfo = ChPyNetSendPack.tagMCCrossRealmPKPlayerHisSeasonInfo()
    hisSeasonInfo.SeasonList = []
    for seasonID in xrange(1, mapSeasonID + 1):
        seasonInfo = ChPyNetSendPack.tagMCCrossRealmPKPlayerHisSeason()
        seasonInfo.SeasonID = seasonID
        seasonInfo.DanLV = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_CrossPK_SeasonDanLV % seasonID)
        seasonInfo.Order = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_CrossPK_SeasonOrder % seasonID)
        seasonInfo.AwardLV = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_CrossPK_SeasonAwardLV % seasonID)
        hisSeasonInfo.SeasonList.append(seasonInfo)
    hisSeasonInfo.Count = len(hisSeasonInfo.SeasonList)
    NetPackCommon.SendFakePack(curPlayer, hisSeasonInfo)
    return
def DR_GetCrossPKAward(curPlayer, zoneID, seasonID, eventName, isMail, drDataDict):
    ## 记录领奖流向
    drDataDict.update({"zoneID":zoneID, "seasonID":seasonID, "isMail":isMail})
    DataRecordPack.SendEventPack("GetCrossPKAward_%s" % eventName, drDataDict, curPlayer)
    return
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerEventCounter.py
@@ -38,9 +38,7 @@
import GameLogInfo
import GameServerRefresh
import ShareDefine
import ReadCaptchaImage
import PlayerGameWallow
import ItemCommon
import Operate_PlayerBuyZhenQi
import PlayerSignDay
import PlayerCoin
@@ -52,30 +50,22 @@
import PlayerHorse
import PlayerLoginDayAward
import NPCCommon
import GameLogic_MergeBoss
import GameLogic_ManorWar
import FunctionNPCCommon
import PlayerGoldGift
import PlayerActivity
import PlayerTeHui
import PlayerBindJadeWheel
import PlayerAction
import PlayerTruck
import FBCommon
import PlayerDienstgrad
import PlayerSuccess
import PlayerMixLoginDayAward
import PlayerFreeGoods
import PlayerMagicWeapon
import ShopItemManage
import ChItem
import PlayerGoldInvest
import PlayerNewGuyCard
import PlayerMergeKing
import PlayerMergePK
import PlayerCrossRealmPK
import PlayerPet
import ReloadModule
import BossHurtMng
import PlayerRecover
import GameLogic_FamilyParty
@@ -1337,24 +1327,28 @@
    #===============================================================================================
    
    #领地争夺战
    elif key == ShareDefine.Def_Notify_WorldKey_ManorWar:
        GameLogic_ManorWar.OnManorWarStateChange(value, tick)
    #elif key == ShareDefine.Def_Notify_WorldKey_ManorWar:
    #    GameLogic_ManorWar.OnManorWarStateChange(value, tick)
    #定时商店刷新
    elif key.startswith(ShareDefine.Def_Notify_WorldKey_TimeShopRefreshTime[:-2]):
        ShopItemManage.OnTimeShopRefresh(key, value, tick)
        
    #跨服boss
    elif key == ShareDefine.Def_Notify_WorldKey_MergeBoss:
        GameLogic_MergeBoss.OnMergeBossStateChange(value, tick)
    #elif key == ShareDefine.Def_Notify_WorldKey_MergeBoss:
    #    GameLogic_MergeBoss.OnMergeBossStateChange(value, tick)
        
    # 跨服PK, 赛季开始时间不用处理,仅存储即可
    elif key in [ShareDefine.Def_Notify_WorldKey_MergePKDayID, ShareDefine.Def_Notify_WorldKey_MergePKSeasonID]:
        PlayerMergePK.OnMergePKActionChange(key, value)
    #elif key in [ShareDefine.Def_Notify_WorldKey_MergePKDayID, ShareDefine.Def_Notify_WorldKey_MergePKSeasonID]:
    #    PlayerMergePK.OnMergePKActionChange(key, value)
        
    # 跨服王者争霸
    elif key in [ShareDefine.Def_Notify_WorldKey_Merge_KingStartID, ShareDefine.Def_Notify_WorldKey_Merge_KingOverID]:
        PlayerMergeKing.OnMergeKingActionChange(key, value)
    #elif key in [ShareDefine.Def_Notify_WorldKey_Merge_KingStartID, ShareDefine.Def_Notify_WorldKey_Merge_KingOverID]:
    #    PlayerMergeKing.OnMergeKingActionChange(key, value)
    # 跨服PK
    elif key == ShareDefine.Def_Notify_WorldKey_CrossPKSeasonID:
        PlayerCrossRealmPK.OnCrossRealmPKSeasonChange(value)
        
    # 仙盟宴会
    elif key == ShareDefine.Def_Notify_WorldKey_FBFuncState % ChConfig.Def_FBMapID_FamilyParty:
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/RemoteQuery/GY_Query_CrossPKSeasonOrder.py
New file
@@ -0,0 +1,49 @@
#!/usr/bin/python
# -*- coding: GBK -*-
#-------------------------------------------------------------------------------
#
##@package Player.RemoteQuery.GY_Query_CrossPKSeasonOrder
#
# @todo:跨服PK赛季名次
# @author hxp
# @date 2018-12-25
# @version 1.0
#
# 详细描述: 跨服PK赛季名次
#
#-------------------------------------------------------------------------------
#"""Version = 2018-12-25 21:30"""
#-------------------------------------------------------------------------------
import GameWorld
import PlayerCrossRealmPK
#------------------------------------------------------------------------------
## 跨服赛报名调用接口
#  @param query_Type 请求类型
#  @param query_ID 请求的玩家ID
#  @param packCMDList 发包命令
#  @param tick 当前时间
#  @return "True" or "False" or ""
#  @remarks 函数详细说明.
def DoLogic(query_Type, query_ID, packCMDList, tick):
    return
#------------------------------------------------------------------------------
## 执行结果
#  @param curPlayer 发出请求的玩家
#  @param callFunName 功能名称
#  @param funResult 查询的结果
#  @param tick 当前时间
#  @return None
#  @remarks 函数详细说明.
def DoResult(curPlayer, callFunName, funResult, tick):
    msgList = eval(funResult)
    playerID = curPlayer.GetPlayerID()
    GameWorld.Log("GY_Query_CrossPKSeasonOrder msgList=%s" % (msgList), playerID)
    PlayerCrossRealmPK.GameServer_CrossPKSeasonOrder(curPlayer, msgList)
    return