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 | 291 +++++++++------------------------------------------------
1 files changed, 47 insertions(+), 244 deletions(-)
diff --git a/ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerPackData.py b/ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerPackData.py
index e9b9854..8775a48 100644
--- a/ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerPackData.py
+++ b/ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerPackData.py
@@ -24,25 +24,25 @@
# 如切磋一下,玩家可以在任意场景对任意本服或跨服玩家发起切磋,与其镜像进行一场友谊PK,纯娱乐
# 这种为被动式,即目标玩家可能不存在打包数据表中,需要取拉取
#
+# 由于打包数据较大,影响开关服及备档的速度,还会导致内存不足,故改为db直接管理打包数据获取及入库
+# GameServer仅保留单次启动后有同步/获取的玩家数据,一般比db少,只保留打包数据信息,玩家基本信息改为从ViewCahce中获取
#-------------------------------------------------------------------------------
#"""Version = 2024-10-17 15:00"""
#-------------------------------------------------------------------------------
-import CommFunc
import GameWorld
import PyDataManager
import PlayerViewCache
import PyGameDataStruct
-import CrossChampionship
import CrossRealmMsg
import PlayerControl
import ShareDefine
import PyGameData
import ChConfig
-import time
import base64
+Def_CahceCountMax = 100 # 最大缓存个数,注:GameServer缓不缓存这个数据都无所谓(改为在db缓存),保留原取数据逻辑不变,暂时缓存个x条,方便本服的直接取
TempDBPlayer = PyGameDataStruct.tagDBPlayer()
def GetDBPlayerByPackData(packData):
@@ -51,245 +51,48 @@
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():
- ## 玩家打包数据管理
+ ## 玩家打包数据管理 - 这里仅管理本次启动后的热数据缓存,不入库
def __init__(self):
self.Clear()
return
def Clear(self):
- self.__packDataList = [] # [PlayerPackDataObj, ...]
- self.__idIndexDict = {} # {playerID:index, ...}
- self.__needSort = False
- self.__serverIDRangePlayerIDDict = {} # {serverIDRangeTuple:[playerID, ...], ....}
+ self.__packDataDcit = {} # {playerID:packData, ...}
+ self.__packDataPlayerIDList = [] # [playerID, ...] # 限制缓存数,先进先出
return
-
- def GetPlayerPackObj(self, playerID, isAddNew=False):
- packDataObj = None
- 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
+ return playerID in self.__packDataDcit
- 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 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.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)
+ 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
-
- 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
- def GetSaveData(self):
- savaData = ""
- cntData = ""
- cnt = 0
-
- for index in xrange(self.GetCount()):
- dataObj = self.At(index)
- if not dataObj.dbPlayerPackData:
- continue
- cnt += 1
- savaData += dataObj.dbPlayerPackData.getBuffer()
- if cnt >= 200:
- break
-
- 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)
- playerID = dbData.PlayerID
-
- packObj = self.GetPlayerPackObj(playerID, True)
- packObj.dbPlayerPackData = dbData
- packObj.Unpack()
-
- self.Sort()
- return pos
-
-def IsSaveDB(packDataObj):
- ## 是否入库
- 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.GetUpdTime()
- if passTime < MaxTime:
- return True
-
- return False
-
-def DelOutofTimePackData():
- ## 删除过期
-
- packDataMgr = PyDataManager.GetDBPlayerPackDataManager()
- for index in range(packDataMgr.GetCount())[::-1]: # 可能删数据,倒序遍历
- packDataObj = packDataMgr.At(index)
- if IsSaveDB(packDataObj):
- continue
- packDataMgr.DelPlayerPackData(packDataObj.playerID)
-
- return
def IsPackDataPlayer(playerID):
return PyDataManager.GetDBPlayerPackDataManager().IsPlayerIn(playerID)
@@ -337,6 +140,7 @@
# pullFrom 0-跨服拉子服; >0-子服通过跨服拉子服
if GameWorld.IsCrossServer():
+ PlayerViewCache.SetNeedViewCache(pullPlayerIDList) # 拉打包数据的时候默认需要缓存数据
# 广播给子服拉数据
msgInfo["pullFrom"] = 0
dataMsg = {"pullPlayerIDList":pullPlayerIDList, "msgInfo":msgInfo}
@@ -367,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)
# 在线的转发给地图
@@ -438,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", {})
@@ -465,21 +266,23 @@
msgInfo = msgData["msgInfo"]
pullPlayerIDList = msgData["pullPlayerIDList"]
+ dbPackDataIDList = msgData.get("dbPackDataIDList", []) # db标记的有打包数据的玩家ID
otherServerPlayerIDList = []
packDataMgr = PyDataManager.GetDBPlayerPackDataManager()
for playerID in pullPlayerIDList:
- packObj = packDataMgr.GetPlayerPackObj(playerID)
+ packData = packDataMgr.GetPlayerPackdata(playerID)
# 已经有的数据先推送回去
- if packObj:
- GameWorld.DebugLog("跨服有缓存玩家打包数据,直接推给子服! playerID=%s" % playerID)
- dataMsg = {"playerID":playerID, "packData":packObj.GetPackData(), "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)
@@ -504,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.GetPackData(), "msgInfo":msgInfo}
+ dataMsg = {"playerID":playerID, "packData":packData, "msgInfo":msgInfo}
CrossRealmMsg.SendMsgToCrossServer(ShareDefine.ClientServerMsg_PlayerPackData, dataMsg)
else:
DoPullPlayerPackData(playerID, msgInfo)
@@ -537,14 +340,14 @@
if not packDataSyncState or not packData:
return
- # 本服需要,先更新数据
- if packDataSyncState&pow(2, 0):
+ # 本服需要,先更新数据;跨服需要则也默认本服需要
+ 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&pow(2, 1):
- cacheBase = PlayerViewCache.GetSyncCrossCacheBase(curPlayer) if curPlayer else {}
- dataMsg = {"playerID":playerID, "packData":packData, "cacheBase":cacheBase, "msgInfo":msgInfo}
+ dataMsg = {"playerID":playerID, "packData":packData, "msgInfo":msgInfo}
CrossRealmMsg.SendMsgToCrossServer(ShareDefine.ClientServerMsg_PlayerPackData, dataMsg)
# 本服需要的功能
@@ -581,9 +384,9 @@
requestID = msgInfo["requestID"]
mirrorIDList = msgInfo["mirrorIDList"]
for mirrorID in mirrorIDList:
- packObj = packDataMgr.GetPlayerPackObj(mirrorID)
- if packObj:
- packDataDict[mirrorID] = packObj.GetPackData()
+ packData = packDataMgr.GetPlayerPackdata(mirrorID)
+ if packData:
+ packDataDict[mirrorID] = packData
continue
pullPlayerIDList.append(mirrorID)
--
Gitblit v1.8.0