hxp
2019-10-29 2941a7635bb04ca59afa820b51a23aca9dc70eb9
ServerPython/CoreServerGroup/GameServer/Script/GameWorldLogic/CrossBoss.py
@@ -26,6 +26,7 @@
import CrossRealmMsg
import ShareDefine
import PyGameData
import PlayerFB
import time
@@ -51,25 +52,21 @@
g_bossRecDataDict = {} # boss对应rec记录缓存 {(zoneID, bossID):recData, ...}
def GetCrossBossZoneID(realMapID, dataMapID, copyMapID):
def GetCrossBossZoneID(mapID, realMapID, copyMapID):
    ## 获取地图跨服boss所属分区
    if dataMapID not in ChConfig.Def_CrossMapIDList:
    if mapID not in ChConfig.Def_CrossMapIDList:
        return 0
    # 固定线路分配的
    if dataMapID in ChConfig.Def_CrossZoneMapTableName:
        tableName = ChConfig.Def_CrossZoneMapTableName[dataMapID]
        zoneIpyData = IpyGameDataPY.GetIpyGameData(tableName, realMapID, dataMapID, copyMapID)
    if mapID in ChConfig.Def_CrossZoneMapTableName:
        tableName = ChConfig.Def_CrossZoneMapTableName[mapID]
        zoneIpyData = IpyGameDataPY.GetIpyGameData(tableName, realMapID, mapID, copyMapID)
        if not zoneIpyData:
            return 0
        return zoneIpyData.GetZoneID()
    
    # 动态线路分配的
    elif dataMapID in ChConfig.Def_CrossDynamicLineMap:
        zoneLineDict = PyGameData.g_crossDynamicLineInfo.get(dataMapID, {}) # {dataMapID:{(zoneID, funcLineID):[mapID, copyMapID], ...}, ...}
        for zoneLineInfo, mapCopyInfo in zoneLineDict.items():
            if realMapID == mapCopyInfo[0] and copyMapID == mapCopyInfo[1]:
                return zoneLineInfo[0]
        return 0
    elif mapID in ChConfig.Def_CrossDynamicLineMap:
        return PlayerFB.GetCrossDynamicLineZoneID(mapID, realMapID, copyMapID)
    return 0
