From 00f4a55d20b44485efb11172bf61263e8cfb57fa Mon Sep 17 00:00:00 2001
From: hxp <ale99527@vip.qq.com>
Date: 星期三, 12 三月 2025 15:09:14 +0800
Subject: [PATCH] 10416 【英文】【bt】【GM】【砍树】登录基金和幻境基金 完成后可以重置购买(重置关联的充值ID)

---
 ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerPackData.py |  204 +++++++++++++++++++-------------------------------
 1 files changed, 79 insertions(+), 125 deletions(-)

diff --git a/ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerPackData.py b/ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerPackData.py
index 11fb6b1..8775a48 100644
--- a/ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerPackData.py
+++ b/ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerPackData.py
@@ -24,11 +24,12 @@
 #            如切磋一下,玩家可以在任意场景对任意本服或跨服玩家发起切磋,与其镜像进行一场友谊PK,纯娱乐
 #            这种为被动式,即目标玩家可能不存在打包数据表中,需要取拉取
 #
+# 由于打包数据较大,影响开关服及备档的速度,还会导致内存不足,故改为db直接管理打包数据获取及入库
+# GameServer仅保留单次启动后有同步/获取的玩家数据,一般比db少,只保留打包数据信息,玩家基本信息改为从ViewCahce中获取
 #-------------------------------------------------------------------------------
 #"""Version = 2024-10-17 15:00"""
 #-------------------------------------------------------------------------------
 
-import CommFunc
 import GameWorld
 import PyDataManager
 import PlayerViewCache
@@ -39,113 +40,69 @@
 import PyGameData
 import ChConfig
 
-import time
+import base64
 
+Def_CahceCountMax = 100 # 最大缓存个数,注:GameServer缓不缓存这个数据都无所谓(改为在db缓存),保留原取数据逻辑不变,暂时缓存个x条,方便本服的直接取
+TempDBPlayer = PyGameDataStruct.tagDBPlayer()
+
+def GetDBPlayerByPackData(packData):
+    ## 根据 curPlayer.GetPackData() 打包返回的数据获取DBPlayer数据
+    TempDBPlayer.clear()
+    if packData:
+        TempDBPlayer.readData(base64.b64decode(packData))
+    return TempDBPlayer
+    
 class DBPlayerPackDataManager():
-    ## 玩家打包数据管理
+    ## 玩家打包数据管理 - 这里仅管理本次启动后的热数据缓存,不入库
     
     def __init__(self):
         self.Clear()
         return
     
     def Clear(self):
-        self.playerPackDataDict = {} # {playerID:tagDBPlayerPackData, ...}
+        self.__packDataDcit = {} # {playerID:packData, ...}
+        self.__packDataPlayerIDList = [] # [playerID, ...] # 限制缓存数,先进先出
         return
+        
+    def IsPlayerIn(self, playerID):
+        return playerID in self.__packDataDcit
     
-    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
-        return packDataObj
+    def GetCount(self): return len(self.__packDataDcit)
+    
+    def GetPlayerPackdata(self, playerID):
+        if playerID not in self.__packDataDcit:
+            return ""
+        # 恢复数据热度
+        if playerID in self.__packDataPlayerIDList:
+            self.__packDataPlayerIDList.remove(playerID)
+        self.__packDataPlayerIDList.append(playerID)
+        GameWorld.DebugLog("获取打包数据缓存数更新: %s,%s" % (len(self.__packDataPlayerIDList), self.__packDataPlayerIDList))
+        return self.__packDataDcit[playerID]
     
     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)
+        self.__packDataDcit[playerID] = packData
+        if playerID in self.__packDataPlayerIDList:
+            # 添加热度,重复更新的不影响热度
+            self.__packDataPlayerIDList.append(playerID)
+            if len(self.__packDataPlayerIDList) > Def_CahceCountMax:
+                delPlayerID = self.__packDataPlayerIDList.pop(0)
+                if delPlayerID in self.__packDataDcit:
+                    del self.__packDataDcit[delPlayerID]
+                GameWorld.DebugLog("删除打包数据缓存: delPlayerID=%s" % delPlayerID)
+            GameWorld.DebugLog("添加打包数据缓存数更新: %s,%s" % (len(self.__packDataPlayerIDList), self.__packDataPlayerIDList))
         return
