| #!/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 CrossRealmPlayer  | 
| import CrossRealmMsg  | 
| import ShareDefine  | 
| import CrossBoss  | 
|   | 
| import random  | 
| #---------------------------------------------------------------------  | 
|   | 
| ## ¿ç·þµØÍ¼¶¯Ì¬·ÖÅäµÄ¹¦ÄÜÏß·£¬Èç¹ûÓÐÈËÊýÉÏÏ޵ģ¬Ôòͬ·ÖÇøÍ¬µØÍ¼Íæ·¨µÄ¿ÉÄÜͬʱ´æÔÚ¶à¸öÏàͬ¹¦ÄÜÏß·µÄÊý¾Ý  | 
| class CrossFuncLineInfo():  | 
|       | 
|     def __init__(self):  | 
|         self.mapID = 0  | 
|         self.copyMapID = 0  | 
|         self.funcLineDataCache = None # ¹¦ÄÜÏß·×Ô¶¨Ò建´æÊý¾Ý  | 
|         return  | 
|       | 
|     def OnCopyMapClose(self, funcLineDataCache):  | 
|         self.mapID = 0  | 
|         self.copyMapID = 0  | 
|         self.funcLineDataCache = funcLineDataCache  | 
|         return  | 
|   | 
| ## ¿ç·þµØÍ¼¶¯Ì¬·ÖÅäµÄÐéÄâÏß·ÐÅÏ¢  | 
| class CrossCopyMapInfo():  | 
|       | 
|     def __init__(self, zoneID, funcLineID):  | 
|         self.zoneID = zoneID  | 
|         self.funcLineID = funcLineID  | 
|         self.openState = 0  | 
|         self.fbPlayerDict = {} # ¸±±¾ÖеÄÍæ¼ÒÐÅÏ¢ {playerID:serverGroupID, ...}  | 
|         self.waitPlayerDict = {} # µÈ´ý½øÈëµÄÍæ¼ÒÐÅÏ¢ {playerID:[serverGroupID, tick], ...}  | 
|         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"]  | 
|     dataMapID = msgData["DataMapID"]  | 
|     funcLineID = msgData["FuncLineID"]  | 
|       | 
|     zoneIpyData = CrossRealmPlayer.GetCrossZoneIpyDataByServerGroupID(dataMapID, serverGroupID)  | 
|     if not zoneIpyData:  | 
|         return  | 
|     zoneID = zoneIpyData.GetZoneID()  | 
|       | 
|     copyMapPlayerMax = 0 # 0Ϊ²»ÏÞÖÆÈËÊý£¬Ä¬Èϲ»ÏÞÖÆ  | 
|     if dataMapID == 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 dataMapID in [ChConfig.Def_FBMapID_CrossGrasslandLing, ChConfig.Def_FBMapID_CrossGrasslandXian]:  | 
|         copyMapPlayerMax = 10  | 
|           | 
|     else:  | 
|         return  | 
|       | 
|     mapCopyLineInfo = __GetCrossDynamicLineInfo(playerID, serverGroupID, dataMapID, funcLineID, zoneID, copyMapPlayerMax, tick)  | 
|     if not mapCopyLineInfo:  | 
|         return  | 
|     mapID, copyMapID, openState = mapCopyLineInfo  | 
|     if not openState:  | 
|         return  | 
|       | 
|     playerIDList = [playerID]  | 
|     retInfo = [playerIDList, dataMapID, mapID, copyMapID, funcLineID]  | 
|     CrossRealmMsg.SendMsgToClientServer(ShareDefine.CrossServerMsg_EnterFBRet, retInfo, [serverGroupID])  | 
|     return  | 
|   | 
| def CrossServerMsg_EnterFBRet(msgData, tick):  | 
|     ## ÊÕµ½¿ç·þ·þÎñÆ÷¶¯Ì¬·ÖÅäµÄ¿ç·þ¸±±¾½øÈëÐÅÏ¢  | 
|       | 
|     playerIDList, dataMapID, mapID, copyMapID, funcLineID = msgData  | 
|       | 
|     dynamicLineMapDict = IpyGameDataPY.GetFuncEvalCfg("CrossDynamicLineMap", 1)  | 
|     if dataMapID not in dynamicLineMapDict:  | 
|         return  | 
|     mapPosInfo = dynamicLineMapDict[dataMapID][0]  | 
|     posX, posY = mapPosInfo[:2]  | 
|     dist = mapPosInfo[2] if len(mapPosInfo) > 2 else 0  | 
|     if dist > 0:  | 
|         posX, posY = random.randint(posX - dist, posX + dist), random.randint(posY - dist, posY + dist)  | 
|           | 
|     for playerID in playerIDList:  | 
|         curPlayer = GameWorld.GetPlayerManager().FindPlayerByID(playerID)  | 
|         if not curPlayer:  | 
|             continue  | 
|         CrossRealmPlayer.SendCrossRealmReg(curPlayer, dataMapID, mapID, dataMapID, copyMapID, posX, posY, lineID=funcLineID)  | 
|           | 
|     return  | 
|   | 
| def __GetCrossDynamicLineInfo(playerID, serverGroupID, dataMapID, funcLineID, zoneID, copyMapPlayerMax, tick):  | 
|     '''»ñÈ¡¿ç·þ·ÖÇø¶ÔÓ¦¶¯Ì¬·ÖÅäµÄ¸±±¾µØÍ¼ÐéÄâÏß·ÐÅÏ¢, ÓÉÓÚÐèÒªÖ§³Ö¶àµØÍ¼·ÖÁ÷£¬ËùÒÔÖ±½ÓÓÉGameServer¹ÜÀí·ÖÅä  | 
|             Ã¿¸ö¹¦ÄÜÏß·֧³Ö°´ÈËÊý·ÖÁ÷£¬³¬¹ý×î´óÈËÊýºó¿É¿ªÆôÒ»ÌõÏàͬ¹¦ÄÜÏß·µÄÐéÄâÏß·½øÐзÖÁ÷£¬ËùÒÔͬһ·ÖÇøÍ¬Ò»µØÍ¼µÄ¹¦ÄÜÏß·ID¿ÉÄܶÔÓ¦¶àÌõÐéÄâÏß·  | 
|     '''  | 
|       | 
|     zoneLineKey = (zoneID, funcLineID)  | 
|     if dataMapID not in PyGameData.g_crossDynamicLineInfo:  | 
|         PyGameData.g_crossDynamicLineInfo[dataMapID] = {}  | 
|     zoneLineDict = PyGameData.g_crossDynamicLineInfo[dataMapID] # ¿ç·þ¶¯Ì¬Ïß·ÐÅÏ¢ {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):  | 
|         mapID, copyMapID = funcLineObj.mapID, funcLineObj.copyMapID  | 
|         if not mapID:  | 
|             newFuncLineNum, newFuncLineObj = index, funcLineObj  | 
|             break  | 
|           | 
|         key = (mapID, copyMapID)  | 
|         if key not in PyGameData.g_crossDynamicLineCopyMapInfo:  | 
|             GameWorld.ErrLog("ÒѾ·ÖÅäµÄÐéÄâÏß·²»´æÔÚ»º´æ¶ÔÓ¦¹ØÏµÀzoneID=%s,funcLineID=%s,mapID=%s,copyMapID=%s"   | 
|                              % (zoneID, funcLineID, mapID, copyMapID))  | 
|             continue  | 
|           | 
|         copyMapObj = PyGameData.g_crossDynamicLineCopyMapInfo[key]  | 
|         openState = copyMapObj.openState  | 
|         canEnter = copyMapObj.OnRequestEnterCrossCopyMap(playerID, serverGroupID, tick, copyMapPlayerMax)  | 
|         if canEnter:  | 
|             #GameWorld.DebugLog("¿É½øÈ붯̬·Ö²¼µÄÐéÄâÏß·! mapID=%s,copyMapID=%s,openState=%s" % (mapID, copyMapID, openState))  | 
|             #GameWorld.DebugLog("    ¸±±¾ÖеÄÍæ¼ÒID: %s" % copyMapObj.fbPlayerDict)  | 
|             #GameWorld.DebugLog("    µÈ´ýÖеÄÍæ¼ÒID: %s" % copyMapObj.waitPlayerDict)  | 
|             return mapID, copyMapID, openState  | 
|           | 
|     dynamicLineMapDict = IpyGameDataPY.GetFuncEvalCfg("CrossDynamicLineMap", 1)  | 
|     if dataMapID not in dynamicLineMapDict:  | 
|         return  | 
|     mapIDList = dynamicLineMapDict[dataMapID][1]  | 
|       | 
|     openMapID, openCopyMapID = 0, 0  | 
|     for mapID in mapIDList:  | 
|         maxCopyMapCount = PyGameData.g_crossMapCopyMapCountDict.get(mapID, 0)  | 
|         for copyMapID in xrange(maxCopyMapCount):  | 
|             if (mapID, copyMapID) not in PyGameData.g_crossDynamicLineCopyMapInfo:  | 
|                 openMapID, openCopyMapID = mapID, copyMapID  | 
|                 break  | 
|         if openMapID:  | 
|             break  | 
|     if not openMapID:  | 
|         GameWorld.ErrLog("ûÓпÕÓàµÄÐéÄâÏß·£¬ÎÞ·¨¶¯Ì¬¿ªÆô¿ç·þ¸±±¾!dataMapID=%s, funcLineID=%s, zoneID=%s, mapIDList=%s"   | 
|                          % (dataMapID, funcLineID, zoneID, mapIDList))  | 
|         return  | 
|       | 
|     if newFuncLineObj == None:  | 
|         newFuncLineObj = CrossFuncLineInfo()  | 
|         funcLineObjList.append(newFuncLineObj)  | 
|         newFuncLineNum = len(funcLineObjList)  | 
|     mapID, copyMapID = openMapID, openCopyMapID  | 
|     newFuncLineObj.mapID = mapID  | 
|     newFuncLineObj.copyMapID = copyMapID  | 
|     funcLineDataCache = newFuncLineObj.funcLineDataCache  | 
|       | 
|     key = (mapID, 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,mapID=%s,copyMapID=%s,propertyID=%s"   | 
|                        % (zoneID, funcLineID, mapID, copyMapID, propertyID))  | 
|       | 
|     # Í¨ÖªµØÍ¼¿ªÆôеĵØÍ¼ÐéÄâ·ÖÏß  | 
|     msgInfo = str([copyMapID, propertyID, funcLineDataCache])  | 
|     GameWorld.GetPlayerManager().MapServer_QueryPlayer(0, 0, 0, mapID, "OpenFB", msgInfo, len(msgInfo))  | 
|     return mapID, copyMapID, openState  | 
|   | 
| def GetCrossDynamicLineZoneID(dataMapID, mapID, copyMapID):  | 
|     ## »ñÈ¡¿ç·þ¶¯Ì¬·ÖÅäµÄÐéÄâÏß·¶ÔÓ¦·ÖÇøID  | 
|     zoneLineDict = PyGameData.g_crossDynamicLineInfo.get(dataMapID, {})  | 
|     for key, funcLineObjList in zoneLineDict.items():  | 
|         for funcLineObj in funcLineObjList:  | 
|             if funcLineObj.mapID == mapID and funcLineObj.copyMapID == copyMapID:  | 
|                 zoneID = key[0]  | 
|                 return zoneID  | 
|     return 0  | 
|   | 
| def OnCrossDynamicLineOpen(mapID, copyMapID):  | 
|     ## ¶¯Ì¬·ÖÅäÏß·µÄµØÍ¼ÐéÄâÏß·Æô¶¯³É¹¦  | 
|       | 
|     key = (mapID, copyMapID)  | 
|     if key not in PyGameData.g_crossDynamicLineCopyMapInfo:  | 
|         return  | 
|     copyMapObj = PyGameData.g_crossDynamicLineCopyMapInfo[key]  | 
|     copyMapObj.openState = 1  | 
|     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)  | 
|           | 
|     dataMapID = GetRecordMapID(mapID)  | 
|     GameWorld.Log("¶¯Ì¬·ÖÅäÐéÄâÏß·Æô¶¯³É¹¦£¬Í¨Öª×Ó·þµÈ´ýÍæ¼Ò¿É½øÈë: dataMapID=%s,mapID=%s,copyMapID=%s,serverPlayerIDListDict=%s"   | 
|                   % (dataMapID, mapID, copyMapID, serverPlayerIDListDict))  | 
|     for serverGroupID, playerIDList in serverPlayerIDListDict.items():  | 
|         retInfo = [playerIDList, dataMapID, mapID, 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 OnCrossDynamicLineClose(mapID, copyMapID, funcLineDataCache):  | 
|     ## ¶¯Ì¬·ÖÅäÏß·µÄµØÍ¼ÐéÄâÏß·¹Ø±Õ  | 
|           | 
|     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.mapID == mapID and funcLineObj.copyMapID == copyMapID:  | 
|                 funcLineObj.OnCopyMapClose(funcLineDataCache)  | 
|                 zoneID, funcLineID = key  | 
|                 GameWorld.Log("    ·ÖÇø¶ÔÓ¦¹¦ÄÜÏß·ÐéÄâ·ÖÏ߹رÕ: zoneID=%s,dataMapID%s,funcLineID=%s" % (zoneID, dataMapID, funcLineID))  | 
|                 break  | 
|       | 
|     key = (mapID, copyMapID)  | 
|     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 OnCrossDynamicMapReset(mapID, copyMapCount):  | 
|     ## ¶¯Ì¬·ÖÅäÏß·µÄµØÍ¼ÖØÖà  | 
|       | 
|     dataMapID = GetRecordMapID(mapID)  | 
|     GameWorld.Log("¶¯Ì¬·ÖÅäÐéÄâÏß·µØÍ¼ÖØÖàdataMapID=%s,mapID=%s,copyMapCount=%s" % (dataMapID, mapID, copyMapCount))  | 
|     PyGameData.g_crossMapCopyMapCountDict[mapID] = copyMapCount  | 
|       | 
|     zoneLineDict = PyGameData.g_crossDynamicLineInfo.get(dataMapID, {})  | 
|     for key, funcLineObjList in zoneLineDict.items():  | 
|         for funcLineObj in funcLineObjList:  | 
|             if funcLineObj.mapID == mapID:  | 
|                 funcLineObj.OnCopyMapClose(None)  | 
|               | 
|     for key in PyGameData.g_crossDynamicLineCopyMapInfo.keys():  | 
|         if key[0] == mapID:  | 
|             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.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)  | 
|     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)  | 
|       | 
|     #GameWorld.DebugLog("Íæ¼ÒÍ˳ö¶¯Ì¬·ÖÅäµÄ¿ç·þµØÍ¼: GetMapID=%s,GetRealMapID=%s,GetFBID()=%s"   | 
|     #                   % (curPlayer.GetMapID(), mapID, copyMapID), playerID)  | 
|     #GameWorld.DebugLog("    ¸±±¾ÖеÄÍæ¼ÒID: %s" % copyMapObj.fbPlayerDict)  | 
|     #GameWorld.DebugLog("    µÈ´ýÖеÄÍæ¼ÒID: %s" % copyMapObj.waitPlayerDict)  | 
|     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  |