From c3157e52b794a43cbdab6e1dc4da5fbcf53fd753 Mon Sep 17 00:00:00 2001
From: hxp <ale99527@vip.qq.com>
Date: 星期一, 26 九月 2022 19:00:34 +0800
Subject: [PATCH] 9701 【后端】【越南】【BT7】【主干】跨服竞技64位排位赛(优化多余分区存在的问题;多分区PK地图分配优化;排位状态异常后支持运行命令 ChampionshipErrorDo 返还未结算的投注;排位赛数据定时存档)

---
 ServerPython/CoreServerGroup/GameServer/Script/GameWorldLogic/CrossChampionship.py |  164 +++++++++++++++++++++++++++++++++++++++++++++---------
 1 files changed, 136 insertions(+), 28 deletions(-)

diff --git a/ServerPython/CoreServerGroup/GameServer/Script/GameWorldLogic/CrossChampionship.py b/ServerPython/CoreServerGroup/GameServer/Script/GameWorldLogic/CrossChampionship.py
index 4fc8b24..40d60ea 100644
--- a/ServerPython/CoreServerGroup/GameServer/Script/GameWorldLogic/CrossChampionship.py
+++ b/ServerPython/CoreServerGroup/GameServer/Script/GameWorldLogic/CrossChampionship.py
@@ -61,6 +61,7 @@
 value3:guessPlayerID     竞猜玩家ID
 value4:tagPlayerID       目标玩家ID
 value5:moneyTotal        投注总货币值