-    
-    # 保存数据 存数据库和realtimebackup
-    def GetSaveData(self):
-        savaData = ""
-        cntData = ""
-        cnt = 0
-        
-        for dbData in self.playerPackDataDict.values():
-            cnt += 1
-            savaData += dbData.getBuffer()
-            
-        GameWorld.Log("Save DBPlayerPackData count :%s len=%s" % (cnt, len(savaData)))
-        return CommFunc.WriteDWORD(cntData, cnt) + savaData
-    
-    # 从数据库载入数据
-    def LoadPyGameData(self, datas, pos, dataslen):
-        cnt, pos = CommFunc.ReadDWORD(datas, pos)
-        GameWorld.Log("Load DBPlayerPackData count :%s" % cnt)
-        
-        self.Clear()
-        
-        for _ in xrange(cnt):
-            dbData = PyGameDataStruct.tagDBPlayerPackData()
-            pos += dbData.readData(datas, pos, dataslen)
-            
-            self.playerPackDataDict[dbData.PlayerID] = dbData
-            
-        return pos
-
-def IsSaveDB(packDataObj):
-    ## 是否入库
-    if not packDataObj:
-        return False
-    
-    # 功能固定需要的
-    # ...
-    
-    maxDays = 7 # 默认7天
-    MaxTime = maxDays * 3600 * 24
-    curTime = int(time.time())
-    passTime = curTime - packDataObj.UpdTime
-    if passTime < MaxTime:
-        return True
-    
-    return False
-
-def DelOutofTimePackData():
-    ## 删除过期
-    
-    packDataMgr = PyDataManager.GetDBPlayerPackDataManager()
-    playerPackDataDict = packDataMgr.playerPackDataDict
-    for playerID, packDataObj in playerPackDataDict.items():
-        if IsSaveDB(packDataObj):
-            continue
-        playerPackDataDict.pop(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 +114,7 @@
     pullPlayerIDList = []
     packDataMgr = PyDataManager.GetDBPlayerPackDataManager()
     for playerID in playerIDList:
-        if playerID in packDataMgr.playerPackDataDict:
+        if packDataMgr.IsPlayerIn(playerID):
             continue
         pullPlayerIDList.append(playerID)
         
@@ -183,6 +140,7 @@
     
     # pullFrom 0-跨服拉子服; >0-子服通过跨服拉子服
     if GameWorld.IsCrossServer():
+        PlayerViewCache.SetNeedViewCache(pullPlayerIDList) # 拉打包数据的时候默认需要缓存数据
         # 广播给子服拉数据
         msgInfo["pullFrom"] = 0
         dataMsg = {"pullPlayerIDList":pullPlayerIDList, "msgInfo":msgInfo}
@@ -213,7 +171,7 @@
     if not curPlayer:
         GameWorld.DebugLog("玩家不在线的调用打包db数据! playerID=%s" % (playerID), playerID)
         data = str(msgInfo)
-        GameWorld.GetGameWorld().SendDBLogic(ChConfig.gstDBLogic_PlayerPackData, playerID, data, len(data))
+        GameWorld.GetGameWorld().SendDBLogic(ChConfig.gstDBLogic_PlayerPackDataReq, playerID, data, len(data))
         return
     GameWorld.DebugLog("玩家在线的发给地图打包数据! playerID=%s" % (playerID), playerID)
     # 在线的转发给地图
@@ -256,22 +214,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:
@@ -283,9 +242,6 @@
     ## 收到子服同步的玩家打包数据
     playerID = msgData["playerID"]
     packData = msgData["packData"]
-    cacheBase = msgData.get("cacheBase", {})
-    if cacheBase:
-        PlayerViewCache.UpdCrossCacheBase(playerID, cacheBase)
     PyDataManager.GetDBPlayerPackDataManager().UpdPlayerPackData(playerID, packData)
     
     msgInfo = msgData.get("msgInfo", {})
@@ -310,23 +266,23 @@
     
     msgInfo = msgData["msgInfo"]
     pullPlayerIDList = msgData["pullPlayerIDList"]
+    dbPackDataIDList = msgData.get("dbPackDataIDList", []) # db标记的有打包数据的玩家ID
     
     otherServerPlayerIDList = []
-    packDataDict = {}
     packDataMgr = PyDataManager.GetDBPlayerPackDataManager()
     for playerID in pullPlayerIDList:
-        packObj = packDataMgr.GetPlayerPackObj(playerID)
+        packData = packDataMgr.GetPlayerPackdata(playerID)
         # 已经有的数据先推送回去
-        if packObj:
-            GameWorld.DebugLog("跨服有缓存玩家打包数据,直接推给子服! playerID=%s" % playerID)
-            packDataDict[playerID] = packObj.PackData
-            dataMsg = {"playerID":playerID, "packData":packObj.PackData, "msgInfo":msgInfo}
+        if packData or playerID in dbPackDataIDList:
+            GameWorld.DebugLog("跨服GameServer或db有缓存玩家打包数据,直接推给子服! playerID=%s" % playerID)
+            dataMsg = {"playerID":playerID, "packData":packData, "msgInfo":msgInfo}
             CrossRealmMsg.SendMsgToClientServer(ShareDefine.CrossServerMsg_PushPlayerPackData, dataMsg, [serverGroupID])
         else:
             otherServerPlayerIDList.append(playerID)
             
     # 还没有数据的,广播给其他子服拉数据
     if otherServerPlayerIDList:
+        PlayerViewCache.SetNeedViewCache(otherServerPlayerIDList) # 拉打包数据的时候默认需要缓存数据
         dataMsg = {"pullPlayerIDList":otherServerPlayerIDList, "msgInfo":msgInfo}
         CrossRealmMsg.SendMsgToClientServer(ShareDefine.CrossServerMsg_PullPlayerPackData, dataMsg)
         
@@ -340,8 +296,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):
@@ -352,10 +307,10 @@
     
     packDataMgr = PyDataManager.GetDBPlayerPackDataManager()
     for playerID in pullPlayerIDList:
