#!/usr/bin/python  
 | 
# -*- coding: GBK -*-  
 | 
#---------------------------------------------------------------------  
 | 
#  
 | 
#---------------------------------------------------------------------  
 | 
##@package PlayerFB  
 | 
# @todo: Íæ¼Ò¸±±¾  
 | 
#  
 | 
# @author: hxp  
 | 
# @date 2013-08-23  
 | 
# @version 1.5  
 | 
#  
 | 
# @note  
 | 
# @change: "2014-04-16 18:00" hxp Ôö¼Ó¼Ò×åboss¸±±¾½øÈëÅÐ¶Ï  
 | 
# @change: "2015-01-09 10:30" hxp ¸ÄΪGetRouteServerIndex  
 | 
# @change: "2015-03-20 15:00" hxp Ìõ¼þÅжÏÐÞ¸Ä  
 | 
# @change: "2015-10-22 23:00" hxp Ôö¼Ó¿ç·þPK  
 | 
# @change: "2017-01-04 12:00" hxp Ôö¼ÓÒì½çÈëÇÖ  
 | 
#---------------------------------------------------------------------  
 | 
#"""Version = 2017-01-04 12:00"""  
 | 
#---------------------------------------------------------------------  
 | 
import GameWorldBoss  
 | 
import PlayerFamilyBoss  
 | 
import PlayerHorsePetBoss  
 | 
import GameWorldFamilyWar  
 | 
import PlayerControl  
 | 
import PyGameData  
 | 
import IpyGameDataPY  
 | 
import PlayerDBGSEvent  
 | 
import PlayerTeam  
 | 
import GameWorld  
 | 
import ChConfig  
 | 
import IPY_PlayerDefine  
 | 
import CrossRealmPlayer  
 | 
import CrossRealmMsg  
 | 
import ShareDefine  
 | 
import CrossBoss  
 | 
  
 | 
#---------------------------------------------------------------------  
 | 
  
 | 
## ¿ç·þµØÍ¼¶¯Ì¬·ÖÅäµÄ¹¦ÄÜÏß·£¬Èç¹ûÓÐÈËÊýÉÏÏ޵ģ¬Ôòͬ·ÖÇøÍ¬µØÍ¼Íæ·¨µÄ¿ÉÄÜͬʱ´æÔÚ¶à¸öÏàͬ¹¦ÄÜÏß·µÄÊý¾Ý  
 | 
class CrossFuncLineInfo():  
 | 
      
 | 
    def __init__(self):  
 | 
        self.realMapID = 0  
 | 
        self.copyMapID = 0  
 | 
        self.funcLineDataCache = None # ¹¦ÄÜÏß·×Ô¶¨Ò建´æÊý¾Ý  
 | 
        return  
 | 
      
 | 
    def OnCopyMapClose(self):  
 | 
        self.realMapID = 0  
 | 
        self.copyMapID = 0  
 | 
        return  
 | 
  
 | 
## ¿ç·þµØÍ¼¶¯Ì¬·ÖÅäµÄÐéÄâÏß·ÐÅÏ¢  
 | 
class CrossCopyMapInfo():  
 | 
      
 | 
    def __init__(self, zoneID, funcLineID):  
 | 
        self.zoneID = zoneID  
 | 
        self.funcLineID = funcLineID  
 | 
        self.openState = IPY_PlayerDefine.fbosClosed  
 | 
        self.fbPlayerDict = {} # ¸±±¾ÖеÄÍæ¼ÒÐÅÏ¢ {playerID:serverGroupID, ...}  
 | 
        self.waitPlayerDict = {} # µÈ´ý½øÈëµÄÍæ¼ÒÐÅÏ¢ {playerID:[serverGroupID, tick], ...}  
 | 
        self.offlinePlayerDict = {} # µôÏßµÄÍæ¼ÒÐÅÏ¢£¬·ÇÖ÷¶¯Í˳öµÄ {playerID:serverGroupID, ...}  
 | 
        return  
 | 
      
 | 
    def OnRequestEnterCrossCopyMap(self, playerID, serverGroupID, tick, copyMapPlayerMax):  
 | 
        # ÒѾÔÚÇëÇó¶ÓÁÐÀ¿É½øÈë  
 | 
        if playerID in self.waitPlayerDict or not copyMapPlayerMax:  
 | 
            self.waitPlayerDict[playerID] = [serverGroupID, tick]  
 | 
            return True  
 | 
          
 | 
        # ÒƳýÇëÇó½øÈ볬ʱµÄÍæ¼Ò  
 | 
        for waitPlayerID, playerInfo in self.waitPlayerDict.items():  
 | 
            serverGroupID, requestTick = playerInfo  
 | 
            if tick - requestTick > 60000: # ÇëÇó½øÈëʱ¼ä±£Áô1·ÖÖÓ  
 | 
                self.waitPlayerDict.pop(waitPlayerID)  
 | 
                  
 | 
        # ÅжÏÊÇ·ñ³¬¹ýÈËÊýÉÏÏÞ  
 | 
        fbPlayerCount, waitPlayerCount = len(self.fbPlayerDict), len(self.waitPlayerDict)  
 | 
        if fbPlayerCount + waitPlayerCount >= copyMapPlayerMax:  
 | 
            return False  
 | 
          
 | 
        self.waitPlayerDict[playerID] = [serverGroupID, tick]  
 | 
        return True  
 | 
      
 | 
