From 6a875d29696c5625a779a379b0de523b2383d7ef Mon Sep 17 00:00:00 2001 From: hxp <ale99527@vip.qq.com> Date: 星期四, 28 十一月 2024 16:41:11 +0800 Subject: [PATCH] 10312 【越南】【英文】【bt】【砍树】查看跨服玩家数据向对应子服查询 --- ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerViewCache.py | 358 +++++++++++++++++++++++++++++++++++++++++++++++----------- 1 files changed, 287 insertions(+), 71 deletions(-) diff --git a/ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerViewCache.py b/ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerViewCache.py index 9257609..eee9715 100644 --- a/ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerViewCache.py +++ b/ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerViewCache.py @@ -34,14 +34,18 @@ import PlayerPackData import IpyGameDataPY import PyDataManager +import CrossRealmMsg import CrossRealmPK import ShareDefine +import PyGameData import ChPlayer import ChConfig import json import time import random + +TempCache = PyGameDataStruct.tagPlayerViewCachePy() def DoOnDayEx(): DelOutofTimeViewCacheData() @@ -137,6 +141,7 @@ continue playerViewCachePyDict.pop(playerID) + PyGameData.g_crossPlayerViewCache = {} # 每日直接清空跨服玩家查看缓存 return def DeleteViewCache(playerID): @@ -254,7 +259,7 @@ def UpdCrossCacheBase(playerID, cacheBase, isLogout=False): ## 更新同步跨服基础查看缓存 - curCache = FindViewCache(playerID, True) + curCache = FindViewCache(playerID, True, cacheBase) if not curCache: return {} curCache.LV = cacheBase.get("LV", 0) @@ -270,6 +275,7 @@ return {} return cacheDict +ItemDataClassMax = 20 # 最大装备阶数 #//04 01 地图同步玩家缓存数据到GameServer#tagMGUpdatePlayerCache # #struct tagMGUpdatePlayerCache @@ -298,8 +304,10 @@ playerID = curPackData.PlayerID #playerLV = curPackData.PlayerLV isLogout = curPackData.IsLogouting - GameWorld.DebugLog('ViewCache### OnMGUpdatePlayerCache isLogout=%s' % isLogout, playerID) - isSaveAll = True # 是否保存所有数据 + 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: @@ -315,23 +323,26 @@ #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, 20 + 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) + PlayerPackData.OnMGUpdatePlayerPackData(curPlayer, curPackData, msgInfo) if isLogout: #不需要保存离线数据的,直接删除缓存数据 @@ -365,15 +376,106 @@ 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: 是否查看简短信息 + ''' + 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): @@ -396,60 +498,35 @@ 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): 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 - answerPack.Face = 0 - answerPack.FacePic = 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 - answerPack.Face = cacheDict.get("Face", 0) - answerPack.FacePic = cacheDict.get("FacePic", 0) - - if GameWorld.IsCrossServer(): - answerPack.ServerGroupID = cacheDict.get("ServerGroupID", 0) - else: - answerPack.ServerGroupID = GameWorld.GetServerGroupID() + if not curCache: + # 实在找不到设置为初始化数据 + answerPack.PlayerID = curCache.PlayerID + answerPack.PlayerName = "" + answerPack.Job = 1 + answerPack.LV = 1 + answerPack.RealmLV = 1 + answerPack.OnlineType = ChConfig.Def_Offline + answerPack.ServerGroupID = 0 + answerPack.Face = 0 + answerPack.FacePic = 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) - answerPack.Face = tagPlayer.GetFace() - answerPack.FacePic = tagPlayer.GetFacePic() - - curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index) + 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.ServerGroupID = GameWorld.GetServerGroupID() NetPackCommon.SendFakePack(curPlayer, answerPack) return @@ -466,3 +543,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