From 350137e48a88e5a19588434edd8e78860d90647f Mon Sep 17 00:00:00 2001 From: hxp <ale99527@vip.qq.com> Date: 星期一, 02 九月 2024 10:36:38 +0800 Subject: [PATCH] 10130 【后端】福地争夺资源功能(剩余时间为0报错防范;) --- ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerViewCache.py | 265 ++++++++++++++++++++++++++++++++++++++++++---------- 1 files changed, 211 insertions(+), 54 deletions(-) diff --git a/ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerViewCache.py b/ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerViewCache.py index 3e4270a..1c2a8cf 100644 --- a/ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerViewCache.py +++ b/ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerViewCache.py @@ -19,73 +19,112 @@ #--------------------------------------------------------------------- import GameWorld +import GameWorship import PlayerControl import NetPackCommon import GameWorldArena import ChPyNetSendPack +import ChGameToMapPyPack import PlayerFBHelpBattle +import GameWorldSkyTower +import CrossChampionship +import CrossBattlefield +import CrossRealmPlayer import PyGameDataStruct import IpyGameDataPY import PyDataManager +import CrossRealmPK +import ShareDefine +import ChPlayer import ChConfig import json import time +import random def DoOnDayEx(): DelOutofTimeViewCacheData() return -def IsSaveDBViewCache(playerID, playerLV): - ## 是否保存基本的缓存数据 +def IsSaveDBViewCache(viewCache): + ## 缓存数据是否入库 + if not viewCache: + return False + + playerID = viewCache.PlayerID if PlayerFBHelpBattle.IsInHelpBattleCheckInList(playerID): return True if GameWorldArena.IsArenaBattlePlayer(playerID): + return True + + if CrossBattlefield.IsBattlefieldCallPlayer(playerID): + return True + + if CrossChampionship.IsChampionshipPlayer(playerID): + return True + + if GameWorship.IsWorshipPlayer(playerID): + return True + + if PyDataManager.GetDBPyFuncTeamManager().IsTeamPlayer(playerID): + return True + + if GameWorldSkyTower.IsSkyTowerPassPlayer(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 + + if CrossRealmPK.IsCrossRealmPKPlayer(playerID, checkPreSeason=True): + return True + else: + 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 + + # 以上是相关功能需要用到的数据,必定不能删除的 + + # 以下是保留近期活跃玩家,等级限制 + playerLV = viewCache.LV + offTime = viewCache.OffTime + if not playerLV and not offTime: + # 跨服服务器之前某些情况没有存储LV及OffTime,防止误删,做旧数据兼容用 return True SaveDBLimitLV = IpyGameDataPY.GetFuncCfg("PlayerViewCache", 1) - #校验玩家等级 - if playerLV < SaveDBLimitLV: - return False - - return True - -def IsSaveAllViewCache(playerID): - ## 是否保存所有缓存数据 - - if PlayerFBHelpBattle.IsInHelpBattleCheckInList(playerID): - return True - - if GameWorldArena.IsArenaBattlePlayer(playerID): - return True - - NeedCheckBillBoardType = IpyGameDataPY.GetFuncEvalCfg("PlayerViewCache", 2) - #校验玩家是否上排行榜 - billboardMgr = GameWorld.GetBillboard() - for BillBoardType in NeedCheckBillBoardType: - curBillboard = billboardMgr.FindBillboard(BillBoardType) - if not curBillboard: - continue - if curBillboard.FindByID(playerID): + if playerLV >= SaveDBLimitLV: + maxDays = IpyGameDataPY.GetFuncCfg("PlayerViewCache", 3) + if not maxDays: + maxDays = 7 # 默认7天 + MaxTime = maxDays * 3600 * 24 + curTime = int(time.time()) + passTime = curTime - viewCache.OffTime + if passTime < MaxTime: return True - return False + return True def DelOutofTimeViewCacheData(): ## 删除过期的查看缓存数据 - curTime = int(time.time()) - MaxTime = IpyGameDataPY.GetFuncCfg("PlayerViewCache", 3) * 3600 * 24 - pyViewCacheMgr = PyDataManager.GetPlayerViewCachePyManager() playerViewCachePyDict = pyViewCacheMgr.playerViewCachePyDict for playerID, viewCache in playerViewCachePyDict.items(): - - passTime = curTime - viewCache.OffTime - if passTime < MaxTime: - continue - if IsSaveAllViewCache(playerID): + if IsSaveDBViewCache(viewCache): continue playerViewCachePyDict.pop(playerID) @@ -99,26 +138,123 @@ GameWorld.DebugLog("删除查看缓存!", playerID) return -def FindViewCache(playerID, isAddNew=False): +def FindViewCache(playerID, isAddNew=False, newPropData={}): ## 查找玩家缓存 + # @param newPropData: 新数据初始PropData {}, key: LV,RealmLV,Job,VIPLV,Name,FamilyID,FamilyName,FightPower curCache = None pyViewCacheMgr = PyDataManager.GetPlayerViewCachePyManager() playerViewCachePyDict = pyViewCacheMgr.playerViewCachePyDict if playerID in playerViewCachePyDict: curCache = playerViewCachePyDict[playerID] - elif isAddNew: + elif isAddNew or playerID < 10000: + # 内网测试假玩家 + if playerID < 10000 and not newPropData: + openJobList = IpyGameDataPY.GetFuncEvalCfg("OpenJob", 1) + fakeName = "神秘道友".decode(ShareDefine.Def_Game_Character_Encoding).encode(GameWorld.GetCharacterEncoding()) + fakeName = "%s%s" % (fakeName, playerID) + serverID = playerID % 200 + 1 # 1 ~ 200 服 + serverGroupID = serverID + if serverID < 50: + serverGroupID = serverGroupID / 10 + 1 # 前50服每10服1主服 + isOnline = True if playerID % 2 == 0 else False + olMgr = ChPlayer.GetOnlinePlayerMgr() + olMgr.SetOnlineState(playerID, isOnline, serverGroupID) + accID = "fake%s@test@s%s" % (playerID, serverID) + newPropData = { + "AccID":accID, + "PlayerID":playerID, + "Name":fakeName, + "Job":random.choice(openJobList) if openJobList else 1, + "LV":random.randint(100, 200), + "RealmLV":random.randint(5, 15), + "FightPower":random.randint(1000000, 100000000), + "ServerGroupID":serverGroupID, + } curCache = PyGameDataStruct.tagPlayerViewCachePy() curCache.PlayerID = playerID + curCache.OffTime = int(time.time()) + if newPropData: + curCache.PropData = json.dumps(newPropData, ensure_ascii=False).replace(" ", "") + curCache.PropDataSize = len(curCache.PropData) playerViewCachePyDict[playerID] = curCache return curCache def GetCachePropDataDict(curCache): ## 获取缓存基础属性字典信息 + if not curCache: + return {} if not hasattr(curCache, "PropDataDict"): curCache.PropDataDict = {} - if not curCache.PropDataDict: + if not curCache.PropDataDict and curCache.PropData: curCache.PropDataDict = eval(curCache.PropData) return curCache.PropDataDict + +def GetShotCahceDict(playerID, withEquip=False): + ## 获取玩家简短的缓存信息字典 + viewCache = FindViewCache(playerID) + cacheDict = GetCachePropDataDict(viewCache) + if not cacheDict: + return {} + olMgr = ChPlayer.GetOnlinePlayerMgr() + shotCacheDict = { + "PlayerID":playerID, + "Name":cacheDict["Name"], + "Job":cacheDict["Job"], + "LV":cacheDict["LV"], + "RealmLV":cacheDict["RealmLV"], + "FightPower":cacheDict["FightPower"], + "ServerID":GameWorld.GetAccIDServerID(cacheDict["AccID"]), + "OfflineValue":olMgr.GetOfflineValue(playerID, viewCache) + } + if withEquip: + shotCacheDict.update({ + "TitleID":cacheDict.get("TitleID", 0), + "EquipShowSwitch":cacheDict.get("EquipShowSwitch", 0), + "EquipShowID":cacheDict.get("EquipShowID", 0), + }) + return shotCacheDict + +def GetSyncCrossCacheBase(curPlayer): + ## 获取同步跨服基础查看缓存,主要用于个别功能需要提前先同步玩家基础缓存到跨服,因为跨服不一定有玩家缓存,需要提前同步 + playerID = curPlayer.GetPlayerID() + cacheDict = GetCachePropDataDict(FindViewCache(playerID)) + cacheBase = { + "AccID":curPlayer.GetAccID(), + "LV":curPlayer.GetLV(), + "RealmLV":curPlayer.GetOfficialRank(), + "Job":curPlayer.GetJob(), + "VIPLV":curPlayer.GetVIPLv(), + "Name":CrossRealmPlayer.GetCrossPlayerName(curPlayer), + "FamilyID":curPlayer.GetFamilyID(), + "FamilyName":cacheDict.get("FamilyName", ""), + "TitleID":cacheDict.get("TitleID", 0), + "FightPower":PlayerControl.GetFightPower(curPlayer), + "EquipShowSwitch":cacheDict.get("EquipShowSwitch", 0), + "EquipShowID":cacheDict.get("EquipShowID", 0), + "ServerGroupID":PlayerControl.GetPlayerServerGroupID(curPlayer), + } + return cacheBase + +def UpdCrossCacheBase(playerID, cacheBase, isLogout=False): + ## 更新同步跨服基础查看缓存 + #更新跨服在线状态,只要有同步即视为在线,除了指定是Logout的 + olMgr = ChPlayer.GetOnlinePlayerMgr() + olMgr.SetOnlineState(playerID, not isLogout, cacheBase.get("ServerGroupID", 0)) + curCache = FindViewCache(playerID, True) + if not curCache: + return {} + curCache.LV = cacheBase.get("LV", 0) + curCache.OffTime = int(time.time()) # 每次都更新,最后一次可视为跨服玩家的最近一次离线时间 + cacheDict = GetCachePropDataDict(curCache) + if not cacheBase: + return cacheDict + for k, v in cacheBase.items(): + cacheDict[k] = v + if isLogout: + if not IsSaveDBViewCache(curCache): + DeleteViewCache(playerID) + return {} + return cacheDict #//04 01 地图同步玩家缓存数据到GameServer#tagMGUpdatePlayerCache # @@ -136,34 +272,22 @@ # WORD ItemDataSize1; # char ItemData1[ItemDataSize1]; //1阶装备数据 # ... ... -# WORD ItemDataSize15; -# char ItemData15[ItemDataSize15]; +# WORD ItemDataSize20; +# char ItemData20[ItemDataSize20]; #}; def OnMGUpdatePlayerCache(routeIndex, mapID, curPackData, tick): playerID = curPackData.PlayerID - playerLV = curPackData.PlayerLV + #playerLV = curPackData.PlayerLV isLogout = curPackData.IsLogouting GameWorld.DebugLog('ViewCache### OnMGUpdatePlayerCache isLogout=%s' % isLogout, playerID) isSaveAll = True # 是否保存所有数据 - if isLogout: - #不需要保存离线数据的,直接删除缓存数据 - if not IsSaveDBViewCache(playerID, playerLV): - DeleteViewCache(playerID) - return - isSaveAll = IsSaveAllViewCache(playerID) - GameWorld.DebugLog(" isSaveAll=%s" % isSaveAll, playerID) curCache = FindViewCache(playerID, True) if not curCache: return curCache.LV = curPackData.PlayerLV curCache.OffTime = curPackData.OffTime - if isLogout: - curPlayer = GameWorld.GetPlayerManager().FindPlayerByID(playerID) - if curPlayer: - curCache.GeTuiID = curPlayer.GetGeTuiClientID() - curCache.GeTuiIDSize = len(curCache.GeTuiID) - + curCache.PropDataDict = {} # 每次更新数据时,重置字典缓存,下次获取时重新eval缓存 curCache.PropData = curPackData.PropData curCache.PropDataSize = curPackData.PropDataSize @@ -174,7 +298,7 @@ #GameWorld.DebugLog(" 更新Plus数据: size=%s, %s" % (curCache.PlusDataSize, curCache.PlusData), playerID) # 装备数据存储,不保存装备数据的话则清空 - for classLV in xrange(1, 15 + 1): + for classLV in xrange(1, 20 + 1): if not isSaveAll: itemDataSize = 0 itemData = "" @@ -187,6 +311,16 @@ setattr(curCache, "ItemDataSize%s" % classLV, itemDataSize) #GameWorld.DebugLog(" 更新Item数据: classLV=%s,size=%s, %s" % (classLV, itemDataSize, itemData), playerID) + if isLogout: + #不需要保存离线数据的,直接删除缓存数据 + if not IsSaveDBViewCache(curCache): + DeleteViewCache(playerID) + return + curPlayer = GameWorld.GetPlayerManager().FindPlayerByID(playerID) + if curPlayer: + curCache.GeTuiID = curPlayer.GetGeTuiClientID() + curCache.GeTuiIDSize = len(curCache.GeTuiID) + #GameWorld.DebugLog(" %s" % curCache.outputString()) # 同步更新助战信息 if PlayerFBHelpBattle.IsInHelpBattleCheckInList(playerID): @@ -205,16 +339,36 @@ # DWORD PlayerID; //玩家ID # DWORD FindPlayerID; //要查询的玩家ID # BYTE EquipClassLV; //大于0为查看指定境界阶装备信息, 0为查看默认信息 +# BYTE CallMap; //是否需要通知地图 #}; def OnMGQueryPlayerCache(routeIndex, mapID, curPackData, tick): curPlayer = GameWorld.GetPlayerManager().FindPlayerByID(curPackData.PlayerID) findPlayerID = curPackData.FindPlayerID equipClassLV = curPackData.EquipClassLV + callMap = curPackData.CallMap curCache = FindViewCache(findPlayerID) if not curCache: PlayerControl.NotifyCode(curPlayer, "ViewPlayer_OffLine") + if callMap: + sendPack = ChGameToMapPyPack.tagGMPlayerCache() + sendPack.PlayerID = curPlayer.GetPlayerID() + sendPack.FindPlayerID = findPlayerID + sendPack.PropData = "" + sendPack.PropDataSize = len(sendPack.PropData) + sendPack.PlusData = "" + sendPack.PlusDataSize = len(sendPack.PlusData) + NetPackCommon.SendPyPackToMapServer(routeIndex, mapID, sendPack) return Sync_PlayerCache(curPlayer, curCache, equipClassLV) + if callMap: + sendPack = ChGameToMapPyPack.tagGMPlayerCache() + sendPack.PlayerID = curPlayer.GetPlayerID() + sendPack.FindPlayerID = findPlayerID + sendPack.PropData = curCache.PropData + sendPack.PropDataSize = len(sendPack.PropData) + sendPack.PlusData = curCache.PlusData + sendPack.PlusDataSize = len(sendPack.PlusData) + NetPackCommon.SendPyPackToMapServer(routeIndex, mapID, sendPack) return def Sync_PlayerCache(curPlayer, curCache, equipClassLV=0): @@ -265,6 +419,7 @@ answerPack.RealmLV = 1 answerPack.OnlineType = ChConfig.Def_Offline answerPack.ServerGroupID = 0 + answerPack.Face = 0 else: cacheDict = GetCachePropDataDict(curCache) answerPack.PlayerID = clientPack.PlayerID @@ -273,6 +428,7 @@ answerPack.LV = cacheDict["LV"] answerPack.RealmLV = cacheDict["RealmLV"] answerPack.OnlineType = ChConfig.Def_Offline + answerPack.Face = cacheDict.get("Face", 0) if GameWorld.IsCrossServer(): answerPack.ServerGroupID = cacheDict.get("ServerGroupID", 0) @@ -287,6 +443,7 @@ answerPack.OnlineType = ChConfig.Def_Online answerPack.IsInTeam = tagPlayer.GetTeamID() > 0 answerPack.ServerGroupID = PlayerControl.GetPlayerServerGroupID(tagPlayer) + answerPack.Face = tagPlayer.GetFace() curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index) NetPackCommon.SendFakePack(curPlayer, answerPack) -- Gitblit v1.8.0