#---------------------------------------------------------------------  
 | 
def GetFBLineIpyData(mapID, lineID, isDefaultLine=True):  
 | 
    mapID = GetRecordMapID(mapID)  
 | 
    fbLineIpyData = IpyGameDataPY.GetIpyGameDataNotLog("FBLine", mapID, lineID)  
 | 
    if not fbLineIpyData and isDefaultLine:  
 | 
        #GameWorld.DebugLog("ûÓÐÖ¸¶¨¹¦ÄÜÏß·µÄÔòĬÈÏÈ¡0£¬ÔÙûÓеϰ¾ÍÊDz»ÐèÒªµÄmapID=%s, lineID=%s" % (mapID, lineID))  
 | 
        fbLineIpyData = IpyGameDataPY.GetIpyGameDataNotLog("FBLine", mapID, 0)  
 | 
    return fbLineIpyData  
 | 
  
 | 
## »ñÈ¡¼Ç¼ֵµÄmapID  
 | 
#  @param mapID ËùÒª²éµÄmapID  
 | 
#  @return  
 | 
#  @remarks Ò»°ãÓÃÓÚ¼¸ÕŵØÍ¼¹«ÓÃÒ»·Ý´æ´¢¼Ç¼£¬Èç×é¶Ó¸±±¾½øÈë´ÎÊý£¬CDʱ¼äµÈÊý¾ÝÐè¹²Ïí  
 | 
def GetRecordMapID(mapID):  
 | 
    DataMapIDDict = IpyGameDataPY.GetConfigEx("DataMapIDDict")  
 | 
    if not DataMapIDDict:  
 | 
        dMapIDDict = {}  
 | 
        ipyDataMgr = IpyGameDataPY.IPY_Data()  
 | 
        for i in xrange(ipyDataMgr.GetFBLineCount()):  
 | 
            ipyData = ipyDataMgr.GetFBLineByIndex(i)  
 | 
            dMapID = ipyData.GetDataMapID()  
 | 
            mID = ipyData.GetMapID()  
 | 
            dMapIDList= dMapIDDict.get(dMapID, [])  
 | 
            if mID not in dMapIDList:  
 | 
                dMapIDList.append(mID)  
 | 
                dMapIDDict[dMapID] = dMapIDList  
 | 
              
 | 
        for dMapID in dMapIDDict.keys():  
 | 
            if len(dMapIDDict[dMapID]) == 1:  
 | 
                dMapIDDict.pop(dMapID)  
 | 
        DataMapIDDict = IpyGameDataPY.SetConfigEx("DataMapIDDict", dMapIDDict)  
 | 
        #GameWorld.Log("¼ÓÔØDataMapIDDict=%s" % DataMapIDDict)  
 | 
          
 | 
    for dataMapID, mapIDList in DataMapIDDict.items():  
 | 
        if mapID in mapIDList:  
 | 
            return dataMapID  
 | 
    return mapID  
 | 
  
 | 
def ClientServerMsg_EnterFB(serverGroupID, msgData, tick):  
 | 
    ## ÊÕµ½×Ó·þÇëÇó½øÈ붯̬·ÖÅäµÄ¿ç·þ¸±±¾  
 | 
    playerID = msgData["PlayerID"]  
 | 
    mapID = msgData["MapID"]  
 | 
    funcLineID = msgData["FuncLineID"]  
 | 
      
 | 
    zoneIpyData = CrossRealmPlayer.GetCrossZoneIpyDataByServerGroupID(mapID, serverGroupID)  
 | 
    if not zoneIpyData:  
 | 
        return  
 | 
    zoneID = zoneIpyData.GetZoneID()  
 | 
      
 | 
    dynamicLineMaxPlayerCountDict = IpyGameDataPY.GetFuncEvalCfg("CrossDynamicLineMap", 2)  
 | 
    copyMapPlayerMax = dynamicLineMaxPlayerCountDict.get(mapID, 0) # 0Ϊ²»ÏÞÖÆÈËÊý£¬Ä¬Èϲ»ÏÞÖÆ  
 | 
    if mapID == ChConfig.Def_FBMapID_CrossDemonKing:  
 | 
        bossID = msgData["BossID"]  
 | 
        if not CrossBoss.GetCrossBossIsAliveOrCanReborn(zoneID, bossID):  
 | 
            GameWorld.DebugLog("µ±Ç°¿ç·þÑýÍõËÀÍö״̬£¬²»¿É½øÈë! serverGroupID=%s,funcLineID=%s,zoneID=%s,bossID=%s" % (serverGroupID, funcLineID, zoneID, bossID))  
 | 
            return  
 | 
          
 | 
    elif mapID in [ChConfig.Def_FBMapID_CrossGrasslandLing, ChConfig.Def_FBMapID_CrossGrasslandXian]:  
 | 
        pass  
 | 
          
 | 
    else:  
 | 
        return  
 | 
      
 | 
    mapCopyLineInfo = __GetCrossDynamicLineInfo(playerID, serverGroupID, mapID, funcLineID, zoneID, copyMapPlayerMax, tick)  
 | 
    if not mapCopyLineInfo:  
 | 
        return  
 | 
    realMapID, copyMapID, openState = mapCopyLineInfo  
 | 
    if openState != IPY_PlayerDefine.fbosOpen:  
 | 
        return  
 | 
      
 | 
    playerIDList = [playerID]  
 | 
    retInfo = [playerIDList, mapID, realMapID, copyMapID, funcLineID]  
 | 
    CrossRealmMsg.SendMsgToClientServer(ShareDefine.CrossServerMsg_EnterFBRet, retInfo, [serverGroupID])  
 | 
    return  
 | 
  
 | 
