From d8be7b4165074fed794ca9addf3af73cbfb24b61 Mon Sep 17 00:00:00 2001
From: hxp <ale99527@vip.qq.com>
Date: 星期三, 26 二月 2025 17:54:22 +0800
Subject: [PATCH] 10385 【越南】【英语】【BT】【GM】【砍树】福地新增鼠管及优化-服务端(优化结算奖励逻辑;)

---
 ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerPackData.py |  263 +++++++++++++++++++++++++++++++++++++++++-----------
 1 files changed, 207 insertions(+), 56 deletions(-)

diff --git a/ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerPackData.py b/ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerPackData.py
index 11fb6b1..42e35af 100644
--- a/ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerPackData.py
+++ b/ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerPackData.py
@@ -33,6 +33,7 @@
 import PyDataManager
 import PlayerViewCache
 import PyGameDataStruct
+import CrossChampionship
 import CrossRealmMsg
 import PlayerControl
 import ShareDefine
@@ -40,7 +41,68 @@
 import ChConfig
 
 import time
+import base64
 
+TempDBPlayer = PyGameDataStruct.tagDBPlayer()
+
+def GetDBPlayerByPackData(packData):
+    ## 根据 curPlayer.GetPackData() 打包返回的数据获取DBPlayer数据
+    TempDBPlayer.clear()
+    if packData:
+        TempDBPlayer.readData(base64.b64decode(packData))
+    return TempDBPlayer
+
+class PlayerPackDataObj():
+    
+    def __init__(self):
+        self.dbPlayerPackData = None
+        self.playerID = 0
+        self.playerName = ""
+        self.accID = ""
+        self.lv = 0
+        self.job = 0
+        self.realmLV = 0
+        self.face = 0
+        self.facePic = 0
+        self.fightPower = 0
+        self.serverID = 0
+        return
+    
+    def GetBaseDict(self):
+        return {"playerID":self.playerID, "playerName":self.playerName, "lv":self.lv, "job":self.job, 
+                "realmLV":self.realmLV, "face":self.face, "facePic":self.facePic, "fightPower":self.fightPower}
+        
+    def UpdPackData(self, packData):
+        if not packData:
+            return
+        if not self.dbPlayerPackData:
+            self.dbPlayerPackData = PyGameDataStruct.tagDBPlayerPackData()
+        self.dbPlayerPackData.PlayerID = self.playerID
+        self.dbPlayerPackData.PackData = packData
+        self.dbPlayerPackData.PackDataSize = len(self.dbPlayerPackData.PackData)
+        self.dbPlayerPackData.UpdTime = int(time.time())
+        self.Unpack()
+        return
+    
+    def Unpack(self):
+        if not self.dbPlayerPackData:
+            return
+        dbPlayer = GetDBPlayerByPackData(self.dbPlayerPackData.PackData)
+        self.playerID = dbPlayer.PlayerID
+        self.accID = dbPlayer.AccID
+        self.playerName = dbPlayer.PlayerName
+        self.lv = dbPlayer.LV
+        self.job = dbPlayer.Job
+        self.realmLV = dbPlayer.OfficialRank
+        self.face = dbPlayer.Face
+        self.facePic = dbPlayer.FacePic
+        self.fightPower = dbPlayer.FightPowerEx * ChConfig.Def_PerPointValue + dbPlayer.FightPower
+        self.serverID = GameWorld.GetAccIDServerID(self.accID)
+        return
+    
+    def GetPackData(self): return self.dbPlayerPackData.PackData if self.dbPlayerPackData else ""
+    def GetUpdTime(self): return self.dbPlayerPackData.UpdTime if self.dbPlayerPackData else 0
+    
 class DBPlayerPackDataManager():
     ## 玩家打包数据管理
     
@@ -49,26 +111,92 @@
         return
     
     def Clear(self):
