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