def CrossServerMsg_EnterFBRet(msgData, tick):  
 | 
    ## ÊÕµ½¿ç·þ·þÎñÆ÷¶¯Ì¬·ÖÅäµÄ¿ç·þ¸±±¾½øÈëÐÅÏ¢  
 | 
      
 | 
    playerIDList, dataMapID, mapID, copyMapID, funcLineID = msgData  
 | 
      
 | 
    for playerID in playerIDList:  
 | 
        curPlayer = GameWorld.GetPlayerManager().FindPlayerByID(playerID)  
 | 
        if not curPlayer:  
 | 
            continue  
 | 
        CrossRealmPlayer.SendCrossRealmReg(curPlayer, dataMapID, mapID, dataMapID, copyMapID, lineID=funcLineID)  
 | 
          
 | 
    return  
 | 
  
 | 
def __GetCrossDynamicLineInfo(playerID, serverGroupID, mapID, funcLineID, zoneID, copyMapPlayerMax, tick):  
 | 
    '''»ñÈ¡¿ç·þ·ÖÇø¶ÔÓ¦¶¯Ì¬·ÖÅäµÄ¸±±¾µØÍ¼ÐéÄâÏß·ÐÅÏ¢, ÓÉÓÚÐèÒªÖ§³Ö¶àµØÍ¼·ÖÁ÷£¬ËùÒÔÖ±½ÓÓÉGameServer¹ÜÀí·ÖÅä  
 | 
            Ã¿¸ö¹¦ÄÜÏß·֧³Ö°´ÈËÊý·ÖÁ÷£¬³¬¹ý×î´óÈËÊýºó¿É¿ªÆôÒ»ÌõÏàͬ¹¦ÄÜÏß·µÄÐéÄâÏß·½øÐзÖÁ÷£¬ËùÒÔͬһ·ÖÇøÍ¬Ò»µØÍ¼µÄ¹¦ÄÜÏß·ID¿ÉÄܶÔÓ¦¶àÌõÐéÄâÏß·  
 | 
    '''  
 | 
      
 | 
    zoneLineKey = (zoneID, funcLineID)  
 | 
    if mapID not in PyGameData.g_crossDynamicLineInfo:  
 | 
        PyGameData.g_crossDynamicLineInfo[mapID] = {}  
 | 
    zoneLineDict = PyGameData.g_crossDynamicLineInfo[mapID] # ¿ç·þ¶¯Ì¬Ïß·ÐÅÏ¢ {dataMapID:{(zoneID, funcLineID):[CrossFuncLineInfo, CrossFuncLineInfo, ...], ...}, ...}  
 | 
    if zoneLineKey not in zoneLineDict:  
 | 
        zoneLineDict[zoneLineKey] = []  
 | 
    funcLineObjList = zoneLineDict[zoneLineKey]  
 | 
      
 | 
    newFuncLineNum = None  
 | 
    newFuncLineObj = None  
 | 
    for index, funcLineObj in enumerate(funcLineObjList, 1):  
 | 
        realMapID, copyMapID = funcLineObj.realMapID, funcLineObj.copyMapID  
 | 
        if not realMapID:  
 | 
            if not newFuncLineObj:  
 | 
                newFuncLineNum, newFuncLineObj = index, funcLineObj  
 | 
            continue  
 | 
          
 | 
        key = (realMapID, copyMapID)  
 | 
        if key not in PyGameData.g_crossDynamicLineCopyMapInfo:  
 | 
            GameWorld.ErrLog("ÒѾ·ÖÅäµÄÐéÄâÏß·²»´æÔÚ»º´æ¶ÔÓ¦¹ØÏµÀzoneID=%s,funcLineID=%s,realMapID=%s,copyMapID=%s"   
 | 
                             % (zoneID, funcLineID, realMapID, copyMapID))  
 | 
            continue  
 | 
          
 | 
        copyMapObj = PyGameData.g_crossDynamicLineCopyMapInfo[key]  
 | 
        openState = copyMapObj.openState  
 | 
        if openState == IPY_PlayerDefine.fbosWaitForClose:  
 | 
            if not copyMapPlayerMax:  
 | 
                PlayerControl.CrossNotifyCode(serverGroupID, playerID, "HazyRegionClose")  
 | 
                return  
 | 
            #GameWorld.DebugLog("    ÐéÄâÏß·µÈ´ý¹Ø±ÕÖÐ! index=%s,realMapID=%s,copyMapID=%s" % (index, realMapID, copyMapID))  
 | 
            continue  
 | 
          
 | 
        canEnter = copyMapObj.OnRequestEnterCrossCopyMap(playerID, serverGroupID, tick, copyMapPlayerMax)  
 | 
        if canEnter:  
 | 
            #GameWorld.DebugLog("¿É½øÈ붯̬·Ö²¼µÄÐéÄâÏß·! realMapID=%s,copyMapID=%s,openState=%s" % (realMapID, copyMapID, openState))  
 | 
            #GameWorld.DebugLog("    ¸±±¾ÖеÄÍæ¼ÒID: %s" % copyMapObj.fbPlayerDict)  
 | 
            #GameWorld.DebugLog("    µÈ´ýÖеÄÍæ¼ÒID: %s" % copyMapObj.waitPlayerDict)  
 | 
            return realMapID, copyMapID, openState  
 | 
          
 | 
    dynamicLineMapDict = IpyGameDataPY.GetFuncEvalCfg("CrossDynamicLineMap", 1)  
 | 
    dynamicMapIDList = dynamicLineMapDict.get(mapID, [mapID])  
 | 
      
 | 
    openMapID, openCopyMapID = 0, 0  
 | 
    for realMapID in dynamicMapIDList:  
 | 
        maxCopyMapCount = PyGameData.g_crossMapCopyMapCountDict.get(realMapID, 0)  
 | 
        for copyMapID in xrange(maxCopyMapCount):  
 | 
            if (realMapID, copyMapID) not in PyGameData.g_crossDynamicLineCopyMapInfo:  
 | 
                openMapID, openCopyMapID = realMapID, copyMapID  
 | 
                break  
 | 
        if openMapID:  
 | 
            break  
 | 
    if not openMapID:  
 | 
        GameWorld.ErrLog("ûÓпÕÓàµÄÐéÄâÏß·£¬ÎÞ·¨¶¯Ì¬¿ªÆô¿ç·þ¸±±¾!mapID=%s, funcLineID=%s, zoneID=%s, dynamicMapIDList=%s"   
 | 
                         % (mapID, funcLineID, zoneID, dynamicMapIDList))  
 | 
        return  
 | 
      
 | 
    if newFuncLineObj == None:  
 | 
        newFuncLineObj = CrossFuncLineInfo()  
 | 
        funcLineObjList.append(newFuncLineObj)  
 | 
        newFuncLineNum = len(funcLineObjList)  
 | 
    realMapID, copyMapID = openMapID, openCopyMapID  
 | 
    newFuncLineObj.realMapID = realMapID  
 | 
    newFuncLineObj.copyMapID = copyMapID  
 | 
    funcLineDataCache = newFuncLineObj.funcLineDataCache  
 | 
      
 | 
    key = (realMapID, copyMapID)  
 | 
    copyMapObj = CrossCopyMapInfo(zoneID, funcLineID)  
 | 
    PyGameData.g_crossDynamicLineCopyMapInfo[key] = copyMapObj  
 | 
    copyMapObj.waitPlayerDict[playerID] = [serverGroupID, tick]  
 | 
    openState = copyMapObj.openState  
 | 
      
 | 
    propertyID = int("%d%03d%d" % (zoneID, funcLineID, newFuncLineNum))  
 | 
    GameWorld.DebugLog("²»´æÔڸ÷ÖÇø¹¦ÄÜÏß·ID£¬ÖØÐ·ÖÅä: zoneID=%s,funcLineID=%s,realMapID=%s,copyMapID=%s,propertyID=%s"   
 | 
                       % (zoneID, funcLineID, realMapID, copyMapID, propertyID))  
 | 
      
 | 
    # Í¨ÖªµØÍ¼¿ªÆôеĵØÍ¼ÐéÄâ·ÖÏß  
 | 
    msgInfo = str([copyMapID, propertyID, funcLineDataCache])  
 | 
    GameWorld.GetPlayerManager().MapServer_QueryPlayer(0, 0, 0, realMapID, "OpenFB", msgInfo, len(msgInfo))  
 | 
    return realMapID, copyMapID, openState  
 | 
  
 | 
