From b1d37ed3a47ba7b8d6356bf64943daae9023418c Mon Sep 17 00:00:00 2001 From: hxp <ale99527@vip.qq.com> Date: 星期一, 09 六月 2025 11:20:18 +0800 Subject: [PATCH] 10263 【英文】【越南】【BT】【砍树】后端支持NPC仿真实玩家战斗和快速战斗(防范剩余血量计算报错;) --- ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerViewCache.py | 601 ++++++++++++++++++++++++++++++++++++++++++++---------- 1 files changed, 488 insertions(+), 113 deletions(-) diff --git a/ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerViewCache.py b/ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerViewCache.py index 3e4270a..60b3d25 100644 --- a/ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerViewCache.py +++ b/ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerViewCache.py @@ -19,55 +19,109 @@ #--------------------------------------------------------------------- import GameWorld +import GameWorship +import GameXiangong import PlayerControl import NetPackCommon import GameWorldArena import ChPyNetSendPack import PlayerFBHelpBattle +import GameWorldSkyTower +import CrossChampionship +import CrossBattlefield +import CrossRealmPlayer import PyGameDataStruct +import PlayerPackData import IpyGameDataPY import PyDataManager +import CrossRealmMsg +import ShareDefine +import PyGameData +import ChPlayer import ChConfig import json import time +import random + +TempCache = PyGameDataStruct.tagPlayerViewCachePy() 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 GameXiangong.IsXiangongPlayer(playerID): + return True + + if GameWorldSkyTower.IsSkyTowerPassPlayer(playerID): + return True + + if PlayerPackData.IsPackDataPlayer(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: + 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 @@ -75,20 +129,20 @@ def DelOutofTimeViewCacheData(): ## 删除过期的查看缓存数据 - curTime = int(time.time()) - MaxTime = IpyGameDataPY.GetFuncCfg("PlayerViewCache", 3) * 3600 * 24 + PlayerPackData.DelOutofTimePackData() + onlineMgr = ChPlayer.GetOnlinePlayerMgr() pyViewCacheMgr = PyDataManager.GetPlayerViewCachePyManager() playerViewCachePyDict = pyViewCacheMgr.playerViewCachePyDict for playerID, viewCache in playerViewCachePyDict.items(): - - passTime = curTime - viewCache.OffTime - if passTime < MaxTime: + if IsSaveDBViewCache(viewCache): continue - if IsSaveAllViewCache(playerID): + if onlineMgr.IsOnline(playerID): + #在线的先不删除 continue playerViewCachePyDict.pop(playerID) + PyGameData.g_crossPlayerViewCache = {} # 每日直接清空跨服玩家查看缓存 return def DeleteViewCache(playerID): @@ -99,27 +153,134 @@ 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 GetShotCacheDict(playerID, *exAttrs): + ## 获取玩家简短的缓存信息字典 + viewCache = FindViewCache(playerID) + cacheDict = GetCachePropDataDict(viewCache) + if not cacheDict: + return {} + shotCacheDict = { + "Name":cacheDict["Name"], + "Job":cacheDict["Job"], + "LV":cacheDict["LV"], + "RealmLV":cacheDict["RealmLV"], + } + for attrName in exAttrs: + if attrName == "PlayerID": + shotCacheDict["PlayerID"] = playerID + elif attrName == "ServerID": + shotCacheDict["ServerID"] = GameWorld.GetAccIDServerID(cacheDict["AccID"]) + elif attrName == "OfflineValue": + olMgr = ChPlayer.GetOnlinePlayerMgr() + shotCacheDict["OfflineValue"] = olMgr.GetOfflineValue(playerID, viewCache) + # 附带外观模型展示相关 + elif attrName == "Model": + shotCacheDict.update({ + "TitleID":cacheDict.get("TitleID", 0), + "EquipShowSwitch":cacheDict.get("EquipShowSwitch", 0), + "EquipShowID":cacheDict.get("EquipShowID", []), + }) + elif attrName in cacheDict: + shotCacheDict[attrName] = cacheDict[attrName] + return shotCacheDict + +def GetSyncCrossCacheBase(curPlayer): + ## 获取同步跨服基础查看缓存,主要用于个别功能需要提前先同步玩家基础缓存到跨服,因为跨服不一定有玩家缓存,需要提前同步 + if isinstance(curPlayer, int): + playerID = curPlayer + curPlayer = None + else: + playerID = curPlayer.GetPlayerID() + cacheDict = GetCachePropDataDict(FindViewCache(playerID)) + cacheBase = { + "AccID":curPlayer.GetAccID() if curPlayer else cacheDict.get("AccID", ""), + "LV":curPlayer.GetLV() if curPlayer else cacheDict.get("LV", 1), + "RealmLV":curPlayer.GetOfficialRank() if curPlayer else cacheDict.get("RealmLV", 1), + "Job":curPlayer.GetJob() if curPlayer else cacheDict.get("Job", 1), + "VIPLV":curPlayer.GetVIPLv() if curPlayer else cacheDict.get("VIPLV", 0), + "Name":curPlayer.GetName() if curPlayer else cacheDict.get("Name", ""), # 此处不用跨服名称,如前端需要展示跨服名称,可通过ServerID或AccID取得ServerID展示 + "Face":curPlayer.GetFace() if curPlayer else cacheDict.get("Face", 0), + "FacePic":curPlayer.GetFacePic() if curPlayer else cacheDict.get("FacePic", 0), + "FamilyID":curPlayer.GetFamilyID() if curPlayer else cacheDict.get("FacmilyID", 0), + "FamilyName":cacheDict.get("FamilyName", ""), + "TitleID":cacheDict.get("TitleID", 0), + "FightPower":PlayerControl.GetFightPower(curPlayer) if curPlayer else cacheDict.get("FightPower", 0), + "EquipShowSwitch":cacheDict.get("EquipShowSwitch", 0), + "EquipShowID":cacheDict.get("EquipShowID", []), + "ServerGroupID":PlayerControl.GetPlayerServerGroupID(curPlayer) if curPlayer else cacheDict.get("ServerGroupID", GameWorld.GetServerGroupID()), + } + return cacheBase + +def UpdCrossCacheBase(playerID, cacheBase, isLogout=False): + ## 更新同步跨服基础查看缓存 + curCache = FindViewCache(playerID, True, cacheBase) + 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 + +ItemDataClassMax = 20 # 最大装备阶数 #//04 01 地图同步玩家缓存数据到GameServer#tagMGUpdatePlayerCache # #struct tagMGUpdatePlayerCache @@ -136,34 +297,28 @@ # WORD ItemDataSize1; # char ItemData1[ItemDataSize1]; //1阶装备数据 # ... ... -# WORD ItemDataSize15; -# char ItemData15[ItemDataSize15]; +# WORD ItemDataSize20; +# char ItemData20[ItemDataSize20]; +# BYTE PackDataSyncState; // 打包数据同步状态: 0-不同步;个位-是否同步本服;十位-是否同步跨服 +# DWORD PackDataLen; +# char PackData[PackDataLen]; +# WORD PackMsgLen; +# char PackMsg[PackMsgLen]; #}; 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) + packDataSyncState = curPackData.PackDataSyncState + packDataLen = curPackData.PackDataLen + GameWorld.DebugLog('地图同步玩家缓存: isLogout=%s,packDataSyncState=%s,packDataLen=%s' + % (isLogout, packDataSyncState, packDataLen), 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 @@ -173,20 +328,36 @@ #GameWorld.DebugLog(" 更新Prop数据: size=%s, %s" % (curCache.PropDataSize, curCache.PropData), playerID) #GameWorld.DebugLog(" 更新Plus数据: size=%s, %s" % (curCache.PlusDataSize, curCache.PlusData), playerID) - # 装备数据存储,不保存装备数据的话则清空 - for classLV in xrange(1, 15 + 1): - if not isSaveAll: - itemDataSize = 0 - itemData = "" - else: - itemDataSize = getattr(curPackData, "ItemDataSize%s" % classLV) - if not itemDataSize: - continue - itemData = getattr(curPackData, "ItemData%s" % classLV) + # 装备数据存储,只更新有同步的阶,只要该阶有同步,则至少是 {} + for classLV in xrange(1, ItemDataClassMax + 1): + itemDataSize = getattr(curPackData, "ItemDataSize%s" % classLV) + if not itemDataSize: + continue + itemData = getattr(curPackData, "ItemData%s" % classLV) setattr(curCache, "ItemData%s" % classLV, itemData) setattr(curCache, "ItemDataSize%s" % classLV, itemDataSize) #GameWorld.DebugLog(" 更新Item数据: classLV=%s,size=%s, %s" % (classLV, itemDataSize, itemData), playerID) + msgInfo = eval(curPackData.PackMsg) if curPackData.PackMsg else {} # 打包数据附带的信息 + + # 需要同步跨服 + if packDataSyncState&pow(2, 2): + dataMsg = {"playerID":playerID, "cacheBuffer":curCache.getBuffer(), "msgInfo":msgInfo} + CrossRealmMsg.SendMsgToCrossServer(ShareDefine.ClientServerMsg_PushPlayerCache, dataMsg) + + curPlayer = GameWorld.GetPlayerManager().FindPlayerByID(playerID) + # 在可能删除之前执行打包数据相关逻辑 + PlayerPackData.OnMGUpdatePlayerPackData(curPlayer, curPackData, msgInfo) + + if isLogout: + #不需要保存离线数据的,直接删除缓存数据 + if not IsSaveDBViewCache(curCache): + DeleteViewCache(playerID) + return + if curPlayer: + curCache.GeTuiID = curPlayer.GetGeTuiClientID() + curCache.GeTuiIDSize = len(curCache.GeTuiID) + #GameWorld.DebugLog(" %s" % curCache.outputString()) # 同步更新助战信息 if PlayerFBHelpBattle.IsInHelpBattleCheckInList(playerID): @@ -210,15 +381,108 @@ curPlayer = GameWorld.GetPlayerManager().FindPlayerByID(curPackData.PlayerID) findPlayerID = curPackData.FindPlayerID equipClassLV = curPackData.EquipClassLV - curCache = FindViewCache(findPlayerID) + OnQueryPlayerCache(curPlayer, findPlayerID, equipClassLV) + return + +#// C0 02 查看跨服玩家信息 #tagCGViewCrossPlayerInfo +# +#struct tagCGViewCrossPlayerInfo +#{ +# tagHead Head; +# DWORD PlayerID; // 跨服玩家ID +# BYTE EquipClassLV; //大于0为查看指定境界阶装备信息, 0为查看默认信息 +#}; +def OnViewCrossPlayerInfo(index, clientData, tick): + curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index) + tagPlayerID = clientData.PlayerID + equipClassLV = clientData.EquipClassLV + OnQueryPlayerCache(curPlayer, tagPlayerID, equipClassLV) + return + +#=============================================================================== +# //B3 06 查询玩家的简短信息 #tagCGViewPlayerShortInfo +# struct tagCGViewPlayerShortInfo +# { +# tagHead Head; +# DWORD PlayerID; +# }; +#=============================================================================== +def OnViewPlayerShortInfo(index, clientPack, tick): + curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index) + tagPlayerID = clientPack.PlayerID + tagPlayer = GameWorld.GetPlayerManager().FindPlayerByID(tagPlayerID) + if tagPlayer: + answerPack = ChPyNetSendPack.tagGCAnswerPlayerShortInfo() + answerPack.Clear() + answerPack.PlayerID = clientPack.PlayerID + answerPack.PlayerName = tagPlayer.GetName() + answerPack.Job = tagPlayer.GetJob() + answerPack.LV = tagPlayer.GetLV() + answerPack.RealmLV = tagPlayer.GetOfficialRank() + answerPack.OnlineType = ChConfig.Def_Online + answerPack.IsInTeam = tagPlayer.GetTeamID() > 0 + answerPack.ServerGroupID = PlayerControl.GetPlayerServerGroupID(tagPlayer) + answerPack.Face = tagPlayer.GetFace() + answerPack.FacePic = tagPlayer.GetFacePic() + NetPackCommon.SendFakePack(curPlayer, answerPack) + else: + OnQueryPlayerCache(curPlayer, tagPlayerID, isShort=1) + return + +def OnQueryPlayerCache(curPlayer, tagPlayerID, equipClassLV=0, isShort=0): + '''查询玩家缓存,支持直接在本服或跨服查询任意服务器玩家 + @param tagPlayerID: 目标玩家ID + @param equipClassLV: 指定查看某一阶装备信息 + @param isShort: 是否查看简短信息 + ''' + if not curPlayer: + return + playerID = curPlayer.GetPlayerID() + GameWorld.DebugLog("查看玩家: tagPlayerID=%s,equipClassLV=%s,isShort=%s" % (tagPlayerID, equipClassLV, isShort), playerID) + # 在跨服服务器查询 + if GameWorld.IsCrossServer(): + curCache = FindViewCache(tagPlayerID) + if curCache: + GameWorld.DebugLog(" 在跨服查看玩家跨服有数据,直接回包! tagPlayerID=%s" % tagPlayerID, playerID) + Sync_PlayerCache(curPlayer, curCache, equipClassLV, isShort) + else: + GameWorld.DebugLog(" 在跨服查看玩家跨服无数据,从子服拉取! tagPlayerID=%s" % tagPlayerID, playerID) + viewFrom = 0 + msgInfo = {"playerID":playerID, "tagPlayerID":tagPlayerID, "equipClassLV":equipClassLV, "isShort":isShort, "viewFrom":viewFrom} + dataMsg = {"tagPlayerID":tagPlayerID, "msgInfo":msgInfo} + CrossRealmMsg.SendMsgToClientServer(ShareDefine.CrossServerMsg_PullPlayerViewCache, dataMsg) + + # 在子服服务器查询 + else: + # 同db玩家 + if PlayerControl.GetDBPlayerAccIDByID(tagPlayerID): + GameWorld.DebugLog(" 查看玩家本服有数据,直接回包! tagPlayerID=%s" % tagPlayerID, playerID) + curCache = FindViewCache(tagPlayerID) + Sync_PlayerCache(curPlayer, curCache, equipClassLV, isShort) + else: + if tagPlayerID in PyGameData.g_crossPlayerViewCache: + tick = GameWorld.GetGameWorld().GetTick() + curCache, cacheTick = PyGameData.g_crossPlayerViewCache[tagPlayerID] + if tick - cacheTick <= 1 * 60 * 1000: + GameWorld.DebugLog(" 1分钟内重复查看跨服玩家且本服有数据,直接回包! tagPlayerID=%s" % tagPlayerID, playerID) + Sync_PlayerCache(curPlayer, curCache, equipClassLV, isShort) + return + + GameWorld.DebugLog(" 查看玩家本服没有数据,发跨服查! tagPlayerID=%s" % tagPlayerID, playerID) + viewFrom = GameWorld.GetServerGroupID() + dataMsg = {"playerID":playerID, "tagPlayerID":tagPlayerID, "equipClassLV":equipClassLV, "isShort":isShort, "viewFrom":viewFrom} + CrossRealmMsg.SendMsgToCrossServer(ShareDefine.ClientServerMsg_ViewPlayerCache, dataMsg) + return + +def Sync_PlayerCache(curPlayer, curCache, equipClassLV=0, isShort=0): + ## 同步玩家缓存 + + if isShort: + Sync_PlayerShortInfo(curPlayer, curCache) + return if not curCache: PlayerControl.NotifyCode(curPlayer, "ViewPlayer_OffLine") return - Sync_PlayerCache(curPlayer, curCache, equipClassLV) - return - -def Sync_PlayerCache(curPlayer, curCache, equipClassLV=0): - ## 同步玩家缓存 if equipClassLV: itemData = "" if hasattr(curCache, "ItemDataSize%s" % equipClassLV): @@ -241,54 +505,26 @@ NetPackCommon.SendFakePack(curPlayer, sendPack) return -#=============================================================================== -# //B3 06 查询玩家的简短信息 #tagCGViewPlayerShortInfo -# struct tagCGViewPlayerShortInfo -# { -# tagHead Head; -# DWORD PlayerID; -# }; -#=============================================================================== -def OnViewPlayerShortInfo(index, clientPack, tick): - ## 封包通知 - tagPlayer = GameWorld.GetPlayerManager().FindPlayerByID(clientPack.PlayerID) +def Sync_PlayerShortInfo(curPlayer, curCache): + if not curCache: + PlayerControl.NotifyCode(curPlayer, "ViewPlayer_OffLine") + return answerPack = ChPyNetSendPack.tagGCAnswerPlayerShortInfo() answerPack.Clear() - if not tagPlayer: - curCache = FindViewCache(clientPack.PlayerID) - if not curCache: - # 实在找不到设置为初始化数据 - answerPack.PlayerID = clientPack.PlayerID - answerPack.PlayerName = "" - answerPack.Job = 1 - answerPack.LV = 1 - answerPack.RealmLV = 1 - answerPack.OnlineType = ChConfig.Def_Offline - answerPack.ServerGroupID = 0 - else: - cacheDict = GetCachePropDataDict(curCache) - answerPack.PlayerID = clientPack.PlayerID - answerPack.PlayerName = cacheDict["Name"] - answerPack.Job = cacheDict["Job"] - answerPack.LV = cacheDict["LV"] - answerPack.RealmLV = cacheDict["RealmLV"] - answerPack.OnlineType = ChConfig.Def_Offline - - if GameWorld.IsCrossServer(): - answerPack.ServerGroupID = cacheDict.get("ServerGroupID", 0) - else: - answerPack.ServerGroupID = GameWorld.GetServerGroupID() + cacheDict = GetCachePropDataDict(curCache) + answerPack.PlayerID = curCache.PlayerID + answerPack.PlayerName = cacheDict["Name"] + answerPack.Job = cacheDict["Job"] + answerPack.LV = cacheDict["LV"] + answerPack.RealmLV = cacheDict["RealmLV"] + answerPack.OnlineType = ChConfig.Def_Offline + answerPack.Face = cacheDict.get("Face", 0) + answerPack.FacePic = cacheDict.get("FacePic", 0) + + if GameWorld.IsCrossServer(): + answerPack.ServerGroupID = cacheDict.get("ServerGroupID", 0) else: - answerPack.PlayerID = clientPack.PlayerID - answerPack.PlayerName = tagPlayer.GetName() - answerPack.Job = tagPlayer.GetJob() - answerPack.LV = tagPlayer.GetLV() - answerPack.RealmLV = tagPlayer.GetOfficialRank() - answerPack.OnlineType = ChConfig.Def_Online - answerPack.IsInTeam = tagPlayer.GetTeamID() > 0 - answerPack.ServerGroupID = PlayerControl.GetPlayerServerGroupID(tagPlayer) - - curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index) + answerPack.ServerGroupID = GameWorld.GetServerGroupID() NetPackCommon.SendFakePack(curPlayer, answerPack) return @@ -305,3 +541,142 @@ curCache.PropDataSize = len(curCache.PropData) return +def ClientServerMsg_ViewPlayerCache(serverGroupID, msgData): + playerID = msgData["playerID"] + tagPlayerID = msgData["tagPlayerID"] + GameWorld.DebugLog("收到子服查看跨服玩家信息: serverGroupID=%s,playerID=%s,tagPlayerID=%s" % (serverGroupID, playerID, tagPlayerID)) + + curCache = FindViewCache(tagPlayerID) + if curCache: + Send_CrossServerMsg_ViewPlayerCacheRet(curCache, msgData, serverGroupID) + else: + dataMsg = {"tagPlayerID":tagPlayerID, "msgInfo":msgData} + CrossRealmMsg.SendMsgToClientServer(ShareDefine.CrossServerMsg_PullPlayerViewCache, dataMsg) + return + +def Send_CrossServerMsg_ViewPlayerCacheRet(curCache, msgData, serverGroupID): + ## 发送查看玩家缓存结果给目标子服 + msgData["cacheBuffer"] = curCache.getBuffer() if curCache else "" + CrossRealmMsg.SendMsgToClientServer(ShareDefine.CrossServerMsg_ViewPlayerCacheRet, msgData, [serverGroupID]) + return + +def ClientServerMsg_PushPlayerCache(serverGroupID, msgData): + ## 收到子服推送玩家缓存信息 + + playerID = msgData["playerID"] + cacheBuffer = msgData["cacheBuffer"] + msgInfo = msgData.get("msgInfo", {}) + + curCache = None + if not cacheBuffer: + GameWorld.DebugLog("子服推送的玩家缓存数据为空! playerID=%s" % playerID, serverGroupID) + else: + curCache = FindViewCache(playerID, True) + __updCacheBufferToCacheObj(playerID, cacheBuffer, curCache) + + if not msgInfo: + return + + viewFrom = msgInfo.get("viewFrom", 0) + if viewFrom != 0: + # 其他子服查询的,推送给目标服务器 + Send_CrossServerMsg_ViewPlayerCacheRet(curCache, msgInfo, viewFrom) + return + + # 在跨服查询的,直接回包 + viewPlayerID = msgInfo.get("playerID", 0) + if not viewPlayerID: + return + curPlayer = GameWorld.GetPlayerManager().FindPlayerByID(viewPlayerID) + if not curPlayer: + return + equipClassLV = msgInfo.get("equipClassLV", 0) + isShort = msgInfo.get("isShort", 0) + Sync_PlayerCache(curPlayer, curCache, equipClassLV, isShort) + return + +def __updCacheBufferToCacheObj(playerID, cacheBuffer, cacheObj): + try: + TempCache.clear() + if TempCache.readData(cacheBuffer) == -1: + GameWorld.ErrLog("玩家缓存数据readData失败! playerID=%s" % playerID) + return + except: + GameWorld.ErrLog("玩家缓存数据readData异常! playerID=%s" % playerID) + return + if TempCache.PlayerID != playerID: + GameWorld.ErrLog("玩家缓存数据readData后玩家ID不一致! playerID=%s != cachePlayerID=%s" % (playerID, TempCache.PlayerID)) + return + + cacheObj.PropDataDict = {} # 每次更新数据时,重置字典缓存,下次获取时重新eval缓存 + cacheObj.PlayerID = TempCache.PlayerID + cacheObj.GeTuiIDSize = TempCache.GeTuiIDSize + cacheObj.GeTuiID = TempCache.GeTuiID + cacheObj.LV = TempCache.LV + cacheObj.OffTime = TempCache.OffTime + cacheObj.PropData = TempCache.PropData + cacheObj.PropDataSize = TempCache.PropDataSize + cacheObj.PlusData = TempCache.PlusData + cacheObj.PlusDataSize = TempCache.PlusDataSize + for classLV in xrange(1, ItemDataClassMax + 1): + itemDataSize = getattr(TempCache, "ItemDataSize%s" % classLV) + if not itemDataSize: + continue + itemData = getattr(TempCache, "ItemData%s" % classLV) + setattr(cacheObj, "ItemData%s" % classLV, itemData) + setattr(cacheObj, "ItemDataSize%s" % classLV, itemDataSize) + + return True + +def CrossServerMsg_ViewPlayerCacheRet(msgData, tick): + ## 收到跨服服务器回复的查看玩家信息 + playerID = msgData["playerID"] + tagPlayerID = msgData["tagPlayerID"] + cacheBuffer = msgData["cacheBuffer"] + equipClassLV = msgData["equipClassLV"] + isShort = msgData["isShort"] + + curCache = None + if cacheBuffer: + if tagPlayerID in PyGameData.g_crossPlayerViewCache: + curCache = PyGameData.g_crossPlayerViewCache[tagPlayerID][0] + else: + curCache = PyGameDataStruct.tagPlayerViewCachePy() + if __updCacheBufferToCacheObj(tagPlayerID, cacheBuffer, curCache): + PyGameData.g_crossPlayerViewCache[tagPlayerID] = [curCache, tick] # 更新信息 + + curPlayer = GameWorld.GetPlayerManager().FindPlayerByID(playerID) + if curPlayer: + Sync_PlayerCache(curPlayer, curCache, equipClassLV, isShort) + return + +def CrossServerMsg_PullPlayerViewCache(msgData): + ## 收到跨服服务器拉取玩家玩家缓存数据 + msgInfo = msgData["msgInfo"] + tagPlayerID = msgData["tagPlayerID"] + DoPullPlayerViewCache(tagPlayerID, msgInfo) + return + +def DoPullPlayerViewCache(playerID, msgInfo): + if not PlayerControl.GetDBPlayerAccIDByID(playerID): + # 不是本服db玩家不处理 + return + + curCache = FindViewCache(playerID) + if curCache: + GameWorld.DebugLog("本服有缓存玩家数据,直接推给跨服!", playerID) + dataMsg = {"playerID":playerID, "cacheBuffer":curCache.getBuffer(), "msgInfo":msgInfo} + CrossRealmMsg.SendMsgToCrossServer(ShareDefine.ClientServerMsg_PushPlayerCache, dataMsg) + return + + curPlayer = GameWorld.GetPlayerManager().FindPlayerByID(playerID) + if not curPlayer: + GameWorld.DebugLog("本服无缓存玩家数据且不在线,直接回空数据给跨服!", playerID) + dataMsg = {"playerID":playerID, "cacheBuffer":"", "msgInfo":msgInfo} + CrossRealmMsg.SendMsgToCrossServer(ShareDefine.ClientServerMsg_PushPlayerCache, dataMsg) + return + + GameWorld.DebugLog("玩家在线的发给地图同步缓存数据!", playerID) + # 在线的转发给地图 + PlayerPackData.QueryPlayerResult_PlayerMirror(curPlayer, "PullPlayerViewCache", msgInfo) + return -- Gitblit v1.8.0