def __GetCrossBossRecData(zoneID, bossID):
@@ -115,44 +112,58 @@
    @param serverGroupID: 为0时同步所有子服
    '''
    
    GameWorld.Log("同步给子服跨服boss信息: syncServerGroupID=%s" % (serverGroupID))
    zoneIpyDataList = CrossRealmPlayer.GetCrossCommZoneIpyDataListByServerGroupID(serverGroupID)
    if not zoneIpyDataList:
        GameWorld.Log("    没有跨服boss分区信息!")
        return
    crossMapBossIDListDict = {}
    ipyDataMgr = IpyGameDataPY.IPY_Data()
    for zoneIpyData in zoneIpyDataList:
        zoneID = zoneIpyData.GetZoneID()
        bossInfoList = []
        for i in xrange(ipyDataMgr.GetBOSSInfoCount()):
            ipyData = ipyDataMgr.GetBOSSInfoByIndex(i)
            mapID = ipyData.GetMapID()
            if mapID not in ChConfig.Def_CrossMapIDList:
                continue
            bossID = ipyData.GetNPCID()
            bossRecData = __GetCrossBossRecData(zoneID, bossID)
            killedTime = GetRecKilledTime(bossRecData)
            refreshTime = GetRecRefreshTime(bossRecData)
            killedRecord = GetRecKilledRecord(bossRecData)
            isAlive = __GetCrossBossIsAlive(zoneID, bossID)
            killerExInfo = [] # 重连成功的信息同步不发送击杀者信息
            bossInfoList.append([zoneID, bossID, killedTime, refreshTime, killedRecord, isAlive, killerExInfo])
        if bossInfoList:
    for i in xrange(ipyDataMgr.GetBOSSInfoCount()):
        ipyData = ipyDataMgr.GetBOSSInfoByIndex(i)
        mapID = ipyData.GetMapID()
        bossID = ipyData.GetNPCID()
        if mapID not in ChConfig.Def_CrossZoneTypeName:
            continue
        if mapID not in crossMapBossIDListDict:
            crossMapBossIDListDict[mapID] = []
        bossIDList = crossMapBossIDListDict[mapID]
        bossIDList.append(bossID)
    crossZoneName = GameWorld.GetCrossZoneName()
    GameWorld.Log("同步给子服跨服boss信息: crossZoneName=%s,syncServerGroupID=%s" % (crossZoneName, serverGroupID))
    # 由于不同功能的跨服boss分区可能不一样,同步子服就需要按分区分步同步,所以需先发送一条初始化的信息类型先清空子服保存的跨服boss数据,再根据功能所属分区推送
    serverGroupIDList = [serverGroupID] if serverGroupID else []
    bossInfoDict = {"BossInfoType":"InitOK"}
    CrossRealmMsg.SendMsgToClientServer(ShareDefine.CrossServerMsg_CrossBossInfo, bossInfoDict, serverGroupIDList)
    for mapID, bossIDList in crossMapBossIDListDict.items():
        GameWorld.Log("    mapID=%s, bossIDList=%s" % (mapID, bossIDList))
        zoneIpyDataList = CrossRealmPlayer.GetCrossZoneIpyDataListByServerGroupID(mapID, serverGroupID)
        if not zoneIpyDataList:
            continue
        for zoneIpyData in zoneIpyDataList:
            zoneID = zoneIpyData.GetZoneID()
            serverGroupIDList = [serverGroupID] if serverGroupID else zoneIpyData.GetServerGroupIDList()
            bossInfoDict = {"BossInfoType":"InitOK", "BossInfoList":bossInfoList}
            CrossRealmMsg.SendMsgToClientServer(ShareDefine.CrossServerMsg_CrossBossInfo, bossInfoDict, serverGroupIDList)
        else:
            GameWorld.Log("没有跨服boss信息! zoneID=%s" % zoneID)
            bossInfoList = []
            for bossID in bossIDList:
                bossRecData = __GetCrossBossRecData(zoneID, bossID)
                killedTime = GetRecKilledTime(bossRecData)
                refreshTime = GetRecRefreshTime(bossRecData)
                killedRecord = GetRecKilledRecord(bossRecData)
                isAlive = __GetCrossBossIsAlive(zoneID, bossID)
                killerExInfo = [] # 重连成功的信息同步不发送击杀者信息
                bossInfoList.append([zoneID, bossID, killedTime, refreshTime, killedRecord, isAlive, killerExInfo])
            if bossInfoList:
                bossInfoDict = {"BossInfoList":bossInfoList}
                CrossRealmMsg.SendMsgToClientServer(ShareDefine.CrossServerMsg_CrossBossInfo, bossInfoDict, serverGroupIDList)
            else:
                GameWorld.Log("没有跨服boss信息! mapID=%s,zoneID=%s" % (mapID, zoneID))
    return
def DoCrossBossOnKilled(bossID, killPlayerName, realMapID, dataMapID, copyMapID, killerIDList):
def DoCrossBossOnKilled(bossID, killPlayerName, mapID, realMapID, copyMapID, killerIDList):
    ## 跨服boss被杀
    zoneID = GetCrossBossZoneID(realMapID, dataMapID, copyMapID)
    GameWorld.Log("击杀跨服boss: zoneID=%s,bossID=%s,realMapID=%s,dataMapID=%s,copyMapID=%s,killerIDList=%s"
                  % (zoneID, bossID, realMapID, dataMapID, copyMapID, killerIDList))
    zoneID = GetCrossBossZoneID(mapID, realMapID, copyMapID)
    GameWorld.Log("击杀跨服boss: zoneID=%s,bossID=%s,mapID=%s,realMapID=%s,copyMapID=%s,killerIDList=%s"
                  % (zoneID, bossID, mapID, realMapID, copyMapID, killerIDList))
    if not zoneID:
        return
    
@@ -167,35 +178,39 @@
    refreshTime = SetBossRefreshTime(zoneID, bossID, killedTime, bossRecData)
    
    # 广播子服跨服boss被击杀
    zoneIpyData = CrossRealmPlayer.GetCrossCommZoneIpyDataByZoneID(zoneID)
    zoneIpyData = CrossRealmPlayer.GetCrossZoneIpyDataByZoneID(mapID, zoneID)
    if zoneIpyData == None:
        return
    serverGroupIDList = zoneIpyData.GetServerGroupIDList()
    killedRecord = GetRecKilledRecord(bossRecData)
    killerExInfo = [killerIDList, dataMapID]
    killerExInfo = [killerIDList, mapID]
    bossInfoList = [[zoneID, bossID, killedTime, refreshTime, killedRecord, isAlive, killerExInfo]]
    bossInfoDict = {"BossInfoType":"OnKilled", "BossInfoList":bossInfoList}
    CrossRealmMsg.SendMsgToClientServer(ShareDefine.CrossServerMsg_CrossBossInfo, bossInfoDict, serverGroupIDList)
    return
def DoCrossBossStateChange(bossID, isAlive, dataMapID, realMapID, copyMapID):
def DoCrossBossStateChange(bossID, isAlive, mapID, realMapID, copyMapID):
    ## 跨服boss状态变更
    zoneID = GetCrossBossZoneID(realMapID, dataMapID, copyMapID)
    GameWorld.Log("跨服boss状态变更: zoneID=%s,bossID=%s,isAlive=%s,realMapID=%s,dataMapID=%s,copyMapID=%s"
                  % (zoneID, bossID, isAlive, realMapID, dataMapID, copyMapID))
    zoneID = GetCrossBossZoneID(mapID, realMapID, copyMapID)
    GameWorld.Log("跨服boss状态变更: zoneID=%s,bossID=%s,isAlive=%s,mapID=%s,realMapID=%s,copyMapID=%s"
                  % (zoneID, bossID, isAlive, mapID, realMapID, copyMapID))
    if not zoneID:
        return
    
    __SetCrossBossIsAlive(zoneID, bossID, isAlive)
    if isAlive:
        # 广播子服跨服boss复活
        zoneIpyData = CrossRealmPlayer.GetCrossCommZoneIpyDataByZoneID(zoneID)
        if zoneIpyData != None:
            serverGroupIDList = zoneIpyData.GetServerGroupIDList()
            stateInfo = [zoneID, bossID, isAlive]
            CrossRealmMsg.SendMsgToClientServer(ShareDefine.CrossServerMsg_CrossBossState, stateInfo, serverGroupIDList)
    if __GetCrossBossIsAlive(zoneID, bossID) != isAlive:
        __SetCrossBossIsAlive(zoneID, bossID, isAlive)
        if isAlive:
            # 广播子服跨服boss复活
            SendClientServerCrossBossState(mapID, zoneID, {bossID:isAlive})
    return
def SendClientServerCrossBossState(mapID, zoneID, bossStateDict={}):
    # 广播子服跨服boss复活
    zoneIpyData = CrossRealmPlayer.GetCrossZoneIpyDataByZoneID(mapID, zoneID)
    if zoneIpyData != None:
        serverGroupIDList = zoneIpyData.GetServerGroupIDList()
        stateInfo = [zoneID, bossStateDict]
        CrossRealmMsg.SendMsgToClientServer(ShareDefine.CrossServerMsg_CrossBossState, stateInfo, serverGroupIDList)
    return
def __SetKilledRecord(bossRecData, killedTime, playerName):
@@ -261,13 +276,13 @@
                bossRecData = __GetCrossBossRecData(zoneID, bossID)
                killedTime = GetRecKilledTime(bossRecData)
                refreshTime = GetRecRefreshTime(bossRecData)
                PyGameData.g_sortBOSSRefreshList.append([bossID, killedTime, refreshTime, zoneID])
                PyGameData.g_sortBOSSRefreshList.append([bossID, killedTime, refreshTime, zoneID, mapID])
        PyGameData.g_sortBOSSRefreshList.sort(key=lambda asd:max(0, asd[2] - (curTime - asd[1])))
        
    #GameWorld.DebugLog("检查boss复活: PyGameData.g_sortBOSSRefreshList=%s" % PyGameData.g_sortBOSSRefreshList)
    syncBOSSIDList = []
    zoneMapBossStateDict = {}
    for bossInfo in PyGameData.g_sortBOSSRefreshList:
        bossID, killedTime, refreshTime, zoneID = bossInfo
        bossID, killedTime, refreshTime, zoneID, mapID = bossInfo
        isAlive = __GetCrossBossIsAlive(zoneID, bossID)
        if isAlive:
            #GameWorld.DebugLog("    zoneID=%s,bossID=%s,未被击杀!" % (zoneID, bossID))
@@ -278,12 +293,21 @@
            #GameWorld.DebugLog("    zoneID=%s,bossID=%s,refreshTime=%s,curTime=%s,killedTime=%s,重生倒计时秒(%s)!" % (zoneID, bossID, refreshTime, curTime, killedTime, rebornSecond))
            break
        
        __SetCrossBossIsAlive(zoneID, bossID, 1)
        syncBOSSIDList.append(bossID)
        isAlive = 1
        __SetCrossBossIsAlive(zoneID, bossID, isAlive)
        key = (mapID, zoneID)
        if key not in zoneMapBossStateDict:
            zoneMapBossStateDict[key] = {}
        bossStateDict = zoneMapBossStateDict[key]
        bossStateDict[bossID] = isAlive
        
        GameWorld.SendMapServerMsgEx(ShareDefine.Def_Notify_WorldKey_GameWorldBossRebornCross % (zoneID, bossID), 1)
        GameWorld.DebugLog("    通知MapServer重生: zoneID=%s,bossID=%s,killedTime=%s,rebornSecond=%s" % (zoneID, bossID, killedTime, rebornSecond))
        
    for key, bossStateDict in zoneMapBossStateDict.items():
        mapID, zoneID = key
        SendClientServerCrossBossState(mapID, zoneID, bossStateDict)
    return
def GetCrossBossIsAliveOrCanReborn(zoneID, bossID):
@@ -336,8 +360,8 @@
    ## 收到跨服服务器同步的跨服boss信息 {"BossInfoType":"InitOK", "BossInfoList":bossInfoList}
    global g_bossRecDataDict
    
    bossInfoType = bossInfoDict["BossInfoType"]
    bossInfoList = bossInfoDict["BossInfoList"]
    bossInfoType = bossInfoDict.get("BossInfoType", "")
    bossInfoList = bossInfoDict.get("BossInfoList", [])
    
    GameWorld.DebugLog("收到跨服同步的跨服boss信息: bossInfoType=%s" % (bossInfoType))
    
@@ -346,7 +370,8 @@
        recTypeListData = GameWorld.GetUniversalRecMgr().GetTypeList(ShareDefine.Def_UniversalGameRecType_CrossBossInfo)
        recTypeListData.Clear()
        g_bossRecDataDict = {}
        return
    syncBOSSIDList = []
    for bossInfo in bossInfoList:
        zoneID, bossID, killedTime, refreshTime, killedRecord, isAlive, killerExInfo = bossInfo
@@ -360,14 +385,14 @@
        if not killerExInfo:
            continue
        
        killerIDList, dataMapID = killerExInfo
        killerIDList, mapID = killerExInfo
        for playerID in killerIDList:
            killer = GameWorld.GetPlayerManager().FindPlayerByID(playerID)
            if not killer:
                GameWorld.ErrLog("击杀跨服boss时主服玩家不在线, playerID=%s,dataMapID=%s,bossID=%s" % (playerID, dataMapID, bossID))
                GameWorld.ErrLog("击杀跨服boss时主服玩家不在线, playerID=%s,mapID=%s,bossID=%s" % (playerID, mapID, bossID))
                DataRecordPack.SendEventPack("CrossBoss_Error", {"PlayerID":playerID, "Error":"MainServerOffline"})
                continue
            msgInfo = str([dataMapID, bossID])
            msgInfo = str([mapID, bossID])
            killer.MapServer_QueryPlayerResult(0, 0, "CrossKillBoss", msgInfo, len(msgInfo))
            
    Sync_CrossBossInfo(None, syncBOSSIDList)
@@ -376,13 +401,17 @@
def CrossServerMsg_CrossBossState(msgInfo):
    ## 收到跨服服务器同步的跨服boss状态
    
    zoneID, bossID, isAlive = msgInfo
    GameWorld.DebugLog("收到跨服服务器同步的跨服boss状态: zoneID=%s, bossID=%s, isAlive=%s" % (zoneID, bossID, isAlive))
    zoneID, bossStateDict = msgInfo
    GameWorld.DebugLog("收到跨服服务器同步的跨服boss状态: zoneID=%s, bossStateDict=%s" % (zoneID, bossStateDict))
    
    __SetCrossBossIsAlive(zoneID, bossID, isAlive)
    aliveBossIDList = []
    for bossID, isAlive in bossStateDict.items():
        __SetCrossBossIsAlive(zoneID, bossID, isAlive)
        if isAlive:
            aliveBossIDList.append(bossID)
    
    if isAlive:
        Sync_CrossBossInfo(None, [bossID])
    if aliveBossIDList:
        Sync_CrossBossInfo(None, aliveBossIDList)
        
    return