def GetCrossDynamicLineZoneID(mapID, realMapID, copyMapID):  
 | 
    ## »ñÈ¡¿ç·þ¶¯Ì¬·ÖÅäµÄÐéÄâÏß·¶ÔÓ¦·ÖÇøID  
 | 
    zoneLineDict = PyGameData.g_crossDynamicLineInfo.get(mapID, {})  
 | 
    for key, funcLineObjList in zoneLineDict.items():  
 | 
        for funcLineObj in funcLineObjList:  
 | 
            if funcLineObj.realMapID == realMapID and funcLineObj.copyMapID == copyMapID:  
 | 
                zoneID = key[0]  
 | 
                return zoneID  
 | 
    return 0  
 | 
  
 | 
def OnCrossDynamicLineStateChange(msgList):  
 | 
    realMapID, copyMapID, state = msgList[:3]  
 | 
      
 | 
    if state == IPY_PlayerDefine.fbosWaitForClose:  
 | 
        funcLineDataCache = msgList[3]  
 | 
        OnCrossDynamicLineWaitForClose(realMapID, copyMapID, funcLineDataCache)  
 | 
    elif state == IPY_PlayerDefine.fbosClosed:  
 | 
        OnCrossDynamicLineClose(realMapID, copyMapID)  
 | 
    elif state == IPY_PlayerDefine.fbosOpen:  
 | 
        OnCrossDynamicLineOpen(realMapID, copyMapID)  
 | 
          
 | 
    return  
 | 
  
 | 
