|  |  | 
 |  |  | #---------------------------------------------------------------------
 | 
 |  |  | import GameWorldBoss
 | 
 |  |  | import PlayerFamilyBoss
 | 
 |  |  | import PlayerHorsePetBoss
 | 
 |  |  | import GameWorldFamilyWar
 | 
 |  |  | import PlayerControl
 | 
 |  |  | import PyGameData
 | 
 |  |  | 
 |  |  | 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)
 | 
 |  |  | 
 |  |  |             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: 请求回调名
 | 
 |  |  | 
 |  |  |     
 | 
 |  |  |     # 组队副本, 有队伍的情况才验证其他队员可否进入,否则代表单人进入
 | 
 |  |  |     if gameMap.GetMapFBType() == ChConfig.fbtTeam:
 | 
 |  |  |         if tagMapID == ChConfig.Def_FBMapID_Love:
 | 
 |  |  |             onlyDoubleTeam = IpyGameDataPY.GetFuncCfg("LoveFB", 1)
 | 
 |  |  |             if onlyDoubleTeam:
 | 
 |  |  |                 if PlayerTeam.CheckTeamOnLineCount(curPlayer.GetTeam(), includeTJG=False) != 2:
 | 
 |  |  |                     PlayerControl.NotifyCode(curPlayer, "OnlyTwoMemTeamCanEnter", [tagMapID])
 | 
 |  |  |                     return
 | 
 |  |  |         PlayerTeam.OnEnterFBTeamAsk(curPlayer, PlayerTeam.TeamFBAskType_Enter, tagMapID, tagLineID, tick)
 | 
 |  |  |         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())
 |