From 2fca4ba3abab2ea232d64ef084be1991506d57a2 Mon Sep 17 00:00:00 2001
From: hxp <ale99527@vip.qq.com>
Date: 星期四, 27 六月 2024 16:32:51 +0800
Subject: [PATCH] 10178 【越南】【香港】【主干】挂机奖励(屏蔽跨服上线通知:古宝、神通、战令、福地、挂机)

---
 ServerPython/CoreServerGroup/GameServer/Script/GameWorldLogic/CrossBoss.py |  248 ++++++++++++++++++++++++++++++++++++-------------
 1 files changed, 180 insertions(+), 68 deletions(-)

diff --git a/ServerPython/CoreServerGroup/GameServer/Script/GameWorldLogic/CrossBoss.py b/ServerPython/CoreServerGroup/GameServer/Script/GameWorldLogic/CrossBoss.py
index af21a5e..ddaceb7 100644
--- a/ServerPython/CoreServerGroup/GameServer/Script/GameWorldLogic/CrossBoss.py
+++ b/ServerPython/CoreServerGroup/GameServer/Script/GameWorldLogic/CrossBoss.py
@@ -20,11 +20,13 @@
 import IpyGameDataPY
 import ChPyNetSendPack
 import CrossRealmPlayer
+#import DataRecordPack
 import PlayerControl
 import NetPackCommon
 import CrossRealmMsg
 import ShareDefine
 import PyGameData
+import PlayerFB
 
 import time
 
@@ -50,15 +52,22 @@
 
 g_bossRecDataDict = {} # boss对应rec记录缓存 {(zoneID, bossID):recData, ...}
 
-def GetCrossBossZoneIpyData(realMapID, dataMapID, copyMapID):
+def GetCrossBossZoneID(mapID, realMapID, copyMapID):
     ## 获取地图跨服boss所属分区
-    if dataMapID not in ChConfig.Def_CrossMapIDList:
-        return
-    if dataMapID not in ChConfig.Def_CrossZoneTableName:
-        GameWorld.ErrLog("跨服boss没有分区表!dataMapID=%s" % dataMapID)
-        return
-    tableName = ChConfig.Def_CrossZoneTableName[dataMapID]
-    return IpyGameDataPY.GetIpyGameData(tableName, realMapID, dataMapID, copyMapID)
+    if mapID not in ChConfig.Def_CrossMapIDList:
+        return 0
+    # 固定线路分配的
+    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 mapID in ChConfig.Def_CrossDynamicLineMap:
+        return PlayerFB.GetCrossDynamicLineZoneID(mapID, realMapID, copyMapID)
+    return 0
 
 def __GetCrossBossRecData(zoneID, bossID):
     ## 获取跨服Boss Rec数据
@@ -98,38 +107,63 @@
     ## 获取跨服世界boss是否活着
     return GameWorld.GetGameWorld().GetDictByKey(ChConfig.Def_WorldKey_CrossBossIsAlive % (zoneID, bossID))
 
-def ClientServerMsg_ServerInitOK(serverGroupID):
-    ## 子服连接成功
+def Sync_CrossBossInitDataToClientServer(serverGroupID=0):
+    ''' 同步跨服Boss活动数据到子服务器
+    @param serverGroupID: 为0时同步所有子服
+    '''
     
-    bossInfoList = []
+    crossMapBossIDListDict = {}
     ipyDataMgr = IpyGameDataPY.IPY_Data()
     for i in xrange(ipyDataMgr.GetBOSSInfoCount()):
         ipyData = ipyDataMgr.GetBOSSInfoByIndex(i)
         mapID = ipyData.GetMapID()
-        zoneIpyData = CrossRealmPlayer.GetServerCrossZoneIpyData(mapID, serverGroupID)
-        if not zoneIpyData:
-            continue
-        zoneID = zoneIpyData.GetZoneID()
         bossID = ipyData.GetNPCID()
-        bossRecData = __GetCrossBossRecData(zoneID, bossID)
-        killedTime = GetRecKilledTime(bossRecData)
-        refreshTime = GetRecRefreshTime(bossRecData)
-        killedRecord = GetRecKilledRecord(bossRecData)
-        isAlive = __GetCrossBossIsAlive(zoneID, bossID)
-        bossInfoList.append([zoneID, bossID, killedTime, refreshTime, killedRecord, isAlive])
-        
-    if bossInfoList:
-        bossInfoDict = {"BossInfoType":"InitOK", "BossInfoList":bossInfoList}
-        CrossRealmMsg.SendMsgToClientServer(ShareDefine.CrossServerMsg_CrossBossInfo, bossInfoDict, [serverGroupID])
-        
+        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()
+            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):
+def DoCrossBossOnKilled(bossID, killPlayerName, mapID, realMapID, copyMapID, killerIDList):
     ## 跨服boss被杀