def OnCrossDynamicLineOpen(realMapID, copyMapID):  
 | 
    ## ¶¯Ì¬·ÖÅäÏß·µÄµØÍ¼ÐéÄâÏß·Æô¶¯³É¹¦  
 | 
      
 | 
    key = (realMapID, copyMapID)  
 | 
    if key not in PyGameData.g_crossDynamicLineCopyMapInfo:  
 | 
        return  
 | 
    copyMapObj = PyGameData.g_crossDynamicLineCopyMapInfo[key]  
 | 
    copyMapObj.openState = IPY_PlayerDefine.fbosOpen  
 | 
    funcLineID = copyMapObj.funcLineID  
 | 
      
 | 
    # Í¨Öª×Ó·þµÈ´ýÖеÄÍæ¼Ò¿ÉÒÔ½øÈ븱±¾  
 | 
    serverPlayerIDListDict = {}  
 | 
    for playerID, playerInfo in copyMapObj.waitPlayerDict.items():  
 | 
        serverGroupID = playerInfo[0]  
 | 
        if serverGroupID not in serverPlayerIDListDict:  
 | 
            serverPlayerIDListDict[serverGroupID] = []  
 | 
        playerIDList = serverPlayerIDListDict[serverGroupID]  
 | 
        playerIDList.append(playerID)  
 | 
          
 | 
    mapID = GetRecordMapID(realMapID)  
 | 
    GameWorld.Log("¶¯Ì¬·ÖÅäÐéÄâÏß·Æô¶¯³É¹¦£¬Í¨Öª×Ó·þµÈ´ýÍæ¼Ò¿É½øÈë: mapID=%s,realMapID=%s,copyMapID=%s,serverPlayerIDListDict=%s"   
 | 
                  % (mapID, realMapID, copyMapID, serverPlayerIDListDict))  
 | 
    for serverGroupID, playerIDList in serverPlayerIDListDict.items():  
 | 
        retInfo = [playerIDList, mapID, realMapID, copyMapID, funcLineID]  
 | 
        CrossRealmMsg.SendMsgToClientServer(ShareDefine.CrossServerMsg_EnterFBRet, retInfo, [serverGroupID])  
 | 
          
 | 
    #GameWorld.DebugLog("    PyGameData.g_crossDynamicLineInfo=%s" % PyGameData.g_crossDynamicLineInfo)  
 | 
    #GameWorld.DebugLog("    PyGameData.g_crossDynamicLineCopyMapInfo=%s" % PyGameData.g_crossDynamicLineCopyMapInfo)  
 | 
    return  
 | 
  
 | 
def OnCrossDynamicLineWaitForClose(realMapID, copyMapID, funcLineDataCache):  
 | 
    ## ¶¯Ì¬·ÖÅäÏß·µÄµØÍ¼ÐéÄâÏß·¹Ø±Õ  
 | 
          
 | 
    mapID = GetRecordMapID(realMapID)  
 | 
    GameWorld.Log("¶¯Ì¬·ÖÅäÐéÄâÏß·µÈ´ý¹Ø±Õ mapID=%s,realMapID=%s,copyMapID=%s,funcLineDataCache=%s" % (mapID, realMapID, copyMapID, funcLineDataCache))  
 | 
    zoneLineDict = PyGameData.g_crossDynamicLineInfo.get(mapID, {})   
 | 
    for key, funcLineObjList in zoneLineDict.items():  
 | 
        for funcLineObj in funcLineObjList:  
 | 
            if funcLineObj.realMapID == realMapID and funcLineObj.copyMapID == copyMapID:  
 | 
                funcLineObj.funcLineDataCache = funcLineDataCache  
 | 
                zoneID, funcLineID = key  
 | 
                GameWorld.Log("    ·ÖÇø¶ÔÓ¦¹¦ÄÜÏß·ÐéÄâ·ÖÏߵȴý¹Ø±Õ: zoneID=%s,mapID=%s,funcLineID=%s" % (zoneID, mapID, funcLineID))  
 | 
                break  
 | 
      
 | 
    key = (realMapID, copyMapID)  
 | 
    if key in PyGameData.g_crossDynamicLineCopyMapInfo:  
 | 
        copyMapObj = PyGameData.g_crossDynamicLineCopyMapInfo[key]  
 | 
        copyMapObj.openState = IPY_PlayerDefine.fbosWaitForClose  
 | 
          
 | 
    #GameWorld.DebugLog("    PyGameData.g_crossDynamicLineInfo=%s" % PyGameData.g_crossDynamicLineInfo)  
 | 
    #GameWorld.DebugLog("    PyGameData.g_crossDynamicLineCopyMapInfo=%s" % PyGameData.g_crossDynamicLineCopyMapInfo)  
 | 
    return  
 | 
  
 | 