-        self.playerPackDataDict = {} # {playerID:tagDBPlayerPackData, ...}
+        self.__packDataList = [] # [PlayerPackDataObj, ...]
+        self.__idIndexDict = {} # {playerID:index, ...}
+        self.__needSort = False
+        self.__serverIDRangePlayerIDDict = {} # {serverIDRangeTuple:[playerID, ...], ....}
         return
     
     def GetPlayerPackObj(self, playerID, isAddNew=False):
         packDataObj = None
-        if playerID in self.playerPackDataDict:
-            packDataObj = self.playerPackDataDict[playerID]
-        elif isAddNew:
-            packDataObj = PyGameDataStruct.tagDBPlayerPackData()
-            packDataObj.PlayerID = playerID
-            self.playerPackDataDict[playerID] = packDataObj
+        self.__refreshIDIndex()
+        if playerID in self.__idIndexDict:
+            index = self.__idIndexDict[playerID]
+            if index < len(self.__packDataList):
+                packDataObj = self.__packDataList[index]
+                
+        if not packDataObj and isAddNew:
+            packDataObj = PlayerPackDataObj()
+            packDataObj.playerID = playerID
+            self.__packDataList.append(packDataObj)
+            self.__idIndexDict[playerID] = len(self.__packDataList) - 1
+            self.__needSort = True
+            
         return packDataObj
+    
+    def GetPlayerIDListByServerIDInfo(self, serverIDList):
+        ## 根据服务器ID列表信息获取对应服务器ID范围的玩家ID战力排序列表
+        self.Sort()
+        key = tuple(serverIDList)
+        if key not in self.__serverIDRangePlayerIDDict:
+            playerIDList = []
+            for dataObj in self.__packDataList:
+                playerID = dataObj.playerID
+                serverID = dataObj.serverID
+                for idInfo in serverIDList:
+                    if (isinstance(idInfo, int) and serverID == idInfo) \
+                        or ((isinstance(idInfo, tuple) or isinstance(idInfo, list)) \
+                            and len(idInfo) == 2 and idInfo[0] <= serverID <= idInfo[1]):
+                        playerIDList.append(playerID)
+            GameWorld.DebugLog("重新加载区服打包玩家ID列表: %s, %s, %s" % (key, len(playerIDList), playerIDList))
+            self.__serverIDRangePlayerIDDict[key] = playerIDList
+        return self.__serverIDRangePlayerIDDict[key]
+    
+    def IsPlayerIn(self, playerID):
+        self.__refreshIDIndex()
+        return playerID in self.__idIndexDict
+    
+    def __refreshIDIndex(self):
+        if not self.__idIndexDict:
+            self.__idIndexDict = {}
+            for index, dataObj in enumerate(self.__packDataList):
+                self.__idIndexDict[dataObj.playerID] = index
+        return self.__idIndexDict
     
     def UpdPlayerPackData(self, playerID, packData):
         if not packData:
             return
         packObj = self.GetPlayerPackObj(playerID, True)
-        packObj.UpdTime = int(time.time())
-        packObj.PackData = packData
-        packObj.PackDataSize = len(packObj.PackData)
+        packObj.UpdPackData(packData)
+        self.__needSort = True
+        return packObj
+    
+    def DelPlayerPackData(self, playerID):
+        self.__refreshIDIndex()
+        index = self.__idIndexDict.pop(playerID, -1)
+        if index >= 0 and index < len(self.__packDataList):
+            self.__packDataList.pop(index)
+        for playerIDList in self.__serverIDRangePlayerIDDict.values():
+            if playerID in playerIDList:
+                playerIDList.remove(playerID)
+        return
+    
+    def GetCount(self): return len(self.__packDataList)    
+    def At(self, index):
+        dataObj = self.__packDataList[index]
+        if not dataObj and False:
+            dataObj = PlayerPackDataObj() # 不会执行到,只为了.出代码提示
+        return dataObj
+    
+    def Sort(self):
+        ## 默认按战力倒序排
+        if not self.__needSort:
+            return
+        self.__needSort = False
+        self.__packDataList.sort(key=lambda d: (d.fightPower), reverse=True)
+        self.__idIndexDict = {}
+        self.__serverIDRangePlayerIDDict = {}
+        self.__refreshIDIndex()
         return
     
     # 保存数据 存数据库和realtimebackup