-    zoneIpyData = GetCrossBossZoneIpyData(realMapID, dataMapID, copyMapID)
-    zoneID = 0 if not zoneIpyData else zoneIpyData.GetZoneID()
-    GameWorld.Log("击杀跨服boss: zoneID=%s,bossID=%s,realMapID=%s,dataMapID=%s,copyMapID=%s" 
-                  % (zoneID, bossID, realMapID, dataMapID, copyMapID))
+    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
     
@@ -144,30 +178,39 @@
     refreshTime = SetBossRefreshTime(zoneID, bossID, killedTime, bossRecData)
     
     # 广播子服跨服boss被击杀
+    zoneIpyData = CrossRealmPlayer.GetCrossZoneIpyDataByZoneID(mapID, zoneID)
+    if zoneIpyData == None:
+        return
     serverGroupIDList = zoneIpyData.GetServerGroupIDList()
     killedRecord = GetRecKilledRecord(bossRecData)
-    bossInfoList = [[zoneID, bossID, killedTime, refreshTime, killedRecord, isAlive]]
+    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状态变更
-    zoneIpyData = GetCrossBossZoneIpyData(realMapID, dataMapID, copyMapID)
-    zoneID = 0 if not zoneIpyData else zoneIpyData.GetZoneID()
-    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复活
+    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, bossID, isAlive]
+        stateInfo = [zoneID, bossStateDict]
         CrossRealmMsg.SendMsgToClientServer(ShareDefine.CrossServerMsg_CrossBossState, stateInfo, serverGroupIDList)
-        
     return
 
 def __SetKilledRecord(bossRecData, killedTime, playerName):
@@ -214,29 +257,35 @@
     
     curTime = int(time.time())
     if not PyGameData.g_sortBOSSRefreshList:
+        crossZoneName = GameWorld.GetCrossZoneName()
         ipyDataMgr = IpyGameDataPY.IPY_Data()
         for i in xrange(ipyDataMgr.GetBOSSInfoCount()):
             ipyData = ipyDataMgr.GetBOSSInfoByIndex(i)
             bossID = ipyData.GetNPCID()
             mapID = ipyData.GetMapID()
-            if mapID not in ChConfig.Def_CrossZoneTableName:
+            if mapID not in ChConfig.Def_CrossZoneTypeName:
                 continue
-            tableName = ChConfig.Def_CrossZoneTableName[mapID]
-            if not hasattr(ipyDataMgr, "Get%sCount" % tableName):
+            refreshTimeStr = ipyData.GetRefreshTime()
+            if not refreshTimeStr or refreshTimeStr == "0":
                 continue
-            for i in xrange(getattr(ipyDataMgr, "Get%sCount" % tableName)()):
-                zoneIpyData = getattr(ipyDataMgr, "Get%sByIndex" % tableName)(i)
+            zoneTypeName = ChConfig.Def_CrossZoneTypeName[mapID]
+            if not hasattr(ipyDataMgr, "Get%sCount" % zoneTypeName):
+                continue
+            for i in xrange(getattr(ipyDataMgr, "Get%sCount" % zoneTypeName)()):
+                zoneIpyData = getattr(ipyDataMgr, "Get%sByIndex" % zoneTypeName)(i)
+                if zoneIpyData.GetCrossZoneName() != crossZoneName:
+                    continue
                 zoneID = zoneIpyData.GetZoneID()
                 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))
@@ -247,13 +296,33 @@
             #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):
+    ##BOSS是否活着或者可重生
+    if __GetCrossBossIsAlive(zoneID, bossID):
+        return True
+    bossRecData = __GetCrossBossRecData(zoneID, bossID)
+    killedTime = GetRecKilledTime(bossRecData)
+    refreshTime = GetRecRefreshTime(bossRecData)    
+    curTime = int(time.time())
+    rebornSecond = max(0, refreshTime - (curTime - killedTime))
+    return rebornSecond == 0
 
 def OnCrossMapServerInitOK():
     __SendMapServerAliveCrossBoss()
@@ -261,18 +330,21 @@
 
 def __SendMapServerAliveCrossBoss():
     ## 同步当前还活着的boss,防止地图重启后已经刷新的boss不刷新
+    crossZoneName = GameWorld.GetCrossZoneName()
     ipyDataMgr = IpyGameDataPY.IPY_Data()
     for i in xrange(IpyGameDataPY.IPY_Data().GetBOSSInfoCount()):
         ipyData = IpyGameDataPY.IPY_Data().GetBOSSInfoByIndex(i)
         bossID = ipyData.GetNPCID()
         mapID = ipyData.GetMapID()
-        if mapID not in ChConfig.Def_CrossZoneTableName:
+        if mapID not in ChConfig.Def_CrossZoneTypeName:
             continue
-        tableName = ChConfig.Def_CrossZoneTableName[mapID]
-        if not hasattr(ipyDataMgr, "Get%sCount" % tableName):
+        zoneTypeName = ChConfig.Def_CrossZoneTypeName[mapID]
+        if not hasattr(ipyDataMgr, "Get%sCount" % zoneTypeName):
             continue