def OnCrossDynamicLineClose(mapID, copyMapID):  
 | 
    ## ¶¯Ì¬·ÖÅäÏß·µÄµØÍ¼ÐéÄâÏß·¹Ø±Õ  
 | 
      
 | 
    dataMapID = GetRecordMapID(mapID)  
 | 
    GameWorld.Log("¶¯Ì¬·ÖÅäÐéÄâÏß·¹Ø±Õ dataMapID=%s,mapID=%s,copyMapID=%s" % (dataMapID, mapID, copyMapID))  
 | 
    zoneLineDict = PyGameData.g_crossDynamicLineInfo.get(dataMapID, {})   
 | 
    for key, funcLineObjList in zoneLineDict.items():  
 | 
        for funcLineObj in funcLineObjList:  
 | 
            if funcLineObj.realMapID == mapID and funcLineObj.copyMapID == copyMapID:  
 | 
                funcLineObj.OnCopyMapClose()  
 | 
                zoneID, funcLineID = key  
 | 
                GameWorld.Log("    ·ÖÇø¶ÔÓ¦¹¦ÄÜÏß·ÐéÄâ·ÖÏ߹رÕ: zoneID=%s,dataMapID%s,funcLineID=%s" % (zoneID, dataMapID, funcLineID))  
 | 
                break  
 | 
      
 | 
    key = (mapID, copyMapID)  
 | 
    copyMapObj = PyGameData.g_crossDynamicLineCopyMapInfo.pop(key, None)  
 | 
    if not copyMapObj:  
 | 
        return  
 | 
    #GameWorld.DebugLog("    PyGameData.g_crossDynamicLineInfo=%s" % PyGameData.g_crossDynamicLineInfo)  
 | 
    #GameWorld.DebugLog("    PyGameData.g_crossDynamicLineCopyMapInfo=%s" % PyGameData.g_crossDynamicLineCopyMapInfo)  
 | 
      
 | 
    playerCount = 0  
 | 
    zoneID = copyMapObj.zoneID  
 | 
    funcLineID = copyMapObj.funcLineID  
 | 
    playerCountInfo = [playerCount]  
 | 
    SyncClientServerCrossFBFuncLinePlayerCount(zoneID, mapID, funcLineID, playerCountInfo)  
 | 
      
 | 
    #Èç¹ûÐéÄâ·ÖÏ߹رÕʱ£¬ÓеôÏßµÄÍæ¼Ò£¬Ôò֪ͨ×Ó·þÖØÖÃÕâÐ©Íæ¼ÒµÄ¿ç·þ״̬  
 | 
    for playerID, serverGroupID in copyMapObj.offlinePlayerDict.items():  
 | 
        CrossRealmMsg.SendMsgToClientServer(ShareDefine.CrossServerMsg_ExitCrossServer, playerID, [serverGroupID])  
 | 
          
 | 
    return  
 | 
  
 | 
def OnCrossDynamicMapReset(msgList):  
 | 
    ## ¶¯Ì¬·ÖÅäÏß·µÄµØÍ¼ÖØÖà  
 | 
    realMapID, copyMapCount = msgList  
 | 
    mapID = GetRecordMapID(realMapID)  
 | 
    GameWorld.Log("¶¯Ì¬·ÖÅäÐéÄâÏß·µØÍ¼ÖØÖàmapID=%s,realMapID=%s,copyMapCount=%s" % (mapID, realMapID, copyMapCount))  
 | 
    PyGameData.g_crossMapCopyMapCountDict[realMapID] = copyMapCount  
 | 
      
 | 
    zoneLineDict = PyGameData.g_crossDynamicLineInfo.get(mapID, {})  
 | 
    for key, funcLineObjList in zoneLineDict.items():  
 | 
        for funcLineObj in funcLineObjList:  
 | 
            if funcLineObj.realMapID == realMapID:  
 | 
                funcLineObj.OnCopyMapClose()  
 | 
              
 | 
    for key in PyGameData.g_crossDynamicLineCopyMapInfo.keys():  
 | 
        if key[0] == realMapID:  
 | 
            PyGameData.g_crossDynamicLineCopyMapInfo.pop(key)  
 | 
              
 | 
    #GameWorld.DebugLog("    PyGameData.g_crossDynamicLineInfo=%s" % PyGameData.g_crossDynamicLineInfo)  
 | 
    #GameWorld.DebugLog("    PyGameData.g_crossDynamicLineCopyMapInfo=%s" % PyGameData.g_crossDynamicLineCopyMapInfo)   
 | 
    return  
 | 
  
 | 
def PlayerLoginLoadCrossMapOK(curPlayer):  
 | 
    ## Íæ¼ÒµÇ¼¿ç·þµØÍ¼  
 | 
      
 | 
    mapID, copyMapID = curPlayer.GetRealMapID(), curPlayer.GetFBID()  
 | 
    key = (mapID, copyMapID)  
 | 
    if key not in PyGameData.g_crossDynamicLineCopyMapInfo:  
 | 
        return  
 | 
    copyMapObj = PyGameData.g_crossDynamicLineCopyMapInfo[key]  
 | 
      
 | 
    playerID = curPlayer.GetPlayerID()  
 | 
    serverGroupID = PlayerControl.GetPlayerServerGroupID(curPlayer)  
 | 
    copyMapObj.waitPlayerDict.pop(playerID, None)  
 | 
    copyMapObj.offlinePlayerDict.pop(playerID, None)  
 | 
    copyMapObj.fbPlayerDict[playerID] = serverGroupID  
 | 
      
 | 
    #GameWorld.DebugLog("Íæ¼ÒµÇ¼¶¯Ì¬·ÖÅäµÄ¿ç·þµØÍ¼: GetMapID=%s,GetRealMapID=%s,GetFBID()=%s,serverGroupID=%s"   
 | 
    #                   % (curPlayer.GetMapID(), mapID, copyMapID, serverGroupID), playerID)  
 | 
    #GameWorld.DebugLog("    ¸±±¾ÖеÄÍæ¼ÒID: %s" % copyMapObj.fbPlayerDict)  
 | 
    #GameWorld.DebugLog("    µÈ´ýÖеÄÍæ¼ÒID: %s" % copyMapObj.waitPlayerDict)  
 | 
    #GameWorld.DebugLog("    ÀëÏßÖеÄÍæ¼ÒID: %s" % copyMapObj.offlinePlayerDict)  
 | 
      
 | 
    playerCount = len(copyMapObj.fbPlayerDict) # µÈ´ý½øÈëµÄÔÝʱ²»Ëã  
 | 
    zoneID = copyMapObj.zoneID  
 | 
    funcLineID = copyMapObj.funcLineID  
 | 
    playerCountInfo = [playerCount]  
 | 
    SyncClientServerCrossFBFuncLinePlayerCount(zoneID, mapID, funcLineID, playerCountInfo)  
 | 
    return  
 | 
  
 | 