@@ -77,9 +205,14 @@
         cntData = ""
         cnt = 0
         
-        for dbData in self.playerPackDataDict.values():
+        for index in xrange(self.GetCount()):
+            dataObj = self.At(index)
+            if not dataObj.dbPlayerPackData:
+                continue
             cnt += 1
-            savaData += dbData.getBuffer()
+            savaData += dataObj.dbPlayerPackData.getBuffer()
+            if cnt >= 10:
+                break
             
         GameWorld.Log("Save DBPlayerPackData count :%s len=%s" % (cnt, len(savaData)))
         return CommFunc.WriteDWORD(cntData, cnt) + savaData
@@ -94,9 +227,13 @@
         for _ in xrange(cnt):
             dbData = PyGameDataStruct.tagDBPlayerPackData()
             pos += dbData.readData(datas, pos, dataslen)
+            playerID = dbData.PlayerID
             
-            self.playerPackDataDict[dbData.PlayerID] = dbData
+            packObj = self.GetPlayerPackObj(playerID, True)
+            packObj.dbPlayerPackData = dbData
+            packObj.Unpack()
             
+        self.Sort()
         return pos
 
 def IsSaveDB(packDataObj):
@@ -104,13 +241,39 @@
     if not packDataObj:
         return False
     
-    # 功能固定需要的
-    # ...
+    playerID = packDataObj.playerID
+    
+    if CrossChampionship.IsChampionshipPlayer(playerID):
+        return True
+    
+    #跨服榜单上的默认保留
+    if GameWorld.IsCrossServer():
+        billboardMgr = PyDataManager.GetCrossBillboardManager()
+        for billboardType in ShareDefine.CrossBillboardTypeList:
+            groupList = billboardMgr.GetBillboardGroupList(billboardType)
+            for billboardType, groupValue1, groupValue2 in groupList:
+                billboardObj = billboardMgr.GetCrossBillboard(billboardType, groupValue1, groupValue2)
+                if billboardObj.FindByID(playerID):
+                    return True
+                
+    else:
+        pass
+#        NeedCheckBillBoardType = IpyGameDataPY.GetFuncEvalCfg("PlayerViewCache", 2)
+#        #校验玩家是否上排行榜
+#        billboardMgr = GameWorld.GetBillboard()
+#        for BillBoardType in NeedCheckBillBoardType:
+#            curBillboard = billboardMgr.FindBillboard(BillBoardType)
+#            if not curBillboard:
+#                continue
+#            if curBillboard.FindByID(playerID):
+#                return True
+            
+    # 以上是相关功能需要用到的数据,必定不能删除的
     
     maxDays = 7 # 默认7天
     MaxTime = maxDays * 3600 * 24
     curTime = int(time.time())
-    passTime = curTime - packDataObj.UpdTime
+    passTime = curTime - packDataObj.GetUpdTime()
     if passTime < MaxTime:
         return True
     
@@ -120,32 +283,23 @@
     ## 删除过期
     
     packDataMgr = PyDataManager.GetDBPlayerPackDataManager()
-    playerPackDataDict = packDataMgr.playerPackDataDict
-    for playerID, packDataObj in playerPackDataDict.items():
+    for index in range(packDataMgr.GetCount())[::-1]: # 可能删数据,倒序遍历
+        packDataObj = packDataMgr.At(index)
         if IsSaveDB(packDataObj):
             continue
-        playerPackDataDict.pop(playerID)
+        packDataMgr.DelPlayerPackData(packDataObj.playerID)
         
     return
 
 def IsPackDataPlayer(playerID):