+StrValue1:isClose        是否已结算
 '''
 
 Def_RecType_CrossChampionshipOfficial = ShareDefine.Def_UniversalGameRecType_CrossChampionshipOfficial
@@ -180,6 +181,7 @@
         self.tagPlayerID = 0 # 目标玩家ID
         self.moneyTotal = 0 # 投注总货币值
         self.guessRank = 0 # 竞猜名次,没有名次的竞猜默认0;1-代表第一名
+        self.isClose = 0 # 是否已结算
         return
     
     def GetString(self):
@@ -361,12 +363,15 @@
         return
     
     def GetChampPKZoneIDList(self): return self._pkZoneInfo.keys()
-    def GetChampPKZoneMgr(self, zoneID):
+    def GetChampPKZoneMgr(self, zoneID, addNew=False):
+        pkZoneMgr = None
         if zoneID in self._pkZoneInfo:
             pkZoneMgr = self._pkZoneInfo[zoneID]
-        else:
+        elif addNew:
             pkZoneMgr = ChampionshipPKZoneMgr(zoneID)
             self._pkZoneInfo[zoneID] = pkZoneMgr
+        if not pkZoneMgr:
+            GameWorld.ErrLog("找不到跨服排位赛分区管理! zoneID=%s" % zoneID)
         return pkZoneMgr
     
     def GetPlayerPKZoneID(self, playerID):
@@ -374,6 +379,8 @@
         # @return: 如果在排位中则返回所在排位分区,否则返回当前服务器所在跨服匹配PK分区
         for zoneID in self._pkZoneInfo.keys():
             pkZoneMgr = self.GetChampPKZoneMgr(zoneID)
+            if not pkZoneMgr:
+                continue
             if playerID in pkZoneMgr.GetBatPlayerIDList():
                 return zoneID
         return GameWorld.GetGameWorld().GetDictByKey(ShareDefine.Def_Notify_WorldKey_CrossPKZoneID)
@@ -436,7 +443,7 @@
         groupMark = groupInfo / 100
         battleNum = groupInfo % 100
         
-        pkZoneMgr = champMgr.GetChampPKZoneMgr(zoneID)
+        pkZoneMgr = champMgr.GetChampPKZoneMgr(zoneID, True)
         
         if groupMark in groupMarkList and battleNum:
             battle = ChampionshipBattle()
@@ -471,8 +478,11 @@
         guessPlayerID = recData.GetValue3()
         tagPlayerID = recData.GetValue4()
         moneyTotal = recData.GetValue5()
+        isClose = GameWorld.ToIntDef(recData.GetStrValue1(), 0)
         
         pkZoneMgr = champMgr.GetChampPKZoneMgr(zoneID)
+        if not pkZoneMgr:
+            continue
         playerGuessList = pkZoneMgr.GetPlayerGuessList(guessPlayerID, guessType)
         guessObj = ChampionshipGuess()
         guessObj.zoneID = zoneID
@@ -481,6 +491,7 @@
         guessObj.guessPlayerID = guessPlayerID
         guessObj.tagPlayerID = tagPlayerID
         guessObj.moneyTotal = moneyTotal
+        guessObj.isClose = isClose
         playerGuessList.append(guessObj)
         
         if guessType not in pkZoneMgr.supportCountInfo:
@@ -547,7 +558,10 @@
     return
 
 def OnServerClose():
-    
+    SaveChampionshipData()
+    return
+
+def SaveChampionshipData():
     if not GameWorld.IsCrossServer():
         return
     
@@ -560,7 +574,8 @@
     groupRecDataList = universalRecMgr.GetTypeList(Def_RecType_CrossChampionshipGroup)
     for zoneID in pkZoneIDList:
         pkZoneMgr = champMgr.GetChampPKZoneMgr(zoneID)
-        
+        if not pkZoneMgr:
+            continue
         # 保存参赛玩家名单
         batPlayerIDList = pkZoneMgr.GetBatPlayerIDList()
         GameWorld.Log("    zoneID=%s,batPlayerIDCount=%s, %s" % (zoneID, len(batPlayerIDList), batPlayerIDList))
@@ -589,6 +604,8 @@
     guessRecDataList = universalRecMgr.GetTypeList(Def_RecType_CrossChampionshipGuess)
     for zoneID in pkZoneIDList:
         pkZoneMgr = champMgr.GetChampPKZoneMgr(zoneID)
+        if not pkZoneMgr:
+            continue
         for guessType, playerGuessDict in pkZoneMgr.guessInfo.items():
             for guessPlayerID, guessObjList in playerGuessDict.items():
                 #GameWorld.Log("    zoneID=%s,guessType=%s,guessPlayerID=%s,guessCount=%s" % (zoneID, guessType, guessPlayerID, len(guessObjList)))
@@ -599,6 +616,7 @@
                     recData.SetValue3(guessPlayerID)
                     recData.SetValue4(guessObj.tagPlayerID)
                     recData.SetValue5(guessObj.moneyTotal)
+                    recData.SetStrValue1("%s" % guessObj.isClose)
                     
     offZoneIDList = champMgr.GetChampOfficialZoneIDList()
     GameWorld.Log("保存跨服排位玩家官职信息! offZoneIDList=%s" % offZoneIDList)
@@ -705,6 +723,8 @@
     champMgr = GetChampionshipMgr()
     for zoneID in champMgr.GetChampPKZoneIDList():
         pkZoneMgr = champMgr.GetChampPKZoneMgr(zoneID)
+        if not pkZoneMgr:
+            continue
         if playerID in pkZoneMgr.GetBatPlayerIDList():
             # 是参赛玩家
             return True
@@ -754,6 +774,8 @@
     if pkZoneIDList:
         playerZoneID = champMgr.GetPlayerPKZoneID(playerID)
         pkZoneMgr = champMgr.GetChampPKZoneMgr(playerZoneID)
+        if not pkZoneMgr:
+            return
         if playerID not in pkZoneMgr.syncGuessPlayerIDInfo:
             sendMsg = {"zoneID":playerZoneID, "playerID":playerID, "exDataType":"ChampionshipGuessQuery"}
             CrossRealmMsg.SendMsgToCrossServer(ShareDefine.ClientServerMsg_ChampionshipGuess, sendMsg)
@@ -763,11 +785,60 @@
             
     return
 
-def OnMinuteProcess():
+def ChampionshipErrorDo():
+    ## 状态异常后处理
+    
+    stateError = PlayerDBGSEvent.GetDBGSTrig_ByKey(PlayerDBGSEvent.Def_CrossChampionshipStateError)
+    if not stateError:
+        return "state is not error."
+    
+    if PlayerDBGSEvent.GetDBGSTrig_ByKey(PlayerDBGSEvent.Def_CrossChampionshipErrorDo):
+        return "already done."
+    
+    champMgr = GetChampionshipMgr()
+    
+    # 返还未结算的竞猜消耗
+    moneyType, _ = IpyGameDataPY.GetFuncEvalCfg("CrossChamGuess", 1)
+    moneyItemID = ChConfig.MoneyItemIDDict.get(moneyType)
+    for zoneID in champMgr.GetChampPKZoneIDList():
+        pkZoneMgr = champMgr.GetChampPKZoneMgr(zoneID)
+        if not pkZoneMgr:
+            continue
+        
+        backGuessTypeList = []
+        playerGuessMoneyInfo = {}
+        for guessType, playerGuessDict in pkZoneMgr.guessInfo.items():
+            for guessPlayerID, guessObjList in playerGuessDict.items():
+                for guessObj in guessObjList:
+                    if guessObj.isClose:
+                        # 已经结算的不处理
+                        continue
+                    guessObj.isClose = 1
+                    if guessType not in backGuessTypeList:
+                        backGuessTypeList.append(guessType)
+                    playerGuessMoneyInfo[guessPlayerID] = playerGuessMoneyInfo.get(guessPlayerID, 0) + guessObj.moneyTotal
+                    
+        GameWorld.Log("竞猜需要返还玩家信息: moneyItemID=%s,zoneID=%s,backGuessTypeList=%s, %s" % (moneyItemID, zoneID, backGuessTypeList, playerGuessMoneyInfo))
+        if not moneyItemID or not playerGuessMoneyInfo:
+            continue
+        
+        for guessPlayerID, totalMoney in playerGuessMoneyInfo.items():
+            paramList = []
+            addItemList = [[moneyItemID, totalMoney, 0]]
+            PlayerCompensation.SendMailByKey("CrossChampionshipGuessBack", [guessPlayerID], addItemList, paramList, crossMail=True)
+            
+    PlayerDBGSEvent.SetDBGSTrig_ByKey(PlayerDBGSEvent.Def_CrossChampionshipErrorDo, 1)
+    return "OK"
+
+def OnMinuteProcess(curMinute):
     if not GameWorld.IsCrossServer():
         return
     
     Dispose_CrossChampionshipState()
+    
+    # 每半小时存档一次
+    if curMinute % 30 == 0:
+        SaveChampionshipData()
     return
 
 def __GetChampionshipStartDate():
@@ -985,6 +1056,7 @@
     PlayerDBGSEvent.SetDBGSTrig_ByKey(PlayerDBGSEvent.Def_CrossChampionshipID, crossChampionshipID)
     PlayerDBGSEvent.SetDBGSTrig_ByKey(PlayerDBGSEvent.Def_CrossChampionshipState, updState)
     PlayerDBGSEvent.SetDBGSTrig_ByKey(PlayerDBGSEvent.Def_CrossChampionshipStateError, 0)
+    PlayerDBGSEvent.SetDBGSTrig_ByKey(PlayerDBGSEvent.Def_CrossChampionshipErrorDo, 0)
     
     champMgr = GetChampionshipMgr()
     champMgr.ClearPKZone() # 仅清理PK分区信息,仙官信息不变
@@ -998,7 +1070,7 @@
             if not billboardList:
                 # 没有玩家上榜的不处理
                 continue
-            pkZoneMgr = champMgr.GetChampPKZoneMgr(zoneID)
+            pkZoneMgr = champMgr.GetChampPKZoneMgr(zoneID, True)
             battlePlayerList = billboardList[:Def_CrossChampionshipPlayerMax]
             for num, billboardData in enumerate(battlePlayerList, 1):
                 playerID = billboardData.PlayerID
@@ -1034,6 +1106,8 @@
     champMgr = GetChampionshipMgr()
     for zoneID in champMgr.GetChampPKZoneIDList():
         pkZoneMgr = champMgr.GetChampPKZoneMgr(zoneID)
+        if not pkZoneMgr:
+            continue
         # 首轮取所有参赛玩家
         if preGroupMark == 0:
             batPlayerIDList = pkZoneMgr.GetBatPlayerIDList()
@@ -1134,7 +1208,8 @@
     champMgr = GetChampionshipMgr()
     for zoneID in champMgr.GetChampPKZoneIDList():
         pkZoneMgr = champMgr.GetChampPKZoneMgr(zoneID)
-        
+        if not pkZoneMgr:
+            continue
         winPlayerIDList, losePlayerIDList = [], [] # 胜者组、败者组
         battleNumList = pkZoneMgr.battleInfo.get(preGroupMark, {}).keys()
         battleNumList.sort() # 对战编号按之前的分组顺序排序,确保分组顺序一致
@@ -1221,7 +1296,8 @@
     champMgr = GetChampionshipMgr()
     for zoneID in champMgr.GetChampPKZoneIDList():
         pkZoneMgr = champMgr.GetChampPKZoneMgr(zoneID)
-        
+        if not pkZoneMgr:
+            continue
         battleNumList = pkZoneMgr.battleInfo.get(preGroupMark, {}).keys()
         battleNumList.sort() # 对战编号按之前的分组顺序排序,确保分组顺序一致
         for battleNum in battleNumList:
@@ -1251,6 +1327,7 @@
             for guessObj in guessList:
                 if guessObj.guessType != guessType or guessObj.guessPlayerID != guessPlayerID:
                     continue
+                guessObj.isClose = 1
                 tagPlayerID = guessObj.tagPlayerID
                 moneyTotal = guessObj.moneyTotal
                 if not tagPlayerID or tagPlayerID not in top8PlayerIDList:
@@ -1273,19 +1350,23 @@
     if state not in ShareDefine.CrossChampionshipEnterStateInfo:
         return
     groupMark = ShareDefine.CrossChampionshipEnterStateInfo[state]
+    mapIndex = 0
     mapIDList = IpyGameDataPY.GetFuncEvalCfg("CrossChamFB", 3)
     GameWorld.Log("跨服排位争霸赛开启进场副本: groupMark=%s,mapIDList=%s" % (groupMark, mapIDList))
     champMgr = GetChampionshipMgr()
     pkZoneIDList = champMgr.GetChampPKZoneIDList()
-    for index, zoneID in enumerate(pkZoneIDList):
-        if index >= len(mapIDList):
-            GameWorld.ErrLog("该跨服排位争霸赛分区没有分配对战地图! zoneID=%s,index=%s" % (zoneID, index), zoneID)
-            continue
-        mapID = mapIDList[index]
+    for zoneID in pkZoneIDList:
         pkZoneMgr = champMgr.GetChampPKZoneMgr(zoneID)
+        if not pkZoneMgr:
+            continue
         if groupMark not in pkZoneMgr.battleInfo:
             GameWorld.Log("该跨服排位争霸赛分区没有对战组! zoneID=%s,groupMark=%s" % (zoneID, groupMark), zoneID)
             continue
+        if mapIndex >= len(mapIDList):
+            GameWorld.ErrLog("该跨服排位争霸赛分区没有分配对战地图! zoneID=%s,mapIndex=%s" % (zoneID, mapIndex), zoneID)
+            continue
+        mapID = mapIDList[mapIndex]
+        mapIndex += 1
         copyMapID = 0
         copyPropertyList = []
         battleDict = pkZoneMgr.battleInfo[groupMark]
@@ -1339,7 +1420,7 @@
     CrossRealmMsg.SendMsgToClientServer(ShareDefine.CrossServerMsg_ChampionshipState, dataMsg, serverGroupIDList)
     return
 
-def Send_CrossServerMsg_ChampionshipPlayer(syncPlayerIDList=None, serverGroupID=0, isSync=False):
+def Send_CrossServerMsg_ChampionshipPlayer(syncPlayerIDList=None, serverGroupID=0, isSync=False, clearPlayer=False):
     # 通知参赛玩家
     
     zoneBatPlayerInfo = {}
@@ -1347,6 +1428,8 @@
     for zoneID in champMgr.GetChampPKZoneIDList():
         batPlayerList = []
         pkZoneMgr = champMgr.GetChampPKZoneMgr(zoneID)
+        if not pkZoneMgr:
+            continue
         playerIDList = pkZoneMgr.GetBatPlayerIDList() if syncPlayerIDList == None else syncPlayerIDList
         for playerID in playerIDList:
             batPlayer = pkZoneMgr.GetBatPlayer(playerID)
@@ -1355,7 +1438,7 @@
             batPlayerList.append(batPlayer.GetString())
         zoneBatPlayerInfo[zoneID] = batPlayerList
         
-    dataMsg = {"isSync":isSync, "zoneBatPlayerInfo":zoneBatPlayerInfo}
+    dataMsg = {"isSync":isSync, "zoneBatPlayerInfo":zoneBatPlayerInfo, "clearPlayer":clearPlayer}
     serverGroupIDList = [serverGroupID] if serverGroupID else []
     CrossRealmMsg.SendMsgToClientServer(ShareDefine.CrossServerMsg_ChampionshipPlayer, dataMsg, serverGroupIDList)
     return
@@ -1370,6 +1453,8 @@
         champMgr = GetChampionshipMgr()
         for zoneID in champMgr.GetChampPKZoneIDList():
             pkZoneMgr = champMgr.GetChampPKZoneMgr(zoneID)
+            if not pkZoneMgr:
+                continue
             for gMark in syncGroupMarkList:
                 battleDict = pkZoneMgr.battleInfo.get(gMark, {})
                 if not battleDict:
@@ -1394,12 +1479,13 @@
             guessList.append(guessObj.GetString())
         else:
             pkZoneMgr = champMgr.GetChampPKZoneMgr(syncZoneID)
-            for playerGuessDict in pkZoneMgr.guessInfo.values():
-                if playerID not in playerGuessDict:
-                    continue
-                playerGuessList = playerGuessDict[playerID]
-                for guess in playerGuessList:
-                    guessList.append(guess.GetString())
+            if pkZoneMgr:
+                for playerGuessDict in pkZoneMgr.guessInfo.values():
+                    if playerID not in playerGuessDict:
+                        continue
+                    playerGuessList = playerGuessDict[playerID]
+                    for guess in playerGuessList:
+                        guessList.append(guess.GetString())
                     
     dataMsg = {"exData":exData if exData else {}, "guessList":guessList}
     if syncPub:
@@ -1407,6 +1493,8 @@
         syncZoneIDList = [syncZoneID] if syncZoneID else champMgr.GetChampPKZoneIDList()
         for zoneID in syncZoneIDList:
             pkZoneMgr = champMgr.GetChampPKZoneMgr(zoneID)
+            if not pkZoneMgr:
+                continue
             zoneSupportCountInfo[zoneID] = pkZoneMgr.supportCountInfo
         dataMsg["pubInfo"] = {"zoneSupportCountInfo":zoneSupportCountInfo}
         
@@ -1445,14 +1533,16 @@
     ## 收到跨服服务器同步的信息  - 参赛玩家信息
     
     isSync = msgData["isSync"]
+    clearPlayer = msgData["clearPlayer"]
     zoneBatPlayerInfo = msgData["zoneBatPlayerInfo"]
     
     champMgr = GetChampionshipMgr()
     for zoneID, batPlayerList in zoneBatPlayerInfo.items():
-        pkZoneMgr = champMgr.GetChampPKZoneMgr(zoneID)
+        pkZoneMgr = champMgr.GetChampPKZoneMgr(zoneID, True)
         
         if not batPlayerList:
-            pkZoneMgr.playerDict = {}
+            if clearPlayer:
+                pkZoneMgr.playerDict = {}
         else:
             for attrDict in batPlayerList:
                 zoneID = attrDict["zoneID"]
@@ -1478,7 +1568,7 @@
         groupMark = attrDict["groupMark"]
         battleNum = attrDict["battleNum"]
         
-        pkZoneMgr = champMgr.GetChampPKZoneMgr(zoneID)
+        pkZoneMgr = champMgr.GetChampPKZoneMgr(zoneID, True)
         battle = pkZoneMgr.GetBattle(groupMark, battleNum)
         if not battle:
             battle = ChampionshipBattle()
@@ -1533,7 +1623,7 @@
             # 非本服玩家
             continue
         
-        pkZoneMgr = champMgr.GetChampPKZoneMgr(zoneID)
+        pkZoneMgr = champMgr.GetChampPKZoneMgr(zoneID, True)
         
         guessObj = None
         playerGuessList = pkZoneMgr.GetPlayerGuessList(guessPlayerID, guessType)
@@ -1551,7 +1641,7 @@
     if pubInfo != None:
         zoneSupportCountInfo = pubInfo["zoneSupportCountInfo"]
         for zoneID, supportCountInfo in zoneSupportCountInfo.items():
-            pkZoneMgr = champMgr.GetChampPKZoneMgr(zoneID)
+            pkZoneMgr = champMgr.GetChampPKZoneMgr(zoneID, True)
             pkZoneMgr.supportCountInfo = supportCountInfo
             pubZoneIDList.append(zoneID)
             
@@ -1563,7 +1653,7 @@
             # 非本服玩家
             return
         zoneID = exData.get("zoneID", 0)
-        pkZoneMgr = champMgr.GetChampPKZoneMgr(zoneID)
+        pkZoneMgr = champMgr.GetChampPKZoneMgr(zoneID, True)
         pkZoneMgr.syncGuessPlayerIDInfo[playerID] = tick
         curPlayer = GameWorld.GetPlayerManager().FindPlayerByID(playerID)
         if curPlayer == None:
@@ -1615,6 +1705,8 @@
     champMgr = GetChampionshipMgr()
     for zoneID in champMgr.GetChampPKZoneIDList():
         pkZoneMgr = champMgr.GetChampPKZoneMgr(zoneID)
+        if not pkZoneMgr:
+            continue
         if groupMark not in pkZoneMgr.battleInfo:
             continue
         battleDict = pkZoneMgr.battleInfo[groupMark]
@@ -1689,6 +1781,8 @@
     
     champMgr = GetChampionshipMgr()
     pkZoneMgr = champMgr.GetChampPKZoneMgr(zoneID)
+    if not pkZoneMgr:
+        return
     battleObj = pkZoneMgr.GetBattle(groupMark, battleNum)
     if not battleObj:
         return
@@ -1847,6 +1941,8 @@
         GameWorld.Log("=== 结算排位分区: zoneID=%s ===" % zoneID, zoneID)
         finalPlayerIDList = []
         pkZoneMgr = champMgr.GetChampPKZoneMgr(zoneID)
+        if not pkZoneMgr:
+            continue
         battleNumList = pkZoneMgr.battleInfo.get(finalGroupMark, {}).keys()
         for battleNum in battleNumList:
             batObj = pkZoneMgr.GetBattle(finalGroupMark, battleNum)
@@ -1901,6 +1997,7 @@
             for guessObj in guessList:
                 if guessObj.guessType != guessType or guessObj.guessPlayerID != guessPlayerID:
                     continue
+                guessObj.isClose = 1
                 tagPlayerID = guessObj.tagPlayerID
                 guessRank = guessObj.guessRank
                 moneyTotal = guessObj.moneyTotal
@@ -1933,6 +2030,8 @@
     
     champMgr = GetChampionshipMgr()
     pkZoneMgr = champMgr.GetChampPKZoneMgr(zoneID)
+    if not pkZoneMgr:
+        return {}
     
     # 决赛
     finalGroupMark = 2
@@ -2168,6 +2267,8 @@
     
     champMgr = GetChampionshipMgr()
     pkZoneMgr = champMgr.GetChampPKZoneMgr(zoneID)
+    if not pkZoneMgr:
+        return
     tagBatPlayer = pkZoneMgr.GetBatPlayer(tagPlayerID)
     if not tagBatPlayer:
         GameWorld.ErrLog("该分区不存在该参赛玩家,无法排位竞猜! zoneID=%s,tagPlayerID=%s" % (zoneID, tagPlayerID), playerID)
@@ -2746,6 +2847,9 @@
             return
         
     pkZoneMgr = champMgr.GetChampPKZoneMgr(zoneID)
+    if not pkZoneMgr:
+        return
+    
     if groupMarkDict == None:
         groupMarkDict = {}
         for groupMark, groupDict in pkZoneMgr.battleInfo.items():
@@ -2829,6 +2933,8 @@
         return
     
     pkZoneMgr = champMgr.GetChampPKZoneMgr(playerZoneID)
+    if not pkZoneMgr:
+        return
     
     clientPack = ChPyNetSendPack.tagGCChampionshipGuessPriInfo()
     clientPack.ZoneID = playerZoneID
@@ -2872,6 +2978,8 @@
             return
         
     pkZoneMgr = champMgr.GetChampPKZoneMgr(zoneID)
+    if not pkZoneMgr:
+        return
     
     # 公共竞猜信息
     clientPack = ChPyNetSendPack.tagGCChampionshipGuessPubInfo()

--
Gitblit v1.8.0