def SyncClientServerCrossFBFuncLinePlayerCount(zoneID, mapID, funcLineID, playerCountInfo):  
 | 
    ## Í¬²½×Ó·þ¿ç·þ¸±±¾¹¦ÄÜÏß·ÈËÊý  
 | 
    ## ×¢Ò⣺ ´ËÈËÊý²»ÊÇÒ»¸ö¾«È·ÈËÊýÖµ£¬Ö»ÊÇÒ»¸ö´ó¸ÅÈËÊýÖµ£¬²»Óúܾ«È·£¬ÔÝÊ±Ö»Íæ¼Ò½øÈëʱͬ²½ÈËÊýÐÅÏ¢£¬Íæ¼ÒÍ˳öÔݲ»´¦Àí   
 | 
    mapID = GetRecordMapID(mapID)  
 | 
    if mapID not in ChConfig.Def_NeedCountFBFuncLinePlayerCrossMap:  
 | 
        return  
 | 
    zoneIpyData = CrossRealmPlayer.GetCrossZoneIpyDataByZoneID(mapID, zoneID)  
 | 
    if not zoneIpyData:  
 | 
        return  
 | 
    serverGroupIDList = zoneIpyData.GetServerGroupIDList()  
 | 
    playerCountInfo = [mapID, funcLineID, playerCountInfo]  
 | 
    CrossRealmMsg.SendMsgToClientServer(ShareDefine.CrossServerMsg_FBPlayerCount, playerCountInfo, serverGroupIDList)  
 | 
    return  
 | 
  
 | 
def OnPlayerDisconnectCrossServer(curPlayer):  
 | 
    ## Íæ¼ÒÀ뿪¿ç·þ·þÎñÆ÷  
 | 
      
 | 
    mapID, copyMapID = curPlayer.GetRealMapID(), curPlayer.GetFBID()  
 | 
    key = (mapID, copyMapID)  
 | 
    if key not in PyGameData.g_crossDynamicLineCopyMapInfo:  
 | 
        return  
 | 
    copyMapObj = PyGameData.g_crossDynamicLineCopyMapInfo[key]  
 | 
      
 | 
    playerID = curPlayer.GetPlayerID()  
 | 
    copyMapObj.waitPlayerDict.pop(playerID, None)  
 | 
    copyMapObj.fbPlayerDict.pop(playerID, None)  
 | 
      
 | 
    crossMapID = PlayerControl.GetCrossMapID(curPlayer)  
 | 
    # ²»ÊÇÖ÷¶¯Í˳öµÄ  
 | 
    if crossMapID:  
 | 
        copyMapObj.offlinePlayerDict[playerID] = PlayerControl.GetPlayerServerGroupID(curPlayer)  
 | 
      
 | 
    #GameWorld.DebugLog("Íæ¼ÒÍ˳ö¶¯Ì¬·ÖÅäµÄ¿ç·þµØÍ¼: GetMapID=%s,GetRealMapID=%s,GetFBID()=%s,crossMapID=%s"   
 | 
    #                   % (curPlayer.GetMapID(), mapID, copyMapID, crossMapID), playerID)  
 | 
    #GameWorld.DebugLog("    ¸±±¾ÖеÄÍæ¼ÒID: %s" % copyMapObj.fbPlayerDict)  
 | 
    #GameWorld.DebugLog("    µÈ´ýÖеÄÍæ¼ÒID: %s" % copyMapObj.waitPlayerDict)  
 | 
    #GameWorld.DebugLog("    ÀëÏßÖеÄÍæ¼ÒID: %s" % copyMapObj.offlinePlayerDict)  
 | 
    return  
 | 
  
 | 
def CrossServerMsg_FBPlayerCount(msgData):  
 | 
    ## ÊÕµ½¿ç·þ·þÎñÆ÷ͬ²½µÄ¸±±¾¹¦ÄÜÏß·ÈËÊýÐÅÏ¢  
 | 
      
 | 
    mapID, funcLineID, playerCountInfo = msgData  
 | 
    if mapID not in PyGameData.g_crossFBFuncLinePlayerCountInfo:  
 | 
        PyGameData.g_crossFBFuncLinePlayerCountInfo[mapID] = {}  
 | 
    fbLinePlayerInfoDict = PyGameData.g_crossFBFuncLinePlayerCountInfo[mapID]  
 | 
    fbLinePlayerInfoDict[funcLineID] = playerCountInfo  
 | 
    return  
 | 
  
 | 
##--------------------------------------------------------------------------------------------------  
 | 
  
 | 
## ÇëÇó½øÈ븱±¾·ÖÏß  
 | 
#  @param curPlayer: ÇëÇóÍæ¼Ò  
 | 
#  @param queryCallName: ÇëÇ󻨵÷Ãû  
 | 
#  @param sendCMD: ÇëÇóµÄÃüÁî ¸ù¾ÝÇëÇóÀàÐͺÍÇëÇóÃüÁîÀ´¾ö¶¨×îÖÕ²Ù×÷  
 | 