-    return playerID in PyDataManager.GetDBPlayerPackDataManager().playerPackDataDict
+    return PyDataManager.GetDBPlayerPackDataManager().IsPlayerIn(playerID)
 
 def OnPlayerLogin(curPlayer):
     ## 本服登录逻辑
     playerID = curPlayer.GetPlayerID()
     packDataMgr = PyDataManager.GetDBPlayerPackDataManager()
-    if playerID in packDataMgr.playerPackDataDict:
-        isCross, isNeed = 0, 1
-        QueryPlayerResult_PlayerMirror(curPlayer, "PackDataSyncState", [isCross, isNeed])
-    return
-
-def OnPlayerLogin_CrossLogic(serverGroupID, serverID, playerID):
-    ## 跨服登录逻辑
-    packDataMgr = PyDataManager.GetDBPlayerPackDataManager()
-    if playerID in packDataMgr.playerPackDataDict:
-        dataMsg = {"playerID":playerID}
-        CrossRealmMsg.SendMsgToClientServer(ShareDefine.CrossServerMsg_PlayerPackDataState, dataMsg, [serverGroupID])
+    if packDataMgr.IsPlayerIn(playerID):
+        QueryPlayerResult_PlayerMirror(curPlayer, "PackDataSyncState", {"PackData":1})
     return
 
 def SetNeedPackData(playerIDList):
@@ -157,7 +311,7 @@
     pullPlayerIDList = []
     packDataMgr = PyDataManager.GetDBPlayerPackDataManager()
     for playerID in playerIDList:
-        if playerID in packDataMgr.playerPackDataDict:
+        if packDataMgr.IsPlayerIn(playerID):
             continue
         pullPlayerIDList.append(playerID)
         
@@ -256,22 +410,23 @@
     msgType = msgInfo.get("msgType")
     # 镜像战斗
     if msgType == "MirrorBattle":
+        sceneMapID = msgInfo.get("sceneMapID", 0)
         playerID = msgInfo.get("playerID", 0)
-        # 玩家发起的
-        if playerID:
-            playerID = msgInfo["playerID"]
-            curPlayer = GameWorld.GetPlayerManager().FindPlayerByID(playerID)
-            if not curPlayer:
-                return
-            tagMapID = GameWorld.GetQueryPlayerMapID(curPlayer)
-            routeIndex = curPlayer.GetRouteServerIndex()
-        else:
-            tagMapID = msgInfo.get("requestMapID", 0)
-            routeIndex = -1
+        routeIndex = -1
+#        # 玩家发起的
+#        if playerID:
+#            playerID = msgInfo["playerID"]
+#            curPlayer = GameWorld.GetPlayerManager().FindPlayerByID(playerID)
+#            if not curPlayer:
+#                return
+#            sceneMapID = GameWorld.GetQueryPlayerMapID(curPlayer)
+#            routeIndex = curPlayer.GetRouteServerIndex()
+#        else:
+#            routeIndex = -1
             
         sendMsg = str([msgInfo, packDataDict])
-        GameWorld.DebugLog("MapServer_QueryPlayer tagMapID=%s,len=%s" % (tagMapID, len(sendMsg)), playerID)
-        GameWorld.GetPlayerManager().MapServer_QueryPlayer(0, 0, playerID, tagMapID, "PlayerMirror", sendMsg, len(sendMsg), routeIndex)
+        GameWorld.DebugLog("MapServer_QueryPlayer sceneMapID=%s,len=%s" % (sceneMapID, len(sendMsg)), playerID)
+        GameWorld.GetPlayerManager().MapServer_QueryPlayer(0, 0, playerID, sceneMapID, "PlayerMirror", sendMsg, len(sendMsg), routeIndex)
         
     # 其他功能可再扩展
     else:
@@ -312,15 +467,13 @@
     pullPlayerIDList = msgData["pullPlayerIDList"]
     
     otherServerPlayerIDList = []
