ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerViewCache.py
@@ -31,16 +31,20 @@
import CrossBattlefield
import CrossRealmPlayer
import PyGameDataStruct
import PlayerPackData
import IpyGameDataPY
import PyDataManager
import CrossRealmPK
import CrossRealmMsg
import ShareDefine
import PyGameData
import ChPlayer
import ChConfig
import json
import time
import random
TempCache = PyGameDataStruct.tagPlayerViewCachePy()
def DoOnDayEx():
    DelOutofTimeViewCacheData()
@@ -76,6 +80,9 @@
    if GameWorldSkyTower.IsSkyTowerPassPlayer(playerID):
        return True
    
    if PlayerPackData.IsPackDataPlayer(playerID):
        return True
    #跨服榜单上的默认保留
    if GameWorld.IsCrossServer():
        billboardMgr = PyDataManager.GetCrossBillboardManager()
@@ -86,8 +93,6 @@
                if billboardObj.FindByID(playerID):
                    return True
                
        if CrossRealmPK.IsCrossRealmPKPlayer(playerID, checkPreSeason=True):
            return True
    else:
        NeedCheckBillBoardType = IpyGameDataPY.GetFuncEvalCfg("PlayerViewCache", 2)
        #校验玩家是否上排行榜
@@ -124,6 +129,8 @@
def DelOutofTimeViewCacheData():
    ## 删除过期的查看缓存数据
    
    PlayerPackData.DelOutofTimePackData()
    pyViewCacheMgr = PyDataManager.GetPlayerViewCachePyManager()
    playerViewCachePyDict = pyViewCacheMgr.playerViewCachePyDict
    for playerID, viewCache in playerViewCachePyDict.items():
@@ -131,6 +138,7 @@
            continue
        playerViewCachePyDict.pop(playerID)
        
    PyGameData.g_crossPlayerViewCache = {} # 每日直接清空跨服玩家查看缓存
    return
def DeleteViewCache(playerID):
@@ -204,22 +212,23 @@
                     "LV":cacheDict["LV"], 
                     "RealmLV":cacheDict["RealmLV"], 
                     }
    if "PlayerID" in exAttrs:
        shotCacheDict["PlayerID"] = playerID
    if "FightPower" in exAttrs:
        shotCacheDict["FightPower"] = cacheDict["FightPower"]
    if "ServerID" in exAttrs:
        shotCacheDict["ServerID"] = GameWorld.GetAccIDServerID(cacheDict["AccID"])
    if "OfflineValue" in exAttrs:
        olMgr = ChPlayer.GetOnlinePlayerMgr()
        shotCacheDict["OfflineValue"] = olMgr.GetOfflineValue(playerID, viewCache)
    # 附带外观模型展示相关
    if "Model" in exAttrs:
        shotCacheDict.update({
                              "TitleID":cacheDict.get("TitleID", 0),
                              "EquipShowSwitch":cacheDict.get("EquipShowSwitch", 0),
                              "EquipShowID":cacheDict.get("EquipShowID", []),
                              })
    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):
@@ -233,6 +242,8 @@
                 "Job":curPlayer.GetJob(),
                 "VIPLV":curPlayer.GetVIPLv(),
                 "Name":CrossRealmPlayer.GetCrossPlayerName(curPlayer),
                 "Face":curPlayer.GetFace(),
                 "FacePic":curPlayer.GetFacePic(),
                 "FamilyID":curPlayer.GetFamilyID(),
                 "FamilyName":cacheDict.get("FamilyName", ""),
                 "TitleID":cacheDict.get("TitleID", 0),
@@ -245,10 +256,7 @@
def UpdCrossCacheBase(playerID, cacheBase, isLogout=False):
    ## 更新同步跨服基础查看缓存
    #更新跨服在线状态,只要有同步即视为在线,除了指定是Logout的
    olMgr = ChPlayer.GetOnlinePlayerMgr()
    olMgr.SetOnlineState(playerID, not isLogout, cacheBase.get("ServerGroupID", 0))
    curCache = FindViewCache(playerID, True)
    curCache = FindViewCache(playerID, True, cacheBase)
    if not curCache:
        return {}
    curCache.LV = cacheBase.get("LV", 0)
@@ -264,6 +272,7 @@
            return {}
    return cacheDict
ItemDataClassMax = 20 # 最大装备阶数
#//04 01 地图同步玩家缓存数据到GameServer#tagMGUpdatePlayerCache
#
#struct    tagMGUpdatePlayerCache
@@ -282,13 +291,20 @@
#    ...         ...
#    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
    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:
@@ -304,26 +320,32 @@
    #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, msgInfo)
    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)
@@ -351,15 +373,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):
@@ -382,57 +495,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
            answerPack.Face = 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)
            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)
        answerPack.Face = tagPlayer.GetFace()
    curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index)
        answerPack.ServerGroupID = GameWorld.GetServerGroupID()
    NetPackCommon.SendFakePack(curPlayer, answerPack)
    return
@@ -449,3 +531,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