-        for i in xrange(getattr(ipyDataMgr, "Get%sCount" % tableName)()):
-            zoneIpyData = getattr(ipyDataMgr, "Get%sByIndex" % tableName)(i)
+        for i in xrange(getattr(ipyDataMgr, "Get%sCount" % zoneTypeName)()):
+            zoneIpyData = getattr(ipyDataMgr, "Get%sByIndex" % zoneTypeName)(i)
+            if zoneIpyData.GetCrossZoneName() != crossZoneName:
+                continue
             zoneID = zoneIpyData.GetZoneID()
             isAlive = __GetCrossBossIsAlive(zoneID, bossID)
             if not isAlive:
@@ -285,14 +357,15 @@
 
 def OnPlayerLogin(curPlayer):
     Sync_CrossBossInfo(curPlayer)
+    __LoginNotifyKillCrossBoss(curPlayer)
     return
 
 def CrossServerMsg_CrossBossInfo(bossInfoDict):
     ## 收到跨服服务器同步的跨服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))
     
@@ -301,10 +374,11 @@
         recTypeListData = GameWorld.GetUniversalRecMgr().GetTypeList(ShareDefine.Def_UniversalGameRecType_CrossBossInfo)
         recTypeListData.Clear()
         g_bossRecDataDict = {}
-        
+        return
+    
     syncBOSSIDList = []
     for bossInfo in bossInfoList:
-        zoneID, bossID, killedTime, refreshTime, killedRecord, isAlive = bossInfo
+        zoneID, bossID, killedTime, refreshTime, killedRecord, isAlive, killerExInfo = bossInfo
         bossRecData = __GetCrossBossRecData(zoneID, bossID)
         SetRecKilledTime(bossRecData, killedTime)
         SetRecRefreshTime(bossRecData, refreshTime)
@@ -312,19 +386,54 @@
         __SetCrossBossIsAlive(zoneID, bossID, isAlive)
         syncBOSSIDList.append(bossID)
         
+        if not killerExInfo:
+            continue
+        
+        killerIDList, mapID = killerExInfo
+        for playerID in killerIDList:
+            killer = GameWorld.GetPlayerManager().FindPlayerByID(playerID)
+            if not killer:
+                #GameWorld.ErrLog("击杀跨服boss时主服玩家不在线, playerID=%s,mapID=%s,bossID=%s" % (playerID, mapID, bossID))
+                #DataRecordPack.SendEventPack("CrossBoss_Error", {"PlayerID":playerID, "Error":"MainServerOffline"})
+                killTime = int(time.time())
+                PyGameData.g_unNotifyKillCrossBossDict[playerID] = [killTime, mapID, bossID]
+                continue
+            msgInfo = str([mapID, bossID])
+            killer.MapServer_QueryPlayerResult(0, 0, "CrossKillBoss", msgInfo, len(msgInfo))
+            
     Sync_CrossBossInfo(None, syncBOSSIDList)
+    return
+
+def __LoginNotifyKillCrossBoss(curPlayer):
+    ## 登录时通知未通知到的击杀跨服boss
+    playerID = curPlayer.GetPlayerID()
+    if playerID not in PyGameData.g_unNotifyKillCrossBossDict:
+        return
+    killTime, mapID, bossID = PyGameData.g_unNotifyKillCrossBossDict.pop(playerID)
+    curTime = int(time.time())
+    passSeconds = curTime - killTime
+    if passSeconds >= 120:
+        GameWorld.DebugLog("超过120秒上线不处理,主要为了防刷上线捡物品!", playerID)
+        return
+    msgInfo = str([mapID, bossID])
+    curPlayer.MapServer_QueryPlayerResult(0, 0, "CrossKillBoss", msgInfo, len(msgInfo))
+    GameWorld.Log("上线补通知击杀跨服boss: passSeconds=%s, mapID=%s, bossID=%s" % (passSeconds, mapID, bossID), playerID)
     return
 
 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
 
@@ -332,7 +441,7 @@
 def Sync_CrossBossInfo(curPlayer=None, syncBOSSIDList=[]):
     ## 同步boss相关信息
     
-    curTime = int(time.time())
+    curTime = GameWorld.ChangeTimeStrToNum(GameWorld.GetCrossServerTimeStr())
     
     recTypeListData = GameWorld.GetUniversalRecMgr().GetTypeList(ShareDefine.Def_UniversalGameRecType_CrossBossInfo)
     
@@ -357,6 +466,9 @@
         bossInfoObj.RefreshCD = refreshTime
         bossInfo.BossInfoList.append(bossInfoObj)
         
+    if not bossInfo.BossInfoList:
+        return
+    
     bossInfo.BossCnt = len(bossInfo.BossInfoList)
     if not curPlayer:
         # 全服广播在线玩家

--
Gitblit v1.8.0