-    packDataDict = {}
     packDataMgr = PyDataManager.GetDBPlayerPackDataManager()
     for playerID in pullPlayerIDList:
         packObj = packDataMgr.GetPlayerPackObj(playerID)
         # 已经有的数据先推送回去
         if packObj:
             GameWorld.DebugLog("跨服有缓存玩家打包数据,直接推给子服! playerID=%s" % playerID)
-            packDataDict[playerID] = packObj.PackData
-            dataMsg = {"playerID":playerID, "packData":packObj.PackData, "msgInfo":msgInfo}
+            dataMsg = {"playerID":playerID, "packData":packObj.GetPackData(), "msgInfo":msgInfo}
             CrossRealmMsg.SendMsgToClientServer(ShareDefine.CrossServerMsg_PushPlayerPackData, dataMsg, [serverGroupID])
         else:
             otherServerPlayerIDList.append(playerID)
@@ -340,8 +493,7 @@
     curPlayer = GameWorld.GetPlayerManager().FindPlayerByID(playerID)
     if not curPlayer:
         return
-    isCross, isNeed = 1, 1
-    QueryPlayerResult_PlayerMirror(curPlayer, "PackDataSyncState", [isCross, isNeed])
+    QueryPlayerResult_PlayerMirror(curPlayer, "PackDataSyncState", msgData)
     return
 
 def CrossServerMsg_PullPlayerPackData(msgData):
@@ -355,7 +507,7 @@
         packObj = packDataMgr.GetPlayerPackObj(playerID)
         if packObj:
             GameWorld.DebugLog("本服有缓存玩家打包数据,直接推给跨服! playerID=%s" % playerID)
-            dataMsg = {"playerID":playerID, "packData":packObj.PackData, "msgInfo":msgInfo}
+            dataMsg = {"playerID":playerID, "packData":packObj.GetPackData(), "msgInfo":msgInfo}
             CrossRealmMsg.SendMsgToCrossServer(ShareDefine.ClientServerMsg_PlayerPackData, dataMsg)
         else:
             DoPullPlayerPackData(playerID, msgInfo)
@@ -375,7 +527,7 @@
     curPlayer.MapServer_QueryPlayerResult(0, 0, "PlayerMirror", sysMsg, len(sysMsg))
     return
 
-def OnMGUpdatePlayerPackData(curPlayer, curPackData):
+def OnMGUpdatePlayerPackData(curPlayer, curPackData, msgInfo):
     ## 地图同步更新的玩家打包数据
     if GameWorld.IsCrossServer():
         return
@@ -384,14 +536,13 @@
     packData = curPackData.PackData
     if not packDataSyncState or not packData:
         return
-    msgInfo = eval(curPackData.PackMsg) if curPackData.PackMsg else {} # 打包数据附带的信息
     
     # 本服需要,先更新数据
-    if packDataSyncState % 10:
+    if packDataSyncState&pow(2, 0):
         PyDataManager.GetDBPlayerPackDataManager().UpdPlayerPackData(playerID, packData)
         
     # 跨服需要,同步给跨服,由跨服服务器再进一步处理
-    if packDataSyncState / 10:
+    if packDataSyncState&pow(2, 1):
         cacheBase = PlayerViewCache.GetSyncCrossCacheBase(curPlayer) if curPlayer else {}
         dataMsg = {"playerID":playerID, "packData":packData, "cacheBase":cacheBase, "msgInfo":msgInfo}
         CrossRealmMsg.SendMsgToCrossServer(ShareDefine.ClientServerMsg_PlayerPackData, dataMsg)
@@ -432,7 +583,7 @@
     for mirrorID in mirrorIDList:
         packObj = packDataMgr.GetPlayerPackObj(mirrorID)
         if packObj:
-            packDataDict[mirrorID] = packObj.PackData
+            packDataDict[mirrorID] = packObj.GetPackData()
             continue
         pullPlayerIDList.append(mirrorID)
         

--
Gitblit v1.8.0