-        packObj = packDataMgr.GetPlayerPackObj(playerID)
-        if packObj:
+        packData = packDataMgr.GetPlayerPackdata(playerID)
+        if packData:
             GameWorld.DebugLog("本服有缓存玩家打包数据,直接推给跨服! playerID=%s" % playerID)
-            dataMsg = {"playerID":playerID, "packData":packObj.PackData, "msgInfo":msgInfo}
+            dataMsg = {"playerID":playerID, "packData":packData, "msgInfo":msgInfo}
             CrossRealmMsg.SendMsgToCrossServer(ShareDefine.ClientServerMsg_PlayerPackData, dataMsg)
         else:
             DoPullPlayerPackData(playerID, msgInfo)
@@ -375,7 +330,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,16 +339,15 @@
     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) or packDataSyncState&pow(2, 1):
         PyDataManager.GetDBPlayerPackDataManager().UpdPlayerPackData(playerID, packData)
+        GameWorld.GetGameWorld().SendDBLogic(ChConfig.gstDBLogic_PlayerPackDataUpd, playerID, packData, len(packData))
         
     # 跨服需要,同步给跨服,由跨服服务器再进一步处理
-    if packDataSyncState / 10:
-        cacheBase = PlayerViewCache.GetSyncCrossCacheBase(curPlayer) if curPlayer else {}
-        dataMsg = {"playerID":playerID, "packData":packData, "cacheBase":cacheBase, "msgInfo":msgInfo}
+    if packDataSyncState&pow(2, 1):
+        dataMsg = {"playerID":playerID, "packData":packData, "msgInfo":msgInfo}
         CrossRealmMsg.SendMsgToCrossServer(ShareDefine.ClientServerMsg_PlayerPackData, dataMsg)
         
     # 本服需要的功能
@@ -430,9 +384,9 @@
     requestID = msgInfo["requestID"]
     mirrorIDList = msgInfo["mirrorIDList"]
     for mirrorID in mirrorIDList:
-        packObj = packDataMgr.GetPlayerPackObj(mirrorID)
-        if packObj:
-            packDataDict[mirrorID] = packObj.PackData
+        packData = packDataMgr.GetPlayerPackdata(mirrorID)
+        if packData:
+            packDataDict[mirrorID] = packData
             continue
         pullPlayerIDList.append(mirrorID)
         

--
Gitblit v1.8.0