#  @return None  
 | 
def EnterFBLine(curPlayer, queryCallName, sendCMD, tick):  
 | 
    GameWorld.Log("EnterFBLine()...queryCallName=%s,sendCMD=%s" % (queryCallName, sendCMD), curPlayer.GetPlayerID())  
 | 
    playerManager = GameWorld.GetPlayerManager()  
 | 
    try:  
 | 
        mapInfo = eval(sendCMD)  
 | 
    except Exception, e:  
 | 
        GameWorld.ErrLog("EnterFBLine() sendCMD=%s error" % sendCMD)  
 | 
        return  
 | 
      
 | 
    if not mapInfo or len(mapInfo) < 2:  
 | 
        GameWorld.ErrLog("EnterFBLine() sendCMD=%s error!" % sendCMD)  
 | 
        return  
 | 
      
 | 
    #if mapInfo and len(mapInfo) == 2:  
 | 
    tagMapID = mapInfo[0]  
 | 
    tagLineID = mapInfo[1]  
 | 
      
 | 
    fbLineIpyData = GetFBLineIpyData(tagMapID, tagLineID)  
 | 
    sceneMapID = tagMapID if not fbLineIpyData else fbLineIpyData.GetMapID()  
 | 
    gameMap = GameWorld.GetMap(sceneMapID)  
 | 
    if not gameMap:  
 | 
        GameWorld.ErrLog("Ä¿±ê¸±±¾µØÍ¼²»´æÔÚ!tagMapID=%s,sceneMapID=%s" % (tagMapID, sceneMapID), curPlayer.GetPlayerID())  
 | 
        return  
 | 
      
 | 
    # ×é¶Ó¸±±¾, ÓжÓÎéµÄÇé¿ö²ÅÑéÖ¤ÆäËû¶ÓÔ±¿É·ñ½øÈ룬·ñÔò´ú±íµ¥È˽øÈë  
 | 
    if gameMap.GetMapFBType() == ChConfig.fbtTeam:  
 | 
        PlayerTeam.OnEnterFBTeamAsk(curPlayer, PlayerTeam.TeamFBAskType_Enter, tagMapID, tagLineID, tick)  
 | 
        return  
 | 
      
 | 
    #·âħ̳¸±±¾ÅжÏÀïÃæµÄBOSSÊÇ·ñµ½ÁËË¢ÐÂʱ¼ä  
 | 
    if tagMapID in ChConfig.WorldBossFBMapIDList:  
 | 
        bossID = mapInfo[2]  
 | 
        if not GameWorldBoss.GetBossIsAliveOrCanReborn(bossID):  
 | 
            return  
 | 
          
 | 
    elif tagMapID == ChConfig.Def_FBMapID_FamilyWar:  
 | 
        if not GameWorldFamilyWar.CheckPlayerCanEnterFamilyWarFBMap(curPlayer):  
 | 
            return  
 | 
          
 | 
    elif tagMapID == ChConfig.Def_FBMapID_FamilyBossMap:  
 | 
        if not PlayerFamilyBoss.CheckIsFamilyBossFBOpen(curPlayer.GetFamilyID(), tagMapID):  
 | 
            GameWorld.Log("EnterFBLine mapID=%s is familyBossFB, but is not open!" % tagMapID)  
 | 
            return  
 | 
    #ÊØÎÀÈ˻ʠÊÇ·ñÒÑ²Î¼Ó  
 | 
    elif tagMapID == ChConfig.Def_FBMapID_FamilyInvade:  
 | 
        if curPlayer.GetFamilyID() in PyGameData.g_swrhJoinRecord:  
 | 
            PlayerControl.NotifyCode(curPlayer, "TheEmperor1")  
 | 
            return  
 | 
    #¶àÏÉÃËBOSS ÊÇ·ñÒѽáÊø  
 | 
    elif tagMapID == ChConfig.Def_FBMapID_AllFamilyBoss:  
 | 
        if not PlayerFamilyBoss.IsInAllFamilyBoss(tagLineID):  
 | 
            #»î¶¯Î´¿ªÆô  
 | 
            return  
 | 
        if PlayerDBGSEvent.GetDBGSTrig_ByKey(PlayerDBGSEvent.Def_AllFamilyBossTime):  
 | 
            #BOSSÒѱ»»÷ɱ  
 | 
            return  
 | 
    #Æï³èBOSS ÊÇ·ñÒѽáÊø  
 | 
    elif tagMapID == ChConfig.Def_FBMapID_HorsePetBoss:  
 | 
        if not PlayerHorsePetBoss.IsInHorsePetBoss():  
 | 
            #»î¶¯Î´¿ªÆô  
 | 
            return  
 | 
        if PlayerDBGSEvent.GetDBGSTrig_ByKey(PlayerDBGSEvent.Def_HorsePetBossTime % tagLineID):  
 | 
            #BOSSÒѱ»»÷ɱ  
 | 
            return  
 | 
    # MapServer_QueryPlayer(int srcPlayerID, int queryType, int queryID, int mapID, char *callName, char *cmd,WORD cmdLen, int RouteServerIndex)  
 | 
    playerManager.MapServer_QueryPlayer(curPlayer.GetPlayerID(), ChConfig.queryType_EnterFB, 0, tagMapID,  
 | 
                queryCallName, sendCMD, len(sendCMD), curPlayer.GetRouteServerIndex())  
 | 
    return  
 |