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